# HG changeset patch # User Vadim Gelfer # Date 1140193581 28800 # Node ID 50de0887bbcd90a8d375823b2a338f58e3cbe7c8 # Parent 791405fe9991af75ba56f39355d859ee3ca65eab add preoutgoing and outgoing hooks. preoutgoing lets prevent pull over http or ssh. outgoing lets notify after pull. diff -r 791405fe9991 -r 50de0887bbcd doc/hgrc.5.txt --- a/doc/hgrc.5.txt Thu Feb 16 14:34:59 2006 -0800 +++ b/doc/hgrc.5.txt Fri Feb 17 08:26:21 2006 -0800 @@ -160,6 +160,10 @@ Run after a changeset has been pulled, pushed, or unbundled into the local repository. The ID of the newly arrived changeset is in $HG_NODE. + outgoing;; + Run after sending changes from local repository to another. ID of + first changeset sent is in $HG_NODE. Source of operation is in + $HG_SOURCE; see "preoutgoing" hook for description. prechangegroup;; Run before a changegroup is added via push, pull or unbundle. Exit status 0 allows the changegroup to proceed. Non-zero status @@ -168,6 +172,15 @@ Run before starting a local commit. Exit status 0 allows the commit to proceed. Non-zero status will cause the commit to fail. Parent changeset IDs are in $HG_PARENT1 and $HG_PARENT2. + preoutgoing;; + Run before computing changes to send from the local repository to + another. Non-zero status will cause failure. This lets you + prevent pull over http or ssh. Also prevents against local pull, + push (outbound) or bundle commands, but not effective, since you + can just copy files instead then. Source of operation is in + $HG_SOURCE. If "serve", operation is happening on behalf of + remote ssh or http repository. If "push", "pull" or "bundle", + operation is happening on behalf of repository on same system. pretag;; Run before creating a tag. Exit status 0 allows the tag to be created. Non-zero status will cause the tag to fail. ID of diff -r 791405fe9991 -r 50de0887bbcd mercurial/commands.py --- a/mercurial/commands.py Thu Feb 16 14:34:59 2006 -0800 +++ b/mercurial/commands.py Fri Feb 17 08:26:21 2006 -0800 @@ -622,7 +622,7 @@ dest = ui.expandpath(dest, repo.root) other = hg.repository(ui, dest) o = repo.findoutgoing(other) - cg = repo.changegroup(o) + cg = repo.changegroup(o, 'bundle') try: f.write("HG10") @@ -1999,7 +1999,7 @@ arg, roots = getarg() nodes = map(bin, roots.split(" ")) - cg = repo.changegroup(nodes) + cg = repo.changegroup(nodes, 'serve') while 1: d = cg.read(4096) if not d: diff -r 791405fe9991 -r 50de0887bbcd mercurial/hgweb.py --- a/mercurial/hgweb.py Thu Feb 16 14:34:59 2006 -0800 +++ b/mercurial/hgweb.py Fri Feb 17 08:26:21 2006 -0800 @@ -962,7 +962,7 @@ nodes = map(bin, req.form['roots'][0].split(" ")) z = zlib.compressobj() - f = self.repo.changegroup(nodes) + f = self.repo.changegroup(nodes, 'serve') while 1: chunk = f.read(4096) if not chunk: diff -r 791405fe9991 -r 50de0887bbcd mercurial/httprepo.py --- a/mercurial/httprepo.py Thu Feb 16 14:34:59 2006 -0800 +++ b/mercurial/httprepo.py Fri Feb 17 08:26:21 2006 -0800 @@ -119,7 +119,7 @@ self.ui.warn(_("unexpected response:\n") + d[:400] + "\n...\n") raise - def changegroup(self, nodes): + def changegroup(self, nodes, kind): n = " ".join(map(hex, nodes)) f = self.do_cmd("changegroup", roots=n) bytes = 0 diff -r 791405fe9991 -r 50de0887bbcd mercurial/localrepo.py --- a/mercurial/localrepo.py Thu Feb 16 14:34:59 2006 -0800 +++ b/mercurial/localrepo.py Fri Feb 17 08:26:21 2006 -0800 @@ -957,9 +957,9 @@ return 1 if heads is None: - cg = remote.changegroup(fetch) + cg = remote.changegroup(fetch, 'pull') else: - cg = remote.changegroupsubset(fetch, heads) + cg = remote.changegroupsubset(fetch, heads, 'pull') return self.addchangegroup(cg) def push(self, remote, force=False): @@ -984,10 +984,10 @@ " use push -f to force)\n")) return 1 - cg = self.changegroup(update) + cg = self.changegroup(update, 'push') return remote.addchangegroup(cg) - def changegroupsubset(self, bases, heads): + def changegroupsubset(self, bases, heads, source): """This function generates a changegroup consisting of all the nodes that are descendents of any of the bases, and ancestors of any of the heads. @@ -999,6 +999,8 @@ Another wrinkle is doing the reverse, figuring out which changeset in the changegroup a particular filenode or manifestnode belongs to.""" + self.hook('preoutgoing', throw=True, source=source) + # Set up some initial variables # Make it easy to refer to self.changelog cl = self.changelog @@ -1251,14 +1253,19 @@ # Signal that no more groups are left. yield struct.pack(">l", 0) + self.hook('outgoing', node=hex(msng_cl_lst[0]), source=source) + return util.chunkbuffer(gengroup()) - def changegroup(self, basenodes): + def changegroup(self, basenodes, source): """Generate a changegroup of all nodes that we have that a recipient doesn't. This is much easier than the previous function as we can assume that the recipient has any changenode we aren't sending them.""" + + self.hook('preoutgoing', throw=True, source=source) + cl = self.changelog nodes = cl.nodesbetween(basenodes, None)[0] revset = dict.fromkeys([cl.rev(n) for n in nodes]) @@ -1310,6 +1317,7 @@ yield chnk yield struct.pack(">l", 0) + self.hook('outgoing', node=hex(nodes[0]), source=source) return util.chunkbuffer(gengroup()) diff -r 791405fe9991 -r 50de0887bbcd mercurial/sshrepo.py --- a/mercurial/sshrepo.py Thu Feb 16 14:34:59 2006 -0800 +++ b/mercurial/sshrepo.py Fri Feb 17 08:26:21 2006 -0800 @@ -110,7 +110,7 @@ except: raise hg.RepoError(_("unexpected response '%s'") % (d[:400] + "...")) - def changegroup(self, nodes): + def changegroup(self, nodes, kind): n = " ".join(map(hex, nodes)) f = self.do_cmd("changegroup", roots=n) return self.pipei diff -r 791405fe9991 -r 50de0887bbcd tests/test-hook --- a/tests/test-hook Thu Feb 16 14:34:59 2006 -0800 +++ b/tests/test-hook Fri Feb 17 08:26:21 2006 -0800 @@ -74,3 +74,17 @@ echo 'pretxnchangegroup.forbid = echo pretxnchangegroup.forbid hook: tip=`hg -q tip`; exit 1' >> .hg/hgrc hg pull ../a hg -q tip + +# outgoing hooks can see env vars +rm .hg/hgrc +echo '[hooks]' > ../a/.hg/hgrc +echo 'preoutgoing = echo preoutgoing hook: s=$HG_SOURCE' >> ../a/.hg/hgrc +echo 'outgoing = echo outgoing hook: n=$HG_NODE s=$HG_SOURCE' >> ../a/.hg/hgrc +hg pull ../a +hg undo + +# preoutgoing hook can prevent outgoing changes +echo 'preoutgoing.forbid = echo preoutgoing.forbid hook; exit 1' >> ../a/.hg/hgrc +hg pull ../a + +exit 0 diff -r 791405fe9991 -r 50de0887bbcd tests/test-hook.out --- a/tests/test-hook.out Thu Feb 16 14:34:59 2006 -0800 +++ b/tests/test-hook.out Fri Feb 17 08:26:21 2006 -0800 @@ -71,3 +71,18 @@ transaction abort! rollback completed 3:07f3376c1e65 +preoutgoing hook: s=pull +outgoing hook: n=3cd2c6a5a36c5908aad3bc0d717c29873a05dfc2 s=pull +pulling from ../a +searching for changes +adding changesets +adding manifests +adding file changes +added 1 changesets with 1 changes to 1 files +(run 'hg update' to get a working copy) +rolling back last transaction +preoutgoing hook: s=pull +preoutgoing.forbid hook +pulling from ../a +searching for changes +abort: preoutgoing.forbid hook exited with status 1