93 lines
2.1 KiB
Perl
Executable File
93 lines
2.1 KiB
Perl
Executable File
#!/usr/bin/perl
|
|
# SPDX-License-Identifier: MIT
|
|
#
|
|
# reverses the entire git history, producing new commits
|
|
#
|
|
|
|
use IPC::Open2;
|
|
use strict;
|
|
|
|
my $rev_array = [];
|
|
my $rev_ptr = {};
|
|
my $rev_new = {};
|
|
if (!open(FH, "git log '--pretty=format:%H %P' |")) {
|
|
die();
|
|
}
|
|
while (defined(my $line = <FH>)) {
|
|
chomp($line);
|
|
my($commit, @parents) = split(/\s+/, $line);
|
|
|
|
push(@$rev_array, $commit);
|
|
if (!exists($rev_ptr->{$commit})) {
|
|
$rev_ptr->{$commit} = [];
|
|
}
|
|
|
|
foreach my $p (@parents) {
|
|
my $q;
|
|
|
|
if (!exists($rev_ptr->{$p})) {
|
|
$q = [];
|
|
$rev_ptr->{$p} = $q;
|
|
} else {
|
|
$q = $rev_ptr->{$p};
|
|
}
|
|
push(@$q, $commit);
|
|
}
|
|
}
|
|
close FH;
|
|
|
|
sub split_commit
|
|
{
|
|
my($author_name, $author_email, $author_date);
|
|
my($cmit_name, $cmit_email, $cmit_date);
|
|
|
|
while (defined(my $line = shift @_)) {
|
|
chomp $line;
|
|
my($type) = ($line =~ /^(\w+)/);
|
|
|
|
if ($type eq "author") {
|
|
($author_name, $author_email, $author_date) =
|
|
($line =~ /^author (.*) <(.*?)> (.*)/);
|
|
} elsif ($type eq "committer") {
|
|
($cmit_name, $cmit_email, $cmit_date) =
|
|
($line =~ /^committer (.*) <(.*?)> (.*)/);
|
|
} elsif (!defined($type)) {
|
|
last;
|
|
}
|
|
}
|
|
|
|
return ($author_name, $author_email, $author_date,
|
|
$cmit_name, $cmit_email, $cmit_date, join("", @_));
|
|
}
|
|
|
|
foreach my $commit (@$rev_array) {
|
|
my($an, $ae, $ad, $cn, $ce, $cd, $log) =
|
|
split_commit(`git cat-file commit $commit`);
|
|
|
|
my @cmd = ("git", "commit-tree", "$commit^{tree}");
|
|
foreach my $parent (@{$rev_ptr->{$commit}}) {
|
|
push(@cmd, "-p", $rev_new->{$parent});
|
|
}
|
|
|
|
# print "GIT_AUTHOR_NAME=\"$an\" GIT_AUTHOR_DATE=\"$ad\" ";
|
|
# print "GIT_AUTHOR_EMAIL=\"$ae\" ";
|
|
# print "GIT_COMMITER_NAME=\"$cn\" ";
|
|
# print "GIT_COMMITTER_EMAIL=\"$ce\" CIT_COMMITTER_DATE=\"$cd\" ";
|
|
print join(" ", @cmd), "\n";
|
|
my($k_out, $k_in);
|
|
$ENV{GIT_AUTHOR_NAME} = $an;
|
|
$ENV{GIT_AUTHOR_EMAIL} = $ae;
|
|
$ENV{GIT_AUTHOR_DATE} = $ad;
|
|
$ENV{GIT_COMMITTER_NAME} = $cn;
|
|
$ENV{GIT_COMMITTER_EMAIL} = $ce;
|
|
$ENV{GIT_COMMITTER_DATE} = $cd;
|
|
my $pid = open2($k_in, $k_out, @cmd);
|
|
print $k_out $log;
|
|
close $k_out;
|
|
chomp(my $new_commit = <$k_in>);
|
|
close $k_in;
|
|
waitpid($pid, 0);
|
|
$rev_new->{$commit} = $new_commit;
|
|
print "Created $new_commit\n";
|
|
}
|