# dgit
# Integration between git and Debian-style archives
#
-# Copyright (C)2013-2017 Ian Jackson
-# Copyright (C)2017 Sean Whitton
+# Copyright (C)2013-2018 Ian Jackson
+# Copyright (C)2017-2018 Sean Whitton
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
autoflush STDOUT 1;
our $supplementary_message = '';
-our $need_split_build_invocation = 0;
+our $need_split_build_invocation = 1;
our $split_brain = 0;
END {
dopush();
}
-sub cmd_push_source {
- prep_push();
- fail "dgit push-source: --include-dirty/--ignore-dirty does not make".
- "sense with push-source!" if $includedirty;
- if ($changesfile) {
- my $changes = parsecontrol("$buildproductsdir/$changesfile",
- "source changes file");
- unless (test_source_only_changes($changes)) {
- fail "user-specified changes file is not source-only";
- }
- } else {
- # Building a source package is very fast, so just do it
- build_source_for_push();
- }
- dopush();
-}
-
#---------- remote commands' implementation ----------
sub pre_remote_push_build_host {
maybe_unapply_patches_again();
}
+# 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 build_or_push_prep_early () {
our $build_or_push_prep_early_done //= 0;
return if $build_or_push_prep_early_done++;
check_not_dirty();
}
-sub build_prep () {
+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;
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:
build_prep_early();
my @dbp = (@dpkgbuildpackage, qw(-us -uc), changesopts_initial(), @ARGV);
my $wantsrc = massage_dbp_args \@dbp;
+ build_prep($wantsrc);
if ($wantsrc & WANTSRC_SOURCE) {
build_source();
midbuild_checkchanges_vanilla $wantsrc;
- } else {
- build_prep();
}
if ($wantsrc & WANTSRC_BUILDER) {
push @dbp, changesopts_version();
}
}
+ build_prep($wantsrc);
if ($wantsrc & WANTSRC_SOURCE) {
build_source();
midbuild_checkchanges_vanilla $wantsrc;
if (!$clean_using_builder) {
push @cmd, '--git-cleaner=true';
}
- build_prep();
}
maybe_unapply_patches_again();
if ($wantsrc & WANTSRC_BUILDER) {
}
sub cmd_git_build { cmd_gbp_build(); } # compatibility with <= 1.0
-sub build_source_for_push {
- build_source();
- maybe_unapply_patches_again();
- $changesfile = $sourcechanges;
+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 {
- build_prep_early();
- build_prep();
$sourcechanges = changespat $version,'source';
if (act_local()) {
unlink "$buildproductsdir/$sourcechanges" or $!==ENOENT
}
$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 '..';
+
+ printdebug "moving $dscfn, $sourcechanges, etc. to ".bpd_abs()."\n";
+ $dsc = parsecontrol($dscfn, "source package");
+
+ my $mv = sub {
+ my ($why, $l) = @_;
+ printdebug " renaming ($why) $l\n";
+ rename "$l", bpd_abs()."/$l"
+ or fail "put in place new built file ($l): $!";
+ };
+ foreach my $l (split /\n/, getfield $dsc, 'Files') {
+ $l =~ m/\S+$/ or next;
+ $mv->('Files', $&);
+ }
+ $mv->('dsc', $dscfn);
+ $mv->('changes', $sourcechanges);
+
+ changedir $maindir;
}
sub cmd_build_source {
- build_prep_early();
badusage "build-source takes no additional arguments" if @ARGV;
+ build_prep(WANTSRC_SOURCE);
build_source();
maybe_unapply_patches_again();
printdone "source built, results in $dscfn and $sourcechanges";
}
+sub cmd_push_source {
+ prep_push();
+ fail "dgit push-source: --include-dirty/--ignore-dirty does not make".
+ "sense with push-source!" if $includedirty;
+ build_maybe_quilt_fixup();
+ if ($changesfile) {
+ my $changes = parsecontrol("$buildproductsdir/$changesfile",
+ "source changes file");
+ unless (test_source_only_changes($changes)) {
+ fail "user-specified changes file is not source-only";
+ }
+ } else {
+ # Building a source package is very fast, so just do it
+ build_source();
+ die "er, patches are applied dirtily but shouldn't be.."
+ if $patches_applied_dirtily;
+ $changesfile = $sourcechanges;
+ }
+ dopush();
+}
+
sub cmd_sbuild {
+ build_prep(WANTSRC_SOURCE); # not BUILDER because sbuild uses the .dsc
build_source();
midbuild_checkchanges();
in_bpd {
$tagformat_want = [ $1, 'command line', 1 ];
# 1 menas overrides distro configuration
} elsif (m/^--always-split-source-build$/s) {
- # undocumented, for testing
+ # undocumented, was once for testing, now a no-op
push @ropts, $_;
$need_split_build_invocation = 1;
} elsif (m/^--config-lookup-explode=(.+)$/s) {