Mercurial > hg-stable
comparison contrib/hg-ssh @ 16836:1ba3e17186c8
hg-ssh: read-only flag
Allows you to restrict a ssh key to have read-only access to a set of
repos by passing the --read-only flag to hg-ssh.
This is useful in an environment where the number of unix users you
can or are willing to create is limited. In such an environment,
multiple users or applications will share a single unix account. Some
of those applications will likely need read-only access to the
repository. This change makes it possible to grant them such access
without requiring that they use a separate unix account.
author | David Schleimer <dschleimer@fb.com> |
---|---|
date | Tue, 22 May 2012 15:17:37 -0700 |
parents | 67bfe7f64e57 |
children | 2b9cda9040f7 |
comparison
equal
deleted
inserted
replaced
16835:4267c840c481 | 16836:1ba3e17186c8 |
---|---|
22 allow shorter paths with: | 22 allow shorter paths with: |
23 command="cd path/to/my/repositories && hg-ssh repo1 subdir/repo2" | 23 command="cd path/to/my/repositories && hg-ssh repo1 subdir/repo2" |
24 | 24 |
25 You can use pattern matching of your normal shell, e.g.: | 25 You can use pattern matching of your normal shell, e.g.: |
26 command="cd repos && hg-ssh user/thomas/* projects/{mercurial,foo}" | 26 command="cd repos && hg-ssh user/thomas/* projects/{mercurial,foo}" |
27 | |
28 You can also add a --read-only flag to allow read-only access to a key, e.g.: | |
29 command="hg-ssh --read-only repos/*" | |
27 """ | 30 """ |
28 | 31 |
29 # enable importing on demand to reduce startup time | 32 # enable importing on demand to reduce startup time |
30 from mercurial import demandimport; demandimport.enable() | 33 from mercurial import demandimport; demandimport.enable() |
31 | 34 |
33 | 36 |
34 import sys, os, shlex | 37 import sys, os, shlex |
35 | 38 |
36 def main(): | 39 def main(): |
37 cwd = os.getcwd() | 40 cwd = os.getcwd() |
41 readonly = False | |
42 args = sys.argv[1:] | |
43 while len(args): | |
44 if args[0] == '--read-only': | |
45 readonly = True | |
46 args.pop(0) | |
47 else: | |
48 break | |
38 allowed_paths = [os.path.normpath(os.path.join(cwd, | 49 allowed_paths = [os.path.normpath(os.path.join(cwd, |
39 os.path.expanduser(path))) | 50 os.path.expanduser(path))) |
40 for path in sys.argv[1:]] | 51 for path in args] |
41 orig_cmd = os.getenv('SSH_ORIGINAL_COMMAND', '?') | 52 orig_cmd = os.getenv('SSH_ORIGINAL_COMMAND', '?') |
42 try: | 53 try: |
43 cmdargv = shlex.split(orig_cmd) | 54 cmdargv = shlex.split(orig_cmd) |
44 except ValueError, e: | 55 except ValueError, e: |
45 sys.stderr.write('Illegal command "%s": %s\n' % (orig_cmd, e)) | 56 sys.stderr.write('Illegal command "%s": %s\n' % (orig_cmd, e)) |
47 | 58 |
48 if cmdargv[:2] == ['hg', '-R'] and cmdargv[3:] == ['serve', '--stdio']: | 59 if cmdargv[:2] == ['hg', '-R'] and cmdargv[3:] == ['serve', '--stdio']: |
49 path = cmdargv[2] | 60 path = cmdargv[2] |
50 repo = os.path.normpath(os.path.join(cwd, os.path.expanduser(path))) | 61 repo = os.path.normpath(os.path.join(cwd, os.path.expanduser(path))) |
51 if repo in allowed_paths: | 62 if repo in allowed_paths: |
52 dispatch.dispatch(dispatch.request(['-R', repo, | 63 cmd = ['-R', repo, 'serve', '--stdio'] |
53 'serve', | 64 if readonly: |
54 '--stdio'])) | 65 cmd += [ |
66 '--config', | |
67 'hooks.prechangegroup.hg-ssh=python:__main__.rejectpush', | |
68 '--config', | |
69 'hooks.prepushkey.hg-ssh=python:__main__.rejectpush' | |
70 ] | |
71 dispatch.dispatch(dispatch.request(cmd)) | |
55 else: | 72 else: |
56 sys.stderr.write('Illegal repository "%s"\n' % repo) | 73 sys.stderr.write('Illegal repository "%s"\n' % repo) |
57 sys.exit(255) | 74 sys.exit(255) |
58 else: | 75 else: |
59 sys.stderr.write('Illegal command "%s"\n' % orig_cmd) | 76 sys.stderr.write('Illegal command "%s"\n' % orig_cmd) |
60 sys.exit(255) | 77 sys.exit(255) |
61 | 78 |
79 def rejectpush(ui, **kwargs): | |
80 ui.warn("Permission denied\n") | |
81 # mercurial hooks use unix process conventions for hook return values | |
82 # so a truthy return means failure | |
83 return True | |
84 | |
62 if __name__ == '__main__': | 85 if __name__ == '__main__': |
63 main() | 86 main() |