summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Jackson <ijackson@chiark.greenend.org.uk>2017-01-05 01:34:05 +0000
committerIan Jackson <ijackson@chiark.greenend.org.uk>2017-01-05 01:34:05 +0000
commit5374279253457f5f43878619afc4533f809f1e05 (patch)
treea7c16bce0af12b6b3b4b9f640e41bc3412880e65
parente9c288efff0795ad647b2293ece57166a2395c98 (diff)
badcommit-fixup: wip
-rwxr-xr-xbadcommit-fixup134
1 files changed, 47 insertions, 87 deletions
diff --git a/badcommit-fixup b/badcommit-fixup
index 58ad12d..af4b89d 100755
--- a/badcommit-fixup
+++ b/badcommit-fixup
@@ -4,38 +4,53 @@ use strict;
use POSIX;
use IPC::Open2;
+use Data::Dumper;
-$!=0; $?=0;
-my $refs=`git-for-each-ref`;
-die "$? $!" if $?;
+my $gcfpid = open2 \*GCFO, \*GCFI, 'git cat-file --batch' or die $!;
-chomp $refs;
+our %count;
-my $gcfpid = open2 \*GCFO, \*GCFI, 'git cat-file --batch' or die $!;
+no warnings qw(recursion);
sub getobj ($$) {
my ($obj, $type) = @_;
print GCFI $obj, "\n" or die $!;
my $x = <GCFO>;
- $x =~ m/^\w+ (\w+) (\d+)\n/ or die "$obj ?";
- my ($gtype, $gsize) = ($1,$2,$3);
+ my ($gtype, $gsize) = $x =~ m/^\w+ (\w+) (\d+)\n/ or die "$obj ?";
$gtype eq $type or die "$obj $gtype != $type ?";
my $gdata;
- read GFCO, $gdata, $gsize == $gsize or die "$obj $!";
- $x = <GFCO>;
- $x eq "\n" or die "$obj $!";
+ (read GCFO, $gdata, $gsize) == $gsize or die "$obj $!";
+#print STDERR ">$obj|$x|$gdata|$gsize<\n";
+ $x = <GCFO>;
+ $x eq "\n" or die "$obj ($_) $!";
+ $count{inspected}++;
return $gdata;
}
+sub hashobj ($$) {
+ my ($data,$type) = @_;
+ my $gwopid = open2 \*GWO, \*GWI,
+ "git hash-object -t $type --stdin"
+ or die $!;
+ print GWI $data or die $!;
+ close GWI or die $!;
+ $_ = <GWO>;
+ close GWO or die $!;
+ waitpid $gwopid,0 == $gwopid or die $!;
+ die $? if $?;
+ m/^(\w+)\n/ or die "$_ ?";
+ $count{"rewritten $type"}++;
+ return $1;
+}
+
our %memo;
-our %count;
+sub rewrite_commit ($);
sub rewrite_commit ($) {
my ($obj) = @_;
my $m = \ $memo{$obj};
return $$m if defined $$m;
my $olddata = getobj $obj, 'commit';
- die "$obj ?" unless $old;
$olddata =~ m/(?<=\n)(?=\n)/ or die "$obj ?";
my $msg = $';
$_ = $`;
@@ -49,23 +64,13 @@ sub rewrite_commit ($) {
$_ .= $1;
$count{fix_import}++;
}
- $newdata = $_.$msg;
+ my $newdata = $_.$msg;
my $newobj;
if ($newdata eq $olddata) {
- $newobj = $oldobj;
+ $newobj = $obj;
+ $count{unchanged}++;
} else {
- my $gwopid = open2 \*GWO, \*GWI,
- 'git hash-object -t comit --stdin'
- or die $!;
- print GWI $newdata or die $!;
- close GWI or die $!;
- $_ = <GWO>;
- close GWO or die $!;
- waitpid $gwopid,0 == $gwopid or die $!;
- die $? if $?;
- m/^(\w+)\n/ or die "$_ ?";
- $newobj = $1;
- $count{commits}++;
+ $newobj = hashobj $newdata, 'commit';
}
$$m= $newobj;
return $newobj;
@@ -85,13 +90,23 @@ sub rewrite_tag ($) {
if ($oldref eq $newref) {
return $obj;
}
- s/^(?<=object )\w+(?=\n)/$newref/m or die "$obj ?";
-
+ s/^(object )\w+$/ $1.$newref /me or die "$obj ($_) ?";
+ s/^-----BEGIN PGP SIGNATURE-----\n.*^-----END PGP SIGNATURE-----\n$//sm;
+ return hashobj $_, 'tag';
}
+$!=0; $?=0;
+my $refs=`git-for-each-ref`;
+die "$? $!" if $?;
+
+chomp $refs;
+
+our @updates;
+
foreach my $rline (split /\n/, $refs) {
- die "$_ ?" unless m/^(\w+)\s+(\w+)\s+(\S.*)/;
- my ($obj, $type, $refname) = @_;
+ my ($obj, $type, $refname) =
+ $rline =~ m/^(\w+)\s+(\w+)\s+(\S.*)/
+ or die "$_ ?";
my $rewrite;
if ($type eq 'commit') {
$rewrite = rewrite_commit($obj);
@@ -101,63 +116,8 @@ foreach my $rline (split /\n/, $refs) {
warn "ref $refname refers to $type\n";
next;
}
- next if $refname eq $rewrite;
+ next if $rewrite = $obj;
push @updates, [ $refname, $rewrite ];
}
-
-
-if git-symbolic-ref HEAD >/dev/null 2>&1; then
- refs+=' HEAD'
-
-
-
-my $gfo = `LC_MESSAGES=C git fsck --no-dangling 2>&1`;
-$? == 256 or die "$? $!"
-
-
-
-
- m/^error in commit (\w+):.*invalid format - expected 'committer/;
-
-case `wc -l <$tmp/bad` in
- 0)
- echo >&2 'nothing bad found - is git-fsck doing as we expect?' ;
- exit 8 ;;
- 1)
- read <$tmp/bad bads
- nots="^$bads^0 ^$bads^1"
- ;;
- *)
- bads="cat $tmp/bad"
- ;;
-esac
-
-args="$nots"
-
-refs=`git-for-each-ref --format='%(refname)'`
-
-if git-symbolic-ref HEAD >/dev/null 2>&1; then
- refs+=' HEAD'
-fi
-
-for head in $refs; do
- exec <$tmp/bad
- needed=false
- for bad in $bads; do
- if git merge-base --is-ancestor $bad $head; then
- needed=true
- break
- fi
- done
- if ! $needed; then continue; fi
- args+=" $head"
-done
-
-git filter-branch --original dgit-badcommit --commit-filter '
-echo >&2 "FOO $*"
-cat >&2
-echo >&2 ====
-false
- sed -e '\''1,/^$/ s/^commiter /committer /'\''
-' $args
+print Dumper(\@updates, \%count);