From a5ea919cd9bc80267bb1071b41a90e981ada6032 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Sat, 24 Aug 2013 17:47:07 +0100 Subject: More comprehensive workaround for `3.0 (quilt)'. --- debian/changelog | 1 + dgit | 124 ++++++++++++++++++++++++++++++++++++++++++++----------- dgit.1 | 70 +++++++++++++++++-------------- 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->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 <', $editing or die "$editing: $!"; + while () { print O or die $!; } I1->error and die $!; + my $copying = 0; + while () { + $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 -- cgit v1.2.3