X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=dgit.git;a=blobdiff_plain;f=dgit;h=63ef08231ff86ca6599f707f80d555b59eda107c;hp=2365bfce431b45869c07f650f2d398e7f01ed763;hb=60b7ec7b4ed5d79709ef1ec6037b1431691db808;hpb=6be5332d24efc7a21c9b5c57ad30193badb16ff2 diff --git a/dgit b/dgit index 2365bfce..63ef0823 100755 --- a/dgit +++ b/dgit @@ -63,9 +63,10 @@ our @ropts; our $sign = 1; our $dryrun_level = 0; our $changesfile; -our $buildproductsdir = '..'; +our $buildproductsdir; +our $bpd_glob; our $new_package = 0; -our $ignoredirty = 0; +our $includedirty = 0; our $rmonerror = 1; our @deliberatelies; our %previously; @@ -90,6 +91,7 @@ our $chase_dsc_distro=1; our %forceopts = map { $_=>0 } qw(unrepresentable unsupported-source-format dsc-changes-mismatch changes-origs-exactly + uploading-binaries uploading-source-only import-gitapply-absurd import-gitapply-no-absurd import-dsc-with-dgit-field); @@ -188,11 +190,6 @@ sub debiantag ($$) { return $tagformatfn->($v, $distro); } -sub debiantag_maintview ($$) { - my ($v,$distro) = @_; - return "$distro/".dep14_version_mangle $v; -} - sub madformat ($) { $_[0] eq '3.0 (quilt)' } sub lbranch () { return "$branchprefix/$csuite"; } @@ -292,6 +289,12 @@ sub dgit_privdir () { our $dgit_privdir_made //= ensure_a_playground 'dgit'; } +sub bpd_abs () { + my $r = $buildproductsdir; + $r = "$maindir/$r" unless $r =~ m{^/}; + return $r; +} + sub branch_gdr_info ($$) { my ($symref, $head) = @_; my ($status, $msg, $current, $ffq_prev, $gdrlast) = @@ -614,6 +617,7 @@ our %defcfg = ('dgit.default.distro' => 'debian', 'dgit.default.sshpsql-dbname' => 'service=projectb', 'dgit.default.aptget-components' => 'main', 'dgit.default.dgit-tag-format' => 'new,old,maint', + 'dgit.default.source-only-uploads' => 'ok', 'dgit.dsc-url-proto-ok.http' => 'true', 'dgit.dsc-url-proto-ok.https' => 'true', 'dgit.dsc-url-proto-ok.git' => 'true', @@ -628,6 +632,7 @@ our %defcfg = ('dgit.default.distro' => 'debian', 'dgit-distro.debian.git-check' => 'url', 'dgit-distro.debian.git-check-suffix' => '/info/refs', 'dgit-distro.debian.new-private-pushers' => 't', + 'dgit-distro.debian.source-only-uploads' => 'not-wholly-new', 'dgit-distro.debian/push.git-url' => '', 'dgit-distro.debian/push.git-host' => 'push.dgit.debian.org', 'dgit-distro.debian/push.git-user-force' => 'dgit', @@ -959,59 +964,6 @@ sub access_giturl (;$) { return "$url/$package$suffix"; } -sub parsecontrolfh ($$;$) { - my ($fh, $desc, $allowsigned) = @_; - our $dpkgcontrolhash_noissigned; - my $c; - for (;;) { - my %opts = ('name' => $desc); - $opts{allow_pgp}= $allowsigned || !$dpkgcontrolhash_noissigned; - $c = Dpkg::Control::Hash->new(%opts); - $c->parse($fh,$desc) or die "parsing of $desc failed"; - last if $allowsigned; - last if $dpkgcontrolhash_noissigned; - my $issigned= $c->get_option('is_pgp_signed'); - if (!defined $issigned) { - $dpkgcontrolhash_noissigned= 1; - seek $fh, 0,0 or die "seek $desc: $!"; - } elsif ($issigned) { - fail "control file $desc is (already) PGP-signed. ". - " Note that dgit push needs to modify the .dsc and then". - " do the signature itself"; - } else { - last; - } - } - return $c; -} - -sub parsecontrol { - my ($file, $desc, $allowsigned) = @_; - my $fh = new IO::Handle; - open $fh, '<', $file or die "$file: $!"; - my $c = parsecontrolfh($fh,$desc,$allowsigned); - $fh->error and die $!; - close $fh; - return $c; -} - -sub getfield ($$) { - my ($dctrl,$field) = @_; - my $v = $dctrl->{$field}; - return $v if defined $v; - fail "missing field $field in ".$dctrl->get_option('name'); -} - -sub parsechangelog { - my $c = Dpkg::Control::Hash->new(name => 'parsed changelog'); - my $p = new IO::Handle; - my @cmd = (qw(dpkg-parsechangelog), @_); - open $p, '-|', @cmd or die $!; - $c->parse($p); - $?=0; $!=0; close $p or failedcmd @cmd; - return $c; -} - sub commit_getclogp ($) { # Returns the parsed changelog hashref for a particular commit my ($objid) = @_; @@ -1179,6 +1131,12 @@ sub file_in_archive_ftpmasterapi { my $info = api_query($data, "file_in_archive/$pat", 1); } +sub package_not_wholly_new_ftpmasterapi { + my ($proto,$data,$pkg) = @_; + my $info = api_query($data,"madison?package=${pkg}&f=json"); + return !!@$info; +} + #---------- `aptget' archive query method ---------- our $aptget_base; @@ -1286,7 +1244,14 @@ END } my @inreleasefiles = grep { m#/InRelease$# } @releasefiles; @releasefiles = @inreleasefiles if @inreleasefiles; - die "apt updated wrong number of Release files (@releasefiles), erk" + if (!@releasefiles) { + fail <) { - chomp or die; - printdebug "| $_\n"; - m/^(\w+) (\S+)$/ or die "$_ ?"; - push @out, { sha256sum => $1, filename => $2 }; - } - close FIA or die failedcmd @cmd; + my $r = $fn->(); + close FIA or ($!==0 && $?==141) or die failedcmd @cmd; + return $r; +} + +sub file_in_archive_dummycatapi ($$$) { + my ($proto,$data,$filename) = @_; + my @out; + dummycatapi_run_in_mirror ' + find -name "$1" -print0 | + xargs -0r sha256sum + ', [$filename], sub { + while () { + chomp or die; + printdebug "| $_\n"; + m/^(\w+) (\S+)$/ or die "$_ ?"; + push @out, { sha256sum => $1, filename => $2 }; + } + }; return \@out; } +sub package_not_wholly_new_dummycatapi { + my ($proto,$data,$pkg) = @_; + dummycatapi_run_in_mirror " + find -name ${pkg}_*.dsc + ", [], sub { + local $/ = undef; + !!; + }; +} + #---------- `madison' archive query method ---------- sub archive_query_madison { @@ -1420,6 +1406,7 @@ sub canonicalise_suite_madison { } sub file_in_archive_madison { return undef; } +sub package_not_wholly_new_madison { return undef; } #---------- `sshpsql' archive query method ---------- @@ -1497,6 +1484,7 @@ END } sub file_in_archive_sshpsql ($$$) { return undef; } +sub package_not_wholly_new_sshpsql ($$$) { return undef; } #---------- `dummycat' archive query method ---------- @@ -1541,6 +1529,7 @@ sub archive_query_dummycat ($$) { } sub file_in_archive_dummycat () { return undef; } +sub package_not_wholly_new_dummycat () { return undef; } #---------- tag format handling ---------- @@ -1975,12 +1964,12 @@ END if ($found_same) { # in archive, delete from .changes if it's there $changed{$file} = "removed" if - $changes->{$fname} =~ s/^.* \Q$file\E$(?:)\n//m; - } elsif ($changes->{$fname} =~ m/^.* \Q$file\E$(?:)\n/m) { + $changes->{$fname} =~ s/\n.* \Q$file\E$(?:)$//m; + } elsif ($changes->{$fname} =~ m/^.* \Q$file\E$(?:)$/m) { # not in archive, but it's here in the .changes } else { my $dsc_data = getfield $dsc, $fname; - $dsc_data =~ m/^(.* \Q$file\E$)\n/m or die "$dsc_data $file ?"; + $dsc_data =~ m/^(.* \Q$file\E$)$/m or die "$dsc_data $file ?"; my $extra = $1; $extra =~ s/ \d+ /$&$placementinfo / or die "$fname $extra >$dsc_data< ?" @@ -2130,7 +2119,7 @@ sub generate_commits_from_dsc () { foreach my $fi (@dfi) { my $f = $fi->{Filename}; die "$f ?" if $f =~ m#/|^\.|\.dsc$|\.tmp$#; - my $upper_f = "$maindir/../$f"; + my $upper_f = (bpd_abs()."/$f"); printdebug "considering reusing $f: "; @@ -2138,12 +2127,12 @@ sub generate_commits_from_dsc () { printdebug "linked (using ...,fetch).\n"; } elsif ((printdebug "($!) "), $! != ENOENT) { - fail "accessing ../$f,fetch: $!"; + fail "accessing $buildproductsdir/$f,fetch: $!"; } elsif (link_ltarget $upper_f, $f) { printdebug "linked.\n"; } elsif ((printdebug "($!) "), $! != ENOENT) { - fail "accessing ../$f: $!"; + fail "accessing $buildproductsdir/$f: $!"; } else { printdebug "absent.\n"; } @@ -2158,14 +2147,14 @@ sub generate_commits_from_dsc () { printdebug "linked.\n"; } elsif ((printdebug "($!) "), $! != EEXIST) { - fail "saving ../$f: $!"; + fail "saving $buildproductsdir/$f: $!"; } elsif (!$refetched) { printdebug "no need.\n"; } elsif (link $f, "$upper_f,fetch") { printdebug "linked (using ...,fetch).\n"; } elsif ((printdebug "($!) "), $! != EEXIST) { - fail "saving ../$f,fetch: $!"; + fail "saving $buildproductsdir/$f,fetch: $!"; } else { printdebug "cannot.\n"; } @@ -2309,22 +2298,14 @@ sub generate_commits_from_dsc () { } my @clogcmd = qw(dpkg-parsechangelog --format rfc822 --all); - debugcmd "|",@clogcmd; - open CLOGS, "-|", @clogcmd or die $!; - my $clogp; my $r1clogp; printdebug "import clog search...\n"; + parsechangelog_loop \@clogcmd, "package changelog", sub { + my ($thisstanza, $desc) = @_; + no warnings qw(exiting); - for (;;) { - my $stanzatext = do { local $/=""; ; }; - printdebug "import clogp ".Dumper($stanzatext) if $debuglevel>1; - last if !defined $stanzatext; - - my $desc = "package changelog, entry no.$."; - open my $stanzafh, "<", \$stanzatext or die; - my $thisstanza = parsecontrolfh $stanzafh, $desc, 1; $clogp //= $thisstanza; printdebug "import clog $thisstanza->{version} $desc...\n"; @@ -2350,7 +2331,7 @@ sub generate_commits_from_dsc () { # version). Then it remains to choose between the physically # last entry in the file, and the one with the lowest version # number. If these are not the same, we guess that the - # versions were created in a non-monotic order rather than + # versions were created in a non-monotonic order rather than # that the changelog entries have been misordered. printdebug "import clog $thisstanza->{version} vs $upstreamv...\n"; @@ -2359,9 +2340,7 @@ sub generate_commits_from_dsc () { $r1clogp = $thisstanza; printdebug "import clog $r1clogp->{version} becomes r1\n"; - } - die $! if CLOGS->error; - close CLOGS or $?==SIGPIPE or failedcmd @clogcmd; + }; $clogp or fail "package changelog has no entries!"; @@ -2602,7 +2581,7 @@ sub ensure_we_have_orig () { foreach my $fi (@dfi) { my $f = $fi->{Filename}; next unless is_orig_file_in_dsc($f, \@dfi); - complete_file_from_dsc('..', $fi) + complete_file_from_dsc($buildproductsdir, $fi) or next; } } @@ -2851,15 +2830,14 @@ sub mergeinfo_version ($) { sub fetch_from_archive_record_1 ($) { my ($hash) = @_; - runcmd @git, qw(update-ref -m), "dgit fetch $csuite", - 'DGIT_ARCHIVE', $hash; + runcmd git_update_ref_cmd "dgit fetch $csuite", 'DGIT_ARCHIVE', $hash; cmdoutput @git, qw(log -n2), $hash; # ... gives git a chance to complain if our commit is malformed } sub fetch_from_archive_record_2 ($) { my ($hash) = @_; - my @upd_cmd = (@git, qw(update-ref -m), 'dgit fetch', lrref(), $hash); + my @upd_cmd = (git_update_ref_cmd 'dgit fetch', lrref(), $hash); if (act_local()) { cmdoutput @upd_cmd; } else { @@ -3558,7 +3536,7 @@ sub fork_for_multisuite ($) { my $csubsuite = multisuite_suite_child($tsuite, \@mergeinputs, sub { @end = (); - fetch(); + fetch_one(); finish 0; }); # xxx collecte the ref here @@ -3716,7 +3694,7 @@ sub clone ($) { clone_finish($dstdir); } -sub fetch () { +sub fetch_one () { canonicalise_suite(); if (check_for_git()) { git_fetch_us(); @@ -3739,10 +3717,14 @@ END printdone "fetched into ".lrref(); } -sub pull () { +sub dofetch () { my $multi_fetched = fork_for_multisuite(sub { }); - fetch() unless $multi_fetched; # parent - return if $multi_fetched eq '0'; # child + fetch_one() unless $multi_fetched; # parent + finish 0 if $multi_fetched eq '0'; # child +} + +sub pull () { + dofetch(); runcmd_ordryrun_local @git, qw(merge -m),"Merge from $csuite [dgit]", lrref(); printdone "fetched to ".lrref()." and merged into HEAD"; @@ -3755,7 +3737,7 @@ sub check_not_dirty () { } } - return if $ignoredirty; + return if $includedirty; git_check_unmodified(); } @@ -3776,11 +3758,11 @@ sub quiltify_nofix_bail ($$) { } sub commit_quilty_patch () { - my $output = cmdoutput @git, qw(status --porcelain); + my $output = cmdoutput @git, qw(status --ignored --porcelain); my %adds; foreach my $l (split /\n/, $output) { next unless $l =~ m/\S/; - if ($l =~ m{^(?:\?\?| [MADRC]) (.pc|debian/patches)}) { + if ($l =~ m{^(?:[?!][?!]| [MADRC]) (.pc|debian/patches)}) { $adds{$1}++; } } @@ -3850,7 +3832,7 @@ sub maybe_split_brain_save ($$$) { # => message fragment "$saved" describing disposition of $dgitview return "commit id $dgitview" unless defined $split_brain_save; my @cmd = (shell_cmd 'cd "$1"; shift', $maindir, - @git, qw(update-ref -m), + git_update_ref_cmd "dgit --dgit-view-save $msg HEAD=$headref", $split_brain_save, $dgitview); runcmd @cmd; @@ -4014,10 +3996,12 @@ sub splitbrain_pseudomerge ($$$$) { infopair_cond_ff($i_dep14, [ $maintview, 'HEAD' ]); 1; }) { + $@ =~ s/^\n//; chomp $@; print STDERR <[0] into your HEAD."; return $r; @@ -4413,6 +4397,29 @@ END files_compare_inputs($dsc, $changes) unless forceing [qw(dsc-changes-mismatch)]; + # Check whether this is a source only upload + my $hasdebs = $changes->{Files} =~ m{\.deb$}m; + my $sourceonlypolicy = access_cfg 'source-only-uploads'; + if ($sourceonlypolicy eq 'ok') { + } elsif ($sourceonlypolicy eq 'always') { + forceable_fail [qw(uploading-binaries)], + "uploading binaries, although distroy policy is source only" + if $hasdebs; + } elsif ($sourceonlypolicy eq 'never') { + forceable_fail [qw(uploading-source-only)], + "source-only upload, although distroy policy requires .debs" + if !$hasdebs; + } elsif ($sourceonlypolicy eq 'not-wholly-new') { + forceable_fail [qw(uploading-source-only)], + "source-only upload, even though package is entirely NEW\n". + "(this is contrary to policy in ".(access_nomdistro()).")" + if !$hasdebs + && $new_package + && !(archive_query('package_not_wholly_new', $package) // 1); + } else { + badcfg "unknown source-only-uploads policy \`$sourceonlypolicy'"; + } + # Perhaps adjust .dsc to contain right set of origs changes_update_origs_from_dsc($dsc, $changes, $upstreamversion, $changesfile) @@ -4496,7 +4503,7 @@ END runcmd_ordryrun @git, qw(-c push.followTags=false push), access_giturl(), @pushrefs; - runcmd_ordryrun @git, qw(update-ref -m), 'dgit push', lrref(), $dgithead; + runcmd_ordryrun git_update_ref_cmd 'dgit push', lrref(), $dgithead; supplementary_message(<<'END'); Push failed, while obtaining signatures on the .changes and .dsc. @@ -4596,11 +4603,15 @@ sub branchsuite () { } } -sub fetchpullargs () { +sub package_from_d_control () { if (!defined $package) { my $sourcep = parsecontrol('debian/control','debian/control'); $package = getfield $sourcep, 'Source'; } +} + +sub fetchpullargs () { + package_from_d_control(); if (@ARGV==0) { $isuite = branchsuite(); if (!$isuite) { @@ -4619,9 +4630,7 @@ sub fetchpullargs () { sub cmd_fetch { parseopts(); fetchpullargs(); - my $multi_fetched = fork_for_multisuite(sub { }); - finish 0 if $multi_fetched; - fetch(); + dofetch(); } sub cmd_pull { @@ -4636,6 +4645,40 @@ END pull(); } +sub cmd_checkout { + parseopts(); + package_from_d_control(); + @ARGV==1 or badusage "dgit checkout needs a suite argument"; + ($isuite) = @ARGV; + notpushing(); + + foreach my $canon (qw(0 1)) { + if (!$canon) { + $csuite= $isuite; + } else { + undef $csuite; + canonicalise_suite(); + } + if (length git_get_ref lref()) { + # local branch already exists, yay + last; + } + if (!length git_get_ref lrref()) { + if (!$canon) { + # nope + next; + } + dofetch(); + } + # now lrref exists + runcmd (@git, qw(update-ref), lref(), lrref(), ''); + last; + } + local $ENV{GIT_REFLOG_ACTION} = git_reflog_action_msg + "dgit checkout $isuite"; + runcmd (@git, qw(checkout), lbranch()); +} + sub cmd_update_vcs_git () { my $specsuite; if (@ARGV==0 || $ARGV[0] =~ m/^-/) { @@ -4653,11 +4696,10 @@ sub cmd_update_vcs_git () { } } - my $sourcep = parsecontrol 'debian/control', 'debian/control'; - $package = getfield $sourcep, 'Source'; + package_from_d_control(); my $ctrl; if ($specsuite eq '.') { - $ctrl = $sourcep; + $ctrl = parsecontrol 'debian/control', 'debian/control'; } else { $isuite = $specsuite; get_archive_dsc(); @@ -5222,7 +5264,7 @@ END print SERIES "\n" or die $! unless $newline eq "\n"; print SERIES "auto-gitignore\n" or die $!; close SERIES or die $!; - runcmd @git, qw(add -- debian/patches/series), $gipatch; + runcmd @git, qw(add -f -- debian/patches/series), $gipatch; commit_admin <($notp), "\n"; } print STDERR "$us: $_\n" foreach @$failsuggestion; - fail "quilt fixup naive history linearisation failed.\n". + fail + "quilt history linearisation failed. Search \`quilt fixup' in dgit(7).\n". "Use dpkg-source --commit by hand; or, --quilt=smash for one ugly patch"; } elsif ($quilt_mode eq 'smash') { } elsif ($quilt_mode eq 'auto') { @@ -5569,8 +5612,9 @@ END make-patches --quiet-would-amend)); # We tolerate soe snags that gdr wouldn't, by default. if (act_local()) { + debugcmd "+",@cmd; $!=0; $?=-1; - failedcmd @cmd if system @cmd and $?!=7; + failedcmd @cmd if system @cmd and $?!=7*256; } else { dryrun_report @cmd; } @@ -5595,7 +5639,7 @@ END @git, qw(pull --ff-only -q), "$playground/work", qw(master); } -sub quilt_fixup_mkwork ($) { +sub unpack_playtree_mkwork ($) { my ($headref) = @_; mkdir "work" or die $!; @@ -5604,12 +5648,13 @@ sub quilt_fixup_mkwork ($) { runcmd @git, qw(reset -q --hard), $headref; } -sub quilt_fixup_linkorigs ($$) { +sub unpack_playtree_linkorigs ($$) { my ($upstreamversion, $fn) = @_; # calls $fn->($leafname); - foreach my $f (<$maindir/../*>) { #/){ - my $b=$f; $b =~ s{.*/}{}; + opendir QFD, bpd_abs(); + while ($!=0, defined(my $b = readdir QFD)) { + my $f = bpd_abs()."/".$b; { local ($debuglevel) = $debuglevel-1; printdebug "QF linkorigs $b, $f ?\n"; @@ -5619,6 +5664,8 @@ sub quilt_fixup_linkorigs ($$) { link_ltarget $f, $b or die "$b $!"; $fn->($b); } + die "$buildproductsdir: $!" if $!; + closedir QFD; } sub quilt_fixup_delete_pc () { @@ -5640,8 +5687,8 @@ sub quilt_fixup_singlepatch ($$$) { # get it to generate debian/patches/debian-changes, it is # necessary to build the source package. - quilt_fixup_linkorigs($upstreamversion, sub { }); - quilt_fixup_mkwork($headref); + unpack_playtree_linkorigs($upstreamversion, sub { }); + unpack_playtree_mkwork($headref); rmtree("debian/patches"); @@ -5681,7 +5728,7 @@ END print $fakedsc " ".$md->hexdigest." $size $b\n" or die $!; }; - quilt_fixup_linkorigs($upstreamversion, $dscaddfile); + unpack_playtree_linkorigs($upstreamversion, $dscaddfile); my @files=qw(debian/source/format debian/rules debian/control debian/changelog); @@ -5749,7 +5796,7 @@ sub quilt_check_splitbrain_cache ($$) { next unless m/^(\w+) (\S.*\S)$/ && $2 eq $splitbrain_cachekey; my $cachehit = $1; - quilt_fixup_mkwork($headref); + unpack_playtree_mkwork($headref); my $saved = maybe_split_brain_save $headref, $cachehit, "cache-hit"; if ($cachehit ne $headref) { progress "dgit view: found cached ($saved)"; @@ -5880,13 +5927,13 @@ sub quilt_fixup_multipatch ($$$) { failed to apply your git tree's patch stack (from debian/patches/) to the corresponding upstream tarball(s). Your source tree and .orig are probably too inconsistent. dgit can only fix up certain kinds of - anomaly (depending on the quilt mode). See --quilt= in dgit(1). + anomaly (depending on the quilt mode). Please see --quilt= in dgit(1). END } changedir '..'; - quilt_fixup_mkwork($headref); + unpack_playtree_mkwork($headref); my $mustdeletepc=0; if (stat_exists ".pc") { @@ -6133,6 +6180,10 @@ sub changesopts () { return (changesopts_initial(), changesopts_version()); } +# return values from massage_dbp_args are one or both of these flags +sub WANTSRC_SOURCE () { 01; } # caller should build source (separately) +sub WANTSRC_BUILDER () { 02; } # caller should run dpkg-buildpackage + sub massage_dbp_args ($;$) { my ($cmd,$xargs) = @_; # We need to: @@ -6146,16 +6197,11 @@ sub massage_dbp_args ($;$) { # unless we're not doing a split build and want dpkg-source # as cleanmode, in which case we can do nothing # - # return values: - # 0 - source will NOT need to be built separately by caller - # +1 - source will need to be built separately by caller - # +2 - source will need to be built separately by caller AND - # dpkg-buildpackage should not in fact be run at all! 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) { $clean_using_builder = 1; - return 0; + return WANTSRC_BUILDER; } # -nc has the side effect of specifying -b if nothing else specified # and some combinations of -S, -b, et al, are errors, rather than @@ -6171,12 +6217,12 @@ sub massage_dbp_args ($;$) { } push @$cmd, '-nc'; #print STDERR "MASS1 ",Dumper($cmd, $xargs, $dmode); - my $r = 0; + my $r = WANTSRC_BUILDER; if ($need_split_build_invocation) { printdebug "massage split $dmode.\n"; - $r = $dmode =~ m/[S]/ ? +2 : - $dmode =~ y/gGF/ABb/ ? +1 : - $dmode =~ m/[ABb]/ ? 0 : + $r = $dmode =~ m/[S]/ ? WANTSRC_SOURCE : + $dmode =~ y/gGF/ABb/ ? WANTSRC_SOURCE | WANTSRC_BUILDER : + $dmode =~ m/[ABb]/ ? WANTSRC_BUILDER : die "$dmode ?"; } printdebug "massage done $r $dmode.\n"; @@ -6185,15 +6231,16 @@ sub massage_dbp_args ($;$) { return $r; } -sub in_parent (&) { +sub in_bpd (&) { my ($fn) = @_; my $wasdir = must_getcwd(); - changedir ".."; + changedir $buildproductsdir; $fn->(); changedir $wasdir; } -sub postbuild_mergechanges ($) { # must run with CWD=.. (eg in in_parent) +# this sub must run with CWD=$buildproductsdir (eg in in_bpd) +sub postbuild_mergechanges ($) { my ($msg_if_onlyone) = @_; # If there is only one .changes file, fail with $msg_if_onlyone, # or if that is undef, be a no-op. @@ -6235,7 +6282,7 @@ END sub midbuild_checkchanges () { my $pat = changespat $version; return if $rmchanges; - my @unwanted = map { s#^\.\./##; $_; } glob "../$pat"; + my @unwanted = map { s#.*/##; $_; } glob "$bpd_glob/$pat"; @unwanted = grep { $_ ne changespat $version,'source' } @unwanted; fail < 0) { + if ($wantsrc & WANTSRC_SOURCE) { build_source(); midbuild_checkchanges_vanilla $wantsrc; } else { build_prep(); } - if ($wantsrc < 2) { + if ($wantsrc & WANTSRC_BUILDER) { push @dbp, changesopts_version(); maybe_apply_patches_dirtily(); runcmd_ordryrun_local @dbp; @@ -6294,7 +6341,7 @@ sub cmd_gbp_build { # orig is absent. my $upstreamversion = upstreamversion $version; my $origfnpat = srcfn $upstreamversion, '.orig.tar.*'; - my $gbp_make_orig = $version =~ m/-/ && !(() = glob "../$origfnpat"); + my $gbp_make_orig = $version =~ m/-/ && !(() = glob "$bpd_glob/$origfnpat"); if ($gbp_make_orig) { clean_tree(); @@ -6337,7 +6384,7 @@ sub cmd_gbp_build { } } - if ($wantsrc > 0) { + if ($wantsrc & WANTSRC_SOURCE) { build_source(); midbuild_checkchanges_vanilla $wantsrc; } else { @@ -6347,7 +6394,7 @@ sub cmd_gbp_build { build_prep(); } maybe_unapply_patches_again(); - if ($wantsrc < 2) { + if ($wantsrc & WANTSRC_BUILDER) { push @cmd, changesopts(); runcmd_ordryrun_local @cmd, @ARGV; } @@ -6366,7 +6413,7 @@ sub build_source { build_prep(); $sourcechanges = changespat $version,'source'; if (act_local()) { - unlink "../$sourcechanges" or $!==ENOENT + unlink "$buildproductsdir/$sourcechanges" or $!==ENOENT or fail "remove $sourcechanges: $!"; } $dscfn = dscfn($version); @@ -6383,7 +6430,7 @@ sub build_source { ($f =~ m/\.debian\.tar(?:\.\w+)$/ && $f eq srcfn($version, $&)); printdebug "source copy, found $f - renaming\n"; - rename "$playground/$f", "../$f" or $!==ENOENT + rename "$playground/$f", "$buildproductsdir/$f" or $!==ENOENT or fail "put in place new source file ($f): $!"; } } else { @@ -6395,7 +6442,7 @@ sub build_source { } runcmd_ordryrun_local qw(sh -ec), 'exec >$1; shift; exec "$@"','x', - "../$sourcechanges", + "$buildproductsdir/$sourcechanges", @dpkggenchanges, qw(-S), changesopts(); } @@ -6410,7 +6457,7 @@ sub cmd_build_source { sub cmd_sbuild { build_source(); midbuild_checkchanges(); - in_parent { + in_bpd { if (act_local()) { stat_exists $dscfn or fail "$dscfn (in parent directory): $!"; stat_exists $sourcechanges @@ -6419,7 +6466,7 @@ sub cmd_sbuild { runcmd_ordryrun_local @sbuild, qw(-d), $isuite, @ARGV, $dscfn; }; maybe_unapply_patches_again(); - in_parent { + in_bpd { postbuild_mergechanges(<{Filename}; - my $here = "../$f"; + my $here = "$buildproductsdir/$f"; if (lstat $here) { next if stat $here; fail "lstat $here works but stat gives $! !"; @@ -6818,7 +6865,7 @@ sub parseopts () { $quilt_mode = $1; } elsif (m/^--ignore-dirty$/s) { push @ropts, $_; - $ignoredirty = 1; + $includedirty = 1; } elsif (m/^--no-quilt-fixup$/s) { push @ropts, $_; $quilt_mode = 'nocheck'; @@ -7027,6 +7074,11 @@ sub parseopts_late_defaults () { badcfg "unknown clean-mode \`$cleanmode'" unless $cleanmode =~ m/^($cleanmode_re)$(?!\n)/s; } + + $buildproductsdir //= access_cfg('build-products-dir', 'RETURN-UNDEF'); + $buildproductsdir //= '..'; + $bpd_glob = $buildproductsdir; + $bpd_glob =~ s#[][\\{}*?~]#\\$&#g; } if ($ENV{$fakeeditorenv}) {