chiark / gitweb /
dgit: build_source mostly uses a playtree, not $maindir
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Thu, 26 Jul 2018 10:08:45 +0000 (11:08 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Thu, 26 Jul 2018 12:00:46 +0000 (13:00 +0100)
In particular, it uses a playtree unless we are trying to include
uncommitted changes in the source package (which is not supported in
split brain mode).

This change allows build_source to respect $buildproductsdir.  It will
also enable, later, building a source package from HEAD, or arbitrary
git ref, when the working tree is dirty.

This change also requires modifying build_prep to only conditionally
clean $maindir.  It should clean $maindir only when it's $maindir that
we're packing into a source package, or when we are running any
builder in $maindir.

When we are using a playtree we must build the changes file there too,
because dpkg-genchanges cannot be persuaded to look for the .dsc
anywhere but ../.

Right now build-source still cleans the tree needlessly.

We need to change the test suite to not expect a clean unless running
a builder:

dgit now cleans the tree only when including uncommitted changes in a
source package, and when running a builder in $maindir.  The code in
lib-build-modes does not test the including of uncommitted changes in
a source package.  Thus, it should expect the tree to be cleaned only
when running a builder.

Also, we need to not expect a clean with sbuild, for the same reason.

Signed-off-by: Sean Whitton <spwhitton@spwhitton.name>
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
dgit
tests/lib-build-modes

diff --git a/dgit b/dgit
index 5d7d8d7..36afdaf 100755 (executable)
--- a/dgit
+++ b/dgit
@@ -6137,7 +6137,9 @@ sub build_prep_early () {
 sub build_prep ($) {
     my ($wantsrc) = @_;
     build_prep_early();
-    clean_tree();
+    # clean the tree if we're trying to include dirty changes in the
+    # source package, or we are running the builder in $maindir
+    clean_tree() if $includedirty || ($wantsrc & WANTSRC_BUILDER);
     build_maybe_quilt_fixup();
     if ($rmchanges) {
        my $pat = changespat $version;
@@ -6414,6 +6416,35 @@ sub cmd_gbp_build {
 }
 sub cmd_git_build { cmd_gbp_build(); } # compatibility with <= 1.0
 
+sub move_dsc_to_bpd ($) {
+    my ($dscfn) = @_;
+    printdebug "moving $dscfn and all referenced files to ".bpd_abs()."\n";
+    $dsc = parsecontrol($dscfn, "source package");
+    foreach my $l (split /\n/, getfield $dsc, 'Files') {
+        $l =~ m/\S+$/ or next;
+        $l =~ s/.* //;
+        printdebug "found $l - renaming\n";
+        rename "$l", bpd_abs()."/$l"
+          or fail "put in place new source file ($l): $!";
+    }
+    printdebug "moving $dscfn to ".bpd_abs()."/$dscfn\n";
+    rename "$dscfn", bpd_abs()."/$dscfn"
+      or fail "put in place new source file ($dscfn): $!";
+}
+
+sub building_source_in_playtree {
+    # If $includedirty, we have to build the source package from the
+    # working tree, not a playtree, so that uncommitted changes are
+    # included (copying or hardlinking them into the playtree could
+    # cause trouble).
+    #
+    # Note that if we are building a source package in split brain
+    # mode we do not support including uncommitted changes, because
+    # that makes quilt fixup too hard.  I.e. ($split_brain && (dgit is
+    # building a source package)) => !$includedirty
+    return !$includedirty;
+}
+
 sub build_source {
     $sourcechanges = changespat $version,'source';
     if (act_local()) {
@@ -6422,32 +6453,36 @@ sub build_source {
     }
     $dscfn = dscfn($version);
     my @cmd = (@dpkgsource, qw(-b --));
-    if ($split_brain) {
+    my $leafdir;
+    if (building_source_in_playtree()) {
+       $leafdir = 'work';
+        my $headref = git_rev_parse('HEAD');
+        # If we are in split brain, there is already a playtree with
+        # the thing we should package into a .dsc (thanks to quilt
+        # fixup).  If not, make a playtree
+        prep_ud() unless $split_brain;
         changedir $playground;
-        runcmd_ordryrun_local @cmd, "work";
-        my @udfiles = <${package}_*>;
-        changedir $maindir;
-        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 "$playground/$f", "$buildproductsdir/$f" or $!==ENOENT
-              or fail "put in place new source file ($f): $!";
+        unless ($split_brain) {
+            my $upstreamversion = upstreamversion $version;
+            unpack_playtree_linkorigs($upstreamversion, sub { });
+            unpack_playtree_mkwork($headref);
+            changedir '..';
         }
     } else {
-        my $pwd = must_getcwd();
-        my $leafdir = basename $pwd;
-        changedir "..";
-        runcmd_ordryrun_local @cmd, $leafdir;
-        changedir $pwd;
+        $leafdir = basename $maindir;
+        changedir '..';
     }
+    runcmd_ordryrun_local @cmd, $leafdir;
+
+    changedir $leafdir;
     runcmd_ordryrun_local qw(sh -ec),
-      'exec >$1; shift; exec "$@"','x',
-      "$buildproductsdir/$sourcechanges",
+      'exec >../$1; shift; exec "$@"','x', $sourcechanges,
       @dpkggenchanges, qw(-S), changesopts();
+    changedir '..';
+    move_dsc_to_bpd($dscfn);
+    rename "$sourcechanges", bpd_abs()."/$sourcechanges"
+       or fail "put in place source changes file ($sourcechanges): $!";
+    changedir $maindir;
 }
 
 sub cmd_build_source {
index cf9f6cd..6465b61 100644 (file)
@@ -120,7 +120,31 @@ bm-compute-expected () {
        exec 4>$bmexp
        echo >&4 "$heading"
 
-       case $cleanmode in
+       local eff_cleanmode=$cleanmode
+
+       case "$e_targets" in
+       *[^\ ]*)
+               ;;
+       *)
+               # dgit won't bother cleaning the tree
+               # if no build is going to be run
+               eff_cleanmode=none
+               ;;
+       esac
+
+       case "$act" in
+       sbuild*)
+               # dgit sbuild won't bother cleaning the tree
+               # because it doesn't need to to make a .dsc for sbuild
+               eff_cleanmode=none
+               ;;
+       esac
+
+       # we are running the builder in-tree ?
+       # when we have --include-dirty, we will want to check
+       # that too and reset eff_cleanmode to $cleanmode
+
+       case $eff_cleanmode in
        git)            echo >&4 'BUILD-MODES PROGRAM git clean -xdf' ;;
        git-ff)         echo >&4 'BUILD-MODES PROGRAM git clean -xdff' ;;
        check)          echo >&4 'BUILD-MODES PROGRAM git clean -xdn' ;;