summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKent Fredric <kentfredric@gmail.com>2012-11-06 08:25:10 +1300
committerKent Fredric <kentfredric@gmail.com>2012-11-06 10:06:12 +1300
commit6e9887dc876dfcee2c8ece99ce2f30a76c33648a (patch)
treecb5ba109fb2341a803c677713f6a4d27d5032617 /scripts/git
parent[scripts/lib] perform physical resolution of path to perl_experimental.pm (diff)
downloadperl-overlay-6e9887dc876dfcee2c8ece99ce2f30a76c33648a.tar.gz
perl-overlay-6e9887dc876dfcee2c8ece99ce2f30a76c33648a.tar.bz2
perl-overlay-6e9887dc876dfcee2c8ece99ce2f30a76c33648a.zip
[scripts] add branch/tree filter to ignore changes outside a given DIR over a sequence of commits
Diffstat (limited to 'scripts/git')
-rw-r--r--scripts/git/branch-filter/tree-filter/directory_change_restrict.pl146
-rw-r--r--scripts/git/directory_changes_to_branch.pl43
2 files changed, 189 insertions, 0 deletions
diff --git a/scripts/git/branch-filter/tree-filter/directory_change_restrict.pl b/scripts/git/branch-filter/tree-filter/directory_change_restrict.pl
new file mode 100644
index 000000000..c1107cc73
--- /dev/null
+++ b/scripts/git/branch-filter/tree-filter/directory_change_restrict.pl
@@ -0,0 +1,146 @@
+#!/usr/bin/env perl
+
+use v5.12;
+use strict;
+use warnings;
+
+# FILENAME: directory_change_restrict.pl
+# CREATED: 06/11/12 08:04:15 by Kent Fredric (kentnl) <kentfredric@gmail.com>
+# ABSTRACT: Restrict changes to happen in a single dir
+#
+#
+
+sub USAGE {
+ return <<"EOT";
+
+ $0
+
+ $0 PRESERVEPATH COMMIT
+
+ GIVEN: a path in git you wish to keep the history of, and to ignore changes outside of
+
+ a commit to ignore changes beyond
+
+
+ git
+ filter-branch
+ --prune-empty
+ --tree-filter 'perl path/to/$0 PRESERVEPATH COMMIT'
+ range_start..range_end
+
+ABOUT
+
+ If you have a series of commits crossing multiple directories, but you're only
+ interested in *changes* that occurred for certain specific directories for certain specific commit ranges, ie:
+
+ ~9000 previous commits
+
+ COMMIT9000:
+ +- dir/a
+ +- dir/b
+ +- dir/c
+
+ COMMIT9001:
+ +- dir/b
+ +- dir/c
+
+ COMMIT9002:
+ +- dir/a
+
+ COMMIT9003:
+ +- dir/a
+ +- dir/c
+
+
+ You don't want to *delete* paths b & c just to isolate changes to a after commit 9000
+
+ So you create a branch,
+
+ git checkout -b selective-a master
+
+ And filter chanegs only to a
+
+ git filter-branch
+ --prune-empty
+ --tree-filter 'perl path/to/$0 dir/a COMMIT8999'
+ COMMIT9000..COMMIT9003
+
+ The resulting branch 'selective-a' should look like:
+
+ COMMIT9000:
+ +- dir/a
+
+ COMMIT9002:
+ +- dir/a
+
+ COMMIT9003:
+ +- dir/a
+
+
+ But changes to dir/b and dir/c prior to COMMIT9000 are preserved in this branches history.
+
+ This is a useful tool to exercise to split commits pertaining to multiple ebuilds into per-package histories
+ instead of shared history commits.
+
+
+EOT
+}
+
+use Git::Wrapper;
+use Path::Class qw( dir file );
+use File::Temp qw();
+
+my ( $path, $commit ) = @ARGV;
+
+if ( $ENV{DIRECTORY_CHANGE_RESTRICT_path} ) {
+ $path = $ENV{DIRECTORY_CHANGE_RESTRICT_path};
+ $commit = @ARGV;
+}
+if ( $ENV{DIRECTORY_CHANGE_RESTRICT_commit} ) {
+ $commit = $ENV{DIRECTORY_CHANGE_RESTRICT_commit};
+}
+
+if ( not $path or not $commit ) {
+ die USAGE();
+}
+
+my $git = Git::Wrapper->new('.');
+
+if ( not -e $path ) {
+ revert_tree($commit);
+ exit 0;
+}
+
+my $preserve = ( -f $path ? file($path) : dir($path) );
+
+my $tempfile = File::Temp->new( 'git-filter-branch.XXXXX', SUFFIX => '.tar', TMPDIR => 1, UNLINK => 1 );
+
+tar( '-cf', $tempfile->filename, $preserve );
+revert_tree($commit);
+if ( -f $preserve ) {
+ $preserve->remove();
+}
+else {
+ $preserve->rmtree();
+}
+tar( '-xf', $tempfile->filename );
+
+sub revert_tree {
+ my ($commit) = @_;
+ $git->reset( qw( --hard ), $commit, '--' );
+ $git->reset(qw( --soft ORIG_HEAD -- ));
+}
+
+sub tar {
+ my (@args) = @_;
+ open my $fh, '-|', 'tar', @args or do {
+ die "Error calling tar: $? $! $@";
+ };
+ while ( my $line = <$fh> ) {
+ chomp $line;
+ print "\e[39m$line\e[0m\n";
+ }
+ $fh->close or do {
+ warn "Error closing tar: $? $! $@";
+ };
+}
diff --git a/scripts/git/directory_changes_to_branch.pl b/scripts/git/directory_changes_to_branch.pl
new file mode 100644
index 000000000..b88147f68
--- /dev/null
+++ b/scripts/git/directory_changes_to_branch.pl
@@ -0,0 +1,43 @@
+#!/usr/bin/env perl
+eval 'echo "Called with something not perl"' && exit 1 # Non-Perl protection.
+ if 0;
+
+use 5.14.2;
+use strict;
+use warnings;
+
+use FindBin;
+use lib "$FindBin::Bin/../lib";
+
+use env::gentoo::perl_experimental;
+
+
+
+# FILENAME: directory_changes_to_branch.pl
+# CREATED: 06/11/12 08:45:40 by Kent Fredric (kentnl) <kentfredric@gmail.com>
+# ABSTRACT: convert a history of changes to a given path to a dedicated branch
+
+my ( $branchname, $path, $branch_base , $branch_tip ) = @ARGV;
+my ( $env ) = env::gentoo::perl_experimental->new();
+
+use Git::Wrapper;
+use Git::Repository;
+use File::Temp;
+
+my $git = Git::Repository->new( work_tree => $env->root );
+
+say "Creating branch $branchname based on changes in $path since $branch_base";
+
+my $filter = $env->root->subdir('scripts')->subdir('git')->subdir('branch-filter')->subdir('tree-filter')->file('directory_change_restrict.pl');
+
+$ENV{DIRECTORY_CHANGE_RESTRICT_path} = $path;
+$ENV{DIRECTORY_CHANGE_RESTRICT_commit} = $branch_base;
+
+use File::pushd;
+
+my $cwd = pushd( $env->root->stringify );
+
+$git->run('checkout','-b',$branchname , $branch_tip );
+$git->run( 'filter-branch', '-f', qw( --prune-empty --tree-filter ),"$^X $filter", $branch_base . '..' . $branchname );
+
+