On 03/19/2010 11:39 AM, Andy Parkins wrote: > Eli Barzilay wrote: > >> The post-receive-email script goes out of its way to avoid sending >> commits twice by filtering out commits that are included in existing >> refs, but if more than one branch changes then some commits can end up >> not being reported. For example, I made two commits A and B, made one >> branch point at A and another at B, and pushed both -- neither of the >> resulting two emails had A. > > <Andy starts crying> > > I can't see any way to deal with this case easily with post-receive-email as > it is. It inherently processes ref-by-ref. The relevant bit of script is > in generate_update_branch_email(). The comments explain how the same > problem is addressed for another developer changing the same branch before > post-receive-email runs, but after the update is performed. I think the > same method could be applied. > > git rev-parse --not --all | grep -v $(git rev-parse $refname) > > This line is where the particular branches are being included and excluded. > The problem you have is that "--all" means "--all-at-the-moment", and you > want "--all-as-they-were-before-the-update". > > So, --all will have to go, and a manual list built instead. The supplied > change list includes all the information necessary: > > ref1_oldrev ref1_newrev ref1 > ref2_oldrev ref2_newrev ref2 > ref3_oldrev ref3_newrev ref3 > ref4_oldrev ref4_newrev ref4 > > Let's say there is also a ref5 and ref6 in the repository. The revision > list we want for (say) the ref1 call to generate_email would be: > > ref1_newrev > ^ref2_oldrev > ^ref3_oldrev > ^ref4_oldrev > ^ref5 > ^ref6 > > And similarly for ref2, ref3 and ref4. It seems to me that it needs a hash > table keyed on the refname, but I have no idea how to do that in bash. > > %originalreftable{"ref1"} = "^ref1_oldrev" > %originalreftable{"ref2"} = "^ref2_oldrev" > %originalreftable{"ref3"} = "^ref3_oldrev" > %originalreftable{"ref4"} = "^ref4_oldrev" > %originalreftable{"ref5"} = "^ref5" > %originalreftable{"ref6"} = "^ref6" > > This table would be sufficient to create the revision list for every > generate_email(), because each generate_email() knows which ref it's being > updated for, so could easily do: > > %originalreftable{$myref} = "$mynewrev" > > Before using the table (and restore it afterwards). > > In short: yuck. It feels an awful lot like its pushing the boundaries of > what is sensible to do in shell script. Here's how I did it. I did this so quickly and so long ago that I forgot about giving it a final think-through and submitting it. Now that I look at it again, and the fact that it has been working for a good long while, it doesn't look as ugly as I remember it. What do you think? Sane enough? Warning: copy/pasted so beware white space corruption diff --git a/contrib/hooks/post-receive-email b/contrib/hooks/post-receive-email index 58a35c8..42dc4e7 100755 --- a/contrib/hooks/post-receive-email +++ b/contrib/hooks/post-receive-email @@ -619,9 +619,8 @@ show_new_revisions() revspec=$oldrev..$newrev fi - other_branches=$(git for-each-ref --format='%(refname)' refs/heads/ | - grep -F -v $refname) - git rev-parse --not $other_branches | + git rev-parse --not --branches | grep -v $(git rev-parse $refname) | + sed $sed_rev_script | if [ -z "$custom_showrev" ] then git rev-list --pretty --stdin $revspec @@ -680,10 +679,22 @@ if [ -n "$1" -a -n "$2" -a -n "$3" ]; then # Output to the terminal in command line mode - if someone wanted to # resend an email; they could redirect the output to sendmail # themselves + sed_rev_script="-e s/$3/$2/" PAGER= generate_email $2 $3 $1 else + numrevs=0 while read oldrev newrev refname do - generate_email $oldrev $newrev $refname | send_mail + sed_rev_script="$sed_rev_script -e s/$newrev/$oldrev/" + oldrevs[$numrevs]=$oldrev + newrevs[$numrevs]=$newrev + refnames[$numrevs]=$refname + numrevs=$(($numrevs + 1)) + done + i=0 + while [ $i -lt $numrevs ]; do + generate_email ${oldrevs[$i]} ${newrevs[$i]} ${refnames[$i]} | + send_mail + i=$(($i + 1)) done fi -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html