summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Debian/Dgit.pm100
-rw-r--r--debian/tests/control6
-rwxr-xr-xdgit908
-rw-r--r--dgit-maint-debrebase.7.pod37
-rw-r--r--dgit-maint-merge.7.pod32
-rw-r--r--dgit.1119
-rw-r--r--dgit.720
-rwxr-xr-xgit-debrebase75
-rw-r--r--git-debrebase.1.pod2
-rwxr-xr-xinfra/dgit-repos-policy-debian1
-rwxr-xr-xinfra/dgit-repos-server18
-rwxr-xr-xtests/enumerate-tests24
-rw-r--r--tests/lib39
-rw-r--r--tests/lib-baredebian93
-rwxr-xr-xtests/setup/baredebian34
-rwxr-xr-xtests/tests/baredebian-multitar46
-rwxr-xr-xtests/tests/baredebian-plusgit17
-rwxr-xr-xtests/tests/baredebian-push14
-rwxr-xr-xtests/tests/baredebian-tarball21
-rwxr-xr-xtests/tests/debpolicy-taintrm58
-rwxr-xr-xtests/tests/drs-push-rejects3
-rwxr-xr-xtests/tests/forcesplit-linear45
-rwxr-xr-xtests/tests/forcesplit-overwrite37
-rwxr-xr-xtests/tests/newtag-clone-nogit4
-rwxr-xr-xtests/tests/oldnewtagalt25
-rwxr-xr-xtests/tests/oldtag-clone-nogit4
-rwxr-xr-xtests/tests/overwrite-splitbrains1
-rwxr-xr-xtests/tests/quilt-gbp5
-rwxr-xr-xtests/tests/quilt-splitbrains4
-rwxr-xr-xtests/tests/rpush-quilt2
30 files changed, 1259 insertions, 535 deletions
diff --git a/Debian/Dgit.pm b/Debian/Dgit.pm
index 61476d9..887fbb5 100644
--- a/Debian/Dgit.pm
+++ b/Debian/Dgit.pm
@@ -43,9 +43,10 @@ BEGIN {
@ISA = qw(Exporter);
@EXPORT = qw(setup_sigwarn forkcheck_setup forkcheck_mainprocess
dep14_version_mangle
- debiantags debiantag_old debiantag_new
+ debiantags debiantag_new
debiantag_maintview
upstreamversion
+ upstream_commitish_search resolve_upstream_version
stripepoch source_file_leafname is_orig_file_of_p_v
server_branch server_ref
stat_exists link_ltarget rename_link_xf
@@ -59,7 +60,9 @@ BEGIN {
git_for_each_tag_referring is_fast_fwd
git_check_unmodified
git_reflog_action_msg git_update_ref_cmd
- make_commit_text
+ rm_subdir_cached read_tree_subdir
+ read_tree_debian read_tree_upstream
+ make_commit hash_commit hash_commit_text
reflog_cache_insert reflog_cache_lookup
$package_re $component_re $deliberately_re
$distro_re $versiontag_re $series_filename_re
@@ -233,11 +236,6 @@ sub dep14_version_mangle ($) {
return $v;
}
-sub debiantag_old ($$) {
- my ($v,$distro) = @_;
- return "$distro/". dep14_version_mangle $v;
-}
-
sub debiantag_new ($$) {
my ($v,$distro) = @_;
return "archive/$distro/".dep14_version_mangle $v;
@@ -250,7 +248,7 @@ sub debiantag_maintview ($$) {
sub debiantags ($$) {
my ($version,$distro) = @_;
- map { $_->($version, $distro) } (\&debiantag_new, \&debiantag_old);
+ map { $_->($version, $distro) } (\&debiantag_new, \&debiantag_maintview);
}
sub stripepoch ($) {
@@ -622,6 +620,41 @@ sub git_check_unmodified () {
}
}
+sub upstream_commitish_search ($$) {
+ my ($upstream_version, $tried) = @_;
+ # todo: at some point maybe use git-deborig to do this
+ foreach my $tagpfx ('', 'v', 'upstream/') {
+ my $tag = $tagpfx.(dep14_version_mangle $upstream_version);
+ my $new_upstream = git_get_ref "refs/tags/$tag";
+ push @$tried, $tag;
+ return $new_upstream if length $new_upstream;
+ }
+}
+
+sub resolve_upstream_version ($$) {
+ my ($new_upstream, $upstream_version) = @_;
+
+ my $used = $new_upstream;
+ my $message = __ 'using specified upstream commitish';
+ if (!defined $new_upstream) {
+ my @tried;
+ $new_upstream = upstream_commitish_search $upstream_version, \@tried;
+ if (!length $new_upstream) {
+ fail f_
+ "Could not determine appropriate upstream commitish.\n".
+ " (Tried these tags: %s)\n".
+ " Check version, and specify upstream commitish explicitly.",
+ "@tried";
+ }
+ $used = $tried[-1];
+ $message = f_ 'using upstream from git tag %s', $used;
+ }
+ $new_upstream = git_rev_parse $new_upstream;
+
+ return ($new_upstream, $used, $message);
+ # used is a human-readable idea of what we found
+}
+
sub is_fast_fwd ($$) {
my ($ancestor,$child) = @_;
my @cmd = (qw(git merge-base), $ancestor, $child);
@@ -649,6 +682,39 @@ sub git_update_ref_cmd {
return qw(git update-ref -m), $msg, @_;
}
+sub rm_subdir_cached ($) {
+ my ($subdir) = @_;
+ runcmd qw(git rm --quiet -rf --cached --ignore-unmatch), $subdir;
+}
+
+sub read_tree_subdir ($$) {
+ my ($subdir, $new_tree_object) = @_;
+ # If $new_tree_object is '', the subtree is deleted.
+ confess unless defined $new_tree_object;
+ rm_subdir_cached $subdir;
+ runcmd qw(git read-tree), "--prefix=$subdir/", $new_tree_object
+ if length $new_tree_object;
+}
+
+sub read_tree_debian ($) {
+ my ($treeish) = @_;
+ read_tree_subdir 'debian', "$treeish:debian";
+ rm_subdir_cached 'debian/patches';
+}
+
+sub read_tree_upstream ($;$$) {
+ my ($treeish, $keep_patches, $tree_with_debian) = @_;
+ # if $tree_with_debian is supplied, will use that for debian/
+ # otherwise will save and restore it. If $tree_with_debian
+ # is '' then debian/ is deleted.
+ my $debian =
+ defined $tree_with_debian ? "$tree_with_debian:debian"
+ : cmdoutput qw(git write-tree --prefix=debian/);
+ runcmd qw(git read-tree), $treeish;
+ read_tree_subdir 'debian', $debian;
+ rm_subdir_cached 'debian/patches' unless $keep_patches;
+}
+
sub changedir ($) {
my ($newdir) = @_;
printdebug "CD $newdir\n";
@@ -771,7 +837,21 @@ sub parsechangelog_loop ($$$) {
close CLOGS or $?==SIGPIPE or failedcmd @$clogcmd;
}
-sub make_commit_text ($) {
+sub make_commit ($$) {
+ my ($parents, $message_paras) = @_;
+ my $tree = cmdoutput qw(git write-tree);
+ my @cmd = (qw(git commit-tree), $tree);
+ push @cmd, qw(-p), $_ foreach @$parents;
+ push @cmd, qw(-m), $_ foreach @$message_paras;
+ return cmdoutput @cmd;
+}
+
+sub hash_commit ($) {
+ my ($file) = @_;
+ return cmdoutput qw(git hash-object -w -t commit), $file;
+}
+
+sub hash_commit_text ($) {
my ($text) = @_;
my ($out, $in);
my @cmd = (qw(git hash-object -w -t commit --stdin));
@@ -812,7 +892,7 @@ sub reflog_cache_insert ($$$) {
# git update-ref doesn't always update, in this case. *sigh*
my $authline = (ucfirst _us()).
' <'._us().'@example.com> 1000000000 +0000';
- my $dummy = make_commit_text <<ENDU.(__ <<END);
+ my $dummy = hash_commit_text <<ENDU.(__ <<END);
tree $tree
parent $value
author $authline
diff --git a/debian/tests/control b/debian/tests/control
index 7186da1..2b495ac 100644
--- a/debian/tests/control
+++ b/debian/tests/control
@@ -1,3 +1,7 @@
+Tests: baredebian-multitar baredebian-plusgit baredebian-push baredebian-tarball
+Tests-Directory: tests/tests
+Depends: dgit, dgit-infrastructure, devscripts, debhelper (>=8), fakeroot, build-essential, chiark-utils-bin, bc, faketime, quilt, git-debrebase, git-buildpackage, libdpkg-perl, libgit-wrapper-perl, liblist-compare-perl, libstring-shellquote-perl, libtry-tiny-perl
+
Tests: build-modes-gbp
Tests-Directory: tests/tests
Depends: dgit, dgit-infrastructure, devscripts, debhelper (>=8), fakeroot, build-essential, chiark-utils-bin, bc, faketime, git-buildpackage
@@ -68,7 +72,7 @@ Tests: trustingpolicy-replay
Tests-Directory: tests/tests
Depends: dgit, dgit-infrastructure, devscripts, debhelper (>=8), fakeroot, build-essential, chiark-utils-bin, bc, faketime, dput-ng
-Tests: absurd-gitapply badcommit-rewrite build-modes build-modes-long build-modes-source checkout clone-clogsigpipe clone-gitnosuite clone-nogit debpolicy-dbretry debpolicy-newreject debpolicy-quilt-gbp defdistro-rpush defdistro-setup distropatches-reject dpkgsourceignores-correct drs-clone-nogit drs-push-masterupdate drs-push-rejects dsd-clone-nogit dsd-divert fetch-localgitonly fetch-somegit-notlast gbp-orig gitconfig gitworktree import-dsc import-linkorigs import-maintmangle import-native import-nonnative import-tarbomb inarchivecopy mismatches-contents mismatches-dscchanges multisuite newtag-clone-nogit oldnewtagalt oldtag-clone-nogit orig-include-exclude orig-include-exclude-chkquery overwrite-chkclog overwrite-junk overwrite-splitbrains overwrite-version pbuilder protocol-compat push-buildproductsdir push-newpackage push-newrepeat push-nextdgit push-source push-source-with-changes quilt quilt-gbp quilt-gbp-build-modes quilt-singlepatch quilt-splitbrains quilt-useremail rpush rpush-quilt sourceonlypolicy tag-updates unrepresentable version-opt
+Tests: absurd-gitapply badcommit-rewrite build-modes build-modes-long build-modes-source checkout clone-clogsigpipe clone-gitnosuite clone-nogit debpolicy-dbretry debpolicy-newreject debpolicy-quilt-gbp debpolicy-taintrm defdistro-rpush defdistro-setup distropatches-reject dpkgsourceignores-correct drs-clone-nogit drs-push-masterupdate drs-push-rejects dsd-clone-nogit dsd-divert fetch-localgitonly fetch-somegit-notlast forcesplit-linear forcesplit-overwrite gbp-orig gitconfig gitworktree import-dsc import-linkorigs import-maintmangle import-native import-nonnative import-tarbomb inarchivecopy mismatches-contents mismatches-dscchanges multisuite orig-include-exclude orig-include-exclude-chkquery overwrite-chkclog overwrite-junk overwrite-splitbrains overwrite-version pbuilder protocol-compat push-buildproductsdir push-newpackage push-newrepeat push-nextdgit push-source push-source-with-changes quilt quilt-gbp quilt-gbp-build-modes quilt-singlepatch quilt-splitbrains quilt-useremail rpush rpush-quilt sourceonlypolicy tag-updates unrepresentable version-opt
Tests-Directory: tests/tests
Depends: dgit, dgit-infrastructure, devscripts, debhelper (>=8), fakeroot, build-essential, chiark-utils-bin, bc, faketime
diff --git a/dgit b/dgit
index f1b322a..2d235a6 100755
--- a/dgit
+++ b/dgit
@@ -53,7 +53,7 @@ use Debian::Dgit;
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(4 5); # 5 drops tag format specification
our $protovsn;
our $cmd;
@@ -79,16 +79,19 @@ our $changes_since_version;
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 }
@@ -175,7 +178,31 @@ our $keyid;
autoflush STDOUT 1;
our $supplementary_message = '';
-our $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_splitting)
+#
+# source format sane `3.0 (quilt)'
+# madformat_wantfixup()
+#
+# quilt mode normal quiltmode
+# (eg linear) _splitbrain
+#
+# ------------ ------------------------------------------------
+#
+# no split no q cache no q cache forbidden,
+# brain PM on master q fixup on master prevented
+# !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
+#
+# PM = pseudomerge to make ff, due to overwrite (or split view)
+# "no q cache" = do not record in cache on build, do not check cache
+# `3.0 (quilt)' with --quilt=nocheck is treated as sane format
END {
local ($@, $?);
@@ -193,11 +220,6 @@ if (!defined $absurdity) {
$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"; }
@@ -275,10 +297,12 @@ sub deliberately_not_fast_forward () {
}
}
-sub quiltmode_splitbrain () {
- $quilt_mode =~ m/gbp|dpm|unapplied/;
+sub quiltmode_splitting () {
+ $quilt_mode =~ m/gbp|dpm|unapplied|baredebian/;
}
+sub do_split_brain () { !!($do_split_brain // confess) }
+
sub opts_opt_multi_cmd {
my $extra = shift;
my @cmd;
@@ -424,7 +448,7 @@ sub branch_is_gdr ($) {
# > progress NBYTES
# [NBYTES message]
#
-# > supplementary-message NBYTES # $protovsn >= 3
+# > supplementary-message NBYTES
# [NBYTES message]
#
# main sequence:
@@ -444,7 +468,7 @@ sub branch_is_gdr ($) {
#
# > param head DGIT-VIEW-HEAD
# > param csuite SUITE
-# > param tagformat old|new
+# > param tagformat new # $protovsn == 4
# > param maint-view MAINT-VIEW-HEAD
#
# > param buildinfo-filename P_V_X.buildinfo # zero or more times
@@ -709,7 +733,6 @@ our %defcfg = ('dgit.default.distro' => 'debian',
'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',
@@ -919,6 +942,20 @@ sub access_forpush () {
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;
@@ -936,12 +973,36 @@ sub notpushing () {
parseopts_late_defaults();
}
+sub determine_whether_split_brain () {
+ my ($format,) = get_source_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 (madformat_wantfixup($format) && quiltmode_splitting()) {
+ $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;
+
+ return ($format);
+}
+
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 "$!";
@@ -1643,58 +1704,6 @@ sub archive_query_dummycat ($$) {
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 () {
@@ -2109,11 +2118,6 @@ END
}
}
-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';
@@ -2267,62 +2271,9 @@ sub dotdot_bpd_transfer_origs ($$$) {
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.
@@ -2332,14 +2283,13 @@ sub generate_commits_from_dsc () {
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;
@@ -2351,6 +2301,7 @@ sub generate_commits_from_dsc () {
$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;
@@ -2416,6 +2367,7 @@ sub generate_commits_from_dsc () {
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,
};
@@ -2429,36 +2381,15 @@ sub generate_commits_from_dsc () {
$a->{F} cmp $b->{F}
} @tartrees;
- my $any_orig = grep { $_->{Orig} } @tartrees;
-
- my $dscfn = "$package.dsc";
+ @tartrees;
+}
- my $treeimporthow = 'package';
+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
- 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 $any_orig = grep { $_->{Orig} } @$tartrees;
my @clogcmd = qw(dpkg-parsechangelog --format rfc822 --all);
my $clogp;
@@ -2512,20 +2443,22 @@ sub generate_commits_from_dsc () {
$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
@@ -2545,6 +2478,104 @@ END_T
}
}
+ 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 "$!";
@@ -2564,14 +2595,14 @@ $changes
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
@@ -2664,7 +2695,10 @@ END
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) {
@@ -2945,11 +2979,7 @@ sub git_fetch_us () {
# 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;
@@ -3425,7 +3455,7 @@ END
}
close MC or confess "$!";
- $hash = make_commit $mcf;
+ $hash = hash_commit $mcf;
} else {
$hash = $mergeinputs[0]{Commit};
}
@@ -3786,7 +3816,7 @@ sub fork_for_multisuite ($) {
$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";
}
@@ -4096,6 +4126,7 @@ sub pseudomerge_version_check ($$) {
$cd = $gf->('Distribution');
};
if ($@) {
+ $@ =~ s/^\n//s;
$@ =~ s/^dgit: //gm;
fail "$@".
f_ "Perhaps debian/changelog does not mention %s ?", $v;
@@ -4112,7 +4143,7 @@ END
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...",
@@ -4144,7 +4175,7 @@ $msg_msg
END
close MC or confess "$!";
- return make_commit($pmf);
+ return hash_commit($pmf);
}
sub splitbrain_pseudomerge ($$$$) {
@@ -4202,7 +4233,7 @@ ENDT
}
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
@@ -4226,7 +4257,7 @@ sub plain_overwrite_pseudomerge ($$$) {
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;
@@ -4251,7 +4282,7 @@ sub push_parse_changelog ($) {
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;
}
@@ -4275,7 +4306,7 @@ sub push_tagwants ($$$$) {
my ($cversion, $dgithead, $maintviewhead, $tfbase) = @_;
my @tagwants;
push @tagwants, {
- TagFn => \&debiantag,
+ TagFn => \&debiantag_new,
Objid => $dgithead,
TfSuffix => '',
View => 'dgit',
@@ -4287,14 +4318,7 @@ sub push_tagwants ($$$$) {
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,
@@ -4438,14 +4462,10 @@ Push failed, while preparing your push.
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);
@@ -4465,13 +4485,12 @@ END
push_parse_dsc($dscpath, $dscfn, $cversion);
my $format = getfield $dsc, 'Format';
- printdebug "format $format\n";
my $symref = git_get_symref();
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
@@ -4491,9 +4510,8 @@ END
if (madformat_wantfixup($format)) {
# user might have not used dgit build, so maybe do this now:
- if (quiltmode_splitbrain()) {
+ if (do_split_brain()) {
changedir $playground;
- quilt_make_fake_dsc($upstreamversion);
my $cachekey;
($dgithead, $cachekey) =
quilt_check_splitbrain_cache($actualhead, $upstreamversion);
@@ -4501,17 +4519,22 @@ END
"--quilt=%s but no cached dgit view:
perhaps HEAD changed since dgit build[-source] ?",
$quilt_mode;
- $split_brain = 1;
- $dgithead = splitbrain_pseudomerge($clogp,
- $actualhead, $dgithead,
- $archive_hash);
- $maintviewhead = $actualhead;
- changedir $maindir;
- prep_ud(); # so _only_subdir() works, below
- } else {
+ }
+ 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()) {
+ $made_split_brain = 1;
+ $dgithead = splitbrain_pseudomerge($clogp,
+ $actualhead, $dgithead,
+ $archive_hash);
+ $maintviewhead = $actualhead;
+ changedir $maindir;
+ prep_ud(); # so _only_subdir() works, below
+ }
if (defined $overwrite_version && !defined $maintviewhead
&& $archive_hash) {
@@ -4538,6 +4561,8 @@ END
}
}
+ confess unless !!$made_split_brain == do_split_brain();
+
changedir $playground;
progress f_ "checking that %s corresponds to HEAD", $dscfn;
runcmd qw(dpkg-source -x --),
@@ -4551,7 +4576,7 @@ END
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;
@@ -4652,10 +4677,8 @@ ENDT
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
if (defined $maintviewhead) {
- confess "internal error (protovsn=$protovsn)"
- if defined $protovsn and $protovsn < 4;
responder_send_command("param maint-view $maintviewhead");
}
@@ -4858,10 +4881,11 @@ sub cmd_fetch {
sub cmd_pull {
parseopts();
fetchpullargs();
- if (quiltmode_splitbrain()) {
+ determine_whether_split_brain();
+ 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();
@@ -4951,6 +4975,7 @@ sub prep_push () {
parseopts();
build_or_push_prep_early();
pushing();
+ build_or_push_prep_modes();
check_not_dirty();
my $specsuite;
if (@ARGV==0) {
@@ -5024,10 +5049,6 @@ sub cmd_remote_push_responder { cmd_remote_push_build_host(); }
# a good error message)
sub rpush_handle_protovsn_bothends () {
- if ($protovsn < 4) {
- need_tagformat 'old', "rpush negotiated protocol $protovsn";
- }
- select_tagformat();
}
our $i_tmp;
@@ -5095,7 +5116,6 @@ sub cmd_rpush {
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 {
@@ -5168,11 +5188,6 @@ sub i_resp_want ($) {
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;
-
my @localpaths = i_method "i_want", $keyword;
printdebug "[[ $keyword @localpaths\n";
foreach my $localpath (@localpaths) {
@@ -5242,11 +5257,10 @@ sub i_want_signed_tag {
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$/;
@@ -5374,19 +5388,11 @@ sub quiltify_tree_sentinelfiles ($) {
return $r;
}
-sub quiltify_splitbrain_needed () {
- if (!$split_brain) {
- progress __ "dgit view: changes are required...";
- runcmd @git, qw(checkout -q -b dgit-view);
- $split_brain = 1;
- }
-}
-
-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;
@@ -5401,6 +5407,8 @@ sub quiltify_splitbrain ($$$$$$$) {
local $ENV{GIT_AUTHOR_EMAIL} = $authline[1];
local $ENV{GIT_AUTHOR_DATE} = $authline[2];
+ confess unless do_split_brain();
+
my $fulldiffhint = sub {
my ($x,$y) = @_;
my $cmd = "git diff $x $y -- :/ ':!debian'";
@@ -5409,14 +5417,14 @@ sub quiltify_splitbrain ($$$$$$$) {
$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?";
}
@@ -5429,9 +5437,24 @@ sub quiltify_splitbrain ($$$$$$$) {
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
- quiltify_splitbrain_needed();
progress __ "dgit view: creating patches-applied version using gbp pq";
runcmd shell_cmd 'exec >/dev/null', gbp_pq, qw(import);
# gbp pq import creates a fresh branch; push back to dgit-view
@@ -5448,7 +5471,6 @@ END
}
if (($diffbits->{O2H} & 02) && # user has modified .gitignore
!($diffbits->{O2A} & 02)) { # patches do not change .gitignore
- quiltify_splitbrain_needed();
progress __
"dgit view: creating patch to represent .gitignore changes";
ensuredir "debian/patches";
@@ -5488,16 +5510,6 @@ END
[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 ($$$$) {
@@ -5778,8 +5790,6 @@ sub quiltify ($$$$) {
runcmd @git, qw(checkout -q), $cc, qw(debian/changelog);
}
-
- runcmd @git, qw(checkout -q master);
}
sub build_maybe_quilt_fixup () {
@@ -5789,55 +5799,60 @@ sub build_maybe_quilt_fixup () {
check_for_vendor_patches();
- if (quiltmode_splitbrain) {
- 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
- }
-
my $clogp = parsechangelog();
my $headref = git_rev_parse('HEAD');
my $symref = git_get_symref();
-
- if ($quilt_mode eq 'linear'
- && !$fopts->{'single-debian-patch'}
- && branch_is_gdr($headref)) {
- # This is much faster. It also makes patches that gdr
- # likes better for future updates without laundering.
- #
- # However, it can fail in some casses where we would
- # succeed: if there are existing patches, which correspond
- # to a prefix of the branch, but are not in gbp/gdr
- # format, gdr will fail (exiting status 7), but we might
- # be able to figure out where to start linearising. That
- # will be slower so hopefully there's not much to do.
- my @cmd = (@git_debrebase,
- qw(--noop-ok -funclean-mixed -funclean-ordering
- 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 not ($? == 7*256 or
- $? == -1 && $!==ENOENT);
- } else {
- dryrun_report @cmd;
- }
- $headref = git_rev_parse('HEAD');
- }
+ my $upstreamversion = upstreamversion $version;
prep_ud();
changedir $playground;
- my $upstreamversion = upstreamversion $version;
+ my $splitbrain_cachekey;
+
+ if (do_split_brain()) {
+ my $cachehit;
+ ($cachehit, $splitbrain_cachekey) =
+ quilt_check_splitbrain_cache($headref, $upstreamversion);
+ if ($cachehit) {
+ changedir $maindir;
+ return;
+ }
+ }
+
+ unpack_playtree_need_cd_work($headref);
+ 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.
+ confess if $made_split_brain;
+ $made_split_brain = 1;
+ }
+ chdir '..';
if ($fopts->{'single-debian-patch'}) {
+ fail f_
+ "quilt mode %s does not make sense (or is not supported) with single-debian-patch",
+ $quilt_mode
+ if quiltmode_splitting();
quilt_fixup_singlepatch($clogp, $headref, $upstreamversion);
} else {
- quilt_fixup_multipatch($clogp, $headref, $upstreamversion);
+ 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;
@@ -5845,12 +5860,22 @@ END
@git, qw(pull --ff-only -q), "$playground/work", qw(master);
}
-sub unpack_playtree_mkwork ($) {
+sub build_check_quilt_splitbrain () {
+ build_maybe_quilt_fixup();
+}
+
+sub unpack_playtree_need_cd_work ($) {
my ($headref) = @_;
- mkdir "work" or confess "$!";
- changedir "work";
- mktree_in_ud_here();
+ # prep_ud() must have been called already.
+ if (!chdir "work") {
+ # Check in the filesystem because sometimes we run prep_ud
+ # in between multiple calls to unpack_playtree_need_cd_work.
+ confess "$!" unless $!==ENOENT;
+ mkdir "work" or confess "$!";
+ changedir "work";
+ mktree_in_ud_here();
+ }
runcmd @git, qw(reset -q --hard), $headref;
}
@@ -5899,7 +5924,7 @@ sub quilt_fixup_singlepatch ($$$) {
# necessary to build the source package.
unpack_playtree_linkorigs($upstreamversion, sub { });
- unpack_playtree_mkwork($headref);
+ unpack_playtree_need_cd_work($headref);
rmtree("debian/patches");
@@ -5915,9 +5940,14 @@ sub quilt_fixup_singlepatch ($$$) {
commit_quilty_patch();
}
-sub quilt_make_fake_dsc ($) {
+sub quilt_need_fake_dsc ($) {
+ # cwd should be playground
my ($upstreamversion) = @_;
+ return if stat_exists "fake.dsc";
+ # ^ OK to test this as a sentinel because if we created it
+ # we must either have done the rest too, or crashed.
+
my $fakeversion="$upstreamversion-~~DGITFAKE";
my $fakedsc=new IO::File 'fake.dsc', '>' or confess "$!";
@@ -5961,8 +5991,9 @@ END
sub quilt_fakedsc2unapplied ($$) {
my ($headref, $upstreamversion) = @_;
# must be run in the playground
- # quilt_make_fake_dsc must have been called
+ # quilt_need_fake_dsc must have been called
+ quilt_need_fake_dsc($upstreamversion);
runcmd qw(sh -ec),
'exec dpkg-source --no-check --skip-patches -x fake.dsc >/dev/null';
@@ -5990,6 +6021,8 @@ sub quilt_check_splitbrain_cache ($$) {
# Computes the cache key and looks in the cache.
# Returns ($dgit_view_commitid, $cachekey) or (undef, $cachekey)
+ quilt_need_fake_dsc($upstreamversion);
+
my $splitbrain_cachekey;
progress f_
@@ -6001,6 +6034,7 @@ sub quilt_check_splitbrain_cache ($$) {
push @cachekey, $upstreamversion;
push @cachekey, $quilt_mode;
push @cachekey, $headref;
+ push @cachekey, $quilt_upstream_commitish // '-';
push @cachekey, hashfile('fake.dsc');
@@ -6021,12 +6055,12 @@ sub quilt_check_splitbrain_cache ($$) {
"refs/$splitbraincache", $splitbrain_cachekey;
if ($cachehit) {
- unpack_playtree_mkwork($headref);
+ unpack_playtree_need_cd_work($headref);
my $saved = maybe_split_brain_save $headref, $cachehit, "cache-hit";
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";
@@ -6037,8 +6071,32 @@ sub quilt_check_splitbrain_cache ($$) {
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) = @_;
+ my ($clogp, $headref, $upstreamversion, $splitbrain_cachekey) = @_;
progress f_ "examining quilt state (multiple patches, %s mode)",
$quilt_mode;
@@ -6112,16 +6170,39 @@ sub quilt_fixup_multipatch ($$$) {
# afterwards with dpkg-source --before-build. That lets us save a
# tree object corresponding to .origs.
- my $splitbrain_cachekey;
+ if ($quilt_mode eq 'linear'
+ && branch_is_gdr($headref)) {
+ # This is much faster. It also makes patches that gdr
+ # likes better for future updates without laundering.
+ #
+ # However, it can fail in some casses where we would
+ # succeed: if there are existing patches, which correspond
+ # to a prefix of the branch, but are not in gbp/gdr
+ # format, gdr will fail (exiting status 7), but we might
+ # be able to figure out where to start linearising. That
+ # will be slower so hopefully there's not much to do.
- quilt_make_fake_dsc($upstreamversion);
+ unpack_playtree_need_cd_work $headref;
- if (quiltmode_splitbrain()) {
- my $cachehit;
- ($cachehit, $splitbrain_cachekey) =
- quilt_check_splitbrain_cache($headref, $upstreamversion);
- return if $cachehit;
+ my @cmd = (@git_debrebase,
+ qw(--noop-ok -funclean-mixed -funclean-ordering
+ 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 not ($? == 7*256 or
+ $? == -1 && $!==ENOENT);
+ } else {
+ dryrun_report @cmd;
+ }
+ $headref = git_rev_parse('HEAD');
+
+ chdir '..';
}
+
my $unapplied=quilt_fakedsc2unapplied($headref, $upstreamversion);
ensuredir '.pc';
@@ -6140,7 +6221,7 @@ END
changedir '..';
- unpack_playtree_mkwork($headref);
+ unpack_playtree_need_cd_work($headref);
my $mustdeletepc=0;
if (stat_exists ".pc") {
@@ -6161,15 +6242,97 @@ END
# 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),
};
@@ -6184,13 +6347,23 @@ END
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;
@@ -6200,7 +6373,11 @@ END
}
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})) {
@@ -6215,17 +6392,20 @@ END
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 "$!";
@@ -6260,7 +6440,7 @@ sub quilt_fixup_editor () {
}
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.
@@ -6332,6 +6512,18 @@ sub clean_tree_check () {
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};
@@ -6375,9 +6567,30 @@ sub build_or_push_prep_early () {
$dscfn = dscfn($version);
}
+sub build_or_push_prep_modes () {
+ my ($format,) = determine_whether_split_brain();
+
+ 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"
+ }
+}
+
sub build_prep_early () {
build_or_push_prep_early();
notpushing();
+ build_or_push_prep_modes();
check_not_dirty();
}
@@ -6399,7 +6612,7 @@ sub build_prep ($) {
# said -wc we should still do the check.
clean_tree_check();
}
- build_maybe_quilt_fixup();
+ build_check_quilt_splitbrain();
if ($rmchanges) {
my $pat = changespat $version;
foreach my $f (glob "$buildproductsdir/$pat") {
@@ -6688,7 +6901,7 @@ sub building_source_in_playtree {
#
# 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;
}
@@ -6699,6 +6912,8 @@ sub build_source {
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()) {
@@ -6707,12 +6922,12 @@ sub build_source {
# 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_mkwork($headref);
+ unpack_playtree_need_cd_work($headref);
changedir '..';
}
} else {
@@ -6779,7 +6994,7 @@ sub cmd_push_source {
"dgit push-source: --include-dirty/--ignore-dirty does not make".
"sense with push-source!"
if $includedirty;
- build_maybe_quilt_fixup();
+ build_check_quilt_splitbrain();
if ($changesfile) {
my $changes = parsecontrol("$buildproductsdir/$changesfile",
__ "source changes file");
@@ -6878,7 +7093,6 @@ sub cmd_print_unapplied_treeish {
prep_ud();
changedir $playground;
my $uv = upstreamversion $version;
- quilt_make_fake_dsc($uv);
my $u = quilt_fakedsc2unapplied($headref, $uv);
print $u, "\n" or confess "$!";
}
@@ -7070,7 +7284,7 @@ END
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
@@ -7302,7 +7516,7 @@ sub parseopts () {
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) {
@@ -7320,16 +7534,25 @@ sub parseopts () {
} 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;
@@ -7348,11 +7571,6 @@ sub parseopts () {
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, $_;
@@ -7498,6 +7716,7 @@ sub parseopts_late_defaults () {
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;
@@ -7510,19 +7729,10 @@ sub parseopts_late_defaults () {
$$vr = $v;
}
- fail __ "dgit: --include-dirty is not supported in split view quilt mode"
- if $split_brain && $includedirty;
-
- 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');
diff --git a/dgit-maint-debrebase.7.pod b/dgit-maint-debrebase.7.pod
index b91ed16..9c9598b 100644
--- a/dgit-maint-debrebase.7.pod
+++ b/dgit-maint-debrebase.7.pod
@@ -134,6 +134,32 @@ using git-diff(1) to compare the imported tarball to the release tag.
=back
+=head3 Using untagged upstream commits
+
+=over 4
+
+Sometimes upstream does not tag their releases, or you want to package
+an unreleased git snapshot. In such a case you can create your own
+upstream release tag, of the form B<upstream/>I<ver>, where I<ver> is
+the upstream version you plan to put in I<debian/changelog>. The
+B<upstream/> prefix ensures that your tag will not clash with any tags
+upstream later creates.
+
+For example, suppose that the latest upstream release is 1.2.2 and you
+want to package git commit ab34c21 which was made on 2013-12-11. A
+common convention is to use the upstream version number
+1.2.2+git20131211.ab34c21 and so you could use
+
+=over 4
+
+ % git tag -s upstream/1.2.2+git20131211.ab34c21 ab34c21
+
+=back
+
+to obtain a release tag, and then proceed as above.
+
+=back
+
=head2 When upstream releases only tarballs
Because we want to work in git, we need a virtual upstream branch with
@@ -331,6 +357,10 @@ release, and importing that release using git-debrebase(1).
=back
+If you want to package an untagged upstream commit (because upstream
+does not tag releases or because you want to package an upstream
+development snapshot), see "Using untagged upstream commits" above.
+
=head3 When upstream releases only tarballs
You will need the I<debian/gbp.conf> from "When upstream releases only
@@ -375,9 +405,10 @@ release:
=back
-Pass I<--stat> just to see the list of changed files, which is useful
-to determine whether there are any new or deleted files that may need
-accounting for in your copyright file.
+Also, diff with I<--name-status> and I<--diff-filter=ADR> to see
+just the list of added or removed files, which is useful to determine
+whether there are any new or deleted files that may need accounting
+for in your copyright file.
If you obtained a tarball from upstream, you are ready to try a build.
If you merged a git tag from upstream, you will first need to generate
diff --git a/dgit-maint-merge.7.pod b/dgit-maint-merge.7.pod
index c20a252..0ccd8c7 100644
--- a/dgit-maint-merge.7.pod
+++ b/dgit-maint-merge.7.pod
@@ -120,6 +120,32 @@ upstream's tarball instead of running git-deborig(1).
=back
+=head3 Using untagged upstream commits
+
+=over 4
+
+Sometimes upstream does not tag their releases, or you want to package
+an unreleased git snapshot. In such a case you can create your own
+upstream release tag, of the form B<upstream/>I<ver>, where I<ver> is
+the upstream version you plan to put in I<debian/changelog>. The
+B<upstream/> prefix ensures that your tag will not clash with any tags
+upstream later creates.
+
+For example, suppose that the latest upstream release is 1.2.2 and you
+want to package git commit ab34c21 which was made on 2013-12-11. A
+common convention is to use the upstream version number
+1.2.2+git20131211.ab34c21 and so you could use
+
+=over 4
+
+ % git tag -s upstream/1.2.2+git20131211.ab34c21 ab34c21
+
+=back
+
+to obtain a release tag, and then proceed as above.
+
+=back
+
=head2 When upstream releases only tarballs
We need a virtual upstream branch with virtual release tags.
@@ -340,6 +366,10 @@ to git), you can just run dpkg-buildpackage(1) or debuild(1) instead.
=back
+If you want to package an untagged upstream commit (because upstream
+does not tag releases or because you want to package an upstream
+development snapshot), see "Using untagged upstream commits" above.
+
=head3 When upstream releases only tarballs
You will need the I<debian/gbp.conf> from "When upstream releases only
@@ -371,7 +401,7 @@ accounting for in your copyright file:
=over 4
- % git diff --stat master..1.2.3 -- . ':!debian'
+ % git diff --name-status --diff-filter=ADR master..1.2.3 -- . ':!debian'
=back
diff --git a/dgit.1 b/dgit.1
index 682562c..6e0c4f1 100644
--- a/dgit.1
+++ b/dgit.1
@@ -642,6 +642,18 @@ include the changes from your working tree.
This can be useful with build, if you plan to commit later. (dgit
push will still ensure that the .dsc you upload and the git tree
you push are identical, so this option won't make broken pushes.)
+
+Note that this does
+.BR not
+prevent dgit from cleaning your tree, so if the changes in your
+working tree are in the form of untracked files, those might still be
+deleted, especially with --clean=git.
+If you want to include untracked files in the build, you can
+use --clean=none or --clean=dpkg-source[-d]
+in addition to --include-dirty.
+Note that this
+combination can fail if the untracked files are under
+\fIdebian/patches/\fR.
.TP
.BR --ignore-dirty
Deprecated alias for --include-dirty.
@@ -695,7 +707,7 @@ of git merge -s ours) to stitch the archive's version into your own
git history, so that your push is a fast forward from the archive.
(In quilt mode
-.BR gbp ", " dpm " or " unpatched ,
+.BR gbp ", " dpm ", " unpatched " or " baredebian *,
implying a split between the dgit view and the
maintainer view, the pseudo-merge will appear only in the dgit view.)
.TP
@@ -742,7 +754,7 @@ it can mean that
dgit fails to find necessary git commits.
.TP
.BR \-\-save-dgit-view= \fIbranch\fR|\fIref\fR
-Specifies that when a split view quilt mode is in operation,
+Specifies that when split view is in operation,
and dgit calculates
(or looks up in its cache)
a dgit view corresponding to your HEAD,
@@ -753,10 +765,7 @@ so don't specify a branch you want to keep.
This option is effective only with the following operations:
quilt-fixup; push; all builds.
-And it is only effective with
-\-\-[quilt=]gbp,
-\-\-[quilt=]dpm,
-\-\-quilt=unpatched.
+And it is only effective when split view is actually in operation.
If ref does not start with refs/
it is taken to be a branch -
@@ -786,7 +795,7 @@ Debian, use this when you are making a renewed upload of an entirely
new source package whose previous version was not accepted for release
from NEW because of problems with copyright or redistributibility.
-In split view quilt modes,
+When split view is in operation,
this also prevents the construction by dgit of a pseudomerge
to make the dgit view fast forwarding.
Normally only one of
@@ -856,13 +865,17 @@ Do not check whether source format `3.0 (quilt)' metadata needs
fixing up. If you use this option and the metadata did in fact need
fixing up, dgit push will fail.
.TP
-.BR -- [ quilt= ] gbp " | " -- [ quilt= ] dpm " | " --quilt=unapplied
+.BR -- [ quilt= ] gbp " | " -- [ quilt= ] dpm " | " --quilt=unapplied " | " -- [ quilt= ] baredebian [ +git | +tarball ]
Tell dgit that you are using a nearly-dgit-compatible git branch,
aka a
.BR "maintainer view" ,
and
do not want your branch changed by dgit.
+These quilt modes are known as
+.BR "splitting quilt modes" .
+See --split-view, below.
+
.B --gbp
(short for
.BR --quilt=gbp )
@@ -884,7 +897,32 @@ specifies that your HEAD is a patches-unapplied git branch (and
that any changes to upstream .gitignore files are represented as
patches in debian/patches).
-With --quilt=gbp|dpm|unapplied,
+.B --quilt=baredebian
+(or its alias
+.BR --quilt=baredebian+git )
+specifies that your HEAD contains only a debian/ directory,
+with any changes to upstream files represented as
+patches in debian/patches.
+The upstream source must be available in git,
+by default, in a suitably named git tag;
+see --upstream-commitish.
+In this mode, dgit cannot check that
+all edited upstream files are properly represented as patches:
+dgit relies on
+debian/patches being correct.
+
+.B --quilt=baredebian+tarball
+is like --quilt=baredebian,
+but is used when there is no appropriate upstream git history.
+To construct the dgit view,
+dgit will import your orig tarballs' contents into git.
+In this mode, dgit cannot check that
+the upstream parts of your upload correspond to what you intend:
+dgit relies on
+the right orig tarball(s) existing, and
+debian/patches being correct.
+
+With --quilt=gbp|dpm|unapplied|baredebian*,
dgit push (or precursors like quilt-fixup and build) will automatically
generate a conversion of your git branch into the right form.
dgit push will push the
@@ -931,6 +969,42 @@ for fetching (and, for dgit push, altering) a variety of information both
in the archive and in dgit-repos.
How to set this up is not yet documented.
.TP
+.BR \-\-split-view=auto | always | never
+Controls whether dgit operates a split view,
+separating your own branch (as Debian maintainer)
+from that shown to users of dgit clone and dgit fetch.
+
+When split view is in operation
+dgit will not make or merge any commits onto your own branch.
+Specifically, only the dgit view will contain
+dgit's pseudomerges,
+which bring into the git history previous uploads made with dgit push,
+and any commits in debian/patches required
+to make a correct `3.0 (quilt)' source package.
+
+.B auto
+is the default, and splits the view only when needed:
+i.e., when you are working with a `3.0 (quilt)' source package
+and a splitting quilt mode:
+\-\-[quilt=]gbp, dpm, unpatched or baredebian*.
+
+.B always
+splits the view regardless of the source format and the quilt mode.
+
+.B never
+will cause dgit to fail if split view is needed.
+
+When split view is in operation, the dgit view is visible
+in your local git clone,
+but only in refs specific to dgit:
+notably
+.BI remotes/dgit/dgit/ suite
+and
+.BR archive/ \fIdistro\fR / \fIversion\fR.
+
+Note that split view does not affect dgit fetch,
+and is not compatible with dgit pull.
+.TP
.BI \-C changesfile
Specifies the .changes file which is to be uploaded. By default
dgit push looks for a single .changes file in the parent directory whose
@@ -945,6 +1019,14 @@ otherwise, the changes file is expected in that directory (by
default, in
.BR .. ).
.TP
+.BI \-\-upstream-commitish= upstream
+For use with --quilt=baredebian only.
+Specifies the commit containing the upstream source.
+This commit must be identical to your .orig tarball.
+The default is to look for one of the git tags
+.IB U " v" U " upstream/" U
+(in that order), where U is the upstream version.
+.TP
.B \-\-rm-old-changes
When doing a build, delete any changes files matching
.IB package _ version _*.changes
@@ -983,19 +1065,14 @@ Do not delete the destination directory if clone fails.
Generates a DEP-14 tag (eg
.BR debian/ \fIversion\fR)
as well as a dgit tag (eg
-.BR archive/debian/ \fIversion\fR)
-where possible. This is the default.
+.BR archive/debian/ \fIversion\fR).
+This is the default.
.TP
.BI --no-dep14tag
-Do not generate a DEP-14 tag, except in split quilt view mode.
-(On servers where only the old tag format is supported,
-the dgit tag will have the DEP-14 name.
-This option does not prevent that.)
+Do not generate a DEP-14 tag, except when split view is in operation.
.TP
-.BI --dep14tag-always
-Insist on generating a DEP-14 tag
-as well as a dgit tag.
-If the server does not support that, dgit push will fail.
+.BI --always-dep14tag
+Obsolete alias for --dep14tag, retained for compatibility.
.TP
.BI -D
Prints debugging information to stderr. Repeating the option produces
@@ -1298,6 +1375,8 @@ to provide a single git config compatible with different dgit versions.
One of the values for the command line \-\-quilt= option; used if
\-\-quilt is not specified.
.TP
+.BR dgit-distro. \fIdistro\fR .split-view
+.TP
.BR dgit-distro. \fIdistro\fR .rm-old-changes
Boolean, used if neither \-\-rm-old-changes nor \-\-no-rm-old-changes
is specified. The default is not to remove.
@@ -1402,7 +1481,7 @@ or when pushing and
.TP
.BI dgit-distro. distro .dgit-tag-format
.TP
-.BR dgit-distro. \fIdistro\fR .dep14tag " " want | no | always
+.BR dgit-distro. \fIdistro\fR .dep14tag " " want | no [| always ]
.TP
.BI dgit-distro. distro .ssh
.TP
diff --git a/dgit.7 b/dgit.7
index 8325c06..d1e5c7e 100644
--- a/dgit.7
+++ b/dgit.7
@@ -393,7 +393,7 @@ this problem can occur if you have provided
Debian git tooling such as git-debrebase, git-dpm or git-buildpackage
with upstream git commit(s) or tag(s)
which are not 100% identical to your orig tarball(s).
-.SH SPLIT VIEW QUILT MODE
+.SH SPLIT VIEW AND SPLITTING QUILT MODES
When working with git branches intended
for use with the `3.0 (quilt)' source format
dgit can automatically convert a suitable
@@ -401,21 +401,33 @@ maintainer-provided git branch
(in one of a variety of formats)
into a dgit branch.
-When a split view mode is engaged
+When a splitting quilt mode is selected
dgit build commands and
dgit push
will, on each invocation,
convert the user's HEAD into the dgit view,
so that it can be built and/or uploaded.
-dgit push in split view mode will push the dgit view to the dgit
+Split view mode can also be enabled explicitly
+with
+the --split-view command line option
+and
+the .split-view access configuration key.
+
+When split view is in operation,
+regardless of the quilt mode,
+any dgit-generated pseudomerges
+and any quilt fixup commits
+will appear only in the dgit view.
+dgit push
+will push the dgit view to the dgit
git server.
The dgit view is always a descendant of the maintainer view.
dgit push will also make a maintainer view tag
according to DEP-14
and push that to the dgit git server.
-Split view mode must be enabled explicitly
+Splitting quilt modes must be enabled explicitly
(by the use of the applicable command line options,
subcommands, or configuration).
This is because it is not possible to reliably tell
diff --git a/git-debrebase b/git-debrebase
index 71bf39d..01429fb 100755
--- a/git-debrebase
+++ b/git-debrebase
@@ -355,44 +355,6 @@ sub calculate_committer_authline () {
return $&;
}
-sub rm_subdir_cached ($) {
- my ($subdir) = @_;
- runcmd @git, qw(rm --quiet -rf --cached --ignore-unmatch), $subdir;
-}
-
-sub read_tree_subdir ($$) {
- my ($subdir, $new_tree_object) = @_;
- rm_subdir_cached $subdir;
- runcmd @git, qw(read-tree), "--prefix=$subdir/", $new_tree_object;
-}
-
-sub read_tree_debian ($) {
- my ($treeish) = @_;
- read_tree_subdir 'debian', "$treeish:debian";
- rm_subdir_cached 'debian/patches';
-}
-
-sub read_tree_upstream ($;$$) {
- my ($treeish, $keep_patches, $tree_with_debian) = @_;
- # if $tree_with_debian is supplied, will use that for debian/
- # otherwise will save and restore it.
- my $debian =
- $tree_with_debian ? "$tree_with_debian:debian"
- : cmdoutput @git, qw(write-tree --prefix=debian/);
- runcmd @git, qw(read-tree), $treeish;
- read_tree_subdir 'debian', $debian;
- rm_subdir_cached 'debian/patches' unless $keep_patches;
-};
-
-sub make_commit ($$) {
- my ($parents, $message_paras) = @_;
- my $tree = cmdoutput @git, qw(write-tree);
- my @cmd = (@git, qw(commit-tree), $tree);
- push @cmd, qw(-p), $_ foreach @$parents;
- push @cmd, qw(-m), $_ foreach @$message_paras;
- return cmdoutput @cmd;
-}
-
our @snag_force_opts;
sub snag ($$;@) {
my ($tag,$msg) = @_; # ignores extra args, for benefit of keycommits
@@ -768,7 +730,7 @@ sub merge_series_patchqueue_convert ($$$) {
open C, ">", "../mcommit" or confess "$!";
print C $commit or confess "$!";
close C or confess "$!";
- $build = cmdoutput @git, qw(hash-object -w -t commit ../mcommit);
+ $build = hash_commit '../mcommit';
}
$result = $build;
mwrecknote($wrecknotes, 'merged-result', $result);
@@ -1994,39 +1956,6 @@ sub do_stitch ($;$) {
stitch($dangling_head, $ffq_prev, $gdrlast, $ffq_prev_commitish, $prose);
}
-sub upstream_commitish_search ($$) {
- my ($upstream_version, $tried) = @_;
- # todo: at some point maybe use git-deborig to do this
- foreach my $tagpfx ('', 'v', 'upstream/') {
- my $tag = $tagpfx.(dep14_version_mangle $upstream_version);
- my $new_upstream = git_get_ref "refs/tags/$tag";
- push @$tried, $tag;
- return $new_upstream if length $new_upstream;
- }
-}
-
-sub resolve_upstream_version ($$) {
- my ($new_upstream, $upstream_version) = @_;
-
- my $used = $new_upstream;
- if (!defined $new_upstream) {
- my @tried;
- $new_upstream = upstream_commitish_search $upstream_version, \@tried;
- if (!length $new_upstream) {
- fail f_
- "Could not determine appropriate upstream commitish.\n".
- " (Tried these tags: %s)\n".
- " Check version, and specify upstream commitish explicitly.",
- "@tried";
- }
- $used = $tried[-1];
- }
- $new_upstream = git_rev_parse $new_upstream;
-
- return ($new_upstream, $used);
- # used is a human-readable idea of what we found
-}
-
sub cmd_new_upstream () {
# automatically and unconditionally launders before rebasing
# if rebase --abort is used, laundering has still been done
@@ -2733,7 +2662,7 @@ sub cmd_convert_from_dgit_view () {
my $spec = shift @ARGV;
my $commit = git_rev_parse "$spec^{commit}";
push @upstreams, { Commit => $commit,
- Source => (f_ "%s, from command line", $ARGV[0]),
+ Source => (f_ "%s, from command line", $spec),
Only => 1,
};
}
diff --git a/git-debrebase.1.pod b/git-debrebase.1.pod
index cbdf292..af6e364 100644
--- a/git-debrebase.1.pod
+++ b/git-debrebase.1.pod
@@ -531,7 +531,7 @@ This is provided mostly for the benefit of the test suite.
Requests (more) debugging. May be repeated.
-=item --experimntal-merge-resolution
+=item --experimental-merge-resolution
Enable experimental code for handling general merges
(see L<git-debrebase(5)/General merges>).
diff --git a/infra/dgit-repos-policy-debian b/infra/dgit-repos-policy-debian
index f7e5e53..bc370d2 100755
--- a/infra/dgit-repos-policy-debian
+++ b/infra/dgit-repos-policy-debian
@@ -546,6 +546,7 @@ for (;;) {
die unless defined $rcode;
$poldbh->commit;
+ printdebug "poldbh commit\n";
};
last unless length $@;
die $@ unless ref $@ eq $db_busy_exception;
diff --git a/infra/dgit-repos-server b/infra/dgit-repos-server
index a8b9400..7c7262f 100755
--- a/infra/dgit-repos-server
+++ b/infra/dgit-repos-server
@@ -539,15 +539,12 @@ sub readupdates () {
STDIN->error and die $!;
reject "push is missing tag ref update" unless %tags;
- my @newtags = grep { m#^archive/# } keys %tags;
- my @omtags = grep { !m#^archive/# } keys %tags;
- reject "pushing too many similar tags" if @newtags>1 || @omtags>1;
- if (@newtags) {
- ($tagname) = @newtags;
- ($maint_tagname) = @omtags;
- } else {
- ($tagname) = @omtags or die;
- }
+ my @dtags = grep { m#^archive/# } keys %tags;
+ reject "need exactly one archive/* tag" if @dtags!=1;
+ my @mtags = grep { !m#^archive/# } keys %tags;
+ reject "pushing too many non-dgit tags" if @mtags>1;
+ ($tagname) = @dtags;
+ ($maint_tagname) = @mtags;
$tagval = $tags{$tagname};
$maint_tagval = $tags{$maint_tagname // ''};
@@ -862,8 +859,7 @@ sub checks () {
grep { $tagname eq $_ } @expecttagnames or die;
foreach my $othertag (grep { $_ ne $tagname } @expecttagnames) {
- reject "tag $othertag (pushed with differing dgit version)".
- " already exists -".
+ reject "tag $othertag already exists -".
" not replacing previously-pushed version"
if git_get_ref "refs/tags/".$othertag;
}
diff --git a/tests/enumerate-tests b/tests/enumerate-tests
index a532b52..8ee34be 100755
--- a/tests/enumerate-tests
+++ b/tests/enumerate-tests
@@ -52,6 +52,9 @@ restriction-gencontrol () {
gencontrol-add-deps () {
for dep in "$@"; do
+ case " $dependencies," in
+ *" "$dep","*) continue ;;
+ esac
dependencies+="${dependencies:+, }$dep"
done
}
@@ -64,6 +67,13 @@ dependencies-gencontrol () {
GDR) gencontrol-add-deps \
git-debrebase git-buildpackage
;;
+ DEBORIG) gencontrol-add-deps \
+ devscripts libdpkg-perl \
+ libgit-wrapper-perl liblist-compare-perl \
+ libstring-shellquote-perl libtry-tiny-perl \
+ # NB git-deborig is not compatible with
+ # t-tstunt-parsechangelog
+ ;;
*) gencontrol-add-deps "$dep" ;;
esac
done
@@ -104,21 +114,29 @@ finish-gencontrol () {
seddery () {
local seddery=$1
- sed <$t -n '
+ sed <$tf -n '
20q;
/^: t-enumerate-tests-end$/q;
'"$seddery"'
'
}
-for t in $(run-parts --list tests/tests); do
- test-begin-$mode
+allsedderies () {
+ local tf=$1
for r in $(seddery 's/^t-restrict //p'); do
restriction-$mode
done
for deps in $(seddery 's/^t-dependencies //p'); do
dependencies-$mode
done
+ for import in $(seddery 's/^t-setup-import //p'); do
+ allsedderies tests/setup/$import
+ done
+}
+
+for t in $(run-parts --list tests/tests); do
+ test-begin-$mode
+ allsedderies $t
test-done-$mode
done
diff --git a/tests/lib b/tests/lib
index fa553af..28b08e6 100644
--- a/tests/lib
+++ b/tests/lib
@@ -520,6 +520,14 @@ t-setup-done () {
' $vn "$(eval "printf '%s\n' \"\$$vn\"")"
done
+ perl >&4 -"I$root" -MDebian::Dgit -we '
+ foreach my $vn (grep m/^DGIT_TEST_REAL_/, keys %ENV) {
+ print STDERR "saving-exporting $vn\n";
+ printf "export %s=%s\n", $vn, shellquote $ENV{$vn}
+ or die $!;
+ }
+ '
+
(set -e; cd $tmp; tar cf $import.tar $savedirs)
printf >&4 "\n%s\n" "$importeval"
@@ -736,6 +744,7 @@ t-splitbrain-pushed-good--unpack () {
ln -s $tmp/incoming/*.orig*.tar* . ||:
ln -s $incoming_dsc .
ln -s ${incoming_dsc/.dsc/.debian.tar}* .
+ ln -s ${incoming_dsc/.dsc/.tar}* . ||:
dpkg-source "$@" -x *.dsc
cd */.
git init
@@ -782,16 +791,21 @@ t-splitbrain-pushed-good-end-made-dep14 () {
cd $tmp/$p
}
-t-splitbrain-rm-gitignore-patch () {
+t-splitbrain-rm-1-patch () {
+ local patchname=$1
perl -i -pe '
- next unless $_ eq "auto-gitignore\n";
+ next unless $_ eq "'"$patchname"'\n";
die if $counter++;
chomp;
- rename "debian/patches/$_", "../t-auto-gitignore" or die $!;
+ rename "debian/patches/$_", "../t-'"$patchname"'" or die $!;
$_ = "";
' debian/patches/series
}
+t-splitbrain-rm-gitignore-patch () {
+ t-splitbrain-rm-1-patch auto-gitignore
+}
+
t-gbp-pushed-good () {
local suite=${1:-sid}
t-splitbrain-pushed-good-start
@@ -826,18 +840,27 @@ t-gbp-pushed-good () {
}
t-unapplied-pushed-good () {
+ local suite=${1:-sid}
t-splitbrain-pushed-good-start
t-splitbrain-pushed-good--unpack --skip-patches
t-splitbrain-pushed-good-end-made-dep14
}
t-dpm-pushed-good () {
+ local suite=${1:-sid}
t-splitbrain-pushed-good-start
t-splitbrain-pushed-good--unpack
t-splitbrain-rm-gitignore-patch
t-splitbrain-pushed-good-end-made-dep14
}
+t-split-unchanged-pushed-good () {
+ local suite=${1:-sid}
+ t-splitbrain-pushed-good-start
+ t-splitbrain-pushed-good--unpack
+ t-splitbrain-pushed-good-end-made-dep14
+}
+
t-commit-build-push-expect-log () {
local msg=$1
local mpat=$2
@@ -1092,7 +1115,6 @@ t-drs () {
t-git-config dgit-distro.test-dummy.git-url "ext::$troot/drs-git-ext %S "
t-git-config dgit-distro.test-dummy.git-check true
t-git-config dgit-distro.test-dummy.git-create true
- t-git-config dgit-distro.test-dummy.dgit-tag-format new,old,maint
cp $troot/gnupg/{dd.gpg,dm.gpg,dm.txt} $tmp/.
cp $troot/suites $tmp/.
cp $troot/suites $tmp/suites-master
@@ -1114,15 +1136,6 @@ t-drs () {
ln -sf /bin/true $drs_dispatch/policy-hook
}
-t-newtag () {
- export tagpfx=archive/test-dummy
- t-git-config dgit-distro.test-dummy.dgit-tag-format new,maint
-}
-t-oldtag () {
- export tagpfx=test-dummy
- t-git-config dgit-distro.test-dummy.dgit-tag-format old
-}
-
t-dsd () {
t-drs
t-git-config dgit-distro.test-dummy.ssh "$troot/dsd-ssh"
diff --git a/tests/lib-baredebian b/tests/lib-baredebian
new file mode 100644
index 0000000..3ef6569
--- /dev/null
+++ b/tests/lib-baredebian
@@ -0,0 +1,93 @@
+#
+
+baredebian-test-vars () {
+ quiltmode=baredebian
+ v=1.0-1
+ suite=sid
+ uv=${v%-*}
+ uvtag=v$uv
+ origbase=${p}_${uv}.orig
+ xorigcomps=''
+}
+
+baredebian-tarball-mode () {
+ git tag -d $uvtag
+ uvtag=''
+ quiltmode=baredebian+tarball
+}
+
+baredebian-test-minimum () {
+ t-expect-fail 'contradicts clean mode git-ff' \
+ t-dgit -wgf --dgit-view-save=split.f1 --$quiltmode quilt-fixup
+
+ t-dgit -wn --dgit-view-save=split.f1 --$quiltmode quilt-fixup
+}
+
+baredebian-test-core () {
+ tar --strip-components=1 -axf ../$origbase.tar.*
+ for comp in $xorigcomps; do
+ mkdir $comp
+ cd $comp
+ tar --strip-components=1 -axf ../../$origbase-$comp.tar.*
+ cd ..
+ done
+
+ cd debian
+ git clean -xdff
+ git checkout HEAD -- .
+ cd ..
+
+ # Now we are in this insane state that people seem to expect
+
+ export QUILT_PATCHES=debian/patches
+ quilt push -a
+
+ git add -Af .
+ git reset .pc
+ git diff --cached --exit-code split.f1 -- :/ :!/debian
+ git diff --exit-code HEAD..split.f1 -- :/debian
+ git reset
+
+ quilt new made-with-quilt
+ quilt add src.c
+ echo //omg >>src.c
+ quilt refresh
+
+ git add debian/patches/.
+ t-commit 'extra patch made with quilt' 1.0-2
+
+ dpkg-buildpackage -uc -us --build=source
+ # ^ Do this by hand here not because we expect users to do this
+ # (rather than dgit build), but so that we can check that our
+ # output is the same as users are used to.
+
+ t-dgit -wn --quilt=$quiltmode --dgit-view-save=split.b quilt-fixup
+ t-dgit -wn --quilt=$quiltmode --dgit-view-save=split.p --new push
+
+ git merge-base --is-ancestor HEAD split.p
+ if [ "$uvtag" ]; then
+ git merge-base --is-ancestor $uvtag split.p
+ set +e; git merge-base HEAD $uvtag; rc=$?; set -e; [ $rc = 1 ]
+ fi
+
+ git clean -xdff
+ # t-pushed-good-* wants a clean tree to start with, but this
+ # workflow expects a mess
+
+ t-splitbrain-pushed-good-start
+ t-splitbrain-pushed-good--unpack
+
+ find . -mindepth 1 -maxdepth 1 \
+ \! -path ./debian \
+ \! -path ./.git \
+ -print0 \
+ | xargs -0r rm -rf --
+
+ t-splitbrain-pushed-good-end-made-dep14
+}
+
+baredebian-test () {
+ baredebian-test-vars
+ baredebian-test-minimum
+ baredebian-test-core
+}
diff --git a/tests/setup/baredebian b/tests/setup/baredebian
new file mode 100755
index 0000000..bbd901f
--- /dev/null
+++ b/tests/setup/baredebian
@@ -0,0 +1,34 @@
+#!/bin/bash
+set -e
+. tests/lib
+. $troot/lib-gdr
+
+t-dependencies GDR DEBORIG quilt
+
+t-archive-none example
+t-git-none
+
+t-gdr-gbp-import-core-with-queue
+
+git-deborig
+
+for b in \
+ patch-queue/quilt-tip \
+ gitish-only \
+ quilt-tip-1.1 \
+ quilt-tip-2 \
+ indep-arch \
+; do
+ git branch -D $b
+done
+
+git rm -rf . # yikes
+git checkout HEAD -- debian
+t=$(git write-tree)
+t=$(git commit-tree -m 'Convert to bare debian' $t)
+git reset --hard $t
+
+t-setup-done '' "$(echo $p*) git mirror aq" '
+ t-select-package example
+ t-git-next-date
+'
diff --git a/tests/tests/baredebian-multitar b/tests/tests/baredebian-multitar
new file mode 100755
index 0000000..39b6668
--- /dev/null
+++ b/tests/tests/baredebian-multitar
@@ -0,0 +1,46 @@
+#!/bin/bash
+set -e
+. tests/lib
+. $troot/lib-baredebian
+
+t-dependencies quilt
+
+t-setup-import baredebian
+t-tstunt-parsechangelog
+
+cd $p
+baredebian-test-vars
+baredebian-tarball-mode
+
+rm -f ../example_1.0.orig.tar.*
+cp $troot/pkg-srcs/${p}_${uv}.orig*.tar.* ..
+xorigcomps=docs
+
+git tag -d $uvtag
+
+baredebian-test-minimum
+baredebian-test-core
+
+combine=$(
+ git log --pretty=format:%H \
+ --grep "Combine orig tarballs for example $uv" split.p
+)
+
+parentnum=0
+for comp in '' $xorigcomps; do
+ parentnum=$(( $parentnum + 1 ))
+ fn=${origbase}${comp:+-}${comp}.tar.gz
+
+ git checkout --orphan imp$parentnum
+ git rm -rf .
+ tar --strip-components=1 -axf ../$fn
+ git add -Af .
+
+ git commit -m P$parentnum
+ git diff --stat --exit-code $combine^$parentnum
+
+ count=$(git log $combine^$parentnum | grep -Fc $fn)
+ [ $count = 2 ]
+done
+
+t-ok
diff --git a/tests/tests/baredebian-plusgit b/tests/tests/baredebian-plusgit
new file mode 100755
index 0000000..5c53fdd
--- /dev/null
+++ b/tests/tests/baredebian-plusgit
@@ -0,0 +1,17 @@
+#!/bin/bash
+set -e
+. tests/lib
+. $troot/lib-baredebian
+
+t-dependencies quilt
+
+t-setup-import baredebian
+t-tstunt-parsechangelog
+
+cd $p
+baredebian-test-vars
+quiltmode=baredebian+git
+
+baredebian-test-minimum
+
+t-ok
diff --git a/tests/tests/baredebian-push b/tests/tests/baredebian-push
new file mode 100755
index 0000000..f095601
--- /dev/null
+++ b/tests/tests/baredebian-push
@@ -0,0 +1,14 @@
+#!/bin/bash
+set -e
+. tests/lib
+. $troot/lib-baredebian
+
+t-dependencies quilt
+
+t-setup-import baredebian
+t-tstunt-parsechangelog
+
+cd $p
+baredebian-test
+
+t-ok
diff --git a/tests/tests/baredebian-tarball b/tests/tests/baredebian-tarball
new file mode 100755
index 0000000..00b2ad2
--- /dev/null
+++ b/tests/tests/baredebian-tarball
@@ -0,0 +1,21 @@
+#!/bin/bash
+set -e
+. tests/lib
+. $troot/lib-baredebian
+
+t-dependencies quilt
+
+t-setup-import baredebian
+t-tstunt-parsechangelog
+
+cd $p
+baredebian-test-vars
+baredebian-tarball-mode
+
+t-expect-fail 'Could not determine appropriate upstream commitish' \
+t-dgit -wn --dgit-view-save=split.g --baredebian quilt-fixup
+
+baredebian-test-minimum
+baredebian-test-core
+
+t-ok
diff --git a/tests/tests/debpolicy-taintrm b/tests/tests/debpolicy-taintrm
new file mode 100755
index 0000000..8655fb5
--- /dev/null
+++ b/tests/tests/debpolicy-taintrm
@@ -0,0 +1,58 @@
+#!/bin/bash
+set -e
+. tests/lib
+
+t-tstunt-parsechangelog
+
+t-debpolicy
+t-prep-newpackage example 1.0
+
+cd $p
+revision=1
+git tag start
+t-dgit setup-mergechangelogs
+
+
+: upload
+
+t-dgit push-source --new
+
+: cut
+
+rm $tmp/incoming/*
+t-archive-none example
+
+touch -d 'now -1 day' $tmp/git/example*
+
+t-policy-periodic # xxx maybe want test both with and without this
+
+: edit
+t-commit 'edit after cut'
+
+: push, needs --deliberately
+
+t-expect-push-fail \
+ 'all previously pushed versions were found to have been removed from NEW' \
+t-dgit push-source --new
+
+t-dgit push-source --new --deliberately-include-questionable-history
+
+t-archive-process-incoming new
+
+# : t-policy-periodic # maybe want test with this
+
+: accept
+
+mv -f $tmp/aq/package.{new,sid}.$p
+t-aq-archive-updated sid $p
+
+# : t-policy-periodic # maybe want test with this
+
+t-git-dir-time-passes
+
+: 3rd push, no deliberately
+
+t-commit 'edit after accept'
+t-dgit push-source
+
+t-ok
diff --git a/tests/tests/drs-push-rejects b/tests/tests/drs-push-rejects
index afaed4c..f102d95 100755
--- a/tests/tests/drs-push-rejects
+++ b/tests/tests/drs-push-rejects
@@ -110,7 +110,7 @@ mustfail 'push is missing tag ref update' $push_spec1
mustfail 'push is missing head ref update' +$push_spec2
mustfail 'pushing unexpected ref' $push_spec HEAD:refs/wombat
mustfail 'pushing multiple heads' $push_spec HEAD:refs/dgit/wombat
-mustfail E:'pushing multiple tags|pushing too many similar tags' \
+mustfail E:'pushing multiple tags|pushing too many similar tags|need exactly one archive' \
$push_spec HEAD:refs/tags/$tagpfx/wombat
prep unstable sid
@@ -162,7 +162,6 @@ git commit --allow-empty -m 'Dummy update'
mktag
mustfail 'not replacing previously-pushed version' +$push_spec1 +$push_spec2
-t-newtag
re-prep
mktag
mustfail 'not replacing previously-pushed version' +$push_spec1 +$push_spec2
diff --git a/tests/tests/forcesplit-linear b/tests/tests/forcesplit-linear
new file mode 100755
index 0000000..4856d6a
--- /dev/null
+++ b/tests/tests/forcesplit-linear
@@ -0,0 +1,45 @@
+#!/bin/bash
+set -e
+. tests/lib
+
+t-tstunt-parsechangelog
+t-buildproductsdir-config
+
+t-archive example 1.0-1
+t-select-package example
+t-git-none
+
+t-dgit clone $p
+cd $p
+
+echo '/* More patch */' >>src.c
+git add src.c
+
+t-commit 'More patch' 1.0-2
+
+t-refs-same-start
+t-ref-head
+t-dgit --split-view push-source
+t-ref-head
+
+
+t-commit 'More more patch' 1.0-3
+
+t-dgit --split-view --save-dgit-view=split.b quilt-fixup
+
+git reflog expire --expire=all refs/dgit-intern/quilt-cache
+test "x$(git reflog refs/dgit-intern/quilt-cache)" = x
+
+t-refs-same-start
+t-ref-head
+t-dgit --split-view --save-dgit-view=split.p push-source
+t-ref-head
+
+suite=sid
+
+t-splitbrain-pushed-good-start
+t-splitbrain-pushed-good--unpack
+t-splitbrain-rm-1-patch more-patch.patch
+t-splitbrain-pushed-good-end-made-dep14
+
+t-ok
diff --git a/tests/tests/forcesplit-overwrite b/tests/tests/forcesplit-overwrite
new file mode 100755
index 0000000..9600d3a
--- /dev/null
+++ b/tests/tests/forcesplit-overwrite
@@ -0,0 +1,37 @@
+#!/bin/bash
+set -e
+. tests/lib
+
+# This tests a native package with split view, including that the
+# pseudomerges end up in the right place.
+
+t-setup-import examplegit
+
+t-select-package example
+cd example
+
+suite=stable
+
+t-commit 'No changes, just send to stable' '' stable
+
+t-refs-same-start
+t-ref-head
+
+try () {
+ t-dgit -wgf --split-view "$@" --dgit-view-save=split.p \
+ push-source stable
+}
+
+t-expect-fail E:'maintainer view tag.*not fast forward' \
+try
+
+t-expect-fail F:'debian/changelog does not mention 1.2' \
+try --overwrite
+
+try --overwrite=1.2
+git branch -f split.b split.p
+
+t-ref-head
+t-split-unchanged-pushed-good $suite
+
+t-ok
diff --git a/tests/tests/newtag-clone-nogit b/tests/tests/newtag-clone-nogit
deleted file mode 100755
index 915f9d3..0000000
--- a/tests/tests/newtag-clone-nogit
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/bin/bash
-set -e
-. tests/lib
-t-alt-test
diff --git a/tests/tests/oldnewtagalt b/tests/tests/oldnewtagalt
deleted file mode 100755
index 6730918..0000000
--- a/tests/tests/oldnewtagalt
+++ /dev/null
@@ -1,25 +0,0 @@
-#!/bin/bash
-set -e
-. tests/lib
-
-t-setup-import examplegit
-t-tstunt-parsechangelog
-
-cd $p
-
-test-push () {
- t-commit "$1"
- t-dgit -wgf build-source
- t-dgit push
-}
-
-for count in 1 2; do
- t-oldtag
- test-push "oldtag $count"
-
- t-newtag
- test-push "newtag $count"
-done
-
-t-ok
-
diff --git a/tests/tests/oldtag-clone-nogit b/tests/tests/oldtag-clone-nogit
deleted file mode 100755
index 915f9d3..0000000
--- a/tests/tests/oldtag-clone-nogit
+++ /dev/null
@@ -1,4 +0,0 @@
-#!/bin/bash
-set -e
-. tests/lib
-t-alt-test
diff --git a/tests/tests/overwrite-splitbrains b/tests/tests/overwrite-splitbrains
index 06d1a98..815c207 100755
--- a/tests/tests/overwrite-splitbrains
+++ b/tests/tests/overwrite-splitbrains
@@ -5,7 +5,6 @@ set -e
t-tstunt-parsechangelog
t-gbp-example-prep-no-ff
-t-newtag
t-dgit --quilt=gbp --dgit-view-save=split.b build-source
diff --git a/tests/tests/quilt-gbp b/tests/tests/quilt-gbp
index cf148f6..e502f6b 100755
--- a/tests/tests/quilt-gbp
+++ b/tests/tests/quilt-gbp
@@ -25,11 +25,6 @@ t-gbp-example-prep
t-expect-fail 'quilt fixup cannot be linear' \
t-dgit build-source
-t-git-config dgit-distro.test-dummy.dgit-tag-format new
-t-expect-fail 'requires split view so server needs to support' \
-t-dgit -wgf --quilt=gbp build-source
-t-newtag
-
t-dgit --quilt=gbp --dgit-view-save=split.b1 build-source
git rev-parse split.b1
diff --git a/tests/tests/quilt-splitbrains b/tests/tests/quilt-splitbrains
index 6886cf8..f8d8091 100755
--- a/tests/tests/quilt-splitbrains
+++ b/tests/tests/quilt-splitbrains
@@ -12,8 +12,6 @@ suitespecs+=' stable'
t-tstunt-parsechangelog
-t-newtag
-
# Easiest way to make a patches-unapplied but not-gbp tree is
# to take the patches-unapplied tree and by-hand commit the .gitignore
# changes as a debian patch.
@@ -29,7 +27,7 @@ want-success () {
t-dgit "$@" --quilt=$qmode --dgit-view-save=split.b build-source
t-dgit "$@" --quilt=$qmode --dgit-view-save=split.p push
- t-$qmode-pushed-good
+ t-$qmode-pushed-good $suite
}
diff --git a/tests/tests/rpush-quilt b/tests/tests/rpush-quilt
index 10df9ae..bb49fc6 100755
--- a/tests/tests/rpush-quilt
+++ b/tests/tests/rpush-quilt
@@ -4,8 +4,6 @@ set -e
t-tstunt-parsechangelog
-t-newtag
-
t-gbp-example-prep
t-dgit -wgf --quilt=gbp --dgit-view-save=split.b build-source