our $quilt_modes_re = 'linear|smash|auto|nofix|nocheck|gbp|unapplied';
our $we_are_responder;
our $initiator_tempdir;
+our $patches_applied_dirtily = 00;
our %format_ok = map { $_=>1 } ("1.0","3.0 (native)","3.0 (quilt)");
our (@dpkgsource) = qw(dpkg-source -i\.git/ -I.git);
our (@dpkggenchanges) = qw(dpkg-genchanges);
our (@mergechanges) = qw(mergechanges -f);
-our (@gbppq) = qw(gbp-pq);
+our (@gbp) = qw(gbp);
our (@changesopts) = ('');
our %opts_opt_map = ('dget' => \@dget, # accept for compatibility
'dpkg-source' => \@dpkgsource,
'dpkg-buildpackage' => \@dpkgbuildpackage,
'dpkg-genchanges' => \@dpkggenchanges,
+ 'gbp' => \@gbp,
'ch' => \@changesopts,
'mergechanges' => \@mergechanges);
my $format = getfield $dsc, 'Format';
printdebug "format $format\n";
+
if (madformat($format)) {
# user might have not used dgit build, so maybe do this now:
commit_quilty_patch();
}
+
+ die 'xxx fast forward (should not depend on quilt mode, but will always be needed if we did $split_brain)' if $split_brain;
+
check_not_dirty();
changedir $ud;
progress "checking that $dscfn corresponds to HEAD";
sub quiltify_splitbrain_needed () {
if (!$split_brain) {
- progress "creating dgit view";
+ progress "dgit view: changes are required...";
runcmd @git, qw(checkout -q -b dgit-view);
$split_brain = 1;
}
local $ENV{GIT_COMMITTER_NAME} = $authline[0];
local $ENV{GIT_COMMITTER_EMAIL} = $authline[1];
local $ENV{GIT_COMMITTER_DATE} = $authline[2];
+
if ($quilt_mode =~ m/gbp|unapplied/ &&
- ($diffbits->{O2A} & 01) && # some patches
- !($diffbits->{H2O} & 01)) { # but HEAD is like orig
+ ($diffbits->{H2O} & 01)) {
+ my $msg =
+ "--quilt=$quilt_mode specified, implying patches-unapplied git tree\n".
+ " but git tree differs from orig in upstream files.";
+ if (!stat_exists "debian/patches") {
+ $msg .=
+ "\n ... debian/patches is missing; perhaps this is a patch queue branch?";
+ }
+ fail $msg;
+ }
+ if ($quilt_mode =~ m/gbp|unapplied/ &&
+ ($diffbits->{O2A} & 01)) { # some patches
quiltify_splitbrain_needed();
- progress "creating patches-applied version using gbp-pq";
- open STDOUT, ">/dev/null" or die $!;
- runcmd shell_cmd 'exec >/dev/null', @gbppq, qw(import);
- # gbp-pq import creates a fresh branch; push back to dgit-view
+ progress "dgit view: creating patches-applied version using gbp pq";
+ runcmd shell_cmd 'exec >/dev/null', @gbp, qw(pq import);
+ # gbp pq import creates a fresh branch; push back to dgit-view
runcmd @git, qw(update-ref refs/heads/dgit-view HEAD);
- runcmd @git, qw(checkout dgit-view);
+ runcmd @git, qw(checkout -q dgit-view);
}
if (($diffbits->{H2O} & 02) && # user has modified .gitignore
!($diffbits->{O2A} & 02)) { # patches do not change .gitignore
quiltify_splitbrain_needed();
- progress "creating patch to represent .gitignore changes";
+ progress "dgit view: creating patch to represent .gitignore changes";
ensuredir "debian/patches";
my $gipatch = "debian/patches/auto-gitignore";
open GIPATCH, ">>", "$gipatch" or die "$gipatch: $!";
runcmd @git, qw(update-ref -m), $cachekey, "refs/$splitbraincache",
$dgitview;
- die 'xxx fast forward (should not depend on quilt mode, but will always be needed if we did $split_brain)';
+ progress "dgit view: created (commit id $dgitview)";
+
changedir '.git/dgit/unpack/work';
}
quilt_fixup_multipatch($clogp, $headref, $upstreamversion);
}
+ die 'bug' if $split_brain && !$need_split_build_invocation;
+
changedir '../../../..';
runcmd_ordryrun_local
@git, qw(pull --ff-only -q .git/dgit/unpack/work master);
sub quilt_fixup_multipatch ($$$) {
my ($clogp, $headref, $upstreamversion) = @_;
- progress "starting quiltify (multiple patches, $quilt_mode mode)";
+ progress "examining quilt state (multiple patches, $quilt_mode mode)";
# Our objective is:
# - honour any existing .pc in case it has any strangeness
}
my $debtar= srcfn $fakeversion,'.debian.tar.gz';
- runcmd qw(env GZIP=-1 tar -zcf), "./$debtar", qw(-C ../../..), @files;
+ runcmd qw(env GZIP=-1n tar -zcf), "./$debtar", qw(-C ../../..), @files;
$dscaddfile->($debtar);
close $fakedsc or die $!;
my $splitbrain_cachekey;
if (quiltmode_splitbrain()) {
+ progress
+ "dgit: split brain (separate dgit view) may needed (--quilt=$quilt_mode).";
# we look in the reflog of dgit-intern/quilt-cache
# we look for an entry whose message is the key for the cache lookup
my @cachekey = (qw(dgit), $our_version);
push @cachekey, $upstreamversion;
+ push @cachekey, $quilt_mode;
push @cachekey, $headref;
push @cachekey, hashfile('fake.dsc');
my $cachehit = $1;
quilt_fixup_mkwork($headref);
if ($cachehit ne $headref) {
- progress "quilt fixup ($quilt_mode mode) found cached tree";
+ progress "dgit view: found cached (commit id $cachehit)";
runcmd @git, qw(checkout -q -b dgit-view), $cachehit;
$split_brain = 1;
return;
}
- progress "quilt fixup ($quilt_mode mode)".
- " found cached indication that no changes needed";
+ progress "dgit view: found cached, no changes required";
return;
}
die $! if GC->error;
return;
}
+ progress "starting quiltify (multiple patches, $quilt_mode mode)";
quiltify($clogp,$headref,$oldtiptree,\@failsuggestion);
if (!open P, '>>', ".pc/applied-patches") {
exit 0;
}
+sub maybe_apply_patches_dirtily () {
+ return unless $quilt_mode =~ m/gbp|unapplied/;
+ print STDERR <<END or die $!;
+
+dgit: Building, or cleaning with rules target, in patches-unapplied tree.
+dgit: Have to apply the patches - making the tree dirty.
+dgit: (Consider specifying --clean=git and (or) using dgit sbuild.)
+
+END
+ $patches_applied_dirtily = 01;
+ $patches_applied_dirtily |= 02 unless stat_exists '.pc';
+ runcmd qw(dpkg-source --before-build .);
+}
+
+sub maybe_unapply_patches_again () {
+ progress "dgit: Unapplying patches again to tidy up the tree."
+ if $patches_applied_dirtily;
+ runcmd qw(dpkg-source --after-build .)
+ if $patches_applied_dirtily & 01;
+ rmtree '.pc'
+ if $patches_applied_dirtily & 02;
+}
+
#----- other building -----
-our $suppress_clean;
+our $clean_using_builder;
+# ^ tree is to be cleaned by dpkg-source's builtin idea that it should
+# clean the tree before building (perhaps invoked indirectly by
+# whatever we are using to run the build), rather than separately
+# and explicitly by us.
sub clean_tree () {
- return if $suppress_clean;
+ return if $clean_using_builder;
if ($cleanmode eq 'dpkg-source') {
+ maybe_apply_patches_dirtily();
runcmd_ordryrun_local @dpkgbuildpackage, qw(-T clean);
} elsif ($cleanmode eq 'dpkg-source-d') {
+ maybe_apply_patches_dirtily();
runcmd_ordryrun_local @dpkgbuildpackage, qw(-d -T clean);
} elsif ($cleanmode eq 'git') {
runcmd_ordryrun_local @git, qw(clean -xdf);
badusage "clean takes no additional arguments" if @ARGV;
notpushing();
clean_tree();
+ maybe_unapply_patches_again();
}
sub build_prep () {
debugcmd '#massaging#', @$cmd if $debuglevel>1;
#print STDERR "MASS0 ",Dumper($cmd, $xargs, $need_split_build_invocation);
if ($cleanmode eq 'dpkg-source' && !$need_split_build_invocation) {
- $suppress_clean = 1;
+ $clean_using_builder = 1;
return 0;
}
# -nc has the side effect of specifying -b if nothing else specified
#print STDERR "MASS1 ",Dumper($cmd, $xargs, $dmode);
my $r = 0;
if ($need_split_build_invocation) {
+ printdebug "massage split $dmode.\n";
$r = $dmode =~ m/[S]/ ? +2 :
$dmode =~ y/gGF/ABb/ ? +1 :
$dmode =~ m/[ABb]/ ? 0 :
die "$dmode ?";
}
+ printdebug "massage done $r $dmode.\n";
push @$cmd, $dmode;
#print STDERR "MASS2 ",Dumper($cmd, $xargs, $r);
return $r;
}
if ($wantsrc < 2) {
push @dbp, changesopts_version();
+ maybe_apply_patches_dirtily();
runcmd_ordryrun_local @dbp;
}
+ maybe_unapply_patches_again();
printdone "build successful\n";
}
if ($wantsrc > 0) {
build_source();
} else {
- if (!$suppress_clean) {
+ if (!$clean_using_builder) {
push @cmd, '--git-cleaner=true';
}
build_prep();
push @cmd, "--git-debian-branch=".lbranch();
}
push @cmd, changesopts();
+ maybe_apply_patches_dirtily();
runcmd_ordryrun_local @cmd, @ARGV;
}
+ maybe_unapply_patches_again();
printdone "build successful\n";
}
sub cmd_git_build { cmd_gbp_build(); } # compatibility with <= 1.0
sub build_source {
- if ($cleanmode =~ m/^dpkg-source/) {
- # dpkg-source will clean, so we shouldn't
- $suppress_clean = 1;
+ my $our_cleanmode = $cleanmode;
+ if ($need_split_build_invocation) {
+ # Pretend that clean is being done some other way. This
+ # forces us not to try to use dpkg-buildpackage to clean and
+ # build source all in one go; and instead we run dpkg-source
+ # (and build_prep() will do the clean since $clean_using_builder
+ # is false).
+ $our_cleanmode = 'ELSEWHERE';
+ }
+ if ($our_cleanmode =~ m/^dpkg-source/) {
+ # dpkg-source invocation (below) will clean, so build_prep shouldn't
+ $clean_using_builder = 1;
}
build_prep();
$sourcechanges = changespat $version,'source';
or fail "remove $sourcechanges: $!";
}
$dscfn = dscfn($version);
- if ($cleanmode eq 'dpkg-source') {
+ if ($our_cleanmode eq 'dpkg-source') {
+ maybe_apply_patches_dirtily();
runcmd_ordryrun_local @dpkgbuildpackage, qw(-us -uc -S),
- changesopts();
- } elsif ($cleanmode eq 'dpkg-source-d') {
+ changesopts();
+ } elsif ($our_cleanmode eq 'dpkg-source-d') {
+ maybe_apply_patches_dirtily();
runcmd_ordryrun_local @dpkgbuildpackage, qw(-us -uc -S -d),
- changesopts();
+ changesopts();
} else {
- my $pwd = must_getcwd();
- my $leafdir = basename $pwd;
- changedir "..";
- runcmd_ordryrun_local @dpkgsource, qw(-b --), $leafdir;
- changedir $pwd;
+ my @cmd = (@dpkgsource, qw(-b --));
+ if ($split_brain) {
+ changedir $ud;
+ runcmd_ordryrun_local @cmd, "work";
+ my @udfiles = <${package}_*>;
+ changedir "../../..";
+ foreach my $f (@udfiles) {
+ printdebug "source copy, found $f\n";
+ next unless
+ $f eq $dscfn or
+ ($f =~ m/\.debian\.tar(?:\.\w+)$/ &&
+ $f eq srcfn($version, $&));
+ printdebug "source copy, found $f - renaming\n";
+ rename "$ud/$f", "../$f" or $!==ENOENT
+ or fail "put in place new source file ($f): $!";
+ }
+ } else {
+ my $pwd = must_getcwd();
+ my $leafdir = basename $pwd;
+ changedir "..";
+ runcmd_ordryrun_local @cmd, $leafdir;
+ changedir $pwd;
+ }
runcmd_ordryrun_local qw(sh -ec),
'exec >$1; shift; exec "$@"','x',
"../$sourcechanges",
sub cmd_build_source {
badusage "build-source takes no additional arguments" if @ARGV;
build_source();
+ maybe_unapply_patches_again();
printdone "source built, results in $dscfn and $sourcechanges";
}
rename "$cf", "$cf.inmulti" or fail "$cf\{,.inmulti}: $!";
}
}
+ maybe_unapply_patches_again();
printdone "build successful, results in $multichanges\n" or die $!;
}
$quilt_mode = $1;
}
+$need_split_build_invocation ||= quiltmode_splitbrain();
+
if (!defined $cleanmode) {
local $access_forpush;
$cleanmode = access_cfg('clean-mode', 'RETURN-UNDEF');