##// END OF EJS Templates
hg-ssh: copy doc string to man page...
Sean Farley -
r29090:7b52cb38 stable
parent child Browse files
Show More
@@ -0,0 +1,71
1 ========
2 hg-ssh
3 ========
4
5 ----------------------------------------
6 restricted ssh login shell for Mercurial
7 ----------------------------------------
8
9 :Author: Thomas Arendsen Hein <thomas@intevation.de>
10 :Organization: Mercurial
11 :Manual section: 8
12 :Manual group: Mercurial Manual
13
14 .. contents::
15 :backlinks: top
16 :class: htmlonly
17 :depth: 1
18
19 Synopsis
20 """"""""
21 **hg-ssh** repositories...
22
23 Description
24 """""""""""
25 **hg-ssh** is a wrapper for ssh access to a limited set of mercurial repos.
26
27 To be used in ~/.ssh/authorized_keys with the "command" option, see sshd(8):
28 command="hg-ssh path/to/repo1 /path/to/repo2 ~/repo3 ~user/repo4" ssh-dss ...
29 (probably together with these other useful options:
30 no-port-forwarding,no-X11-forwarding,no-agent-forwarding)
31
32 This allows pull/push over ssh from/to the repositories given as arguments.
33
34 If all your repositories are subdirectories of a common directory, you can
35 allow shorter paths with:
36 command="cd path/to/my/repositories && hg-ssh repo1 subdir/repo2"
37
38 You can use pattern matching of your normal shell, e.g.:
39 command="cd repos && hg-ssh user/thomas/* projects/{mercurial,foo}"
40
41 You can also add a --read-only flag to allow read-only access to a key, e.g.:
42 command="hg-ssh --read-only repos/\*"
43
44 Bugs
45 """"
46 Probably lots, please post them to the mailing list (see Resources_
47 below) when you find them.
48
49 See Also
50 """"""""
51 |hg(1)|_
52
53 Author
54 """"""
55 Written by Matt Mackall <mpm@selenic.com>
56
57 Resources
58 """""""""
59 Main Web Site: https://mercurial-scm.org/
60
61 Source code repository: http://selenic.com/hg
62
63 Mailing list: http://selenic.com/mailman/listinfo/mercurial
64
65 Copying
66 """""""
67 Copyright (C) 2005-2016 Matt Mackall.
68 Free use of this software is granted under the terms of the GNU General
69 Public License version 2 or any later version.
70
71 .. include:: common.txt
@@ -1,223 +1,224
1 1 #!/usr/bin/env python
2 2 """usage: %s DOC ...
3 3
4 4 where DOC is the name of a document
5 5 """
6 6
7 7 from __future__ import absolute_import
8 8
9 9 import os
10 10 import sys
11 11 import textwrap
12 12
13 13 # This script is executed during installs and may not have C extensions
14 14 # available. Relax C module requirements.
15 15 os.environ['HGMODULEPOLICY'] = 'allow'
16 16 # import from the live mercurial repo
17 17 sys.path.insert(0, "..")
18 18 from mercurial import demandimport; demandimport.enable()
19 19 from mercurial import (
20 20 commands,
21 21 extensions,
22 22 help,
23 23 minirst,
24 24 ui as uimod,
25 25 )
26 26 from mercurial.i18n import (
27 27 gettext,
28 28 _,
29 29 )
30 30
31 31 table = commands.table
32 32 globalopts = commands.globalopts
33 33 helptable = help.helptable
34 34 loaddoc = help.loaddoc
35 35
36 36 def get_desc(docstr):
37 37 if not docstr:
38 38 return "", ""
39 39 # sanitize
40 40 docstr = docstr.strip("\n")
41 41 docstr = docstr.rstrip()
42 42 shortdesc = docstr.splitlines()[0].strip()
43 43
44 44 i = docstr.find("\n")
45 45 if i != -1:
46 46 desc = docstr[i + 2:]
47 47 else:
48 48 desc = shortdesc
49 49
50 50 desc = textwrap.dedent(desc)
51 51
52 52 return (shortdesc, desc)
53 53
54 54 def get_opts(opts):
55 55 for opt in opts:
56 56 if len(opt) == 5:
57 57 shortopt, longopt, default, desc, optlabel = opt
58 58 else:
59 59 shortopt, longopt, default, desc = opt
60 60 optlabel = _("VALUE")
61 61 allopts = []
62 62 if shortopt:
63 63 allopts.append("-%s" % shortopt)
64 64 if longopt:
65 65 allopts.append("--%s" % longopt)
66 66 if isinstance(default, list):
67 67 allopts[-1] += " <%s[+]>" % optlabel
68 68 elif (default is not None) and not isinstance(default, bool):
69 69 allopts[-1] += " <%s>" % optlabel
70 70 if '\n' in desc:
71 71 # only remove line breaks and indentation
72 72 desc = ' '.join(l.lstrip() for l in desc.split('\n'))
73 73 desc += default and _(" (default: %s)") % default or ""
74 74 yield (", ".join(allopts), desc)
75 75
76 76 def get_cmd(cmd, cmdtable):
77 77 d = {}
78 78 attr = cmdtable[cmd]
79 79 cmds = cmd.lstrip("^").split("|")
80 80
81 81 d['cmd'] = cmds[0]
82 82 d['aliases'] = cmd.split("|")[1:]
83 83 d['desc'] = get_desc(gettext(attr[0].__doc__))
84 84 d['opts'] = list(get_opts(attr[1]))
85 85
86 86 s = 'hg ' + cmds[0]
87 87 if len(attr) > 2:
88 88 if not attr[2].startswith('hg'):
89 89 s += ' ' + attr[2]
90 90 else:
91 91 s = attr[2]
92 92 d['synopsis'] = s.strip()
93 93
94 94 return d
95 95
96 96 def showdoc(ui):
97 97 # print options
98 98 ui.write(minirst.section(_("Options")))
99 99 multioccur = False
100 100 for optstr, desc in get_opts(globalopts):
101 101 ui.write("%s\n %s\n\n" % (optstr, desc))
102 102 if optstr.endswith("[+]>"):
103 103 multioccur = True
104 104 if multioccur:
105 105 ui.write(_("\n[+] marked option can be specified multiple times\n"))
106 106 ui.write("\n")
107 107
108 108 # print cmds
109 109 ui.write(minirst.section(_("Commands")))
110 110 commandprinter(ui, table, minirst.subsection)
111 111
112 112 # print help topics
113 113 # The config help topic is included in the hgrc.5 man page.
114 114 helpprinter(ui, helptable, minirst.section, exclude=['config'])
115 115
116 116 ui.write(minirst.section(_("Extensions")))
117 117 ui.write(_("This section contains help for extensions that are "
118 118 "distributed together with Mercurial. Help for other "
119 119 "extensions is available in the help system."))
120 120 ui.write("\n\n"
121 121 ".. contents::\n"
122 122 " :class: htmlonly\n"
123 123 " :local:\n"
124 124 " :depth: 1\n\n")
125 125
126 126 for extensionname in sorted(allextensionnames()):
127 127 mod = extensions.load(ui, extensionname, None)
128 128 ui.write(minirst.subsection(extensionname))
129 129 ui.write("%s\n\n" % gettext(mod.__doc__))
130 130 cmdtable = getattr(mod, 'cmdtable', None)
131 131 if cmdtable:
132 132 ui.write(minirst.subsubsection(_('Commands')))
133 133 commandprinter(ui, cmdtable, minirst.subsubsubsection)
134 134
135 135 def showtopic(ui, topic):
136 136 extrahelptable = [
137 137 (["common"], '', loaddoc('common')),
138 138 (["hg.1"], '', loaddoc('hg.1')),
139 (["hg-ssh.8"], '', loaddoc('hg-ssh.8')),
139 140 (["hgignore.5"], '', loaddoc('hgignore.5')),
140 141 (["hgrc.5"], '', loaddoc('hgrc.5')),
141 142 (["hgignore.5.gendoc"], '', loaddoc('hgignore')),
142 143 (["hgrc.5.gendoc"], '', loaddoc('config')),
143 144 ]
144 145 helpprinter(ui, helptable + extrahelptable, None, include=[topic])
145 146
146 147 def helpprinter(ui, helptable, sectionfunc, include=[], exclude=[]):
147 148 for names, sec, doc in helptable:
148 149 if exclude and names[0] in exclude:
149 150 continue
150 151 if include and names[0] not in include:
151 152 continue
152 153 for name in names:
153 154 ui.write(".. _%s:\n" % name)
154 155 ui.write("\n")
155 156 if sectionfunc:
156 157 ui.write(sectionfunc(sec))
157 158 if callable(doc):
158 159 doc = doc(ui)
159 160 ui.write(doc)
160 161 ui.write("\n")
161 162
162 163 def commandprinter(ui, cmdtable, sectionfunc):
163 164 h = {}
164 165 for c, attr in cmdtable.items():
165 166 f = c.split("|")[0]
166 167 f = f.lstrip("^")
167 168 h[f] = c
168 169 cmds = h.keys()
169 170 cmds.sort()
170 171
171 172 for f in cmds:
172 173 if f.startswith("debug"):
173 174 continue
174 175 d = get_cmd(h[f], cmdtable)
175 176 ui.write(sectionfunc(d['cmd']))
176 177 # short description
177 178 ui.write(d['desc'][0])
178 179 # synopsis
179 180 ui.write("::\n\n")
180 181 synopsislines = d['synopsis'].splitlines()
181 182 for line in synopsislines:
182 183 # some commands (such as rebase) have a multi-line
183 184 # synopsis
184 185 ui.write(" %s\n" % line)
185 186 ui.write('\n')
186 187 # description
187 188 ui.write("%s\n\n" % d['desc'][1])
188 189 # options
189 190 opt_output = list(d['opts'])
190 191 if opt_output:
191 192 opts_len = max([len(line[0]) for line in opt_output])
192 193 ui.write(_("Options:\n\n"))
193 194 multioccur = False
194 195 for optstr, desc in opt_output:
195 196 if desc:
196 197 s = "%-*s %s" % (opts_len, optstr, desc)
197 198 else:
198 199 s = optstr
199 200 ui.write("%s\n" % s)
200 201 if optstr.endswith("[+]>"):
201 202 multioccur = True
202 203 if multioccur:
203 204 ui.write(_("\n[+] marked option can be specified"
204 205 " multiple times\n"))
205 206 ui.write("\n")
206 207 # aliases
207 208 if d['aliases']:
208 209 ui.write(_(" aliases: %s\n\n") % " ".join(d['aliases']))
209 210
210 211
211 212 def allextensionnames():
212 213 return extensions.enabled().keys() + extensions.disabled().keys()
213 214
214 215 if __name__ == "__main__":
215 216 doc = 'hg.1.gendoc'
216 217 if len(sys.argv) > 1:
217 218 doc = sys.argv[1]
218 219
219 220 ui = uimod.ui()
220 221 if doc == 'hg.1.gendoc':
221 222 showdoc(ui)
222 223 else:
223 224 showtopic(ui, sys.argv[1])
@@ -1,138 +1,139
1 1 hg debuginstall
2 2 $ hg debuginstall
3 3 checking encoding (ascii)...
4 4 checking Python executable (*) (glob)
5 5 checking Python version (2.*) (glob)
6 6 checking Python lib (*lib*)... (glob)
7 7 checking installed modules (*mercurial)... (glob)
8 8 checking templates (*mercurial?templates)... (glob)
9 9 checking default template (*mercurial?templates?map-cmdline.default) (glob)
10 10 checking commit editor... (* -c "import sys; sys.exit(0)") (glob)
11 11 checking username (test)
12 12 no problems detected
13 13
14 14 hg debuginstall JSON
15 15 $ hg debuginstall -Tjson | sed 's|\\\\|\\|g'
16 16 [
17 17 {
18 18 "defaulttemplate": "*mercurial?templates?map-cmdline.default", (glob)
19 19 "defaulttemplateerror": null,
20 20 "defaulttemplatenotfound": "default",
21 21 "editor": "* -c \"import sys; sys.exit(0)\"", (glob)
22 22 "editornotfound": false,
23 23 "encoding": "ascii",
24 24 "encodingerror": null,
25 25 "extensionserror": null,
26 26 "hgmodules": "*mercurial", (glob)
27 27 "problems": 0,
28 28 "pythonexe": "*", (glob)
29 29 "pythonlib": "*", (glob)
30 30 "pythonver": "*.*.*", (glob)
31 31 "templatedirs": "*mercurial?templates", (glob)
32 32 "username": "test",
33 33 "usernameerror": null,
34 34 "vinotfound": false
35 35 }
36 36 ]
37 37
38 38 hg debuginstall with no username
39 39 $ HGUSER= hg debuginstall
40 40 checking encoding (ascii)...
41 41 checking Python executable (*) (glob)
42 42 checking Python version (2.*) (glob)
43 43 checking Python lib (*lib*)... (glob)
44 44 checking installed modules (*mercurial)... (glob)
45 45 checking templates (*mercurial?templates)... (glob)
46 46 checking default template (*mercurial?templates?map-cmdline.default) (glob)
47 47 checking commit editor... (* -c "import sys; sys.exit(0)") (glob)
48 48 checking username...
49 49 no username supplied
50 50 (specify a username in your configuration file)
51 51 1 problems detected, please check your install!
52 52 [1]
53 53
54 54 path variables are expanded (~ is the same as $TESTTMP)
55 55 $ mkdir tools
56 56 $ touch tools/testeditor.exe
57 57 #if execbit
58 58 $ chmod 755 tools/testeditor.exe
59 59 #endif
60 60 $ hg debuginstall --config ui.editor=~/tools/testeditor.exe
61 61 checking encoding (ascii)...
62 62 checking Python executable (*) (glob)
63 63 checking Python version (*) (glob)
64 64 checking Python lib (*lib*)... (glob)
65 65 checking installed modules (*mercurial)... (glob)
66 66 checking templates (*mercurial?templates)... (glob)
67 67 checking default template (*mercurial?templates?map-cmdline.default) (glob)
68 68 checking commit editor... (* -c "import sys; sys.exit(0)") (glob)
69 69 checking username (test)
70 70 no problems detected
71 71
72 72 #if test-repo
73 73 $ cat >> wixxml.py << EOF
74 74 > import os, subprocess, sys
75 75 > import xml.etree.ElementTree as ET
76 76 >
77 77 > # MSYS mangles the path if it expands $TESTDIR
78 78 > testdir = os.environ['TESTDIR']
79 79 > ns = {'wix' : 'http://schemas.microsoft.com/wix/2006/wi'}
80 80 >
81 81 > def directory(node, relpath):
82 82 > '''generator of files in the xml node, rooted at relpath'''
83 83 > dirs = node.findall('./{%(wix)s}Directory' % ns)
84 84 >
85 85 > for d in dirs:
86 86 > for subfile in directory(d, relpath + d.attrib['Name'] + '/'):
87 87 > yield subfile
88 88 >
89 89 > files = node.findall('./{%(wix)s}Component/{%(wix)s}File' % ns)
90 90 >
91 91 > for f in files:
92 92 > yield relpath + f.attrib['Name']
93 93 >
94 94 > def hgdirectory(relpath):
95 95 > '''generator of tracked files, rooted at relpath'''
96 96 > hgdir = "%s/../mercurial" % (testdir)
97 97 > args = ['hg', '--cwd', hgdir, 'files', relpath]
98 98 > proc = subprocess.Popen(args, stdout=subprocess.PIPE,
99 99 > stderr=subprocess.PIPE)
100 100 > output = proc.communicate()[0]
101 101 >
102 102 > slash = '/'
103 103 > for line in output.splitlines():
104 104 > if os.name == 'nt':
105 105 > yield line.replace(os.sep, slash)
106 106 > else:
107 107 > yield line
108 108 >
109 109 > tracked = [f for f in hgdirectory(sys.argv[1])]
110 110 >
111 111 > xml = ET.parse("%s/../contrib/wix/%s.wxs" % (testdir, sys.argv[1]))
112 112 > root = xml.getroot()
113 113 > dir = root.find('.//{%(wix)s}DirectoryRef' % ns)
114 114 >
115 115 > installed = [f for f in directory(dir, '')]
116 116 >
117 117 > print('Not installed:')
118 118 > for f in sorted(set(tracked) - set(installed)):
119 119 > print(' %s' % f)
120 120 >
121 121 > print('Not tracked:')
122 122 > for f in sorted(set(installed) - set(tracked)):
123 123 > print(' %s' % f)
124 124 > EOF
125 125
126 126 $ python wixxml.py help
127 127 Not installed:
128 128 help/common.txt
129 help/hg-ssh.8.txt
129 130 help/hg.1.txt
130 131 help/hgignore.5.txt
131 132 help/hgrc.5.txt
132 133 Not tracked:
133 134
134 135 $ python wixxml.py templates
135 136 Not installed:
136 137 Not tracked:
137 138
138 139 #endif
General Comments 0
You need to be logged in to leave comments. Login now