git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Server-side hooks on non-bare repository
@ 2017-03-04  0:10 Mike Lewis
  2017-03-06 21:42 ` Junio C Hamano
  0 siblings, 1 reply; 3+ messages in thread
From: Mike Lewis @ 2017-03-04  0:10 UTC (permalink / raw)
  To: git

Hello,

I’m having some issues with using server-side hooks when pushing to a non-bare repository. In my git config, I have `receive.denyCurrentBranch` set to `updateInstead`, which behaves as expected, and updates the current working tree when the current branch is pushed to. However, attempting to process those changes with pre-receive and post-receive hooks results in some unexpected behavior regarding the current working directory of the scripts and using git commands. I’ve tested these issues using both git 2.11 and 2.12 on various systems (macOS and CentOS), and get the same behavior each time.

Essentially, my problem boils down to two things:

1. When using a non-bare repository, I would expect the the working directory of the hook to be the root directory of the working tree, as this mirrors the behavior of “client”-side hooks like pre-commit. Instead, the working directory is set to the .git directory. That in and of itself is not a huge deal, but it leads into #2:

2. While running the hooks, git treats the repository as being bare, regardless of whether it actually is. For instance, changing the working directory of the scripts to the actual root of the working tree and attempting to run any git commands (for instance, `git rev-parse --abbrev-ref HEAD` to get the current branch name) results in "fatal: Not a git repository: ‘.’” being returned to the client-side `git push` command. I’ve found a workaround to this, which is to explicitly set the “GIT_DIR” to the .git directory, and make sure that is passed to any external scripts as well. However, this is very unintuitive behavior, as the working tree is still there and either unmodified or done being updated, depending on which hook is being called. At the very least, this behavior should be in the documentation somewhere so that users can write their hooks accordingly.

TL;DR: it seems that server-side hooks don’t account for the repository being non-bare, which is no longer a valid assumption with the `receive.denyCurrentBranch=updateInstead` configuration value introduced in 2.3.0.

Thanks, and I’d be happy to provide any other information that anyone needs to take a look at this.

Mike Lewis


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Server-side hooks on non-bare repository
  2017-03-04  0:10 Server-side hooks on non-bare repository Mike Lewis
@ 2017-03-06 21:42 ` Junio C Hamano
  2017-03-06 22:33   ` Mike Lewis
  0 siblings, 1 reply; 3+ messages in thread
From: Junio C Hamano @ 2017-03-06 21:42 UTC (permalink / raw)
  To: Mike Lewis; +Cc: git

Mike Lewis <mike@mplew.is> writes:

> I’m having some issues with using server-side hooks when pushing
> to a non-bare repository. In my git config, I have
> `receive.denyCurrentBranch` set to `updateInstead`, which behaves
> as expected, and updates the current working tree when the current
> branch is pushed to. However, attempting to process those changes
> with pre-receive and post-receive hooks results in some unexpected
> behavior regarding the current working directory of the scripts
> and using git commands.

The pre-receive hook is to inspect the objects and ref updates and
say "yes, allow it" or "no, refuse it"---you are not supposed to do
anything else, so even though what processing you are interested in
doing in your "attempting to process" is unclear, this hook is not
what you want to use anyway.

The post-receive hook is a more interesting case.  It is called only
after everything finishes, so it is like running a custom script
after "git push" is processed.

> I’ve tested these issues using both git
> 2.11 and 2.12 on various systems (macOS and CentOS), and get the
> same behavior each time.

That is a very good news, as I do not think at least in the past few
years we planned to change the established behaviour of the hook.

> 1. When using a non-bare repository, I would expect the the
> working directory of the hook to be the root directory of the
> working tree,...
> 2. While running the hooks, git treats the repository as being
> bare, regardless of whether it actually is.

Yes, and it is unlikely that the behaviour wrt to where $cwd is
during the hook's execution will ever change; otherwise existing
scripts that know what the rule is (i.e. the rule you figured out in
2.) will be broken.  denycurrent=updateinstead *is* an odd-man out,
and its processing is purely internal---its addition does not mean
hook authors are suddenly required to do things differently
depending on bare/non-bare-ness of the repository.



^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Server-side hooks on non-bare repository
  2017-03-06 21:42 ` Junio C Hamano
@ 2017-03-06 22:33   ` Mike Lewis
  0 siblings, 0 replies; 3+ messages in thread
From: Mike Lewis @ 2017-03-06 22:33 UTC (permalink / raw)
  To: Junio C Hamano; +Cc: git

Hi Junio,

Thanks for taking the time to reply. I apologize if there was a misunderstanding in my previous email; I'm relatively new to dealing with some of the more advanced features of git, and did not describe my situation as clearly as possible.

I am using the pre-receive hook to determine whether to allow the push or not. Essentially, I'm rejecting the entire push if a branch not checked out is pushed, and then ensuring that a backup has been made of some critical data to prevent any issues with deployment (and if that backup fails for whatever reason, I also reject the push). The post-receive hook is essentially used for notification of a couple services that the push had been completed.

My point #1 was supposed to be something along the lines of "I found this behavior unintuitive and poorly documented, but it's fine since I can work around it", but it didn't come across that way. I understand that breaking backwards compatibility by changing this behavior would be a huge deal, and I was not intending to suggest it. 

Point #2, however is what I was attempting to discuss in more detail. I'm curious as to why git doesn't recognize that it's currently inside the working tree in that situation, and if that's intended or not. There's no update currently happening in either hook (since they are called immediately before and after any changes), which means that I can't see a reason to have behavior that differs (having to specify a GIT_DIR, which may or may not be a complete workaround) between when the hooks are running and when they're not. That doesn't mean there isn't a reason; it's more likely I'm just not familiar enough with how the hooks are called internally to see it, and am looking for a more thorough explanation as to the motivations behind this behavior. If it's intended and not going to change, I think the behavior should be documented more thoroughly so that nobody has to repeat the process I did to find out why my hooks were failing. I don't mind contributing to this, but I have no idea where to start. 

Anyways, thanks for responding, and I apologize again if my first email was poorly written and rushed. 

Mike Lewis

> On Mar 6, 2017, at 16:42, Junio C Hamano <gitster@pobox.com> wrote:
> 
> Mike Lewis <mike@mplew.is> writes:
> 
>> I’m having some issues with using server-side hooks when pushing
>> to a non-bare repository. In my git config, I have
>> `receive.denyCurrentBranch` set to `updateInstead`, which behaves
>> as expected, and updates the current working tree when the current
>> branch is pushed to. However, attempting to process those changes
>> with pre-receive and post-receive hooks results in some unexpected
>> behavior regarding the current working directory of the scripts
>> and using git commands.
> 
> The pre-receive hook is to inspect the objects and ref updates and
> say "yes, allow it" or "no, refuse it"---you are not supposed to do
> anything else, so even though what processing you are interested in
> doing in your "attempting to process" is unclear, this hook is not
> what you want to use anyway.
> 
> The post-receive hook is a more interesting case.  It is called only
> after everything finishes, so it is like running a custom script
> after "git push" is processed.
> 
>> I’ve tested these issues using both git
>> 2.11 and 2.12 on various systems (macOS and CentOS), and get the
>> same behavior each time.
> 
> That is a very good news, as I do not think at least in the past few
> years we planned to change the established behaviour of the hook.
> 
>> 1. When using a non-bare repository, I would expect the the
>> working directory of the hook to be the root directory of the
>> working tree,...
>> 2. While running the hooks, git treats the repository as being
>> bare, regardless of whether it actually is.
> 
> Yes, and it is unlikely that the behaviour wrt to where $cwd is
> during the hook's execution will ever change; otherwise existing
> scripts that know what the rule is (i.e. the rule you figured out in
> 2.) will be broken.  denycurrent=updateinstead *is* an odd-man out,
> and its processing is purely internal---its addition does not mean
> hook authors are suddenly required to do things differently
> depending on bare/non-bare-ness of the repository.
> 
> 


^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2017-03-06 22:42 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-03-04  0:10 Server-side hooks on non-bare repository Mike Lewis
2017-03-06 21:42 ` Junio C Hamano
2017-03-06 22:33   ` Mike Lewis

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).