summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Jackson <ijackson@chiark.greenend.org.uk>2013-08-24 17:47:07 +0100
committerIan Jackson <ijackson@chiark.greenend.org.uk>2013-08-24 17:47:07 +0100
commita5ea919cd9bc80267bb1071b41a90e981ada6032 (patch)
tree96c926dd9b31d64ce4789e394c26c695b562b83e
parent9a14c7e93fdf2d2bf0fcfa40209f8c56a5abef8e (diff)
More comprehensive workaround for `3.0 (quilt)'.
-rw-r--r--debian/changelog1
-rwxr-xr-xdgit124
-rw-r--r--dgit.170
3 files changed, 139 insertions, 56 deletions
diff --git a/debian/changelog b/debian/changelog
index a6e6f51..a0b54f9 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,6 +1,7 @@
dgit (0.9) unstable; urgency=low
* New cleaning arrangements.
+ * More comprehensive workaround for `3.0 (quilt)'.
--
diff --git a/dgit b/dgit
index b6e79e3..df4ea91 100755
--- a/dgit
+++ b/dgit
@@ -757,24 +757,35 @@ sub check_not_dirty () {
}
}
-sub commit_quilty_patch ($) {
- my ($vsn) = @_;
+sub commit_quilty_patch () {
my $output = cmdoutput @git, qw(status --porcelain);
- my %fixups = map {$_=>1}
- (".pc/debian-changes-$vsn/","debian/patches/debian-changes-$vsn");
- my @files;
+ my %adds;
+ my $bad=0;
foreach my $l (split /\n/, $output) {
- next unless $l =~ s/^\?\? //;
- next unless $fixups{$l};
- push @files, $l;
+ next unless $l =~ m/\S/;
+ if ($l =~ m{^\?\? (.pc|debian/patches)}) {
+ $adds{$1}++;
+ } else {
+ print STDERR "git status: $l\n";
+ $bad++;
+ }
}
- print DEBUG "checking for quilty\n", Dumper(\@files);
- if (@files == 2) {
- my $m = "Commit Debian 3.0 (quilt) metadata";
- print "$m\n";
- runcmd_ordryrun @git, qw(add), @files;
- runcmd_ordryrun @git, qw(commit -m), $m;
+ fail "unexpected output from git status (is tree clean?)" if $bad;
+ if (!%adds) {
+ print "nothing quilty to commit, ok.\n";
+ return;
}
+ runcmd_ordryrun @git, qw(add), sort keys %adds;
+ my $m = "Commit Debian 3.0 (quilt) metadata";
+ print "$m\n";
+ runcmd_ordryrun @git, qw(commit -m), $m;
+}
+
+sub madformat ($) {
+ my ($format) = @_;
+ return 0 unless $format eq '3.0 (quilt)';
+ print "Format \`$format', urgh\n";
+ return 1;
}
sub dopush () {
@@ -794,9 +805,8 @@ sub dopush () {
fail "$dsc is for $dscpackage $dversion".
" but debian/changelog is for $package $cversion";
print DEBUG "format $format\n";
- if ($format eq '3.0 (quilt)') {
- print "Format \`$format', urgh\n";
- commit_quilty_patch($dversion);
+ if (madformat($format)) {
+ commit_quilty_patch();
}
check_not_dirty();
prep_ud();
@@ -960,6 +970,68 @@ sub cmd_push {
dopush();
}
+our $version;
+our $sourcechanges;
+our $dscfn;
+
+our $fakeeditorenv = 'DGIT_FAKE_EDITOR_QUILT';
+
+sub build_maybe_quilt_fixup () {
+ if (!open F, "debian/source/format") {
+ die $! unless $!==&ENOENT;
+ return;
+ }
+ $_ = <F>;
+ F->error and die $!;
+ chomp;
+ return unless madformat($_);
+ # sigh
+ my $headref = rev_parse('HEAD');
+ my $time = time;
+ my $patchname = "auto-$version-$headref-$time";
+ my $author = cmdoutput @git, qw(log -n1), '--pretty=format:%an <%ae>';
+ my $msg = cmdoutput @git, qw(log -n1), "--pretty=format:%s\n%b";
+ my $descfn = ".git/dgit/quilt-description.tmp";
+ open O, '>', $descfn or die "$descfn: $!";
+ $msg =~ s/\n/\n /g;
+ $msg =~ s/^\s+$/ ./mg;
+ print O <<END or die $!;
+Description: $msg
+ [generated from git commit $headref]
+Author: $author
+
+---
+
+END
+ close O or die $!;
+ {
+ local $ENV{'EDITOR'} = cmdoutput qw(realpath --), $0;
+ local $ENV{'VISUAL'} = $ENV{'EDITOR'};
+ local $ENV{$fakeeditorenv} = cmdoutput qw(realpath --), $descfn;
+ runcmd_ordryrun @dpkgsource, qw(--commit .), $patchname;
+ }
+ commit_quilty_patch();
+}
+
+sub quilt_fixup_editor () {
+ my $descfn = $ENV{$fakeeditorenv};
+ my $editing = $ARGV[$#ARGV];
+ open I1, '<', $descfn or die "$descfn: $!";
+ open I2, '<', $editing or die "$editing: $!";
+ unlink $editing or die "$editing: $!";
+ open O, '>', $editing or die "$editing: $!";
+ while (<I1>) { print O or die $!; } I1->error and die $!;
+ my $copying = 0;
+ while (<I2>) {
+ $copying ||= m/^\-\-\- /;
+ next unless $copying;
+ print O or die $!;
+ }
+ I2->error and die $!;
+ close O or die $1;
+ exit 0;
+}
+
sub cmd_build {
# we pass further options and args to git-buildpackage
badusage "-p is not allowed with dgit build" if defined $package;
@@ -967,6 +1039,8 @@ sub cmd_build {
my $clogp = parsechangelog();
$isuite = getfield $clogp, 'Distribution';
$package = getfield $clogp, 'Source';
+ $version = getfield $clogp, 'Version';
+ build_maybe_quilt_fixup();
my @cmd =
(qw(git-buildpackage -us -uc --git-no-sign-tags),
"--git-builder=@dpkgbuildpackage");
@@ -979,19 +1053,16 @@ sub cmd_build {
printdone "build successful\n";
}
-our $version;
-our $sourcechanges;
-our $dscfn;
-
sub build_source {
- check_not_dirty();
badusage "-p is not allowed with this action" if defined $package;
+ check_not_dirty();
my $clogp = parsechangelog();
$package = getfield $clogp, 'Source';
my $isuite = getfield $clogp, 'Distribution';
$version = getfield $clogp, 'Version';
$sourcechanges = "${package}_${version}_source.changes";
$dscfn = dscfn($version);
+ build_maybe_quilt_fixup();
if ($cleanmode eq 'dpkg-source') {
runcmd_ordryrun (@dpkgbuildpackage, qw(-us -uc -S)), changesopts();
} else {
@@ -1041,9 +1112,10 @@ sub cmd_sbuild {
}
sub cmd_quilt_fixup {
- badusage "incorrect arguments to dgit quilt-fixup";
+ badusage "incorrect arguments to dgit quilt-fixup" if @ARGV;
my $clogp = parsechangelog();
- commit_quilty_patch((getfield $clogp, 'Version'));
+ $version = getfield $clogp, 'Version';
+ build_maybe_quilt_fixup();
}
sub parseopts () {
@@ -1115,6 +1187,10 @@ sub parseopts () {
}
}
+if ($ENV{$fakeeditorenv}) {
+ quilt_fixup_editor();
+}
+
parseopts();
print STDERR "DRY RUN ONLY\n" if $dryrun;
if (!@ARGV) {
diff --git a/dgit.1 b/dgit.1
index 322bc3b..1abb7ec 100644
--- a/dgit.1
+++ b/dgit.1
@@ -128,12 +128,6 @@ field, runs debsign to sign the upload (.dsc and .changes), pushes the
signed tag, and finally uses dput to upload the .changes to the
archive.
-For a format `3.0 (quilt)' source package, dgit push
-may also have to make a commit on your current branch to contain
-quilt metadata. It will do this automatically if necessary.
-You can explicitly request that dgit do just this
-dgit quilt-fixup.
-
dgit push always uses the package, suite and version specified in the
debian/changelog and the .dsc, which must agree.
@@ -141,15 +135,12 @@ If dgit push fails while uploading, it is fine to simply retry the
dput on the .changes file at your leisure.
.TP
.B dgit quilt-fixup
-Looks to see if there is quilt patch metadata left over by dpkg-source
--b, and if so makes a git commit of it. This is normally done
-automatically by dgit push. dgit quilt-fixup takes no additional
-arguments. Note that it will only process a patch generated by
-dpkg-source for the most recent version (according to the
-debia/changelog).
-
-It is not normally necessary to run dgit quilt-fixup explicitly;
-where necessary it is done as part of dgit push.
+Looks to see if the tree is one which dpkg-source cannot properly
+represent. If it isn't, dgit will fix it up for you (in quilt terms,
+by making a new debian/ patch containing your unquilty changes) and
+make a commit of the changes it has made.
+
+This is normally done automatically by dgit build and dgit push.
.SH WORKFLOW - SIMPLE
It is always possible with dgit to clone or fetch a package, make
changes in git (using git-commit) on the suite branch
@@ -274,15 +265,34 @@ in git and a fast-forwarding release branch; or you could do your work
directly in a merging way on the
.BI dgit/ suite
branches. If you do this you should probably use a `1.0' format
-source package. In the archive, the delta between upstream will be
-represented in the single Debian patch.
-
-Secondly, you can regard your quiltish patch stack in the archive as
-primary. You will have to use other tools besides dgit to import and
-export this patch stack. For `3.0 (quilt)' packages, dgit has to do
-more work to work around some braindamage in way dpkg-source handles
-changes made to this format. See also the BUGS section. We recommend
-against the use of `3.0 (quilt)'.
+source package if you can. In the archive, the delta between upstream
+will be represented in the single Debian patch.
+
+Secondly, you can use `3.0 (quilt)', and regard your quiltish patch
+stack in the archive as primary. You will have to use other tools
+besides dgit to import and export this patch stack. But see below:
+.SH FORMAT 3.0 (QUILT)
+For a format `3.0 (quilt)' source package, dgit may have to make a
+commit on your current branch to contain metadata used by quilt and
+dpkg-source.
+
+This is because (i) the `3.0 (quilt)' source format cannot represent
+certain trees, and (ii) packing up a tree in `3.0 (quilt)' and then
+unpacking it does not always yield the same tree. Instead,
+dpkg-source insists on the trees having extra quilty metadata and
+patch files in the debian/ and .pc/ directories, which dpkg-source
+sometimes modifies.
+
+dgit will automatically work around this braindamage for you when
+building and pushing. The only thing you need to know is that dgit
+build, sbuild, etc., may make a new commit on your HEAD. If you're
+not a quilt user this commit won't contain any changes to files you
+care about.
+
+You can explicitly request that dgit do just this fixup, by running
+dgit quilt-fixup.
+
+We recommend against the use of `3.0 (quilt)'.
.SH OPTIONS
.TP
.BR --dry-run | -n
@@ -513,14 +523,10 @@ the .orig.tar.gz could be transported via the git repo as git tags.
Doing this is made more complicated by the possibility of a `3.0
(quilt)' package with multiple .orig tarballs.
-`3.0 (quilt)' packages have an additional difficulty: if these are
-edited in the most normal way, and then fed to dpkg-buildpackage,
-dpkg-source will add extra quilt patch metadata to the source tree
-during the source package build. This extra metadata is then of
-course not included in the git history. So dgit push needs to commit
-it for you, to make sure that the git history and archive contents are
-identical. That this is necessary is a bug in the `3.0 (quilt)'
-format.
+dgit's build functions, and dgit push, should not make any changes to
+your current HEAD. Sadly this is necessary for packages in the `3.0
+(quilt)' source format. This is ultimately due to design problems in
+quilt and dpkg-source.
There should be an option which arranges for the `3.0 (quilt)'
autocommit to not appear on your HEAD, but instead only in the