-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathpost-commit-filter.pl
More file actions
executable file
·79 lines (64 loc) · 2.28 KB
/
post-commit-filter.pl
File metadata and controls
executable file
·79 lines (64 loc) · 2.28 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
#!/usr/bin/env perl
# $Author: $Format:%an <%ae>$ $
# $Date: $Format:%ai$ $
# $Revision: $Format:%h$ $
use strict;
use warnings;
use Git;
use Archive::Zip qw(:ERROR_CODES);
my $git = Git->repository();
if (!defined $git) {
print STDERR "Must be executed from within a Git repository.\n";
exit 1;
}
my @files = ();
my $repo_path = $git->repo_path();
my $keywords_path = $repo_path.'/keywords';
my $use_orig_head_path = $keywords_path.'/use_orig_head';
my $use_orig_head;
if (-d $keywords_path && -f $use_orig_head_path) {
$use_orig_head = 1;
@files = $git->command('diff-tree', '--name-only', '-r', 'ORIG_HEAD', 'HEAD');
} else {
@files = $git->command('diff-tree', '--no-commit-id', '--name-only', '-r', 'HEAD');
}
# full file list from ORIG_HEAD to HEAD
# could contain renamed or deleted files
if ($use_orig_head) {
@files = grep { -e } @files;
}
# preserve any working copy changes that weren't staged for commit
# don't want to overwrite pending changes if 'add -p' or similar
my $diff = !!$git->command('diff', '--name-only');
if ($diff) {
$git->command('stash', '--keep-index', '-q');
}
# extract files that were in the latest commit
# or extant files following a merge resolution
for my $file (@files) {
my $commit = $git->command_oneline('log', '-1', '--format=%H', 'HEAD', '--', $file);
my ($fh, $ctx) = $git->command_output_pipe('archive', '--worktree-attributes', '--format=zip', '-0', $commit, $file);
my $zip_file = do { local $/; <$fh> };
$git->command_close_pipe($fh, $ctx);
use IO::String;
my $zh = IO::String->new($zip_file);
my $zip = Archive::Zip->new();
$zip->readFromFileHandle($zh) == AZ_OK or die 'Couldn\'t open original ' . $file . '.';
$zip->extractMember($file);
close($zh) or die 'Failed to close in-memory zip:' . $!;
$git->command('update-index', $file);
}
if ($diff) {
my ($out, $outctx) = $git->command_output_pipe('stash', 'show', '-p');
open(my $in, '|-', 'patch', '-p1', '-s');
while (<$out>) {
print $in $_;
}
$git->command_close_pipe($out, $outctx);
close($in);
$git->command('stash', 'drop', '-q');
}
my $files_path = $keywords_path.'/files';
unlink $use_orig_head_path if $use_orig_head;
unlink $files_path if -e $files_path;
rmdir $keywords_path if -d $keywords_path;