{"thread":{"id":"16424","subject":"What about allowing multiple hooks?","startedAt":"2008-11-21T13:38:28Z","lastAt":"2009-01-22T09:57:02Z","messageCount":10,"participants":["Marc Weber","martin f krafft","Rogan Dawes","Alexander Potashev","Junio C Hamano","Anders Waldenborg","Johannes Schindelin"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"96339","messageId":"20081121133828.GB5912@gmx.de","threadId":"16424","inReplyTo":null,"subject":"What about allowing multiple hooks?","fromName":"Marc Weber","fromEmail":"marco-oweber@gmx.de","sentAt":"2008-11-21T13:38:28Z","receivedAt":"2008-11-21T13:38:28Z","isPatch":false,"sender":{"key":"marco-oweber@gmx.de","avatar":null},"body":"Use case:\n\nI've been reading parts of the topGit code. And it does make for it to\nadd its own checks. However having to change the existing scripts\ninsterting a call to the tg hooks isn't the best way.\nWhy? one is using #/bin/sh the next is using #/bin/ruby maybe..\n\nSo what about allowing (or even enforcing) ths directory layout?\n\n.git/hooks/pre-commit/hook1.sh\n.git/hooks/pre-commit/hook2.sh\n.git/hooks/pre-commit/topGitcheck.sh\n\ninstead of\n.git/hooks/pre-commit # <- the one and only pre-commit hook\n\nso that all can be run in squence?\n\nThis way you can keep the original git sample files and update them\nwhile adding you very own checks more easily.\n\nBut maybe this isn't the best choice either and the way to go is\n\n.git/hooks/list-of-hook-directories # eg containing \".git/hooks/samples\\n.git/hooks/topgit\" ?\n\n.git/hooks/sample/<all the sample hook files>\n.git/hooks/topgit/pro-commit\n\n?\n\nThen you can actually link in your own personal check script directories\neasily *and* you can add them to the repository eg by using\ncomitted-repo-hooks instead of .git/hooks\n?\nThis way you could provide different hook directories for different\nplatforms and all you have to do is enabling them by adding the path to\n.git/list-of-hook-directories ?\n\nI guess the second approach of defining kind of overlays is better\nbecause it doesn't interfer with the existiing scheme?\nMaybe it should be implemented as git config option instead of a file\ncontaining the list of directories?\n\nThe hook direcotry list apporach is better because you've more control\nabout order of execution..\n\nThoughts?\n\nMarc Weber\n"},{"id":"96340","messageId":"20081121135507.GA24516@piper.oerlikon.madduck.net","threadId":"16424","inReplyTo":"20081121133828.GB5912@gmx.de","subject":"Re: What about allowing multiple hooks?","fromName":"martin f krafft","fromEmail":"madduck@madduck.net","sentAt":"2008-11-21T13:55:07Z","receivedAt":"2008-11-21T13:55:07Z","isPatch":false,"sender":{"key":"madduck@madduck.net","avatar":null},"body":"also sprach Marc Weber <marco-oweber@gmx.de> [2008.11.21.1438 +0100]:\n> So what about allowing (or even enforcing) ths directory layout?\n> \n> .git/hooks/pre-commit/hook1.sh\n> .git/hooks/pre-commit/hook2.sh\n> .git/hooks/pre-commit/topGitcheck.sh\n> \n> instead of\n> .git/hooks/pre-commit # <- the one and only pre-commit hook\n\nIf you do this, I strongly suggest .git/hooks/pre-commit.d, and to\nuse .git/hooks/pre-commit to invoke it, which adds to transparency.\nDebian does this all over the place. You need to ignore backup files\nand/or only execute *.hook files, to be able to have other files in\nthere. Or the +x flag, as it is used now.\n\n> The hook direcotry list apporach is better because you've more\n> control about order of execution..\n\nIt's also way more transparent and natural.\n\n-- \nmartin | http://madduck.net/ | http://two.sentenc.es/\n \n\"america may be unique in being a country which has leapt\n from barbarism to decadence without touching civilization.\"\n                                                        -- john o'hara\n \nspamtraps: madduck.bogus@madduck.net\n"},{"id":"96344","messageId":"4926CC03.4000009@dawes.za.net","threadId":"16424","inReplyTo":"20081121133828.GB5912@gmx.de","subject":"Re: What about allowing multiple hooks?","fromName":"Rogan Dawes","fromEmail":"lists@dawes.za.net","sentAt":"2008-11-21T14:56:03Z","receivedAt":"2008-11-21T14:56:03Z","isPatch":false,"sender":{"key":"lists@dawes.za.net","avatar":null},"body":"Marc Weber wrote:\n> Use case:\n> \n> I've been reading parts of the topGit code. And it does make for it to\n> add its own checks. However having to change the existing scripts\n> insterting a call to the tg hooks isn't the best way.\n> Why? one is using #/bin/sh the next is using #/bin/ruby maybe..\n> \n> So what about allowing (or even enforcing) ths directory layout?\n> \n> .git/hooks/pre-commit/hook1.sh\n> .git/hooks/pre-commit/hook2.sh\n> .git/hooks/pre-commit/topGitcheck.sh\n\nI second Martin's suggestion, that you implement:\n\n.git/hooks/pre-commit\n.git/hooks/pre-commit.d/hook1.sh\n\nwhere hooks/pre-commit is e.g. a shell script much like the init scripts \nthat iterate over the executables in the corresponding .d/ directory, \nand execute them one at a time. Basing your script on initscripts will \nlikely save you some time, since they have already considered things \nlike script ordering, backups, etc.\n\nI'm also inclined to think that this is likely to be a local \ncustomisation, because you need to decide what makes sense in your \ncontext, aborting if a script exits with a non-zero result, or \ncontinuing to see if the next script manages to exit with a zero result.\n\ne.g. in the pre-commit case, it *probably* makes sense to allow any \nscript to abort the commit, but your site-specific requirements might be \nthat all hooks must fail to abort the commit.\n\nRegards,\n\nRogan\n"},{"id":"99272","messageId":"20090103233252.GA12095@myhost","threadId":"16424","inReplyTo":"20081121133828.GB5912@gmx.de","subject":"Re: What about allowing multiple hooks?","fromName":"Alexander Potashev","fromEmail":"aspotashev@gmail.com","sentAt":"2009-01-03T23:32:52Z","receivedAt":"2009-01-03T23:32:52Z","isPatch":false,"sender":{"key":"aspotashev@gmail.com","avatar":null},"body":"On 14:38 Fri 21 Nov     , Marc Weber wrote:\n> Use case:\n> \n> I've been reading parts of the topGit code. And it does make for it to\n> add its own checks. However having to change the existing scripts\n> insterting a call to the tg hooks isn't the best way.\n> Why? one is using #/bin/sh the next is using #/bin/ruby maybe..\n> \n> So what about allowing (or even enforcing) ths directory layout?\n> \n> .git/hooks/pre-commit/hook1.sh\n> .git/hooks/pre-commit/hook2.sh\n> .git/hooks/pre-commit/topGitcheck.sh\n> \n> instead of\n> .git/hooks/pre-commit # <- the one and only pre-commit hook\n> \n> so that all can be run in squence?\n\nIf we have a single hook, git just runs a script. But multiple scripts\ncan be run in different orders. We can assume that git should run them\nin lexicographical order, but sometimes it's not the best order can be\nused.\n\nHowever, prefixes can be used to force a particular lexicographical\norder:\n\t.git/hooks/pre-commit/01-hook2.sh\n\t.git/hooks/pre-commit/02-topGitcheck.sh\n\t.git/hooks/pre-commit/03-hook1.sh\n\nIs there a better way to choose the scripts order?\n\n> \n> This way you can keep the original git sample files and update them\n> while adding you very own checks more easily.\n> \n> But maybe this isn't the best choice either and the way to go is\n> \n> .git/hooks/list-of-hook-directories # eg containing \".git/hooks/samples\\n.git/hooks/topgit\" ?\n> \n> .git/hooks/sample/<all the sample hook files>\n> .git/hooks/topgit/pro-commit\n> \n> ?\n> \n> Then you can actually link in your own personal check script directories\n> easily *and* you can add them to the repository eg by using\n> comitted-repo-hooks instead of .git/hooks\n> ?\n> This way you could provide different hook directories for different\n> platforms and all you have to do is enabling them by adding the path to\n> .git/list-of-hook-directories ?\n> \n> I guess the second approach of defining kind of overlays is better\n> because it doesn't interfer with the existiing scheme?\n> Maybe it should be implemented as git config option instead of a file\n> containing the list of directories?\n> \n> The hook direcotry list apporach is better because you've more control\n> about order of execution..\n> \n> Thoughts?\n> \n> Marc Weber\n"},{"id":"99287","messageId":"7vd4f3z8xu.fsf@gitster.siamese.dyndns.org","threadId":"16424","inReplyTo":"20090103233252.GA12095@myhost","subject":"Re: What about allowing multiple hooks?","fromName":"Junio C Hamano","fromEmail":"gitster@pobox.com","sentAt":"2009-01-04T10:01:33Z","receivedAt":"2009-01-04T10:01:33Z","isPatch":false,"sender":{"key":"gitster@pobox.com","avatar":"https://avatars.githubusercontent.com/u/54884?v=4"},"body":"Alexander Potashev <aspotashev@gmail.com> writes:\n\n>> Thoughts?\n\nI deliberately omitted support for multiple scripts in core git Porcelains\nto avoid this exact issue.  It is a huge can of worms and it is dubious if\nyou can have a coherent and generic enough semantics.\n\nIn the meantime, you can have a single .git/hooks/pre-commit script that\ndefines your own convention.  Maybe it uses .git/hooks/pre-commit.d/\ndirectory, full of scripts, and implements the semantics you want,\nincluding:\n\n (1) the execution order and the naming convention of the scripts (e.g.\n     they all live in pre-commit.d/ directory, and executed in ASCII byte\n     value order of their names);\n\n (2) how their exit status combine together.  For example, maybe a failure\n     from one of the scripts prevents none of the later scripts to even\n     run and make the whole hook return a failure; maybe a failure will be\n     remembered, but the other scripts may still want to be run to learn\n     about the fact that the commit was attempted, and the whole hook\n     returns a failure if any of them fail.\n\n     In a hook that is run primarily for its side effects and not for\n     validation, it may even be desireble if the whole hook returns a\n     failure only when all of them fail, iow, for such a hook the status\n     is not ANDed but ORed together.\n\nOnce you have such a framework and get help from others to widely try it\nin the field, it may prove generic enough to include it as the sample hook\nscript to be installed everywhere.\n"},{"id":"101439","messageId":"4977872E.70901@0x63.nu","threadId":"16424","inReplyTo":"7vd4f3z8xu.fsf@gitster.siamese.dyndns.org","subject":"Re: What about allowing multiple hooks?","fromName":"Anders Waldenborg","fromEmail":"anders@0x63.nu","sentAt":"2009-01-21T20:35:58Z","receivedAt":"2009-01-21T20:35:58Z","isPatch":false,"sender":{"key":"anders@0x63.nu","avatar":"https://avatars.githubusercontent.com/u/1566016?v=4"},"body":"Junio C Hamano wrote:\n> I deliberately omitted support for multiple scripts in core git Porcelains\n> to avoid this exact issue.  It is a huge can of worms and it is dubious if\n> you can have a coherent and generic enough semantics.\n> \n> In the meantime, you can have a single .git/hooks/pre-commit script that\n> defines your own convention.  Maybe it uses .git/hooks/pre-commit.d/\n> directory, full of scripts, and implements the semantics you want,\n> including:\n> \n>  (1) the execution order and the naming convention of the scripts (e.g.\n>      they all live in pre-commit.d/ directory, and executed in ASCII byte\n>      value order of their names);\n >\n >  (2) how their exit status combine together.\n\nI need multiple hooks, so I've done some thinking about this, so I \nthought it may be a good idea to share this here.\n\nI currently use configvalues to specify which hooks to run. For example \nthis is how my post-receive looks:\n\ndata=$(cat)\ngit config --get-all hooks.post-receive.hook | while read hook; do\n         $hook <<__EOF__\n\"$data\"\n__EOF__\ndone\n\nNow none of my hooks wants to prevent update, so I don't care about \nreturn status. But it could easily be extended, for example by having \nsome indicator per hook that can have the values (are these enough?):\n\n  ignore - pretent that no failure was returned no matter what\n  sufficient - if this hook suceeds end result is always sucess\n  required - if this hook fails we fail, no more hooks are run\n\nThat could be done with the simple configvalue thing as follows:\n\ngit config -add hooks.post-receive.hook \\\n    \"sufficient allow-repo-owner-to-do-anything.sh\"\ngit config -add hooks.post-receive.hook \\\n    \"required finegrained-access-control.sh\"\ngit config -add hooks.post-receive.hook \\\n    \"required allow-repo-owner-to-do-anything.sh\"\ngit config -add hooks.post-receive.hook \\\n    \"ignore send-mail.sh\"\ngit config -add hooks.post-receive.hook \\\n    \"ignore send-irc-notification.py\"\n\n\nOne problem is that to change order one has to resort to manually \nediting config. So maybe something richer could be used:\n\n[hooks \"allow-repo-owner-to-do-anything\"]\n  cmd = /usr/share/git-hooks/allow-repo-owner-to-do-anything.sh\n  enabled = 1\n  type = post-receive\n  mode = sufficient\n  priority = 10\n\n[hooks \"mail\"]\n  cmd = /usr/share/git-hooks/allow-repo-owner-to-do-anything.sh\n  enabled = 1\n  type = post-receive\n  mode = ignore\n  priority = 1000\n\n(this would even allow running hooks at same priority simultaneously)\n\nAlso then the hook's own config variables fits nicely in same section. \n(note that then each [hooks \"x\"] will be an instance that could use the \nsame script, but different configvars)\n\n\n  anders\n"},{"id":"101449","messageId":"alpine.DEB.1.00.0901212206430.3586@pacific.mpi-cbg.de","threadId":"16424","inReplyTo":"4977872E.70901@0x63.nu","subject":"Re: What about allowing multiple hooks?","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2009-01-21T21:10:46Z","receivedAt":"2009-01-21T21:10:46Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Wed, 21 Jan 2009, Anders Waldenborg wrote:\n\n> I need multiple hooks, so I've done some thinking about this, so I \n> thought it may be a good idea to share this here.\n> \n> I currently use configvalues to specify which hooks to run. For example \n> this is how my post-receive looks:\n> \n> data=$(cat)\n> git config --get-all hooks.post-receive.hook | while read hook; do\n>         $hook <<__EOF__\n> \"$data\"\n> __EOF__\n> done\n\nI wonder why you don't do the obvious thing:\n\n\tdata=$(cat)\n\tfor hook in .git/hooks/update.d/*\n\tdo\n\t\ttest -x \"$hook\" || continue\n\t\techo \"$data\" | \"$hook\" | exit\n\tdone\n\nand then name the hooks in your .git/hooks/update.d/ with leading \nzero-padded numbers so that you guarantee a certain order.\n\nYou can even share special hooks between repositories by symlinking, as is \ndone in /etc/init.d/rc?.d.\n\nHth,\nDscho\n\nP.S.: If you want to save even more interactive work, you can name the \nhooks .git/hooks/update.[0-9]*.\n"},{"id":"101456","messageId":"497793E5.7090107@0x63.nu","threadId":"16424","inReplyTo":"alpine.DEB.1.00.0901212206430.3586@pacific.mpi-cbg.de","subject":"Re: What about allowing multiple hooks?","fromName":"Anders Waldenborg","fromEmail":"anders@0x63.nu","sentAt":"2009-01-21T21:30:13Z","receivedAt":"2009-01-21T21:30:13Z","isPatch":false,"sender":{"key":"anders@0x63.nu","avatar":"https://avatars.githubusercontent.com/u/1566016?v=4"},"body":"Johannes Schindelin wrote:\n>> I currently use configvalues to specify which hooks to run. For example \n>> this is how my post-receive looks:\n>>\n>> data=$(cat)\n>> git config --get-all hooks.post-receive.hook | while read hook; do\n>>         $hook <<__EOF__\n>> \"$data\"\n>> __EOF__\n>> done\n> \n> I wonder why you don't do the obvious thing:\n\n\nBecause I wanted to be able to do things like this:\n\ngit config -add hooks.post-receive.hook \\\n  \"sh hooks/buildbot 192.168.99.9:9989\"\ngit config -add hooks.post-receive.hook \\\n  \"sh hooks/buildbot 192.168.99.9:9988\"\n\nSo, the thing I initially wanted to solve was \"multiple instances\" of \nthe same hook.\n\nThen when I found this thread I saw that the richer meta information \nneeded to implement multiple hooks with sane semantics could be done \nwith the config values.\n\n  anders\n"},{"id":"101461","messageId":"alpine.DEB.1.00.0901212247510.3586@pacific.mpi-cbg.de","threadId":"16424","inReplyTo":"497793E5.7090107@0x63.nu","subject":"Re: What about allowing multiple hooks?","fromName":"Johannes Schindelin","fromEmail":"johannes.schindelin@gmx.de","sentAt":"2009-01-21T21:50:54Z","receivedAt":"2009-01-21T21:50:54Z","isPatch":false,"sender":{"key":"johannes.schindelin@gmx.de","avatar":"https://avatars.githubusercontent.com/u/127790?v=4"},"body":"Hi,\n\nOn Wed, 21 Jan 2009, Anders Waldenborg wrote:\n\n> Johannes Schindelin wrote:\n> > > I currently use configvalues to specify which hooks to run. For example\n> > > this is how my post-receive looks:\n> > >\n> > > data=$(cat)\n> > > git config --get-all hooks.post-receive.hook | while read hook; do\n> > >         $hook <<__EOF__\n> > > \"$data\"\n> > > __EOF__\n> > > done\n> > \n> > I wonder why you don't do the obvious thing:\n> \n> \n> Because I wanted to be able to do things like this:\n> \n> git config -add hooks.post-receive.hook \\\n>  \"sh hooks/buildbot 192.168.99.9:9989\"\n\nYou are missing a \"-\".\n\n> So, the thing I initially wanted to solve was \"multiple instances\" of \n> the same hook.\n\nAnd why not use a shell function for that?\n\n-- snip --\nbuildbot () {\n\techo \"Who is so evil and puts a bot into a post-receive hook?\" >&2\n\techo \"This function would connect to $* if it were building a bot.\"\n}\n\nbuildbot www.google.com\nbuildbot www.kernel.org\n-- snap --\n\n> Then when I found this thread I saw that the richer meta information \n> needed to implement multiple hooks with sane semantics could be done \n> with the config values.\n\nI think this is technically called an \"XY\" problem.  You ask for a \nspecific technical solution, while your real problem would be better \nsolved by other means.\n\nCiao,\nDscho\n"},{"id":"101514","messageId":"497842EE.8000400@0x63.nu","threadId":"16424","inReplyTo":"alpine.DEB.1.00.0901212247510.3586@pacific.mpi-cbg.de","subject":"Re: What about allowing multiple hooks?","fromName":"Anders Waldenborg","fromEmail":"anders@0x63.nu","sentAt":"2009-01-22T09:57:02Z","receivedAt":"2009-01-22T09:57:02Z","isPatch":false,"sender":{"key":"anders@0x63.nu","avatar":"https://avatars.githubusercontent.com/u/1566016?v=4"},"body":"Johannes Schindelin wrote:\n>> So, the thing I initially wanted to solve was \"multiple instances\" of \n>> the same hook.\n> \n> And why not use a shell function for that?\n> \n> -- snip --\n> buildbot () {\n> \techo \"Who is so evil and puts a bot into a post-receive hook?\" >&2\n> \techo \"This function would connect to $* if it were building a bot.\"\n> }\n> \n> buildbot www.google.com\n> buildbot www.kernel.org\n> -- snap --\n\nThat is basically what I started with except that it looked like this:\n\n-- 8< --\n#!/bin/sh\n/opt/git-triggers/buildbot-sendchange.py 192.168.9.99:9989\n/opt/git-triggers/buildbot-sendchange.py 192.168.9.99:9988\n/opt/git-triggers/send-mail\n/opt/git-triggers/irc-notification\n-- 8< --\n\nAt that point it thought \"hey this looks like a configuration file, \nshouldn't a repository's config live in $GIT_DIR/config?\".\n\n\nWe will continue use this config based approach on our site[*] until git \nhas something better. For us it wins over shellscript-as-configuration \nfor two reasons: 1) git config is easier to script  2) it allows us to \ndefine site wide triggers in /etc/gitconfig\n\n[*] (our site is medium sized I guess, ~100 repos when all are converted \nto git)\n\n  anders\n"}]}