chiark / gitweb /
git-debrebase: wip new-upstream
[dgit.git] / git-debrebase
index 128f2f1d682bda4893e3be6596ec97c95c27d312..b27393802ba67e029d71473288b30fdb0180c1af 100755 (executable)
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
+#    git-debrebase new-upstreams-v0 \
+#             NEW-VERSION ORIG-COMMITISH
+#            [EXTRA-ORIG-NAME EXTRA-ORIG-COMMITISH ...]
+
 # usages:
 #    git-debrebase status
 #    git-debrebase start       # like ffqrebase start + debrebase launder
@@ -763,6 +767,121 @@ sub cmd_analyse () {
     STDOUT->error and die $!;
 }
 
+sub cmd_new_upstream_v0 () {
+    badusage
+ "need NEW-VERSION ORIG-COMMITISH [EXTRA-ORIG-NAME EXTRA-ORIG-COMMITISH...]"
+       unless @ARGV % 2 == 0 and @ARGV >= 2;
+    # tree should be clean and this is not checked
+    # automatically and unconditionally launders before rebasing
+    # if rebase --abort is used, laundering has still been done
+
+    # parse args - low commitment
+    my $new_version = new Dpkg::Version scalar(shift @ARGV), 1;
+    my $new_upstream_version = $new_version->version();
+    my $new_orig_commitish = git_rev_parse shift @ARGV;
+    my @extra_origs;
+    while (@ARGV) {
+       my $xo = {
+           Name => shift @ARGV,
+           New => git_rev_parse shift @ARGV,
+                };
+       die unless $xo->{Name} =~ m/^$extra_orig_namepart_re$/;
+       push @extra_origs, $xo;
+    }
+
+    # now we need to investigate the branch this generates the
+    # laundered version but we don't switch to it yet
+    my $old = get_head();
+    my ($laundered_tip,$breakwater) = walk $old;
+
+    my $breakwater_cl = classify $breakwater;
+    my $old_orig_pi = $breakwater_cl->{OrigParents}[0];
+
+    fresh_workarea();
+    in_workarea sub {
+       my $ff_still_ok = 1;
+
+       my $ffnot = sub {
+           my ($msg) = @_;
+           $ff_still_ok = 0;
+           print STDERR "upstream not fast forward: $msg\n";
+       };
+
+       if (@extra_origs) {
+           # check fast forward, and make new combined-orig commit
+           my $old_orig_ci = parsecommit $old_orig_pi->{CommitId};
+           my $n_old_origs = scalar @{ $old_orig_cp->{Parents} };
+           @{ $n_old_origs } == @extra_origs+1 or
+               $ffnot->(sprintf
+                        "previous breakwater upstream has %d parents".
+                        " but new upstream has %d pieces, cannot check ff",
+                        $n_old_origs,
+                        (1 + scalar @extra_origs));
+       }
+
+       my @upstream_merge_parents;
+
+       foreach my $piece_ix (0..$n_old_origs-1) {
+           my $prevpc = $breakwater.'^'.($old_orig_pi->{Ix} + 1);
+           if (@extra_origs) {
+               $prevpc .= '^'.($piece_ix + 1);
+           }
+           die unless $ git_rev_parse $prevpc;
+           my ($newpc,$newdesc,$pcname);
+           if (!$piece_ix) {
+               $newpc = $new_orig_commitish;
+               $newdesc = 'new main upstream piece';
+           } else {
+               $newpc = $extra_origs[$piece_ix+1]{New};
+               $pcname = $extra_origs[$piece_ix-1]{Name}
+               $newdesc = "new upstream extra piece \`$pcname";
+           }
+           $ffwant->($prevpc, "previous upstream piece ($prevpc)",
+                     $newpc, "newdesc ($newpc)");
+
+           push @upstream_merge_parents, $newpc;
+
+           my @cmd = @git, qw(read-tree);
+           if (defined $pcname) {
+               push @cmd, "-prefix=$pcname/";
+               runcmd @git, qw(rm --cached -f --ignore-unmatch), $pcname;
+           }
+           push @cmd, $newpc;
+           runcmd @cmd;
+       }
+
+       # index now contains the new upstream
+       if (!$ff_still_ok) {
+           die "upstreams not fast forward, stopping".
+               " (xxx should be an override option)";
+       }
+
+       if (@extra_origs) {
+           # need to make the upstream subtree merge commit
+           my $us_tree = cmdoutput @git, qw(write-tree);
+           my @cmd = @git, qw(commit-tree), $us_tree;
+           if ($ff_still_ok) {
+               push @cmd, qw(-p), 
+           } else {
+               die 'do we want to make ff from previous upstream comb?"';
+           }
+           push @cmd, qw(-p), $_ foreach @upstream_merge_parents;
+           push @cmd, qw(-m), "Combine upstreams for $new_upstream_version";
+           push @cmd, qw(-m),
+               "[git-debrebase combine-upstreams . ".
+               (join " ", map { $_->{Name} } @extra_upstreams)."]";
+           my $combined = cmdoutput @cmd;
+       }
+       
+
+           my $us_txt = "
+           make_commit_te
+
+    update_head
+    xxx check new orig version is reasonable;
+    xxx decorate new orig version to get new debian version;
+       
+
 sub cmd_downstream_rebase_launder_v0 () {
     badusage "needs 1 argument, the baseline" unless @ARGV==1;
     my ($base) = @ARGV;