add preoutgoing and outgoing hooks.
preoutgoing lets prevent pull over http or ssh.
outgoing lets notify after pull.
--- 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
--- 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:
--- 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:
--- 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
--- 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())
--- 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
--- 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
--- 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