our $cleanmode;
our $changes_since_version;
our $rmchanges;
-our $overwrite_version;
+our $overwrite_version; # undef: not specified; '': check changelog
our $quilt_mode;
our $quilt_modes_re = 'linear|smash|auto|nofix|nocheck|gbp|dpm|unapplied';
our $we_are_responder;
return "$distro/$v";
}
+sub madformat ($) { $_[0] eq '3.0 (quilt)' }
+
sub lbranch () { return "$branchprefix/$csuite"; }
my $lbranch_re = '^refs/heads/'.$branchprefix.'/([^/.]+)$';
sub lref () { return "refs/heads/".lbranch(); }
my ($dctrl,$field) = @_;
my $v = $dctrl->{$field};
return $v if defined $v;
- fail "missing field $field in ".$v->get_option('name');
+ fail "missing field $field in ".$dctrl->get_option('name');
}
sub parsechangelog {
- my $c = Dpkg::Control::Hash->new();
+ my $c = Dpkg::Control::Hash->new(name => 'parsed changelog');
my $p = new IO::Handle;
my @cmd = (qw(dpkg-parsechangelog), @_);
open $p, '-|', @cmd or die $!;
$!=0; $?=0; close GITS or failedcmd @gitscmd;
}
-sub mktree_in_ud_from_only_subdir () {
+sub mktree_in_ud_from_only_subdir (;$) {
+ my ($raw) = @_;
+
# changes into the subdir
my (@dirs) = <*/.>;
- die "@dirs ?" unless @dirs==1;
+ die "expected one subdir but found @dirs ?" unless @dirs==1;
$dirs[0] =~ m#^([^/]+)/\.$# or die;
my $dir = $1;
changedir $dir;
remove_stray_gits();
mktree_in_ud_here();
- my ($format, $fopts) = get_source_format();
- if (madformat($format)) {
- rmtree '.pc';
+ if (!$raw) {
+ my ($format, $fopts) = get_source_format();
+ if (madformat($format)) {
+ rmtree '.pc';
+ }
}
+
runcmd @git, qw(add -Af);
my $tree=git_write_tree();
return ($tree,$dir);
map { $_->{Filename} } dsc_files_info();
}
-sub is_orig_file ($;$) {
- local ($_) = $_[0];
- my $base = $_[1];
- m/\.orig(?:-\w+)?\.tar\.\w+$/ or return 0;
- defined $base or return 1;
- return $` eq $base;
+sub is_orig_file_in_dsc ($$) {
+ my ($f, $dsc_files_info) = @_;
+ return 0 if @$dsc_files_info <= 1;
+ # One file means no origs, and the filename doesn't have a "what
+ # part of dsc" component. (Consider versions ending `.orig'.)
+ return 0 unless $f =~ m/\.orig(?:-\w+)?\.tar(?:\.\w+)?$/;
+ return 1;
+}
+
+sub is_orig_file_of_vsn ($$) {
+ my ($f, $upstreamvsn) = @_;
+ my $base = srcfn $upstreamvsn, '';
+ return 0 unless $f =~ m/^\Q$base\E\.orig(?:-\w+)?\.tar(?:\.\w+)?$/;
+ return 1;
}
sub make_commit ($) {
return cmdoutput @git, qw(hash-object -w -t commit), $file;
}
+sub make_commit_text ($) {
+ my ($text) = @_;
+ my ($out, $in);
+ my @cmd = (@git, qw(hash-object -w -t commit --stdin));
+ debugcmd "|",@cmd;
+ my $child = open2($out, $in, @cmd) or die $!;
+ my $h;
+ eval {
+ print $in $text or die $!;
+ close $in or die $!;
+ $h = <$out>;
+ $h =~ m/^\w+$/ or die;
+ $h = $&;
+ printdebug "=> $h\n";
+ };
+ close $out;
+ waitpid $child, 0 == $child or die "$child $!";
+ $? and failedcmd @cmd;
+ return $h;
+}
+
sub clogp_authline ($) {
my ($clogp) = @_;
my $author = getfield $clogp, 'Maintainer';
prep_ud();
changedir $ud;
- foreach my $fi (dsc_files_info()) {
+ my @dfi = dsc_files_info();
+ foreach my $fi (@dfi) {
my $f = $fi->{Filename};
die "$f ?" if $f =~ m#/|^\.|\.dsc$|\.tmp$#;
complete_file_from_dsc('.', $fi)
or next;
- if (is_orig_file($f)) {
+ if (is_orig_file_in_dsc($f, \@dfi)) {
link $f, "../../../../$f"
or $!==&EEXIST
or die "$f $!";
close C or die $!;
my $rawimport_hash = make_commit qw(../commit.tmp);
my $cversion = getfield $clogp, 'Version';
+ progress "synthesised git commit from .dsc $cversion";
+
my $rawimport_mergeinput = {
Commit => $rawimport_hash,
Info => "Import of source package",
};
my @output = ($rawimport_mergeinput);
- progress "synthesised git commit from .dsc $cversion";
+
if ($lastpush_mergeinput) {
my $oldclogp = mergeinfo_getclogp($lastpush_mergeinput);
my $oversion = getfield $oldclogp, 'Version';
}
sub ensure_we_have_orig () {
- foreach my $fi (dsc_files_info()) {
+ my @dfi = dsc_files_info();
+ foreach my $fi (@dfi) {
my $f = $fi->{Filename};
- next unless is_orig_file($f);
+ next unless is_orig_file_in_dsc($f, \@dfi);
complete_file_from_dsc('..', $fi)
or next;
}
return ($_, \%options);
}
-sub madformat ($) {
+sub madformat_wantfixup ($) {
my ($format) = @_;
return 0 unless $format eq '3.0 (quilt)';
our $quilt_mode_warned;
my $i_arch_v = [ (getfield $arch_clogp, 'Version'),
'version currently in archive' ];
if (defined $overwrite_version) {
- infopair_cond_equal([ $overwrite_version, '--overwrite= version' ],
- $i_arch_v);
+ if (length $overwrite_version) {
+ infopair_cond_equal([ $overwrite_version,
+ '--overwrite= version' ],
+ $i_arch_v);
+ } else {
+ my $v = $i_arch_v->[0];
+ progress "Checking package changelog for archive version $v ...";
+ eval {
+ my @xa = ("-f$v", "-t$v");
+ my $vclogp = parsechangelog @xa;
+ my $cv = [ (getfield $vclogp, 'Version'),
+ "Version field from dpkg-parsechangelog @xa" ];
+ infopair_cond_equal($i_arch_v, $cv);
+ };
+ if ($@) {
+ $@ =~ s/^dgit: //gm;
+ fail "$@".
+ "Perhaps debian/changelog does not mention $v ?";
+ }
+ }
}
printdebug "pseudomerge_version_check i_arch_v @$i_arch_v\n";
return $i_arch_v;
}
-sub pseudomerge_make_commit ($$$$$) {
- my ($clogp, $dgitview, $archive_hash, $i_arch_v, $msg) = @_;
+sub pseudomerge_make_commit ($$$$ $$) {
+ my ($clogp, $dgitview, $archive_hash, $i_arch_v,
+ $msg_cmd, $msg_msg) = @_;
progress "Declaring that HEAD inciudes all changes in $i_arch_v->[0]...";
my $tree = cmdoutput qw(git rev-parse), "${dgitview}:";
my $authline = clogp_authline $clogp;
+ chomp $msg_msg;
+ $msg_cmd .=
+ !defined $overwrite_version ? ""
+ : !length $overwrite_version ? " --overwrite"
+ : " --overwrite=".$overwrite_version;
+
mkpath '.git/dgit';
my $pmf = ".git/dgit/pseudomerge";
open MC, ">", $pmf or die "$pmf $!";
- print MC <<END, $msg or die $!;
+ print MC <<END or die $!;
tree $tree
parent $dgitview
parent $archive_hash
author $authline
commiter $authline
+$msg_msg
+
+[$msg_cmd]
END
close MC or die $!;
my $r = pseudomerge_make_commit
$clogp, $dgitview, $archive_hash, $i_arch_v,
+ "dgit --quilt=$quilt_mode",
(defined $overwrite_version ? <<END_OVERWR : <<END_MAKEFF);
Declare fast forward from $overwrite_version
-
-[dgit --quilt=$quilt_mode --overwrite-version=$overwrite_version]
END_OVERWR
Make fast forward from $i_arch_v->[0]
-
-[dgit --quilt=$quilt_mode]
END_MAKEFF
progress "Made pseudo-merge of $i_arch_v->[0] into dgit view.";
my @tagformats = access_cfg_tagformats();
my @t_overwr =
- map { $_->($overwrite_version, access_basedistro) }
+ map { $_->($i_arch_v->[0], access_basedistro) }
(grep { m/^(?:old|hist)$/ } @tagformats)
? \&debiantags : \&debiantag_new;
my $i_overwr = infopair_lrf_tag_lookup \@t_overwr, "previous version tag";
return $head if is_fast_fwd $archive_hash, $head;
- my $m = "Declare fast forward from $overwrite_version";
+ my $m = "Declare fast forward from $i_arch_v->[0]";
my $r = pseudomerge_make_commit
- $clogp, $head, $archive_hash, $i_arch_v, <<END;
-$m
-
-[dgit --overwrite-version=$overwrite_version]
-END
+ $clogp, $head, $archive_hash, $i_arch_v,
+ "dgit", $m;
runcmd @git, qw(update-ref -m), $m, 'HEAD', $r, $head;
my $dgithead = $actualhead;
my $maintviewhead = undef;
- if (madformat($format)) {
+ if (madformat_wantfixup($format)) {
# user might have not used dgit build, so maybe do this now:
if (quiltmode_splitbrain()) {
my $upstreamversion = $clogp->{Version};
} else {
fail "dgit push: HEAD is not a descendant".
" of the archive's version.\n".
- "dgit: To overwrite its contents,".
- " use git merge -s ours ".lrref().".\n".
- "dgit: To rewind history, if permitted by the archive,".
- " use --deliberately-not-fast-forward";
+ "To overwrite the archive's contents,".
+ " pass --overwrite[=VERSION].\n".
+ "To rewind history, if permitted by the archive,".
+ " use --deliberately-not-fast-forward.";
}
}
sub build_maybe_quilt_fixup () {
my ($format,$fopts) = get_source_format;
- return unless madformat $format;
+ return unless madformat_wantfixup $format;
# sigh
check_for_vendor_patches();
+ if (quiltmode_splitbrain) {
+ foreach my $needtf (qw(new maint)) {
+ next if grep { $_ eq $needtf } access_cfg_tagformats;
+ fail <<END
+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');
local ($debuglevel) = $debuglevel-1;
printdebug "QF linkorigs $b, $f ?\n";
}
- next unless is_orig_file $b, srcfn $upstreamversion,'';
+ next unless is_orig_file_of_vsn $b, $upstreamversion;
printdebug "QF linkorigs $b, $f Y\n";
link_ltarget $f, $b or die "$b $!";
$fn->($b);
rmtree("debian/patches");
runcmd @dpkgsource, qw(-b .);
- chdir "..";
+ changedir "..";
runcmd @dpkgsource, qw(-x), (srcfn $version, ".dsc");
rename srcfn("$upstreamversion", "/debian/patches"),
"work/debian/patches";
- chdir "work";
+ changedir "work";
commit_quilty_patch();
}
} elsif (m/^--no-rm-on-error$/s) {
push @ropts, $_;
$rmonerror = 0;
+ } elsif (m/^--overwrite$/s) {
+ push @ropts, $_;
+ $overwrite_version = '';
+ } elsif (m/^--overwrite=(.+)$/s) {
+ push @ropts, $_;
+ $overwrite_version = $1;
} elsif (m/^--(no-)?rm-old-changes$/s) {
push @ropts, $_;
$rmchanges = !$1;