##// END OF EJS Templates
commands: better argument processing, per-command help...
mpm@selenic.com -
r212:48398a53 default
parent child Browse files
Show More
@@ -1,150 +1,169 b''
1 import os, re
1 import os, re, traceback, sys
2 from mercurial import fancyopts, ui, hg
2 from mercurial import fancyopts, ui, hg
3
3
4 class UnknownCommand(Exception): pass
4 class UnknownCommand(Exception): pass
5
5
6 def relpath(repo, args):
6 def relpath(repo, args):
7 if os.getcwd() != repo.root:
7 if os.getcwd() != repo.root:
8 p = os.getcwd()[len(repo.root) + 1: ]
8 p = os.getcwd()[len(repo.root) + 1: ]
9 return [ os.path.join(p, x) for x in args ]
9 return [ os.path.join(p, x) for x in args ]
10 return args
10 return args
11
11
12 def help(ui, args):
12 def help(ui, cmd=None):
13 '''show help'''
14 if cmd:
15 try:
16 i = find(cmd)
17 ui.write("%s\n\n" % i[2])
18 ui.write(i[0].__doc__, "\n")
19 except UnknownCommand:
20 ui.warn("unknown command %s", cmd)
21 sys.exit(0)
22
13 ui.status("""\
23 ui.status("""\
14 hg commands:
24 hg commands:
15
25
16 add [files...] add the given files in the next commit
26 add [files...] add the given files in the next commit
17 addremove add all new files, delete all missing files
27 addremove add all new files, delete all missing files
18 annotate [files...] show changeset number per file line
28 annotate [files...] show changeset number per file line
19 branch <path> create a branch of <path> in this directory
29 branch <path> create a branch of <path> in this directory
20 checkout [changeset] checkout the latest or given changeset
30 checkout [changeset] checkout the latest or given changeset
21 commit commit all changes to the repository
31 commit commit all changes to the repository
22 diff [files...] diff working directory (or selected files)
32 diff [files...] diff working directory (or selected files)
23 dump <file> [rev] dump the latest or given revision of a file
33 dump <file> [rev] dump the latest or given revision of a file
24 dumpmanifest [rev] dump the latest or given revision of the manifest
34 dumpmanifest [rev] dump the latest or given revision of the manifest
25 export <rev> dump the changeset header and diffs for a revision
35 export <rev> dump the changeset header and diffs for a revision
26 history show changeset history
36 history show changeset history
27 init create a new repository in this directory
37 init create a new repository in this directory
28 log <file> show revision history of a single file
38 log <file> show revision history of a single file
29 merge <path> merge changes from <path> into local repository
39 merge <path> merge changes from <path> into local repository
30 recover rollback an interrupted transaction
40 recover rollback an interrupted transaction
31 remove [files...] remove the given files in the next commit
41 remove [files...] remove the given files in the next commit
32 serve export the repository via HTTP
42 serve export the repository via HTTP
33 status show new, missing, and changed files in working dir
43 status show new, missing, and changed files in working dir
34 tags show current changeset tags
44 tags show current changeset tags
35 undo undo the last transaction
45 undo undo the last transaction
36 """)
46 """)
37
47
38 def init(ui, args):
48 def init(ui):
39 """create a repository"""
49 """create a repository"""
40 hg.repository(ui, ".", create=1)
50 hg.repository(ui, ".", create=1)
41
51
42 def checkout(u, repo, args):
52 def checkout(u, repo, changeset=None):
53 '''checkout a given changeset or the current tip'''
43 node = repo.changelog.tip()
54 node = repo.changelog.tip()
44 if args:
55 if changeset:
45 node = repo.lookup(args[0])
56 node = repo.lookup(changeset)
46 repo.checkout(node)
57 repo.checkout(node)
47
58
48 def annotate(u, repo, args, **ops):
59 def annotate(u, repo, *args, **ops):
49 if not args:
50 return
51
52 def getnode(rev):
60 def getnode(rev):
53 return hg.short(repo.changelog.node(rev))
61 return hg.short(repo.changelog.node(rev))
54
62
55 def getname(rev):
63 def getname(rev):
56 try:
64 try:
57 return bcache[rev]
65 return bcache[rev]
58 except KeyError:
66 except KeyError:
59 cl = repo.changelog.read(repo.changelog.node(rev))
67 cl = repo.changelog.read(repo.changelog.node(rev))
60 name = cl[1]
68 name = cl[1]
61 f = name.find('@')
69 f = name.find('@')
62 if f >= 0:
70 if f >= 0:
63 name = name[:f]
71 name = name[:f]
64 bcache[rev] = name
72 bcache[rev] = name
65 return name
73 return name
66
74
67 bcache = {}
75 bcache = {}
68 opmap = [['user', getname], ['number', str], ['changeset', getnode]]
76 opmap = [['user', getname], ['number', str], ['changeset', getnode]]
69 if not ops['user'] and not ops['changeset']:
77 if not ops['user'] and not ops['changeset']:
70 ops['number'] = 1
78 ops['number'] = 1
71
79
72 args = relpath(repo, args)
80 args = relpath(repo, args)
73 node = repo.current
81 node = repo.current
74 if ops['revision']:
82 if ops['revision']:
75 node = repo.changelog.lookup(ops['revision'])
83 node = repo.changelog.lookup(ops['revision'])
76 change = repo.changelog.read(node)
84 change = repo.changelog.read(node)
77 mmap = repo.manifest.read(change[0])
85 mmap = repo.manifest.read(change[0])
78 maxuserlen = 0
86 maxuserlen = 0
79 maxchangelen = 0
87 maxchangelen = 0
80 for f in args:
88 for f in args:
81 lines = repo.file(f).annotate(mmap[f])
89 lines = repo.file(f).annotate(mmap[f])
82 pieces = []
90 pieces = []
83
91
84 for o, f in opmap:
92 for o, f in opmap:
85 if ops[o]:
93 if ops[o]:
86 l = [ f(n) for n,t in lines ]
94 l = [ f(n) for n,t in lines ]
87 m = max(map(len, l))
95 m = max(map(len, l))
88 pieces.append([ "%*s" % (m, x) for x in l])
96 pieces.append([ "%*s" % (m, x) for x in l])
89
97
90 for p,l in zip(zip(*pieces), lines):
98 for p,l in zip(zip(*pieces), lines):
91 u.write(" ".join(p) + ": " + l[1])
99 u.write(" ".join(p) + ": " + l[1])
92
100
93 def undo(ui, repo, args):
101 def undo(ui, repo):
94 repo.undo()
102 repo.undo()
95
103
96 table = {
104 table = {
97 "init": (init, [], 'hg init'),
105 "init": (init, [], 'hg init'),
98 "help": (help, [], 'hg help'),
106 "help": (help, [], 'hg help [command]'),
99 "checkout|co": (checkout, [], 'hg checkout'),
107 "checkout|co": (checkout, [], 'hg checkout [changeset]'),
100 "ann|annotate": (annotate,
108 "ann|annotate": (annotate,
101 [('r', 'revision', '', 'revision'),
109 [('r', 'revision', '', 'revision'),
102 ('u', 'user', None, 'show user'),
110 ('u', 'user', None, 'show user'),
103 ('n', 'number', None, 'show revision number'),
111 ('n', 'number', None, 'show revision number'),
104 ('c', 'changeset', None, 'show changeset')],
112 ('c', 'changeset', None, 'show changeset')],
105 'hg annotate [-u] [-c] [-n] [-r id] [files]'),
113 'hg annotate [-u] [-c] [-n] [-r id] [files]'),
106 "undo": (undo, [], 'hg undo'),
114 "undo": (undo, [], 'hg undo'),
107 }
115 }
108
116
109 norepo = "init branch help"
117 norepo = "init branch help"
110
118
119 def find(cmd):
120 i = None
121 for e in table.keys():
122 if re.match(e + "$", cmd):
123 return table[e]
124
125 raise UnknownCommand(cmd)
126
111 def dispatch(args):
127 def dispatch(args):
112 options = {}
128 options = {}
113 opts = [('v', 'verbose', None, 'verbose'),
129 opts = [('v', 'verbose', None, 'verbose'),
114 ('d', 'debug', None, 'debug'),
130 ('d', 'debug', None, 'debug'),
115 ('q', 'quiet', None, 'quiet'),
131 ('q', 'quiet', None, 'quiet'),
116 ('y', 'noninteractive', None, 'run non-interactively'),
132 ('y', 'noninteractive', None, 'run non-interactively'),
117 ]
133 ]
118
134
119 args = fancyopts.fancyopts(args, opts, options,
135 args = fancyopts.fancyopts(args, opts, options,
120 'hg [options] <command> [options] [files]')
136 'hg [options] <command> [options] [files]')
121
137
122 if not args:
138 if not args:
123 cmd = "help"
139 cmd = "help"
124 else:
140 else:
125 cmd, args = args[0], args[1:]
141 cmd, args = args[0], args[1:]
126
142
127 u = ui.ui(options["verbose"], options["debug"], options["quiet"],
143 u = ui.ui(options["verbose"], options["debug"], options["quiet"],
128 not options["noninteractive"])
144 not options["noninteractive"])
129
145
130 i = None
146 # deal with unfound commands later
131 for e in table.keys():
147 i = find(cmd)
132 if re.match(e + "$", cmd):
133 i = table[e]
134
135 # deal with this internally later
136 if not i: raise UnknownCommand(cmd)
137
148
138 cmdoptions = {}
149 cmdoptions = {}
139 args = fancyopts.fancyopts(args, i[1], cmdoptions, i[2])
150 args = fancyopts.fancyopts(args, i[1], cmdoptions, i[2])
140
151
141 if cmd not in norepo.split():
152 if cmd not in norepo.split():
142 repo = hg.repository(ui = u)
153 repo = hg.repository(ui = u)
143 d = lambda: i[0](u, repo, args, **cmdoptions)
154 d = lambda: i[0](u, repo, *args, **cmdoptions)
144 else:
155 else:
145 d = lambda: i[0](u, args, **cmdoptions)
156 d = lambda: i[0](u, *args, **cmdoptions)
146
157
147 try:
158 try:
148 d()
159 d()
149 except KeyboardInterrupt:
160 except KeyboardInterrupt:
150 u.warn("interrupted!\n")
161 u.warn("interrupted!\n")
162 except TypeError, inst:
163 # was this an argument error?
164 tb = traceback.extract_tb(sys.exc_info()[2])
165 if len(tb) > 2: # no
166 raise
167 u.warn("%s: invalid arguments\n" % i[0].__name__)
168 u.warn("syntax: %s\n" % i[2])
169 sys.exit(-1)
General Comments 0
You need to be logged in to leave comments. Login now