contrib/hg-ssh
changeset 16836 1ba3e17186c8
parent 16779 67bfe7f64e57
child 25127 2b9cda9040f7
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()