+ $cl = classify $cur;
+ my $ty = $cl->{Type};
+ my $st = $cl->{SubType};
+ $found{$ty. ( defined($st) ? "-$st" : '' )}++;
+ my $p0 = $cl->{Parents}[0]{CommitId};
+ if ($ty eq 'AddPatches') {
+ $cur = $p0;
+ $rewrite_from_here->();
+ next;
+ } elsif ($ty eq 'Packaging') {
+ push @deb_cl, $cl;
+ push @processed, $cl;
+ $cur = $p0;
+ next;
+ } elsif ($ty eq 'Upstream') {
+ push @ups_cl, $cl;
+ push @processed, $cl;
+ $cur = $p0;
+ next;
+ } elsif ($ty eq 'Mixed') {
+ my $queue = sub {
+ my ($q, $wh) = @_;
+ my $cls = { $cl, $xmsg->("split mixed commit: $wh part") };
+ push @$q, $cls;
+ };
+ $queue->(\@deb_cl, "debian");
+ $queue->(\@ups_cl, "upstream");
+ $rewrite_from_here->();
+ next;
+ } elsif ($ty eq 'Pseudomerge') {
+ if (defined $pseudos_must_overwrite_this) {
+ confess 'xxx actually check this';
+ }
+ push @pseudomerges, $cl;
+ $rewrite_from_here->();
+ $cur = $ty->{Contributor};
+ next;
+ } elsif ($ty eq 'BreakwaterUpstreamMerge') {
+ $basis = $cur;
+ last;
+ } elsif ($ty eq 'DgitImportUnpatched' &&
+ @pseudomerges == 1) {
+ # This import has a tree which is just like a breakwater
+ # tree, but it has the wrong history. Its ought to have
+ # the previous breakwater (which dgit ought to have
+ # generated a pseudomerge to overwrite) as an ancestor.
+ # That will make the history of the debian/ files correct.
+ # As for the upstream version: either it's the same upstream
+ # as the previous breakwater, in which case that history is
+ # precisely right. Otherwise, it was a non-gitish upload
+ # of a new upstream version. We can tell these apart
+ # by looking at the tree of the supposed upstream.
+ if ($differs & D_UPS) {
+ push @deb_cl, {
+ %r,
+ SpecialMethod => 'DgitImportUpstreamUpdate',
+ $xmsg->("convert dgit import: debian changes")
+ };
+ }
+ push @deb_cl, {
+ %r,
+ SpecialMethod => 'DgitImportDebianUpdate',
+ $xmsg->("convert dgit import: upstream changes")
+ };
+ my $differs = get_differs $previous_breakwater, $cl->{Tree};
+ $basis = launder $pseudomerges[0]{Overwritten}, undef, 1;
+ $rewrite_from_here->();
+ last;
+ } else {
+ die "Reached difficult commit $cur: ".Dumper($cl);
+ }
+ }
+ # Now we build it back up again
+
+ workarea_fresh();
+ in_workarea sub { xxx attributes xxx };
+
+ my $rewriting = 1;
+
+ my $build = $basis;
+
+ my $rm_tree_cached = sub {
+ my ($subdir) = @_;
+ runcmd @git, qw(rm --quiet -rf --cached), $subdir;
+ };
+ my $read_tree_debian = sub {
+ my ($treeish) = @_;
+ $rm_tree_cached->(qw(debian));
+ runcmd @git, qw(read-tree --prefix=debian/), "$treeish:debian";
+ };
+ my $read_tree_upstream = sub {
+ my ($treeish) = @_;
+ runcmd @git, qw(read-tree), $treeish;
+ $read_tree_debian->($build);
+ };
+
+ my $committer_authline = calculate_committer_authline();
+
+ in_workarea sub {
+ mkdir $rd or $!==EEXIST or die $!;
+ my $current_method;
+ foreach my $cl (qw(Debian), (reverse @deb_cl),
+ { SpecialMethod => 'RecordBreakwaterTip' },
+ qw(Upstream), (reverse @ups_cl)) {
+ if (!ref $cl) {
+ $current_method = $cl;