From 91e2737f7ffeb765d291b6d886626331725f31cd Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Fri, 6 Jan 2017 16:11:52 +0000 Subject: dgit-badcommit-fixup: Rename Signed-off-by: Ian Jackson --- badcommit-fixup | 256 --------------------------------------------------- dgit-badcommit-fixup | 256 +++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 256 insertions(+), 256 deletions(-) delete mode 100755 badcommit-fixup create mode 100755 dgit-badcommit-fixup diff --git a/badcommit-fixup b/badcommit-fixup deleted file mode 100755 index 4573121..0000000 --- a/badcommit-fixup +++ /dev/null @@ -1,256 +0,0 @@ -#!/usr/bin/perl -w - -# usage: -# .../badcommit-fixup --test -# .../badcommit-fixup --real - -use strict; - -use POSIX; -use IPC::Open2; -use Data::Dumper; - -my $real; - -foreach my $a (@ARGV) { - if ($a eq '--test') { - $real = 0; - } elsif ($a eq '--real') { - $real = 1; - } else { - die "$a ?"; - } -} - -die unless defined $real; - -my $gcfpid = open2 \*GCFO, \*GCFI, 'git cat-file --batch' or die $!; - -our %count; - -no warnings qw(recursion); - -sub runcmd { - system @_ and die "@_ $! $?"; -} - -$!=0; $?=0; -my $bare = `git rev-parse --is-bare-repository`; -die "$? $!" if $?; -chomp $bare or die; - -sub getobj ($$) { - my ($obj, $type) = @_; - print GCFI $obj, "\n" or die $!; - my $x = ; - my ($gtype, $gsize) = $x =~ m/^\w+ (\w+) (\d+)\n/ or die "$obj ?"; - $gtype eq $type or die "$obj $gtype != $type ?"; - my $gdata; - (read GCFO, $gdata, $gsize) == $gsize or die "$obj $!"; - $x = ; - $x eq "\n" or die "$obj ($_) $!"; - $count{inspected}++; - return $gdata; -} - -sub hashobj ($$) { - my ($data,$type) = @_; - my $gwopid = open2 \*GWO, \*GWI, - "git hash-object -w -t $type --stdin" - or die $!; - print GWI $data or die $!; - close GWI or die $!; - $_ = ; - close GWO or die $!; - waitpid $gwopid,0 == $gwopid or die $!; - die $? if $?; - m/^(\w+)\n/ or die "$_ ?"; - $count{"rewritten $type"}++; - return $1; -} - -our %memo; - -sub rewrite_commit ($); -sub rewrite_commit ($) { - my ($obj) = @_; - my $m = \ $memo{$obj}; - return $$m if defined $$m; - my $olddata = getobj $obj, 'commit'; - $olddata =~ m/(?<=\n)(?=\n)/ or die "$obj ?"; - my $msg = $'; - local $_ = $`; - s{^(parent )(\w+)$}{ $1 . rewrite_commit($2) }gme; - $count{'fix overwrite'} += s{^commiter }{committer }gm; - if (!m{^author }m && !m{^committer }m) { - m{^parent (\w+)}m or die "$obj ?"; - my $parent = getobj $1, 'commit'; - $parent =~ m/^(?:.+\n)+(author .*\ncommitter .*\n)/; - m/\n$/ or die "$obj ?"; - $_ .= $1; - $count{'fix import'}++; - } - my $newdata = $_.$msg; - my $newobj; - if ($newdata eq $olddata) { - $newobj = $obj; - $count{unchanged}++; - } else { - $newobj = hashobj $newdata, 'commit'; - } - $$m= $newobj; - return $newobj; -} - -sub rewrite_commit_adddummy ($$$) { - my ($ref, $veryold, $old) = @_; - - die "$bare ?" unless $bare eq 'true'; - - 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 $!; - runcmd qw(git checkout -q), $old; - - open C, "debian/changelog" or die $!; - my $clog = do { - local $/ = undef; - ; - }; - C->error and die $!; - close C or die $!; - defined $clog or die $!; - - $!=0; $?=0; - my $v = `dpkg-parsechangelog`; - die "$ref $veryold $old $? $!" if $?; - $v =~ m/^Source: (\S+)$/m or die "$ref $veryold $old ?"; - my $pkg = $1; - $v =~ m/^Version: (\S+)$/m or die "$ref $veryold $old ?"; - my $vsn = $1; - $vsn .= "+~dgitfix"; - - open C, ">", "debian/changelog" or die $!; - print C < Thu, 05 Jan 2017 17:58:21 +0000 - -END - print C $clog or die $!; - close C or die $!; - - runcmd qw(git commit -q), - '--author=Ian Jackson ', - qw(-m), 'Dummy changelog entry to work around #849041 fallout', - qw(debian/changelog); - - $!=0; $?=0; - my $new = `git rev-parse HEAD`; - die "$? $!" if $?; - chomp $new or die; - - chdir '..' or die $!; - runcmd qw(rm -rf), $td; - - $count{dummyadded}++; - - return $new; -} - -sub rewrite_tag ($) { - my ($obj) = @_; - $_ = getobj $obj, 'tag'; - m/^type (\w+)\n/m or die "$obj ?"; - if ($1 ne 'commit') { - $count{"oddtags $1"}++; - return $obj; - } - m/^object (\w+)\n/m or die "$obj ?"; - my $oldref = $1; - my $newref = rewrite_commit $oldref; - if ($oldref eq $newref) { - return $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) { - my ($obj, $type, $refname) = - $rline =~ m/^(\w+)\s+(\w+)\s+(\S.*)/ - or die "$_ ?"; - my $rewrite; - if ($type eq 'commit') { - $rewrite = rewrite_commit($obj); - if ($refname =~ m{^refs/dgit/[^/]+$} && - $rewrite ne $obj) { - $rewrite = rewrite_commit_adddummy $refname, $obj, $rewrite; - } - } elsif ($type eq 'tag') { - $rewrite = rewrite_tag($obj); - } else { - warn "ref $refname refers to $type\n"; - next; - } - next if $rewrite eq $obj; - push @updates, [ $refname, $obj, $rewrite ]; -} - -our $worktree; - -#print Dumper(\@updates); - -open U, "|git update-ref -m 'dgit bad commit fixup' --stdin" or die $!; - -if ($real && $bare eq 'false') { - print "detaching your HEAD\n" or die $!; - runcmd 'git checkout --detach'; -} - -for my $up (@updates) { - my ($ref, $old, $new) = @$up; - my $otherref = $ref; - $otherref =~ s{^refs/}{}; - if ($real) { - print U <; + my ($gtype, $gsize) = $x =~ m/^\w+ (\w+) (\d+)\n/ or die "$obj ?"; + $gtype eq $type or die "$obj $gtype != $type ?"; + my $gdata; + (read GCFO, $gdata, $gsize) == $gsize or die "$obj $!"; + $x = ; + $x eq "\n" or die "$obj ($_) $!"; + $count{inspected}++; + return $gdata; +} + +sub hashobj ($$) { + my ($data,$type) = @_; + my $gwopid = open2 \*GWO, \*GWI, + "git hash-object -w -t $type --stdin" + or die $!; + print GWI $data or die $!; + close GWI or die $!; + $_ = ; + close GWO or die $!; + waitpid $gwopid,0 == $gwopid or die $!; + die $? if $?; + m/^(\w+)\n/ or die "$_ ?"; + $count{"rewritten $type"}++; + return $1; +} + +our %memo; + +sub rewrite_commit ($); +sub rewrite_commit ($) { + my ($obj) = @_; + my $m = \ $memo{$obj}; + return $$m if defined $$m; + my $olddata = getobj $obj, 'commit'; + $olddata =~ m/(?<=\n)(?=\n)/ or die "$obj ?"; + my $msg = $'; + local $_ = $`; + s{^(parent )(\w+)$}{ $1 . rewrite_commit($2) }gme; + $count{'fix overwrite'} += s{^commiter }{committer }gm; + if (!m{^author }m && !m{^committer }m) { + m{^parent (\w+)}m or die "$obj ?"; + my $parent = getobj $1, 'commit'; + $parent =~ m/^(?:.+\n)+(author .*\ncommitter .*\n)/; + m/\n$/ or die "$obj ?"; + $_ .= $1; + $count{'fix import'}++; + } + my $newdata = $_.$msg; + my $newobj; + if ($newdata eq $olddata) { + $newobj = $obj; + $count{unchanged}++; + } else { + $newobj = hashobj $newdata, 'commit'; + } + $$m= $newobj; + return $newobj; +} + +sub rewrite_commit_adddummy ($$$) { + my ($ref, $veryold, $old) = @_; + + die "$bare ?" unless $bare eq 'true'; + + 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 $!; + runcmd qw(git checkout -q), $old; + + open C, "debian/changelog" or die $!; + my $clog = do { + local $/ = undef; + ; + }; + C->error and die $!; + close C or die $!; + defined $clog or die $!; + + $!=0; $?=0; + my $v = `dpkg-parsechangelog`; + die "$ref $veryold $old $? $!" if $?; + $v =~ m/^Source: (\S+)$/m or die "$ref $veryold $old ?"; + my $pkg = $1; + $v =~ m/^Version: (\S+)$/m or die "$ref $veryold $old ?"; + my $vsn = $1; + $vsn .= "+~dgitfix"; + + open C, ">", "debian/changelog" or die $!; + print C < Thu, 05 Jan 2017 17:58:21 +0000 + +END + print C $clog or die $!; + close C or die $!; + + runcmd qw(git commit -q), + '--author=Ian Jackson ', + qw(-m), 'Dummy changelog entry to work around #849041 fallout', + qw(debian/changelog); + + $!=0; $?=0; + my $new = `git rev-parse HEAD`; + die "$? $!" if $?; + chomp $new or die; + + chdir '..' or die $!; + runcmd qw(rm -rf), $td; + + $count{dummyadded}++; + + return $new; +} + +sub rewrite_tag ($) { + my ($obj) = @_; + $_ = getobj $obj, 'tag'; + m/^type (\w+)\n/m or die "$obj ?"; + if ($1 ne 'commit') { + $count{"oddtags $1"}++; + return $obj; + } + m/^object (\w+)\n/m or die "$obj ?"; + my $oldref = $1; + my $newref = rewrite_commit $oldref; + if ($oldref eq $newref) { + return $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) { + my ($obj, $type, $refname) = + $rline =~ m/^(\w+)\s+(\w+)\s+(\S.*)/ + or die "$_ ?"; + my $rewrite; + if ($type eq 'commit') { + $rewrite = rewrite_commit($obj); + if ($refname =~ m{^refs/dgit/[^/]+$} && + $rewrite ne $obj) { + $rewrite = rewrite_commit_adddummy $refname, $obj, $rewrite; + } + } elsif ($type eq 'tag') { + $rewrite = rewrite_tag($obj); + } else { + warn "ref $refname refers to $type\n"; + next; + } + next if $rewrite eq $obj; + push @updates, [ $refname, $obj, $rewrite ]; +} + +our $worktree; + +#print Dumper(\@updates); + +open U, "|git update-ref -m 'dgit bad commit fixup' --stdin" or die $!; + +if ($real && $bare eq 'false') { + print "detaching your HEAD\n" or die $!; + runcmd 'git checkout --detach'; +} + +for my $up (@updates) { + my ($ref, $old, $new) = @$up; + my $otherref = $ref; + $otherref =~ s{^refs/}{}; + if ($real) { + print U <