# dgit
# Integration between git and Debian-style archives
#
-# Copyright (C)2013-2018 Ian Jackson
-# Copyright (C)2017-2018 Sean Whitton
+# Copyright (C)2013-2019 Ian Jackson
+# Copyright (C)2017-2019 Sean Whitton
+# Copyright (C)2019 Matthew Vernon / Genome Research Limited
#
# 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
our $our_version = 'UNRELEASED'; ###substituted###
our $absurdity = undef; ###substituted###
-our @rpushprotovsn_support = qw(4 3 2); # 4 is new tag format
+our @rpushprotovsn_support = qw(6 5 4); # Reverse order!
our $protovsn;
our $cmd;
our $rmchanges;
our $overwrite_version; # undef: not specified; '': check changelog
our $quilt_mode;
-our $quilt_modes_re = 'linear|smash|auto|nofix|nocheck|gbp|dpm|unapplied';
+our $quilt_upstream_commitish;
+our $quilt_upstream_commitish_used;
+our $quilt_upstream_commitish_message;
+our $quilt_options_re = 'gbp|dpm|baredebian(?:\+tarball|\+git)?';
+our $quilt_modes_re = "linear|smash|auto|nofix|nocheck|unapplied|$quilt_options_re";
+our $splitview_mode;
+our $splitview_modes_re = qr{auto|always|never};
our $dodep14tag;
our %internal_object_save;
our $we_are_responder;
our $we_are_initiator;
our $initiator_tempdir;
our $patches_applied_dirtily = 00;
-our $tagformat_want;
-our $tagformat;
-our $tagformatfn;
our $chase_dsc_distro=1;
our %forceopts = map { $_=>0 }
our %format_ok = map { $_=>1 } ("1.0","3.0 (native)","3.0 (quilt)");
-our $suite_re = '[-+.0-9a-z]+';
our $cleanmode_re = qr{(?: dpkg-source (?: -d )? (?: ,no-check | ,all-check )?
| (?: git | git-ff ) (?: ,always )?
| check (?: ,ignores )?
our @dpkg_source_ignores = qw(-i(?:^|/)\.git(?:/|$) -I.git);
-our (@git) = qw(git);
our (@dget) = qw(dget);
our (@curl) = (qw(curl --proto-redir), '-all,http,https', qw(-L));
our (@dput) = qw(dput);
autoflush STDOUT 1;
our $supplementary_message = '';
-our $split_brain = 0;
-our $do_split_brain = 0;
+our $made_split_brain = 0;
+our $do_split_brain;
# Interactions between quilt mode and split brain
# (currently, split brain only implemented iff
-# madformat_wantfixup && quiltmode_splitbrain)
+# madformat_wantfixup && quiltmode_splitting)
#
# source format sane `3.0 (quilt)'
# madformat_wantfixup()
#
# no split no q cache no q cache forbidden,
# brain PM on master q fixup on master prevented
-# !$do_split_brain PM on master
+# !do_split_brain() PM on master
#
# split brain no q cache q fixup cached, to dgit view
# PM in dgit view PM in dgit view
$absurdity =~ s{/[^/]+$}{/absurd} or die;
}
-sub debiantag ($$) {
- my ($v,$distro) = @_;
- return $tagformatfn->($v, $distro);
-}
-
sub madformat ($) { $_[0] eq '3.0 (quilt)' }
sub lbranch () { return "$branchprefix/$csuite"; }
}
}
-sub quiltmode_splitbrain () {
- $quilt_mode =~ m/gbp|dpm|unapplied/;
+sub quiltmode_splitting () {
+ $quilt_mode =~ m/gbp|dpm|unapplied|baredebian/;
+}
+sub format_quiltmode_splitting ($) {
+ my ($format) = @_;
+ return madformat_wantfixup($format) && quiltmode_splitting();
}
+sub do_split_brain () { !!($do_split_brain // confess) }
+
sub opts_opt_multi_cmd {
my $extra = shift;
my @cmd;
# > progress NBYTES
# [NBYTES message]
#
-# > supplementary-message NBYTES # $protovsn >= 3
+# > supplementary-message NBYTES
# [NBYTES message]
#
# main sequence:
#
# > param head DGIT-VIEW-HEAD
# > param csuite SUITE
-# > param tagformat old|new
+# > param tagformat new # $protovsn == 4
+# > param splitbrain 0|1 # $protovsn >= 6
# > param maint-view MAINT-VIEW-HEAD
#
# > param buildinfo-filename P_V_X.buildinfo # zero or more times
'dgit.default.archive-query' => 'madison:',
'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-distro.debian-backports.mirror' => 'http://backports.debian.org/debian-backports/',
'dgit-distro.ubuntu.git-check' => 'false',
'dgit-distro.ubuntu.mirror' => 'http://archive.ubuntu.com/ubuntu',
+ 'dgit-distro.ubuntucloud.git-check' => 'false',
+ 'dgit-distro.ubuntucloud.nominal-distro' => 'ubuntu',
+ 'dgit-distro.ubuntucloud.archive-query' => 'aptget:',
+ 'dgit-distro.ubuntucloud.mirror' => 'http://ubuntu-cloud.archive.canonical.com/ubuntu',
+ 'dgit-distro.ubuntucloud.aptget-suite-map' => 's#^([^-]+):([^:]+)$#${1}-updates/$2#; s#^(.+)-(.+):(.+)#$1-$2/$3#;',
+ 'dgit-distro.ubuntucloud.aptget-suite-rmap' => 's#/(.+)$#-$1#',
'dgit-distro.test-dummy.ssh' => "$td/ssh",
'dgit-distro.test-dummy.username' => "alice",
'dgit-distro.test-dummy.git-check' => "ssh-cmd",
return $access_forpush;
}
+sub default_from_access_cfg ($$$;$) {
+ my ($var, $keybase, $defval, $permit_re) = @_;
+ return if defined $$var;
+
+ $$var = access_cfg("$keybase-newer", 'RETURN-UNDEF');
+ $$var = undef if $$var && $$var !~ m/^$permit_re$/;
+
+ $$var //= access_cfg($keybase, 'RETURN-UNDEF');
+ $$var //= $defval;
+
+ badcfg f_ "unknown %s \`%s'", $keybase, $$var
+ if defined $permit_re and $$var !~ m/$permit_re/;
+}
+
sub pushing () {
confess +(__ 'internal error').' '.Dumper($access_forpush)," ?" if
defined $access_forpush and !$access_forpush;
parseopts_late_defaults();
}
+sub determine_whether_split_brain ($) {
+ my ($format) = @_;
+ {
+ local $access_forpush;
+ default_from_access_cfg(\$splitview_mode, 'split-view', 'auto',
+ $splitview_modes_re);
+ $do_split_brain = 1 if $splitview_mode eq 'always';
+ }
+
+ printdebug "format $format, quilt mode $quilt_mode\n";
+
+ if (format_quiltmode_splitting $format) {
+ $splitview_mode ne 'never' or
+ fail f_ "dgit: quilt mode \`%s' (for format \`%s')".
+ " implies split view, but split-view set to \`%s'",
+ $quilt_mode, $format, $splitview_mode;
+ $do_split_brain = 1;
+ }
+ $do_split_brain //= 0;
+}
+
sub supplementary_message ($) {
my ($msg) = @_;
if (!$we_are_responder) {
$supplementary_message = $msg;
return;
- } elsif ($protovsn >= 3) {
+ } else {
responder_send_command "supplementary-message ".length($msg)
or confess "$!";
print PO $msg or confess "$!";
return @cmd;
}
-sub api_query ($$;$) {
- use JSON;
+sub api_query_raw ($$;$) {
my ($data, $subpath, $ok404) = @_;
badcfg __ "ftpmasterapi archive query method takes no data part"
if length $data;
return undef if $code eq '404' && $ok404;
fail f_ "fetch of %s gave HTTP code %s", $url, $code
unless $url =~ m#^file://# or $code =~ m/^2/;
+ return $json;
+}
+
+sub api_query ($$;$) {
+ my ($data, $subpath, $ok404) = @_;
+ use JSON;
+ my $json = api_query_raw $data, $subpath, $ok404;
+ return undef unless defined $json;
return decode_json($json);
}
my $val = $release->{$name};
if (defined $val) {
printdebug "release file $name: $val\n";
+ cfg_apply_map(\$val, 'suite rmap',
+ access_cfg('aptget-suite-rmap', 'RETURN-UNDEF'));
$val =~ m/^$suite_re$/o or fail f_
"Release file (%s) specifies intolerable %s",
$aptget_releasefile, $name;
- cfg_apply_map(\$val, 'suite rmap',
- access_cfg('aptget-suite-rmap', 'RETURN-UNDEF'));
return $val
}
}
sub file_in_archive_dummycat () { return undef; }
sub package_not_wholly_new_dummycat () { return undef; }
-#---------- tag format handling ----------
-# (untranslated, because everything should be new tag format by now)
-
-sub access_cfg_tagformats () {
- split /\,/, access_cfg('dgit-tag-format');
-}
-
-sub access_cfg_tagformats_can_splitbrain () {
- my %y = map { $_ => 1 } access_cfg_tagformats;
- foreach my $needtf (qw(new maint)) {
- next if $y{$needtf};
- return 0;
- }
- return 1;
-}
-
-sub need_tagformat ($$) {
- my ($fmt, $why) = @_;
- fail "need to use tag format $fmt ($why) but also need".
- " to use tag format $tagformat_want->[0] ($tagformat_want->[1])".
- " - no way to proceed"
- if $tagformat_want && $tagformat_want->[0] ne $fmt;
- $tagformat_want = [$fmt, $why, $tagformat_want->[2] // 0];
-}
-
-sub select_tagformat () {
- # sets $tagformatfn
- return if $tagformatfn && !$tagformat_want;
- die 'bug' if $tagformatfn && $tagformat_want;
- # ... $tagformat_want assigned after previous select_tagformat
-
- my (@supported) = grep { $_ =~ m/^(?:old|new)$/ } access_cfg_tagformats();
- printdebug "select_tagformat supported @supported\n";
-
- $tagformat_want //= [ $supported[0], "distro access configuration", 0 ];
- printdebug "select_tagformat specified @$tagformat_want\n";
-
- my ($fmt,$why,$override) = @$tagformat_want;
-
- fail "target distro supports tag formats @supported".
- " but have to use $fmt ($why)"
- unless $override
- or grep { $_ eq $fmt } @supported;
-
- $tagformat_want = undef;
- $tagformat = $fmt;
- $tagformatfn = ${*::}{"debiantag_$fmt"};
-
- fail "trying to use unknown tag format \`$fmt' ($why) !"
- unless $tagformatfn;
-}
-
#---------- archive query entrypoints and rest of program ----------
sub canonicalise_suite () {
}
sub mktree_in_ud_here () {
- playtree_setup $gitcfgs{local};
+ playtree_setup();
}
sub git_write_tree () {
}
}
-sub make_commit ($) {
- my ($file) = @_;
- return cmdoutput @git, qw(hash-object -w -t commit), $file;
-}
-
sub clogp_authline ($) {
my ($clogp) = @_;
my $author = getfield $clogp, 'Maintainer';
closedir DD;
}
-sub generate_commits_from_dsc () {
- # See big comment in fetch_from_archive, below.
- # See also README.dsc-import.
- prep_ud();
- changedir $playground;
-
- my $bpd_abs = bpd_abs();
- my $upstreamv = upstreamversion $dsc->{version};
- my @dfi = dsc_files_info();
-
- dotdot_bpd_transfer_origs $bpd_abs, $upstreamv,
- sub { grep { $_->{Filename} eq $_[0] } @dfi };
-
- foreach my $fi (@dfi) {
- my $f = $fi->{Filename};
- die "$f ?" if $f =~ m#/|^\.|\.dsc$|\.tmp$#;
- my $upper_f = "$bpd_abs/$f";
-
- printdebug "considering reusing $f: ";
-
- if (link_ltarget "$upper_f,fetch", $f) {
- printdebug "linked (using ...,fetch).\n";
- } elsif ((printdebug "($!) "),
- $! != ENOENT) {
- fail f_ "accessing %s: %s", "$buildproductsdir/$f,fetch", $!;
- } elsif (link_ltarget $upper_f, $f) {
- printdebug "linked.\n";
- } elsif ((printdebug "($!) "),
- $! != ENOENT) {
- fail f_ "accessing %s: %s", "$buildproductsdir/$f", $!;
- } else {
- printdebug "absent.\n";
- }
-
- my $refetched;
- complete_file_from_dsc('.', $fi, \$refetched)
- or next;
-
- printdebug "considering saving $f: ";
-
- if (rename_link_xf 1, $f, $upper_f) {
- printdebug "linked.\n";
- } elsif ((printdebug "($@) "),
- $! != EEXIST) {
- fail f_ "saving %s: %s", "$buildproductsdir/$f", $@;
- } elsif (!$refetched) {
- printdebug "no need.\n";
- } elsif (rename_link_xf 1, $f, "$upper_f,fetch") {
- printdebug "linked (using ...,fetch).\n";
- } elsif ((printdebug "($@) "),
- $! != EEXIST) {
- fail f_ "saving %s: %s", "$buildproductsdir/$f,fetch", $@;
- } else {
- printdebug "cannot.\n";
- }
- }
+sub import_tarball_tartrees ($$) {
+ my ($upstreamv, $dfi) = @_;
+ # cwd should be the playground
# We unpack and record the orig tarballs first, so that we only
# need disk space for one private copy of the unpacked source.
my @tartrees;
my $orig_f_base = srcfn $upstreamv, '';
- foreach my $fi (@dfi) {
+ foreach my $fi (@$dfi) {
# We actually import, and record as a commit, every tarball
# (unless there is only one file, in which case there seems
# little point.
my $f = $fi->{Filename};
printdebug "import considering $f ";
- (printdebug "only one dfi\n"), next if @dfi == 1;
(printdebug "not tar\n"), next unless $f =~ m/\.tar(\.\w+)?$/;
(printdebug "signature\n"), next if $f =~ m/$orig_f_sig_re$/o;
my $compr_ext = $1;
$compr_ext, $orig_f_part
), "\n";
+ my $path = $fi->{Path} // $f;
my $input = new IO::File $f, '<' or die "$f $!";
my $compr_pid;
my @compr_cmd;
Sort => (!$orig_f_part ? 2 :
$orig_f_part =~ m/-/g ? 1 :
0),
+ OrigPart => $orig_f_part, # 'orig', 'orig-XXX', or undef
F => $f,
Tree => $tree,
};
$a->{F} cmp $b->{F}
} @tartrees;
- my $any_orig = grep { $_->{Orig} } @tartrees;
-
- my $dscfn = "$package.dsc";
-
- my $treeimporthow = 'package';
-
- open D, ">", $dscfn or die "$dscfn: $!";
- print D $dscdata or die "$dscfn: $!";
- close D or die "$dscfn: $!";
- my @cmd = qw(dpkg-source);
- push @cmd, '--no-check' if $dsc_checked;
- if (madformat $dsc->{format}) {
- push @cmd, '--skip-patches';
- $treeimporthow = 'unpatched';
- }
- push @cmd, qw(-x --), $dscfn;
- runcmd @cmd;
+ @tartrees;
+}
- my ($tree,$dir) = mktree_in_ud_from_only_subdir(__ "source package");
- if (madformat $dsc->{format}) {
- check_for_vendor_patches();
- }
+sub import_tarball_commits ($$) {
+ my ($tartrees, $upstreamv) = @_;
+ # cwd should be a playtree which has a relevant debian/changelog
+ # fills in $tt->{Commit} for each one
- my $dappliedtree;
- if (madformat $dsc->{format}) {
- my @pcmd = qw(dpkg-source --before-build .);
- runcmd shell_cmd 'exec >/dev/null', @pcmd;
- rmtree '.pc';
- $dappliedtree = git_add_write_tree();
- }
+ my $any_orig = grep { $_->{Orig} } @$tartrees;
my @clogcmd = qw(dpkg-parsechangelog --format rfc822 --all);
my $clogp;
$changes =~ s/^\n//; # Changes: \n
my $cversion = getfield $clogp, 'Version';
- if (@tartrees) {
+ my $r1authline;
+ if (@$tartrees) {
$r1clogp //= $clogp; # maybe there's only one entry;
- my $r1authline = clogp_authline $r1clogp;
+ $r1authline = clogp_authline $r1clogp;
# Strictly, r1authline might now be wrong if it's going to be
# unused because !$any_orig. Whatever.
printdebug "import tartrees authline $authline\n";
printdebug "import tartrees r1authline $r1authline\n";
- foreach my $tt (@tartrees) {
+ foreach my $tt (@$tartrees) {
printdebug "import tartree $tt->{F} $tt->{Tree}\n";
- my $mbody = f_ "Import %s", $tt->{F};
- $tt->{Commit} = make_commit_text($tt->{Orig} ? <<END_O : <<END_T);
+ # untranslated so that different people's imports are identical
+ my $mbody = sprintf "Import %s", $tt->{F};
+ $tt->{Commit} = hash_commit_text($tt->{Orig} ? <<END_O : <<END_T);
tree $tt->{Tree}
author $r1authline
committer $r1authline
}
}
+ return ($authline, $r1authline, $clogp, $changes);
+}
+
+sub generate_commits_from_dsc () {
+ # See big comment in fetch_from_archive, below.
+ # See also README.dsc-import.
+ prep_ud();
+ changedir $playground;
+
+ my $bpd_abs = bpd_abs();
+ my $upstreamv = upstreamversion $dsc->{version};
+ my @dfi = dsc_files_info();
+
+ dotdot_bpd_transfer_origs $bpd_abs, $upstreamv,
+ sub { grep { $_->{Filename} eq $_[0] } @dfi };
+
+ foreach my $fi (@dfi) {
+ my $f = $fi->{Filename};
+ die "$f ?" if $f =~ m#/|^\.|\.dsc$|\.tmp$#;
+ my $upper_f = "$bpd_abs/$f";
+
+ printdebug "considering reusing $f: ";
+
+ if (link_ltarget "$upper_f,fetch", $f) {
+ printdebug "linked (using ...,fetch).\n";
+ } elsif ((printdebug "($!) "),
+ $! != ENOENT) {
+ fail f_ "accessing %s: %s", "$buildproductsdir/$f,fetch", $!;
+ } elsif (link_ltarget $upper_f, $f) {
+ printdebug "linked.\n";
+ } elsif ((printdebug "($!) "),
+ $! != ENOENT) {
+ fail f_ "accessing %s: %s", "$buildproductsdir/$f", $!;
+ } else {
+ printdebug "absent.\n";
+ }
+
+ my $refetched;
+ complete_file_from_dsc('.', $fi, \$refetched)
+ or next;
+
+ printdebug "considering saving $f: ";
+
+ if (rename_link_xf 1, $f, $upper_f) {
+ printdebug "linked.\n";
+ } elsif ((printdebug "($@) "),
+ $! != EEXIST) {
+ fail f_ "saving %s: %s", "$buildproductsdir/$f", $@;
+ } elsif (!$refetched) {
+ printdebug "no need.\n";
+ } elsif (rename_link_xf 1, $f, "$upper_f,fetch") {
+ printdebug "linked (using ...,fetch).\n";
+ } elsif ((printdebug "($@) "),
+ $! != EEXIST) {
+ fail f_ "saving %s: %s", "$buildproductsdir/$f,fetch", $@;
+ } else {
+ printdebug "cannot.\n";
+ }
+ }
+
+ my @tartrees;
+ @tartrees = import_tarball_tartrees($upstreamv, \@dfi)
+ unless @dfi == 1; # only one file in .dsc
+
+ my $dscfn = "$package.dsc";
+
+ my $treeimporthow = 'package';
+
+ open D, ">", $dscfn or die "$dscfn: $!";
+ print D $dscdata or die "$dscfn: $!";
+ close D or die "$dscfn: $!";
+ my @cmd = qw(dpkg-source);
+ push @cmd, '--no-check' if $dsc_checked;
+ if (madformat $dsc->{format}) {
+ push @cmd, '--skip-patches';
+ $treeimporthow = 'unpatched';
+ }
+ push @cmd, qw(-x --), $dscfn;
+ runcmd @cmd;
+
+ my ($tree,$dir) = mktree_in_ud_from_only_subdir(__ "source package");
+ if (madformat $dsc->{format}) {
+ check_for_vendor_patches();
+ }
+
+ my $dappliedtree;
+ if (madformat $dsc->{format}) {
+ my @pcmd = qw(dpkg-source --before-build .);
+ runcmd shell_cmd 'exec >/dev/null', @pcmd;
+ rmtree '.pc';
+ $dappliedtree = git_add_write_tree();
+ }
+
+ my ($authline, $r1authline, $clogp, $changes) =
+ import_tarball_commits(\@tartrees, $upstreamv);
+
+ my $cversion = getfield $clogp, 'Version';
+
printdebug "import main commit\n";
open C, ">../commit.tmp" or confess "$!";
END
close C or confess "$!";
- my $rawimport_hash = make_commit qw(../commit.tmp);
+ my $rawimport_hash = hash_commit qw(../commit.tmp);
if (madformat $dsc->{format}) {
printdebug "import apply patches...\n";
# regularise the state of the working tree so that
# the checkout of $rawimport_hash works nicely.
- my $dappliedcommit = make_commit_text(<<END);
+ my $dappliedcommit = hash_commit_text(<<END);
tree $dappliedtree
author $authline
committer $authline
if ($vcmp < 0) {
@output = ($rawimport_mergeinput, $lastpush_mergeinput,
{ ReverseParents => 1,
- Message => (f_ <<END, $package, $cversion, $csuite) });
+ # untranslated so that different people's pseudomerges
+ # are not needlessly different (although they will
+ # still differ if the series of pulls is different)
+ Message => (sprintf <<END, $package, $cversion, $csuite) });
Record %s (%s) in archive suite %s
END
} elsif ($vcmp > 0) {
# deliberately-not-ff, in which case we must fetch everything.
my @specs = deliberately_not_fast_forward ? qw(tags/*) :
- map { "tags/$_" }
- (quiltmode_splitbrain
- ? (map { $_->('*',access_nomdistro) }
- \&debiantag_new, \&debiantag_maintview)
- : debiantags('*',access_nomdistro));
+ map { "tags/$_" } debiantags('*',access_nomdistro);
push @specs, server_branch($csuite);
push @specs, $rewritemap;
push @specs, qw(heads/*) if deliberately_not_fast_forward;
}
close MC or confess "$!";
- $hash = make_commit $mcf;
+ $hash = hash_commit $mcf;
} else {
$hash = $mergeinputs[0]{Commit};
}
$commit .=
"author $authline\n".
"committer $authline\n\n";
- $output = make_commit_text $commit.$msg;
+ $output = hash_commit_text $commit.$msg;
printdebug "multisuite merge generated $output\n";
}
record_maindir();
setup_new_tree();
clone_set_head();
- my $giturl = access_giturl(1);
- if (defined $giturl) {
- runcmd @git, qw(remote add), 'origin', $giturl;
- }
if ($hasgit) {
progress __ "fetching existing git history";
git_fetch_us();
- runcmd_ordryrun_local @git, qw(fetch origin);
} else {
progress __ "starting new git history";
}
$cd = $gf->('Distribution');
};
if ($@) {
+ $@ =~ s/^\n//s;
$@ =~ s/^dgit: //gm;
fail "$@".
f_ "Perhaps debian/changelog does not mention %s ?", $v;
return $i_arch_v;
}
-sub pseudomerge_make_commit ($$$$ $$) {
+sub pseudomerge_hash_commit ($$$$ $$) {
my ($clogp, $dgitview, $archive_hash, $i_arch_v,
$msg_cmd, $msg_msg) = @_;
progress f_ "Declaring that HEAD includes all changes in %s...",
END
close MC or confess "$!";
- return make_commit($pmf);
+ return hash_commit($pmf);
}
sub splitbrain_pseudomerge ($$$$) {
}
my $arch_v = $i_arch_v->[0];
- my $r = pseudomerge_make_commit
+ my $r = pseudomerge_hash_commit
$clogp, $dgitview, $archive_hash, $i_arch_v,
"dgit --quilt=$quilt_mode",
(defined $overwrite_version
my $m = f_ "Declare fast forward from %s", $i_arch_v->[0];
- my $r = pseudomerge_make_commit
+ my $r = pseudomerge_hash_commit
$clogp, $head, $archive_hash, $i_arch_v,
"dgit", $m;
if (!$we_are_initiator) {
# rpush initiator can't do this because it doesn't have $isuite yet
- my $tag = debiantag($cversion, access_nomdistro);
+ my $tag = debiantag_new($cversion, access_nomdistro);
runcmd @git, qw(check-ref-format), $tag;
}
my ($cversion, $dgithead, $maintviewhead, $tfbase) = @_;
my @tagwants;
push @tagwants, {
- TagFn => \&debiantag,
+ TagFn => \&debiantag_new,
Objid => $dgithead,
TfSuffix => '',
View => 'dgit',
TfSuffix => '-maintview',
View => 'maint',
};
- } elsif ($dodep14tag eq 'no' ? 0
- : $dodep14tag eq 'want' ? access_cfg_tagformats_can_splitbrain
- : $dodep14tag eq 'always'
- ? (access_cfg_tagformats_can_splitbrain or fail <<END)
---dep14tag-always (or equivalent in config) means server must support
- both "new" and "maint" tag formats, but config says it doesn't.
-END
- : die "$dodep14tag ?") {
+ } elsif ($dodep14tag ne 'no') {
push @tagwants, {
TagFn => \&debiantag_maintview,
Objid => $dgithead,
my $cversion = getfield $clogp, 'Version';
my $clogsuite = getfield $clogp, 'Distribution';
+ my $format = getfield $dsc, 'Format';
# We make the git tag by hand because (a) that makes it easier
# to control the "tagger" (b) we can do remote signing
my $authline = clogp_authline $clogp;
- my $delibs = join(" ", "",@deliberatelies);
my $mktag = sub {
my ($tw) = @_;
tagger $authline
END
+
+ my @dtxinfo = @deliberatelies;
+ unshift @dtxinfo, "--quilt=$quilt_mode" if madformat($format);
+ unshift @dtxinfo, do_split_brain() ? "split" : "no-split"
+ # rpush protocol 5 and earlier don't tell us
+ unless $we_are_initiator && $protovsn < 6;
+ my $dtxinfo = join(" ", "",@dtxinfo);
+ my $tag_metadata = <<END;
+[dgit distro=$declaredistro$dtxinfo]
+END
+ foreach my $ref (sort keys %previously) {
+ $tag_metadata .= <<END or confess "$!";
+[dgit previously:$ref=$previously{$ref}]
+END
+ }
+
if ($tw->{View} eq 'dgit') {
- print TO f_ <<ENDT, $package, $cversion, $clogsuite, $csuite
+ print TO sprintf <<ENDT, $package, $cversion, $clogsuite, $csuite
%s release %s for %s (%s) [dgit]
ENDT
or confess "$!";
- print TO <<END or confess "$!";
-[dgit distro=$declaredistro$delibs]
-END
- foreach my $ref (sort keys %previously) {
- print TO <<END or confess "$!";
-[dgit previously:$ref=$previously{$ref}]
-END
- }
} elsif ($tw->{View} eq 'maint') {
- print TO f_ <<END, $package, $cversion, $clogsuite, $csuite,
+ print TO sprintf <<END, $package, $cversion, $clogsuite, $csuite;
%s release %s for %s (%s)
+
+END
+ print TO f_ <<END,
(maintainer view tag generated by dgit --quilt=%s)
END
$quilt_mode
} else {
confess Dumper($tw)."?";
}
+ print TO "\n", $tag_metadata;
close TO or confess "$!";
You can retry the push, after fixing the problem, if you like.
END
- need_tagformat 'new', "quilt mode $quilt_mode"
- if quiltmode_splitbrain;
-
prep_ud();
access_giturl(); # check that success is vaguely likely
rpush_handle_protovsn_bothends() if $we_are_initiator;
- select_tagformat();
my $clogpfn = dgit_privdir()."/changelog.822.tmp";
runcmd shell_cmd "exec >$clogpfn", qw(dpkg-parsechangelog);
my $actualhead = git_rev_parse('HEAD');
if (branch_is_gdr_unstitched_ff($symref, $actualhead, $archive_hash)) {
- if (quiltmode_splitbrain()) {
+ if (quiltmode_splitting()) {
my ($ffq_prev, $gdrlast) = branch_gdr_info($symref, $actualhead);
fail f_ <<END, $ffq_prev, $quilt_mode;
Branch is managed by git-debrebase (%s
if (madformat_wantfixup($format)) {
# user might have not used dgit build, so maybe do this now:
- if ($do_split_brain) {
+ if (do_split_brain()) {
changedir $playground;
my $cachekey;
($dgithead, $cachekey) =
perhaps HEAD changed since dgit build[-source] ?",
$quilt_mode;
}
- if (!$do_split_brain) {
+ if (!do_split_brain()) {
# In split brain mode, do not attempt to incorporate dirty
# stuff from the user's working tree. That would be mad.
commit_quilty_patch();
}
}
- if ($do_split_brain) {
- $split_brain = 1;
+ if (do_split_brain()) {
+ $made_split_brain = 1;
$dgithead = splitbrain_pseudomerge($clogp,
$actualhead, $dgithead,
$archive_hash);
}
}
+ confess unless !!$made_split_brain == do_split_brain();
+
changedir $playground;
progress f_ "checking that %s corresponds to HEAD", $dscfn;
runcmd qw(dpkg-source -x --),
my $r = system @diffcmd;
if ($r) {
if ($r==256) {
- my $referent = $split_brain ? $dgithead : 'HEAD';
+ my $referent = $made_split_brain ? $dgithead : 'HEAD';
my $diffs = cmdoutput @git, qw(diff --stat), $tree, $dgithead;
my @mode_changes;
responder_send_command("param head $dgithead");
responder_send_command("param csuite $csuite");
responder_send_command("param isuite $isuite");
- responder_send_command("param tagformat $tagformat");
+ responder_send_command("param tagformat new"); # needed in $protovsn==4
+ responder_send_command("param splitbrain $do_split_brain");
if (defined $maintviewhead) {
- confess "internal error (protovsn=$protovsn)"
- if defined $protovsn and $protovsn < 4;
responder_send_command("param maint-view $maintviewhead");
}
sub cmd_pull {
parseopts();
fetchpullargs();
- if (quiltmode_splitbrain()) {
+ determine_whether_split_brain get_source_format();
+ if (do_split_brain()) {
my ($format, $fopts) = get_source_format();
madformat($format) and fail f_ <<END, $quilt_mode
-dgit pull not yet supported in split view mode (--quilt=%s)
+dgit pull not yet supported in split view mode (including with view-splitting quilt modes)
END
}
pull();
# a good error message)
sub rpush_handle_protovsn_bothends () {
- if ($protovsn < 4) {
- need_tagformat 'old', "rpush negotiated protocol $protovsn";
- }
- select_tagformat();
}
our $i_tmp;
changedir $i_tmp;
($protovsn) = initiator_expect { m/^dgit-remote-push-ready (\S+)/ };
die "$protovsn ?" unless grep { $_ eq $protovsn } @rpushprotovsn_support;
- $supplementary_message = '' unless $protovsn >= 3;
for (;;) {
my ($icmd,$iargs) = initiator_expect {
}
our %i_wanted;
+our ($i_clogp, $i_version, $i_dscfn, $i_changesfn, @i_buildinfos);
sub i_resp_want ($) {
my ($keyword) = @_;
$isuite = $i_param{'isuite'} // $i_param{'csuite'};
die unless $isuite =~ m/^$suite_re$/;
- pushing();
- rpush_handle_protovsn_bothends();
-
- fail f_ "rpush negotiated protocol version %s".
- " which does not support quilt mode %s",
- $protovsn, $quilt_mode
- if quiltmode_splitbrain && $protovsn < 4;
+ if (!defined $dsc) {
+ pushing();
+ rpush_handle_protovsn_bothends();
+ push_parse_dsc $i_dscfn, 'remote dsc', $i_version;
+ if ($protovsn >= 6) {
+ determine_whether_split_brain getfield $dsc, 'Format';
+ $do_split_brain eq ($i_param{'splitbrain'} // '<unsent>')
+ or badproto \*RO,
+ "split brain mismatch, $do_split_brain != $i_param{'split_brain'}";
+ printdebug "rpush split brain $do_split_brain\n";
+ }
+ }
my @localpaths = i_method "i_want", $keyword;
printdebug "[[ $keyword @localpaths\n";
print RI "files-end\n" or confess "$!";
}
-our ($i_clogp, $i_version, $i_dscfn, $i_changesfn, @i_buildinfos);
-
sub i_localname_parsed_changelog {
return "remote-changelog.822";
}
my $maintview = $i_param{'maint-view'};
die if defined $maintview && $maintview =~ m/[^0-9a-f]/;
- select_tagformat();
- if ($protovsn >= 4) {
+ if ($protovsn == 4) {
my $p = $i_param{'tagformat'} // '<undef>';
- $p eq $tagformat
- or badproto \*RO, "tag format mismatch: $p vs. $tagformat";
+ $p eq 'new'
+ or badproto \*RO, "tag format mismatch: $p vs. new";
}
die unless $i_param{'csuite'} =~ m/^$suite_re$/;
$csuite = $&;
- push_parse_dsc $i_dscfn, 'remote dsc', $i_version;
+ defined $dsc or badproto \*RO, "dsc (before parsed-changelog)";
my @tagwants = push_tagwants $i_version, $head, $maintview, "tag";
return $r;
}
-sub quiltify_splitbrain ($$$$$$$) {
+sub quiltify_splitting ($$$$$$$) {
my ($clogp, $unapplied, $headref, $oldtiptree, $diffbits,
$editedignores, $cachekey) = @_;
my $gitignore_special = 1;
- if ($quilt_mode !~ m/gbp|dpm/) {
+ if ($quilt_mode !~ m/gbp|dpm|baredebian/) {
# treat .gitignore just like any other upstream file
$diffbits = { %$diffbits };
$_ = !!$_ foreach values %$diffbits;
local $ENV{GIT_AUTHOR_EMAIL} = $authline[1];
local $ENV{GIT_AUTHOR_DATE} = $authline[2];
- confess unless $do_split_brain;
+ confess unless do_split_brain();
my $fulldiffhint = sub {
my ($x,$y) = @_;
$cmd;
};
- if ($quilt_mode =~ m/gbp|unapplied/ &&
+ if ($quilt_mode =~ m/gbp|unapplied|baredebian/ &&
($diffbits->{O2H} & 01)) {
my $msg = f_
"--quilt=%s specified, implying patches-unapplied git tree\n".
" but git tree differs from orig in upstream files.",
$quilt_mode;
$msg .= $fulldiffhint->($unapplied, 'HEAD');
- if (!stat_exists "debian/patches") {
+ if (!stat_exists "debian/patches" and $quilt_mode !~ m/baredebian/) {
$msg .= __
"\n ... debian/patches is missing; perhaps this is a patch queue branch?";
}
but git tree differs from result of applying debian/patches to upstream
END
}
- if ($quilt_mode =~ m/gbp|unapplied/ &&
+ if ($quilt_mode =~ m/baredebian/) {
+ # We need to construct a merge which has upstream files from
+ # upstream and debian/ files from HEAD.
+
+ read_tree_upstream $quilt_upstream_commitish, 1, $headref;
+ my $version = getfield $clogp, 'Version';
+ my $upsversion = upstreamversion $version;
+ my $merge = make_commit
+ [ $headref, $quilt_upstream_commitish ],
+ [ +(f_ <<ENDT, $upsversion), $quilt_upstream_commitish_message, <<ENDU ];
+Combine debian/ with upstream source for %s
+ENDT
+[dgit ($our_version) baredebian-merge $version $quilt_upstream_commitish_used]
+ENDU
+ runcmd @git, qw(reset -q --hard), $merge;
+ }
+ if ($quilt_mode =~ m/gbp|unapplied|baredebian/ &&
($diffbits->{O2A} & 01)) { # some patches
progress __ "dgit view: creating patches-applied version using gbp pq";
runcmd shell_cmd 'exec >/dev/null', gbp_pq, qw(import);
[dgit ($our_version) update-gitignore-quilt-fixup]
ENDU
}
-
- my $dgitview = git_rev_parse 'HEAD';
-
- changedir $maindir;
- reflog_cache_insert "refs/$splitbraincache", $cachekey, $dgitview;
-
- changedir "$playground/work";
-
- my $saved = maybe_split_brain_save $headref, $dgitview, __ "converted";
- progress f_ "dgit view: created (%s)", $saved;
}
sub quiltify ($$$$) {
runcmd @git, qw(checkout -q), $cc, qw(debian/changelog);
}
-
- runcmd @git, qw(checkout -q master);
}
sub build_maybe_quilt_fixup () {
my $splitbrain_cachekey;
- if ($do_split_brain) {
+ if (do_split_brain()) {
my $cachehit;
($cachehit, $splitbrain_cachekey) =
quilt_check_splitbrain_cache($headref, $upstreamversion);
}
unpack_playtree_need_cd_work($headref);
- if ($do_split_brain) {
+ if (do_split_brain()) {
runcmd @git, qw(checkout -q -b dgit-view);
# so long as work is not deleted, its current branch will
# remain dgit-view, rather than master, so subsequent calls to
# unpack_playtree_need_cd_work
# will DTRT, resetting dgit-view.
- die if $split_brain;
- $split_brain = 1;
+ confess if $made_split_brain;
+ $made_split_brain = 1;
}
chdir '..';
fail f_
"quilt mode %s does not make sense (or is not supported) with single-debian-patch",
$quilt_mode
- if quiltmode_splitbrain();
+ if quiltmode_splitting();
quilt_fixup_singlepatch($clogp, $headref, $upstreamversion);
} else {
quilt_fixup_multipatch($clogp, $headref, $upstreamversion,
$splitbrain_cachekey);
}
+ if (do_split_brain()) {
+ my $dgitview = git_rev_parse 'HEAD';
+
+ changedir $maindir;
+ reflog_cache_insert "refs/$splitbraincache",
+ $splitbrain_cachekey, $dgitview;
+
+ changedir "$playground/work";
+
+ my $saved = maybe_split_brain_save $headref, $dgitview, __ "converted";
+ progress f_ "dgit view: created (%s)", $saved;
+ }
+
changedir $maindir;
runcmd_ordryrun_local
@git, qw(pull --ff-only -q), "$playground/work", qw(master);
sub build_check_quilt_splitbrain () {
build_maybe_quilt_fixup();
-
- if ($do_split_brain) {
- fail <<END unless access_cfg_tagformats_can_splitbrain;
-quilt mode $quilt_mode requires split view so server needs to support
- both "new" and "maint" tag formats, but config says it doesn't.
-END
- }
}
sub unpack_playtree_need_cd_work ($) {
push @cachekey, $upstreamversion;
push @cachekey, $quilt_mode;
push @cachekey, $headref;
+ push @cachekey, $quilt_upstream_commitish // '-';
push @cachekey, hashfile('fake.dsc');
if ($cachehit ne $headref) {
progress f_ "dgit view: found cached (%s)", $saved;
runcmd @git, qw(checkout -q -b dgit-view), $cachehit;
- $split_brain = 1;
+ $made_split_brain = 1;
return ($cachehit, $splitbrain_cachekey);
}
progress __ "dgit view: found cached, no changes required";
return (undef, $splitbrain_cachekey);
}
+sub baredebian_origtarballs_scan ($$$) {
+ my ($fakedfi, $upstreamversion, $dir) = @_;
+ if (!opendir OD, $dir) {
+ return if $! == ENOENT;
+ fail "opendir $dir (origs): $!";
+ }
+
+ while ($!=0, defined(my $leaf = readdir OD)) {
+ {
+ local ($debuglevel) = $debuglevel-1;
+ printdebug "BDOS $dir $leaf ?\n";
+ }
+ next unless is_orig_file_of_vsn $leaf, $upstreamversion;
+ next if grep { $_->{Filename} eq $leaf } @$fakedfi;
+ push @$fakedfi, {
+ Filename => $leaf,
+ Path => "$dir/$leaf",
+ };
+ }
+
+ die "$dir; $!" if $!;
+ closedir OD;
+}
+
sub quilt_fixup_multipatch ($$$) {
my ($clogp, $headref, $upstreamversion, $splitbrain_cachekey) = @_;
# We calculate some guesswork now about what kind of tree this might
# be. This is mostly for error reporting.
+ my $tentries = cmdoutput @git, qw(ls-tree --name-only -z), $headref;
+ my $onlydebian = $tentries eq "debian\0";
+
+ my $uheadref = $headref;
+ my $uhead_whatshort = 'HEAD';
+
+ if ($quilt_mode =~ m/baredebian\+tarball/) {
+ # We need to make a tarball import. Yuk.
+ # We want to do this here so that we have a $uheadref value
+
+ my @fakedfi;
+ baredebian_origtarballs_scan \@fakedfi, $upstreamversion, bpd_abs();
+ baredebian_origtarballs_scan \@fakedfi, $upstreamversion,
+ "$maindir/.." unless $buildproductsdir eq '..';
+ changedir '..';
+
+ my @tartrees = import_tarball_tartrees $upstreamversion, \@fakedfi;
+
+ fail __ "baredebian quilt fixup: could not find any origs"
+ unless @tartrees;
+
+ changedir 'work';
+ my ($authline, $r1authline, $clogp,) =
+ import_tarball_commits \@tartrees, $upstreamversion;
+
+ if (@tartrees == 1) {
+ $uheadref = $tartrees[0]{Commit};
+ # TRANSLATORS: this translation must fit in the ASCII art
+ # quilt differences display. The untranslated display
+ # says %9.9s, so with that display it must be at most 9
+ # characters.
+ $uhead_whatshort = __ 'tarball';
+ } else {
+ # on .dsc import we do not make a separate commit, but
+ # here we need to do so
+ rm_subdir_cached '.';
+ my $parents;
+ foreach my $ti (@tartrees) {
+ my $c = $ti->{Commit};
+ if ($ti->{OrigPart} eq 'orig') {
+ runcmd qw(git read-tree), $c;
+ } elsif ($ti->{OrigPart} =~ m/orig-/) {
+ read_tree_subdir $', $c;
+ } else {
+ confess "$ti->OrigPart} ?"
+ }
+ $parents .= "parent $c\n";
+ }
+ my $tree = git_write_tree();
+ my $mbody = f_ 'Combine orig tarballs for %s %s',
+ $package, $upstreamversion;
+ $uheadref = hash_commit_text <<END;
+tree $tree
+${parents}author $r1authline
+committer $r1authline
+
+$mbody
+
+[dgit import tarballs combine $package $upstreamversion]
+END
+ # TRANSLATORS: this translation must fit in the ASCII art
+ # quilt differences display. The untranslated display
+ # says %9.9s, so with that display it must be at most 9
+ # characters. This fragmentt is referring to multiple
+ # orig tarballs in a source package.
+ $uhead_whatshort = __ 'tarballs';
+
+ runcmd @git, qw(reset -q);
+ }
+ $quilt_upstream_commitish = $uheadref;
+ $quilt_upstream_commitish_used = '*orig*';
+ $quilt_upstream_commitish_message = '';
+ }
+ if ($quilt_mode =~ m/baredebian$/) {
+ $uheadref = $quilt_upstream_commitish;
+ # TRANSLATORS: this translation must fit in the ASCII art
+ # quilt differences display. The untranslated display
+ # says %9.9s, so with that display it must be at most 9
+ # characters.
+ $uhead_whatshort = __ 'upstream';
+ }
+
my %editedignores;
my @unrepres;
my $diffbits = {
# H = user's HEAD
# O = orig, without patches applied
# A = "applied", ie orig with H's debian/patches applied
- O2H => quiltify_trees_differ($unapplied,$headref, 1,
+ O2H => quiltify_trees_differ($unapplied,$uheadref, 1,
\%editedignores, \@unrepres),
- H2A => quiltify_trees_differ($headref, $oldtiptree,1),
+ H2A => quiltify_trees_differ($uheadref, $oldtiptree,1),
O2A => quiltify_trees_differ($unapplied,$oldtiptree,1),
};
progress f_
"%s: base trees orig=%.20s o+d/p=%.20s",
$us, $unapplied, $oldtiptree;
+ # TRANSLATORS: Try to keep this ascii-art layout right. The 0s in
+ # %9.00009s will be ignored and are there to make the format the
+ # same length (9 characters) as the output it generates. If you
+ # change the value 9, your translations of "upstream" and
+ # 'tarball' must fit into the new length, and you should change
+ # the number of 0s. Do not reduce it below 4 as HEAD has to fit
+ # too.
progress f_
"%s: quilt differences: src: %s orig %s gitignores: %s orig %s\n".
-"%s: quilt differences: HEAD %s o+d/p HEAD %s o+d/p",
+"%s: quilt differences: %9.00009s %s o+d/p %9.00009s %s o+d/p",
$us, $dl[0], $dl[1], $dl[3], $dl[4],
- $us, $dl[2], $dl[5];
+ $us, $uhead_whatshort, $dl[2], $uhead_whatshort, $dl[5];
- if (@unrepres) {
+ if (@unrepres && $quilt_mode !~ m/baredebian/) {
+ # With baredebian, even if the upstream commitish has this
+ # problem, we don't want to print this message, as nothing
+ # is going to try to make a patch out of it anyway.
print STDERR f_ "dgit: cannot represent change: %s: %s\n",
$_->[1], $_->[0]
foreach @unrepres;
}
my @failsuggestion;
- if (!($diffbits->{O2H} & $diffbits->{O2A})) {
+ if ($onlydebian) {
+ push @failsuggestion, [ 'onlydebian', __
+ "This has only a debian/ directory; you probably want --quilt=bare debian." ]
+ unless $quilt_mode =~ m/baredebian/;
+ } elsif (!($diffbits->{O2H} & $diffbits->{O2A})) {
push @failsuggestion, [ 'unapplied', __
"This might be a patches-unapplied branch." ];
} elsif (!($diffbits->{H2A} & $diffbits->{O2A})) {
if stat_exists '.gitattributes';
push @failsuggestion, [ 'origs', __
- "Maybe orig tarball(s) are not identical to git representation?" ];
-
- if (quiltmode_splitbrain()) {
- quiltify_splitbrain($clogp, $unapplied, $headref, $oldtiptree,
- $diffbits, \%editedignores,
- $splitbrain_cachekey);
+ "Maybe orig tarball(s) are not identical to git representation?" ]
+ unless $onlydebian && $quilt_mode !~ m/baredebian/;
+ # ^ in that case, we didn't really look properly
+
+ if (quiltmode_splitting()) {
+ quiltify_splitting($clogp, $unapplied, $headref, $oldtiptree,
+ $diffbits, \%editedignores,
+ $splitbrain_cachekey);
return;
}
progress f_ "starting quiltify (multiple patches, %s mode)", $quilt_mode;
quiltify($clogp,$headref,$oldtiptree,\@failsuggestion);
+ runcmd @git, qw(checkout -q), (qw(master dgit-view)[do_split_brain()]);
if (!open P, '>>', ".pc/applied-patches") {
$!==&ENOENT or confess "$!";
}
sub maybe_apply_patches_dirtily () {
- return unless $quilt_mode =~ m/gbp|unapplied/;
+ return unless $quilt_mode =~ m/gbp|unapplied|baredebian/;
print STDERR __ <<END or confess "$!";
dgit: Building, or cleaning with rules target, in patches-unapplied tree.
sub clean_tree () {
# We always clean the tree ourselves, rather than leave it to the
# builder (dpkg-source, or soemthing which calls dpkg-source).
+ if ($quilt_mode =~ m/baredebian/ and $cleanmode =~ m/git/) {
+ fail f_ <<END, $quilt_mode, $cleanmode;
+quilt mode %s (generally needs untracked upstream files)
+contradicts clean mode %s (which would delete them)
+END
+ # This is not 100% true: dgit build-source and push-source
+ # (for example) could operate just fine with no upstream
+ # source in the working tree. But it doesn't seem likely that
+ # the user wants dgit to proactively delete such things.
+ # -wn, for example, would produce identical output without
+ # deleting anything from the working tree.
+ }
if ($cleanmode =~ m{^dpkg-source}) {
my @cmd = @dpkgbuildpackage;
push @cmd, qw(-d) if $cleanmode =~ m{^dpkg-source-d};
sub build_or_push_prep_early () {
our $build_or_push_prep_early_done //= 0;
return if $build_or_push_prep_early_done++;
- badusage f_ "-p is not allowed with dgit %s", $subcommand
- if defined $package;
my $clogp = parsechangelog();
$isuite = getfield $clogp, 'Distribution';
- $package = getfield $clogp, 'Source';
+ my $gotpackage = getfield $clogp, 'Source';
$version = getfield $clogp, 'Version';
+ $package //= $gotpackage;
+ if ($package ne $gotpackage) {
+ fail f_ "-p specified package %s, but changelog says %s",
+ $package, $gotpackage;
+ }
$dscfn = dscfn($version);
}
sub build_or_push_prep_modes () {
- my ($format,) = get_source_format();
- printdebug "format $format, quilt mode $quilt_mode\n";
- if (madformat_wantfixup($format) && quiltmode_splitbrain()) {
- $do_split_brain = 1;
+ my ($format) = get_source_format();
+ determine_whether_split_brain($format);
+
+ fail __ "dgit: --include-dirty is not supported with split view".
+ " (including with view-splitting quilt modes)"
+ if do_split_brain() && $includedirty;
+
+ if (madformat_wantfixup $format and $quilt_mode =~ m/baredebian$/) {
+ ($quilt_upstream_commitish, $quilt_upstream_commitish_used,
+ $quilt_upstream_commitish_message)
+ = resolve_upstream_version
+ $quilt_upstream_commitish, upstreamversion $version;
+ progress f_ "dgit: --quilt=%s, %s", $quilt_mode,
+ $quilt_upstream_commitish_message;
+ } elsif (defined $quilt_upstream_commitish) {
+ fail __
+ "dgit: --upstream-commitish only makes sense with --quilt=baredebian"
}
- fail __ "dgit: --include-dirty is not supported in split view quilt mode"
- if $do_split_brain && $includedirty;
}
sub build_prep_early () {
#
# 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
+ # that makes quilt fixup too hard. I.e. ($made_split_brain && (dgit is
# building a source package)) => !$includedirty
return !$includedirty;
}
unlink "$buildproductsdir/$sourcechanges" or $!==ENOENT
or fail f_ "remove %s: %s", $sourcechanges, $!;
}
+# confess unless !!$made_split_brain == do_split_brain();
+
my @cmd = (@dpkgsource, qw(-b --));
my $leafdir;
if (building_source_in_playtree()) {
# 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;
+ prep_ud() unless $made_split_brain;
changedir $playground;
- unless ($split_brain) {
+ unless ($made_split_brain) {
my $upstreamversion = upstreamversion $version;
unpack_playtree_linkorigs($upstreamversion, sub { });
unpack_playtree_need_cd_work($headref);
my $version = getfield $dsc, 'Version';
my $clogp = commit_getclogp $newhash;
my $authline = clogp_authline $clogp;
- $newhash = make_commit_text <<ENDU
+ $newhash = hash_commit_text <<ENDU
tree $tree
parent $newhash
parent $oldhash
push @ropts, $_;
my $cmd = shift @$om;
@$om = ($cmd, grep { $_ ne $2 } @$om);
- } elsif (m/^--(gbp|dpm)$/s) {
+ } elsif (m/^--($quilt_options_re)$/s) {
push @ropts, "--quilt=$1";
$quilt_mode = $1;
} elsif (m/^--(?:ignore|include)-dirty$/s) {
} elsif (m/^--overwrite$/s) {
push @ropts, $_;
$overwrite_version = '';
+ } elsif (m/^--split-(?:view|brain)$/s) {
+ push @ropts, $_;
+ $splitview_mode = 'always';
+ } elsif (m/^--split-(?:view|brain)=($splitview_modes_re)$/s) {
+ push @ropts, $_;
+ $splitview_mode = $1;
} elsif (m/^--overwrite=(.+)$/s) {
push @ropts, $_;
$overwrite_version = $1;
} elsif (m/^--delayed=(\d+)$/s) {
push @ropts, $_;
push @dput, $_;
- } elsif (my ($k,$v) =
- m/^--save-(dgit-view)=(.+)$/s ||
+ } elsif (m/^--upstream-commitish=(.+)$/s) {
+ push @ropts, $_;
+ $quilt_upstream_commitish = $1;
+ } elsif (m/^--save-(dgit-view)=(.+)$/s ||
m/^--(dgit-view)-save=(.+)$/s
) {
+ my ($k,$v) = ($1,$2);
push @ropts, $_;
$v =~ s#^(?!refs/)#refs/heads/#;
$internal_object_save{$k} = $v;
f_ "%s: warning: ignoring unknown force option %s\n",
$us, $_;
$_='';
- } elsif (m/^--dgit-tag-format=(old|new)$/s) {
- # undocumented, for testing
- push @ropts, $_;
- $tagformat_want = [ $1, 'command line', 1 ];
- # 1 menas overrides distro configuration
} elsif (m/^--config-lookup-explode=(.+)$/s) {
# undocumented, for testing
push @ropts, $_;
or badcfg f_ "unknown quilt-mode \`%s'", $quilt_mode;
$quilt_mode = $1;
}
+ $quilt_mode =~ s/^(baredebian)\+git$/$1/;
foreach my $moc (@modeopt_cfgs) {
local $access_forpush;
$$vr = $v;
}
- if (!defined $cleanmode) {
+ {
local $access_forpush;
- $cleanmode = access_cfg('clean-mode-newer', 'RETURN-UNDEF');
- $cleanmode = undef if $cleanmode && $cleanmode !~ m/^$cleanmode_re$/;
-
- $cleanmode //= access_cfg('clean-mode', 'RETURN-UNDEF');
- $cleanmode //= 'dpkg-source';
-
- badcfg f_ "unknown clean-mode \`%s'", $cleanmode unless
- $cleanmode =~ m/$cleanmode_re/;
+ default_from_access_cfg(\$cleanmode, 'clean-mode', 'dpkg-source',
+ $cleanmode_re);
}
$buildproductsdir //= access_cfg('build-products-dir', 'RETURN-UNDEF');