--- a/contrib/hg-ssh Sun May 13 10:21:27 2012 +0200
+++ b/contrib/hg-ssh Tue May 22 15:17:37 2012 -0700
@@ -24,6 +24,9 @@
You can use pattern matching of your normal shell, e.g.:
command="cd repos && hg-ssh user/thomas/* projects/{mercurial,foo}"
+
+You can also add a --read-only flag to allow read-only access to a key, e.g.:
+command="hg-ssh --read-only repos/*"
"""
# enable importing on demand to reduce startup time
@@ -35,9 +38,17 @@
def main():
cwd = os.getcwd()
+ readonly = False
+ args = sys.argv[1:]
+ while len(args):
+ if args[0] == '--read-only':
+ readonly = True
+ args.pop(0)
+ else:
+ break
allowed_paths = [os.path.normpath(os.path.join(cwd,
os.path.expanduser(path)))
- for path in sys.argv[1:]]
+ for path in args]
orig_cmd = os.getenv('SSH_ORIGINAL_COMMAND', '?')
try:
cmdargv = shlex.split(orig_cmd)
@@ -49,9 +60,15 @@
path = cmdargv[2]
repo = os.path.normpath(os.path.join(cwd, os.path.expanduser(path)))
if repo in allowed_paths:
- dispatch.dispatch(dispatch.request(['-R', repo,
- 'serve',
- '--stdio']))
+ cmd = ['-R', repo, 'serve', '--stdio']
+ if readonly:
+ cmd += [
+ '--config',
+ 'hooks.prechangegroup.hg-ssh=python:__main__.rejectpush',
+ '--config',
+ 'hooks.prepushkey.hg-ssh=python:__main__.rejectpush'
+ ]
+ dispatch.dispatch(dispatch.request(cmd))
else:
sys.stderr.write('Illegal repository "%s"\n' % repo)
sys.exit(255)
@@ -59,5 +76,11 @@
sys.stderr.write('Illegal command "%s"\n' % orig_cmd)
sys.exit(255)
+def rejectpush(ui, **kwargs):
+ ui.warn("Permission denied\n")
+ # mercurial hooks use unix process conventions for hook return values
+ # so a truthy return means failure
+ return True
+
if __name__ == '__main__':
main()