Show More
@@ -24,6 +24,9 b' command="cd path/to/my/repositories && h' | |||||
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 | |
@@ -35,9 +38,17 b' 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 |
|
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) | |
@@ -49,9 +60,15 b' def main():' | |||||
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) | |
@@ -59,5 +76,11 b' def main():' | |||||
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() |
@@ -308,6 +308,41 b' parameters:' | |||||
308 | Illegal command "'hg' -R 'a'repo' serve --stdio": No closing quotation |
|
308 | Illegal command "'hg' -R 'a'repo' serve --stdio": No closing quotation | |
309 | [255] |
|
309 | [255] | |
310 |
|
310 | |||
|
311 | Test hg-ssh in read-only mode: | |||
|
312 | ||||
|
313 | $ cat > ssh.sh << EOF | |||
|
314 | > userhost="\$1" | |||
|
315 | > SSH_ORIGINAL_COMMAND="\$2" | |||
|
316 | > export SSH_ORIGINAL_COMMAND | |||
|
317 | > PYTHONPATH="$PYTHONPATH" | |||
|
318 | > export PYTHONPATH | |||
|
319 | > python "$TESTDIR/../contrib/hg-ssh" --read-only "$TESTTMP/remote" | |||
|
320 | > EOF | |||
|
321 | ||||
|
322 | $ hg clone --ssh "sh ssh.sh" "ssh://user@dummy/$TESTTMP/remote" read-only-local | |||
|
323 | requesting all changes | |||
|
324 | adding changesets | |||
|
325 | adding manifests | |||
|
326 | adding file changes | |||
|
327 | added 4 changesets with 5 changes to 4 files (+1 heads) | |||
|
328 | updating to branch default | |||
|
329 | 3 files updated, 0 files merged, 0 files removed, 0 files unresolved | |||
|
330 | ||||
|
331 | $ cd read-only-local | |||
|
332 | $ echo "baz" > bar | |||
|
333 | $ hg ci -A -m "unpushable commit" bar | |||
|
334 | $ hg push --ssh "sh ../ssh.sh" | |||
|
335 | pushing to ssh://user@dummy/$TESTTMP/remote | |||
|
336 | searching for changes | |||
|
337 | remote: Permission denied | |||
|
338 | remote: abort: prechangegroup.hg-ssh hook failed | |||
|
339 | remote: Permission denied | |||
|
340 | remote: abort: prepushkey.hg-ssh hook failed | |||
|
341 | abort: unexpected response: empty string | |||
|
342 | [255] | |||
|
343 | ||||
|
344 | $ cd .. | |||
|
345 | ||||
311 | $ cat dummylog |
|
346 | $ cat dummylog | |
312 | Got arguments 1:user@dummy 2:hg -R nonexistent serve --stdio |
|
347 | Got arguments 1:user@dummy 2:hg -R nonexistent serve --stdio | |
313 | Got arguments 1:user@dummy 2:hg -R /$TESTTMP/nonexistent serve --stdio |
|
348 | Got arguments 1:user@dummy 2:hg -R /$TESTTMP/nonexistent serve --stdio |
General Comments 0
You need to be logged in to leave comments.
Login now