chiark / gitweb /
dgit-badcommit-fixup: Implement dgit-rewrite-map
[dgit.git] / dgit-badcommit-fixup
index 46637899d91920f234cb78bb27b4f7eb58af912b..cd62e6820f9155f29d299aa4b3a2b5cd266857c1 100755 (executable)
@@ -129,16 +129,77 @@ sub rewrite_tag ($) {
     return hashobj $_, 'tag';
 }
 
+sub rewrite_rewrite_map ($) {
+    my ($old) = @_;
+
+    my $td = 'dgit-broken-fixup.tmp';
+    runcmd qw(rm -rf), $td;
+    mkdir $td, 0700 or die "$td $!";
+    chdir $td or die $!;
+    runcmd qw(git init -q);
+    runcmd qw(git config gc.auto 0);
+    runcmd qw(rm -rf .git/objects);
+    symlink "../../objects", ".git/objects" or die $!;
+
+    my %map;
+
+    if ($old) {
+       runcmd qw(git checkout -q), $old;
+       open M, "map" or die $!;
+       while (<M>) {
+           m/^(\w+)(?:\s+(\w+))?$/ or die;
+           $map{$1} = $2;
+           $count{rewrite_map_previous}++;
+       }
+       M->error and die $!;
+       close M or die $!;
+    }
+
+    filter_updates();
+    foreach my $up (@updates) {
+       $map{ $_->[1] } = $_->[2];
+    }
+
+    open M, ">", "map" or die $!;
+    print M "%s%s\n",
+       $_, (defined $map{$_} ? " $map{$_}" : "")
+       or die $!;
+       foreach keys %map;
+    close M or die $!;
+
+    runcmd qw(git commit -q), 
+       qw(-m), 'dgit-badcommit-fixup',
+       qw(map);
+
+    $!=0; $?=0;
+    my $new = `git rev-parse HEAD`;
+    die "$? $!" if $?;
+    chomp $new or die;
+
+    chdir '..' or die $!;
+    runcmd qw(rm -rf), $td;
+
+    $count{rewrite_map_updated}++;
+
+    return $new;
+}
+
 $!=0; $?=0;
 my $refs=`git for-each-ref`;
 die "$? $!" if $?;
 
 chomp $refs;
 
+our $org_rewrite_map;
+
 foreach my $rline (split /\n/, $refs) {
     my ($obj, $type, $refname) = 
        $rline =~ m/^(\w+)\s+(\w+)\s+(\S.*)/
        or die "$_ ?";
+    if ($refname eq 'refs/dgit-rewrite-map') {
+       $org_rewrite_map = $obj;
+       continue;
+    }
     my $rewrite;
     if ($type eq 'commit') {
        $rewrite = rewrite_commit($obj);
@@ -151,6 +212,13 @@ foreach my $rline (split /\n/, $refs) {
     push @updates, [ $refname, $obj, $rewrite ];
 }
 
+if ($bare eq 'true') {
+    my $new_rewrite_map = edit_rewrite_map($org_rewrite_map);
+    push @updates, [ 'refs/dgit-rewrite-map',
+                    ($org_rewrite_map // '0'x40),
+                    $new_rewrite_map ];
+}
+
 filter_updates();
 
 #print Dumper(\@updates);