On Wed, 29 Jan 2014 06:51:48 -0800 (PST)
Gabby Romano <omerik...@gmail.com> wrote:

> it might be an easy one but somehow I am not sure how to get my hands
> on it. I want to have a hook which checks the content of the a file
> and to decide whether to deny or accept the push by some validation
> on the content. how do I extract the content of the related files ?
> (bare repo of course)
> 
> I know that git show <branch name>:<path> will do, but that is for
> the current objects in the repo. what I need are the pushed ones,
> before it's being applied.

Your "problem" is that you're supposedly stuck with the idea that
`git show` has to take a branch name while in fact it might be any
"commitish"--a specification which is resolvable to the SHA-1 name
of a commit; this might be a branch name, a tag name, the SHA-1 name of
a commit, directly, something involved like foo~5^3 and so on
(see the gitrevisions manual page for more details).

What this has to do with your problem is that pre-/post-receive and
update hooks receive a list of refs to be updated--each along with the
two SHA-1 names of commits: one is what that ref currently points at,
and another one is its prospective replacement.  The details are in the
githooks manual page.

So your hook program, for each ref to be updated, should parse out the
SHA-1 name of its prospective new commit, check it's not just forty "0"
characters, meaning the ref is about to be deleted, and if these checks
pass, call `git show <sha1name>:<path>` and do whatever it pleases with
the contents of that blob.  Note that you're telling about "current
objects in the repo" and the fact is the objects received during the
push operation *are* in the repo by the time the appropriate hooks run,
just the refs (heads, tags etc) are not yet updated to point to the new
values.  Should a pre- or post-receive hook exit with a non-zero return
code, and the refs won't be updated and the received objects will be
eventually garbage-collected (because they are orphan--not referenced
by any live ref).

As usually, you have to be prepared to deal with two things:
* The <path> might legitimately not exist in a commit, in which case
  `git show` will fail, and you have to be prepared to somehow
  handle this case.
* Using the way just explained, you'll be checking just the tip commit
  but a push operation might update a ref with arbitrary graph of
  commits (that is, not just a single commit and not even with just
  a straight line of commits), so if you want to be sure the blob
  recorded under the name <path> exists in *each* of the commits of
  that graph, and has sensible contents there, you'll have to arrange
  for walking that graph, checking each commit along the way.

You might consider reading [1] and [2] useful.

1. https://groups.google.com/d/msg/git-users/Tj1W7Xuqybw/zQhFbPLks-gJ
2. https://groups.google.com/d/msg/git-users/DzxY0wkyJPE/mFFL83Lm6wsJ

-- 
You received this message because you are subscribed to the Google Groups "Git 
for human beings" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to git-users+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to