From: Colin Watson Date: Sun, 16 Mar 2008 10:45:25 +0000 (+0100) Subject: Add bzr-based source package format X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5705e32f8e8be2ddfd60d914be125bb10a3ac05b;p=dpkg Add bzr-based source package format * scripts/Dpkg/Source/Package/V3_0/bzr.pm: New module handling the "3.0 (bzr)" source package format. It's based on the git one. * scripts/Makefile.am, scripts/po/POTFILES.in: Register the above file. --- diff --git a/scripts/Dpkg/Source/Package/V3_0/bzr.pm b/scripts/Dpkg/Source/Package/V3_0/bzr.pm new file mode 100644 index 00000000..a0e1974d --- /dev/null +++ b/scripts/Dpkg/Source/Package/V3_0/bzr.pm @@ -0,0 +1,206 @@ +#!/usr/bin/perl +# +# bzr support for dpkg-source +# +# Copyright © 2007 Colin Watson . +# Based on Dpkg::Source::Package::V3_0::git, which is: +# Copyright © 2007 Joey Hess . +# Copyright © 2008 Frank Lichtenheld +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +package Dpkg::Source::Package::V3_0::bzr; + +use strict; +use warnings; + +use base 'Dpkg::Source::Package'; + +use Cwd; +use File::Basename; +use File::Find; +use File::Temp qw(tempdir); + +use Dpkg; +use Dpkg::Gettext; +use Dpkg::Compression; +use Dpkg::ErrorHandling qw(error subprocerr syserr info); +use Dpkg::Version qw(check_version); +use Dpkg::Source::Archive; +use Dpkg::Exit; +use Dpkg::Source::Functions qw(erasedir); + +sub import { + foreach my $dir (split(/:/, $ENV{PATH})) { + if (-x "$dir/bzr") { + return 1; + } + } + error(_g("This source package can only be manipulated using bzr, which is not in the PATH.")); +} + +sub sanity_check { + my $srcdir=shift; + + if (! -d "$srcdir/.bzr") { + error(_g("source directory is not the top directory of a bzr repository (%s/.bzr not present), but Format bzr was specified"), + $srcdir); + } + + # Symlinks from .bzr to outside could cause unpack failures, or + # point to files they shouldn't, so check for and don't allow. + if (-l "$srcdir/.bzr") { + error(_g("%s is a symlink"), "$srcdir/.bzr"); + } + my $abs_srcdir=Cwd::abs_path($srcdir); + find(sub { + if (-l $_) { + if (Cwd::abs_path(readlink($_)) !~ /^\Q$abs_srcdir\E(\/|$)/) { + error(_g("%s is a symlink to outside %s"), + $File::Find::name, $srcdir); + } + } + }, "$srcdir/.bzr"); + + return 1; +} + +sub can_build { + my ($self, $dir) = @_; + return (-d "$dir/.bzr", _g("doesn't contain a bzr repository")); +} + +sub do_build { + my ($self, $dir) = @_; + my @argv = @{$self->{'options'}{'ARGV'}}; + # TODO: warn here? + #my @tar_ignore = map { "--exclude=$_" } @{$self->{'options'}{'tar_ignore'}}; + my $diff_ignore_regexp = $self->{'options'}{'diff_ignore_regexp'}; + + $dir =~ s{/+$}{}; # Strip trailing / + my ($dirname, $updir) = fileparse($dir); + + if (scalar(@argv)) { + usageerr(_g("-b takes only one parameter with v3.0 source packages")); + } + + my $sourcepackage = $self->{'fields'}{'Source'}; + my $basenamerev = $self->get_basename(1); + my $basename = $self->get_basename(); + my $basedirname = $basename; + $basedirname =~ s/_/-/; + + sanity_check($dir); + + my $old_cwd=getcwd(); + chdir($dir) || + syserr(_g("unable to chdir to `%s'"), $dir); + + # Check for uncommitted files. + # To support dpkg-source -i, remove any ignored files from the + # output of bzr status. + open(BZR_STATUS, '-|', "bzr", "status") || + subprocerr("bzr status"); + my @files; + while () { + chomp; + next unless s/^ +//; + if (! length $diff_ignore_regexp || + ! m/$diff_ignore_regexp/o) { + push @files, $_; + } + } + close(BZR_STATUS) || syserr(_g("bzr status exited nonzero")); + if (@files) { + error(sprintf(_g("uncommitted, not-ignored changes in working directory: %s"), + join(" ", @files))); + } + + chdir($old_cwd) || + syserr(_g("unable to chdir to `%s'"), $old_cwd); + + my $tmp = tempdir("$dirname.bzr.XXXXXX", DIR => $updir); + push @Dpkg::Exit::handlers, sub { erasedir($tmp) }; + my $tardir = "$tmp/$dirname"; + + system("bzr", "branch", $dir, $tardir); + $? && subprocerr("bzr branch $dir $tardir"); + + # Remove the working tree. + system("bzr", "remove-tree", $tardir); + + # Some branch metadata files are unhelpful. + unlink("$tardir/.bzr/branch/branch-name", + "$tardir/.bzr/branch/parent"); + + # Create the tar file + my $debianfile = "$basenamerev.bzr.tar." . $self->{'options'}{'comp_ext'}; + info(_g("building %s in %s"), + $sourcepackage, $debianfile); + my $tar = Dpkg::Source::Archive->new(filename => $debianfile, + compression => $self->{'options'}{'compression'}, + compression_level => $self->{'options'}{'comp_level'}); + $tar->create('chdir' => $tmp); + $tar->add_directory($dirname); + $tar->finish(); + + erasedir($tmp); + pop @Dpkg::Exit::handlers; + + $self->add_file($debianfile); +} + +# Called after a tarball is unpacked, to check out the working copy. +sub do_extract { + my ($self, $newdirectory) = @_; + my $fields = $self->{'fields'}; + + my $dscdir = $self->{'basedir'}; + + check_version($fields->{'Version'}); + + my $basename = $self->get_basename(); + my $basenamerev = $self->get_basename(1); + + my @files = $self->get_files(); + if (@files > 1) { + error(_g("format v3.0 uses only one source file")); + } + my $tarfile = $files[0]; + if ($tarfile !~ /^\Q$basenamerev\E\.bzr\.tar\.$comp_regex$/) { + error(_g("expected %s, got %s"), + "$basenamerev.bzr.tar.$comp_regex", $tarfile); + } + + erasedir($newdirectory); + + # Extract main tarball + info(_g("unpacking %s"), $tarfile); + my $tar = Dpkg::Source::Archive->new(filename => "$dscdir$tarfile"); + $tar->extract($newdirectory); + + sanity_check($newdirectory); + + my $old_cwd=getcwd(); + chdir($newdirectory) || + syserr(_g("unable to chdir to `%s'"), $newdirectory); + + # Reconstitute the working tree. + system("bzr", "checkout"); + + chdir($old_cwd) || + syserr(_g("unable to chdir to `%s'"), $old_cwd); +} + +1 diff --git a/scripts/Makefile.am b/scripts/Makefile.am index a9c6e91c..2300d9b2 100644 --- a/scripts/Makefile.am +++ b/scripts/Makefile.am @@ -113,6 +113,7 @@ nobase_dist_perllib_DATA = \ Dpkg/Source/Package.pm \ Dpkg/Source/Package/V1_0.pm \ Dpkg/Source/Package/V2_0.pm \ + Dpkg/Source/Package/V3_0/bzr.pm \ Dpkg/Source/Package/V3_0/native.pm \ Dpkg/Source/Package/V3_0/git.pm \ Dpkg/Source/Package/V3_0/quilt.pm \ diff --git a/scripts/po/POTFILES.in b/scripts/po/POTFILES.in index 7cc9903b..33413ca9 100644 --- a/scripts/po/POTFILES.in +++ b/scripts/po/POTFILES.in @@ -35,6 +35,7 @@ scripts/Dpkg/Source/Patch.pm scripts/Dpkg/Source/Package.pm scripts/Dpkg/Source/Package/V1_0.pm scripts/Dpkg/Source/Package/V2_0.pm +scripts/Dpkg/Source/Package/V3_0/bzr.pm scripts/Dpkg/Source/Package/V3_0/native.pm scripts/Dpkg/Source/Package/V3_0/git.pm scripts/Dpkg/Source/Package/V3_0/quilt.pm