2 # This is a generic update hook script for GIT repositories.
3 # Written by Martin Mares <mj@ucw.cz> and placed into public domain.
13 my $subject_prefix = "GIT";
17 'mail-to=s' => \$mail_to,
18 'subject-prefix=s' => \$subject_prefix,
19 'max-diff-size=s' => \$max_diff_size,
20 ) and @ARGV == 3 or die <<AMEN ;
21 Usage: $0 [<options>] <refname> <sha1-old> <sha1-new>
24 --mail-to=<address> Send mail to the given address
25 --max-diff-size=<bytes> If the diff is too long, send just a summary
26 --subject-prefix=<px> Prefix subjects with [<px>] (default: GIT)
29 my ($ref, $old, $new) = @ARGV;
30 $ref =~ s{^refs/heads/}{} or exit 0;
31 $old ne $new or exit 0;
33 my $subj = '[' . $subject_prefix . ($ref eq 'master' ? '' : "/$ref") . ']';
34 my $out = File::Temp->new() or die;
35 my $outname = $out->filename;
38 open STDOUT, '>&', $out or die;
40 my @rev_list_options = ('--pretty', '--no-abbrev', '--date=iso');
41 my @diff_options = ('-C');
44 # Is there any branch pointing to $new ?
45 for (`git branch -v --no-abbrev`) {
47 my ($name, $sha) = /^..(\S+)\s+(\S+)/ or die;
48 if ($name ne $ref && $sha eq $new) {
56 print $out "Most recent commits:\n\n";
57 system 'git', 'rev-list', @rev_list_options, '--max-count=20', $new;
66 # Creation of a branch
67 $subj .= ' Created branch';
68 my $copy_of = scan_branches();
69 if (defined $copy_of) {
70 $subj .= " as a copy of $copy_of";
71 print $out "Created branch $ref as a copy of $copy_of.\n";
73 print $out "Created branch $ref.\n\n";
76 } elsif ($new =~ /^0+$/) {
77 # Deletion of a branch
78 $subj .= ' Branch deleted';
79 print $out "Deleted branch $ref.\n\nPrevious tip was $old.\n";
81 my $lca = `git merge-base $old $new`; die if $?;
85 # Scan all commits first and construct subject
86 my @commits = `git rev-list $old..$new --pretty=oneline --no-abbrev --no-merges`; $? and die;
93 # If there are multiple commits, print an overall diffstat first
96 print $out "Overall diffstat:\n\n";
97 system 'git', 'diff', '--stat', $old, $new;
98 print $out "\nCommits:\n\n";
100 my $pos_after_header = output_size();
102 # Show individual commits with diffs and stats
103 system 'git', 'log', @rev_list_options, '--reverse', @diff_options, '-p', '--stat', "$old..$new";
105 # If the file is too long, truncate it and print just a summary
106 if (defined($max_diff_size) && output_size() > $max_diff_size) {
107 $out->truncate($pos_after_header);
109 print $out "Diff was too long, printing just a summary.\n\n";
110 system 'git', 'log', @rev_list_options, '--reverse', "$old..$new";
112 } elsif ($lca eq $new) {
114 $subj .= ' Branch rewound';
115 print $out "Rewound branch $ref to commit $new.\n\n";
118 # Otherwise it is a rebase
119 $subj .= ' Branch rebased';
120 print $out "Rebased branch $ref to commit $new.\n\n";
121 print $out "Commits from common ancestor:\n\n";
122 system 'git', 'rev-list', @rev_list_options, $new, "^$old";
127 if (defined $mail_to) {
129 open STDIN, '<', $outname;
134 'set charset="utf-8"; set send_charset="us-ascii:iso-8859-2:utf-8"',
138 print STDERR "Subject: $subj\n\n";