hxtools/examples/git-deconstruct

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";
}