##// END OF EJS Templates
hgk: remove repetitious (and wrong) command syntax descriptions
Andrew Shadura -
r24511:0ecc1e42 default
parent child Browse files
Show More
@@ -1,354 +1,354 b''
1 # Minimal support for git commands on an hg repository
1 # Minimal support for git commands on an hg repository
2 #
2 #
3 # Copyright 2005, 2006 Chris Mason <mason@suse.com>
3 # Copyright 2005, 2006 Chris Mason <mason@suse.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 '''browse the repository in a graphical way
8 '''browse the repository in a graphical way
9
9
10 The hgk extension allows browsing the history of a repository in a
10 The hgk extension allows browsing the history of a repository in a
11 graphical way. It requires Tcl/Tk version 8.4 or later. (Tcl/Tk is not
11 graphical way. It requires Tcl/Tk version 8.4 or later. (Tcl/Tk is not
12 distributed with Mercurial.)
12 distributed with Mercurial.)
13
13
14 hgk consists of two parts: a Tcl script that does the displaying and
14 hgk consists of two parts: a Tcl script that does the displaying and
15 querying of information, and an extension to Mercurial named hgk.py,
15 querying of information, and an extension to Mercurial named hgk.py,
16 which provides hooks for hgk to get information. hgk can be found in
16 which provides hooks for hgk to get information. hgk can be found in
17 the contrib directory, and the extension is shipped in the hgext
17 the contrib directory, and the extension is shipped in the hgext
18 repository, and needs to be enabled.
18 repository, and needs to be enabled.
19
19
20 The :hg:`view` command will launch the hgk Tcl script. For this command
20 The :hg:`view` command will launch the hgk Tcl script. For this command
21 to work, hgk must be in your search path. Alternately, you can specify
21 to work, hgk must be in your search path. Alternately, you can specify
22 the path to hgk in your configuration file::
22 the path to hgk in your configuration file::
23
23
24 [hgk]
24 [hgk]
25 path=/location/of/hgk
25 path=/location/of/hgk
26
26
27 hgk can make use of the extdiff extension to visualize revisions.
27 hgk can make use of the extdiff extension to visualize revisions.
28 Assuming you had already configured extdiff vdiff command, just add::
28 Assuming you had already configured extdiff vdiff command, just add::
29
29
30 [hgk]
30 [hgk]
31 vdiff=vdiff
31 vdiff=vdiff
32
32
33 Revisions context menu will now display additional entries to fire
33 Revisions context menu will now display additional entries to fire
34 vdiff on hovered and selected revisions.
34 vdiff on hovered and selected revisions.
35 '''
35 '''
36
36
37 import os
37 import os
38 from mercurial import cmdutil, commands, patch, revlog, scmutil
38 from mercurial import cmdutil, commands, patch, revlog, scmutil
39 from mercurial.node import nullid, nullrev, short
39 from mercurial.node import nullid, nullrev, short
40 from mercurial.i18n import _
40 from mercurial.i18n import _
41
41
42 cmdtable = {}
42 cmdtable = {}
43 command = cmdutil.command(cmdtable)
43 command = cmdutil.command(cmdtable)
44 testedwith = 'internal'
44 testedwith = 'internal'
45
45
46 @command('debug-diff-tree',
46 @command('debug-diff-tree',
47 [('p', 'patch', None, _('generate patch')),
47 [('p', 'patch', None, _('generate patch')),
48 ('r', 'recursive', None, _('recursive')),
48 ('r', 'recursive', None, _('recursive')),
49 ('P', 'pretty', None, _('pretty')),
49 ('P', 'pretty', None, _('pretty')),
50 ('s', 'stdin', None, _('stdin')),
50 ('s', 'stdin', None, _('stdin')),
51 ('C', 'copy', None, _('detect copies')),
51 ('C', 'copy', None, _('detect copies')),
52 ('S', 'search', "", _('search'))],
52 ('S', 'search', "", _('search'))],
53 ('hg git-diff-tree [OPTION]... NODE1 NODE2 [FILE]...'),
53 ('[OPTION]... NODE1 NODE2 [FILE]...'),
54 inferrepo=True)
54 inferrepo=True)
55 def difftree(ui, repo, node1=None, node2=None, *files, **opts):
55 def difftree(ui, repo, node1=None, node2=None, *files, **opts):
56 """diff trees from two commits"""
56 """diff trees from two commits"""
57 def __difftree(repo, node1, node2, files=[]):
57 def __difftree(repo, node1, node2, files=[]):
58 assert node2 is not None
58 assert node2 is not None
59 mmap = repo[node1].manifest()
59 mmap = repo[node1].manifest()
60 mmap2 = repo[node2].manifest()
60 mmap2 = repo[node2].manifest()
61 m = scmutil.match(repo[node1], files)
61 m = scmutil.match(repo[node1], files)
62 modified, added, removed = repo.status(node1, node2, m)[:3]
62 modified, added, removed = repo.status(node1, node2, m)[:3]
63 empty = short(nullid)
63 empty = short(nullid)
64
64
65 for f in modified:
65 for f in modified:
66 # TODO get file permissions
66 # TODO get file permissions
67 ui.write(":100664 100664 %s %s M\t%s\t%s\n" %
67 ui.write(":100664 100664 %s %s M\t%s\t%s\n" %
68 (short(mmap[f]), short(mmap2[f]), f, f))
68 (short(mmap[f]), short(mmap2[f]), f, f))
69 for f in added:
69 for f in added:
70 ui.write(":000000 100664 %s %s N\t%s\t%s\n" %
70 ui.write(":000000 100664 %s %s N\t%s\t%s\n" %
71 (empty, short(mmap2[f]), f, f))
71 (empty, short(mmap2[f]), f, f))
72 for f in removed:
72 for f in removed:
73 ui.write(":100664 000000 %s %s D\t%s\t%s\n" %
73 ui.write(":100664 000000 %s %s D\t%s\t%s\n" %
74 (short(mmap[f]), empty, f, f))
74 (short(mmap[f]), empty, f, f))
75 ##
75 ##
76
76
77 while True:
77 while True:
78 if opts['stdin']:
78 if opts['stdin']:
79 try:
79 try:
80 line = raw_input().split(' ')
80 line = raw_input().split(' ')
81 node1 = line[0]
81 node1 = line[0]
82 if len(line) > 1:
82 if len(line) > 1:
83 node2 = line[1]
83 node2 = line[1]
84 else:
84 else:
85 node2 = None
85 node2 = None
86 except EOFError:
86 except EOFError:
87 break
87 break
88 node1 = repo.lookup(node1)
88 node1 = repo.lookup(node1)
89 if node2:
89 if node2:
90 node2 = repo.lookup(node2)
90 node2 = repo.lookup(node2)
91 else:
91 else:
92 node2 = node1
92 node2 = node1
93 node1 = repo.changelog.parents(node1)[0]
93 node1 = repo.changelog.parents(node1)[0]
94 if opts['patch']:
94 if opts['patch']:
95 if opts['pretty']:
95 if opts['pretty']:
96 catcommit(ui, repo, node2, "")
96 catcommit(ui, repo, node2, "")
97 m = scmutil.match(repo[node1], files)
97 m = scmutil.match(repo[node1], files)
98 diffopts = patch.difffeatureopts(ui)
98 diffopts = patch.difffeatureopts(ui)
99 diffopts.git = True
99 diffopts.git = True
100 chunks = patch.diff(repo, node1, node2, match=m,
100 chunks = patch.diff(repo, node1, node2, match=m,
101 opts=diffopts)
101 opts=diffopts)
102 for chunk in chunks:
102 for chunk in chunks:
103 ui.write(chunk)
103 ui.write(chunk)
104 else:
104 else:
105 __difftree(repo, node1, node2, files=files)
105 __difftree(repo, node1, node2, files=files)
106 if not opts['stdin']:
106 if not opts['stdin']:
107 break
107 break
108
108
109 def catcommit(ui, repo, n, prefix, ctx=None):
109 def catcommit(ui, repo, n, prefix, ctx=None):
110 nlprefix = '\n' + prefix
110 nlprefix = '\n' + prefix
111 if ctx is None:
111 if ctx is None:
112 ctx = repo[n]
112 ctx = repo[n]
113 # use ctx.node() instead ??
113 # use ctx.node() instead ??
114 ui.write(("tree %s\n" % short(ctx.changeset()[0])))
114 ui.write(("tree %s\n" % short(ctx.changeset()[0])))
115 for p in ctx.parents():
115 for p in ctx.parents():
116 ui.write(("parent %s\n" % p))
116 ui.write(("parent %s\n" % p))
117
117
118 date = ctx.date()
118 date = ctx.date()
119 description = ctx.description().replace("\0", "")
119 description = ctx.description().replace("\0", "")
120 lines = description.splitlines()
120 lines = description.splitlines()
121 if lines and lines[-1].startswith('committer:'):
121 if lines and lines[-1].startswith('committer:'):
122 committer = lines[-1].split(': ')[1].rstrip()
122 committer = lines[-1].split(': ')[1].rstrip()
123 else:
123 else:
124 committer = ""
124 committer = ""
125
125
126 ui.write(("author %s %s %s\n" % (ctx.user(), int(date[0]), date[1])))
126 ui.write(("author %s %s %s\n" % (ctx.user(), int(date[0]), date[1])))
127 if committer != '':
127 if committer != '':
128 ui.write(("committer %s %s %s\n" % (committer, int(date[0]), date[1])))
128 ui.write(("committer %s %s %s\n" % (committer, int(date[0]), date[1])))
129 ui.write(("revision %d\n" % ctx.rev()))
129 ui.write(("revision %d\n" % ctx.rev()))
130 ui.write(("branch %s\n" % ctx.branch()))
130 ui.write(("branch %s\n" % ctx.branch()))
131 ui.write(("phase %s\n\n" % ctx.phasestr()))
131 ui.write(("phase %s\n\n" % ctx.phasestr()))
132
132
133 if prefix != "":
133 if prefix != "":
134 ui.write("%s%s\n" % (prefix,
134 ui.write("%s%s\n" % (prefix,
135 description.replace('\n', nlprefix).strip()))
135 description.replace('\n', nlprefix).strip()))
136 else:
136 else:
137 ui.write(description + "\n")
137 ui.write(description + "\n")
138 if prefix:
138 if prefix:
139 ui.write('\0')
139 ui.write('\0')
140
140
141 @command('debug-merge-base', [], _('hg debug-merge-base REV REV'))
141 @command('debug-merge-base', [], _('REV REV'))
142 def base(ui, repo, node1, node2):
142 def base(ui, repo, node1, node2):
143 """output common ancestor information"""
143 """output common ancestor information"""
144 node1 = repo.lookup(node1)
144 node1 = repo.lookup(node1)
145 node2 = repo.lookup(node2)
145 node2 = repo.lookup(node2)
146 n = repo.changelog.ancestor(node1, node2)
146 n = repo.changelog.ancestor(node1, node2)
147 ui.write(short(n) + "\n")
147 ui.write(short(n) + "\n")
148
148
149 @command('debug-cat-file',
149 @command('debug-cat-file',
150 [('s', 'stdin', None, _('stdin'))],
150 [('s', 'stdin', None, _('stdin'))],
151 _('hg debug-cat-file [OPTION]... TYPE FILE'),
151 _('[OPTION]... TYPE FILE'),
152 inferrepo=True)
152 inferrepo=True)
153 def catfile(ui, repo, type=None, r=None, **opts):
153 def catfile(ui, repo, type=None, r=None, **opts):
154 """cat a specific revision"""
154 """cat a specific revision"""
155 # in stdin mode, every line except the commit is prefixed with two
155 # in stdin mode, every line except the commit is prefixed with two
156 # spaces. This way the our caller can find the commit without magic
156 # spaces. This way the our caller can find the commit without magic
157 # strings
157 # strings
158 #
158 #
159 prefix = ""
159 prefix = ""
160 if opts['stdin']:
160 if opts['stdin']:
161 try:
161 try:
162 (type, r) = raw_input().split(' ')
162 (type, r) = raw_input().split(' ')
163 prefix = " "
163 prefix = " "
164 except EOFError:
164 except EOFError:
165 return
165 return
166
166
167 else:
167 else:
168 if not type or not r:
168 if not type or not r:
169 ui.warn(_("cat-file: type or revision not supplied\n"))
169 ui.warn(_("cat-file: type or revision not supplied\n"))
170 commands.help_(ui, 'cat-file')
170 commands.help_(ui, 'cat-file')
171
171
172 while r:
172 while r:
173 if type != "commit":
173 if type != "commit":
174 ui.warn(_("aborting hg cat-file only understands commits\n"))
174 ui.warn(_("aborting hg cat-file only understands commits\n"))
175 return 1
175 return 1
176 n = repo.lookup(r)
176 n = repo.lookup(r)
177 catcommit(ui, repo, n, prefix)
177 catcommit(ui, repo, n, prefix)
178 if opts['stdin']:
178 if opts['stdin']:
179 try:
179 try:
180 (type, r) = raw_input().split(' ')
180 (type, r) = raw_input().split(' ')
181 except EOFError:
181 except EOFError:
182 break
182 break
183 else:
183 else:
184 break
184 break
185
185
186 # git rev-tree is a confusing thing. You can supply a number of
186 # git rev-tree is a confusing thing. You can supply a number of
187 # commit sha1s on the command line, and it walks the commit history
187 # commit sha1s on the command line, and it walks the commit history
188 # telling you which commits are reachable from the supplied ones via
188 # telling you which commits are reachable from the supplied ones via
189 # a bitmask based on arg position.
189 # a bitmask based on arg position.
190 # you can specify a commit to stop at by starting the sha1 with ^
190 # you can specify a commit to stop at by starting the sha1 with ^
191 def revtree(ui, args, repo, full="tree", maxnr=0, parents=False):
191 def revtree(ui, args, repo, full="tree", maxnr=0, parents=False):
192 def chlogwalk():
192 def chlogwalk():
193 count = len(repo)
193 count = len(repo)
194 i = count
194 i = count
195 l = [0] * 100
195 l = [0] * 100
196 chunk = 100
196 chunk = 100
197 while True:
197 while True:
198 if chunk > i:
198 if chunk > i:
199 chunk = i
199 chunk = i
200 i = 0
200 i = 0
201 else:
201 else:
202 i -= chunk
202 i -= chunk
203
203
204 for x in xrange(chunk):
204 for x in xrange(chunk):
205 if i + x >= count:
205 if i + x >= count:
206 l[chunk - x:] = [0] * (chunk - x)
206 l[chunk - x:] = [0] * (chunk - x)
207 break
207 break
208 if full is not None:
208 if full is not None:
209 if (i + x) in repo:
209 if (i + x) in repo:
210 l[x] = repo[i + x]
210 l[x] = repo[i + x]
211 l[x].changeset() # force reading
211 l[x].changeset() # force reading
212 else:
212 else:
213 if (i + x) in repo:
213 if (i + x) in repo:
214 l[x] = 1
214 l[x] = 1
215 for x in xrange(chunk - 1, -1, -1):
215 for x in xrange(chunk - 1, -1, -1):
216 if l[x] != 0:
216 if l[x] != 0:
217 yield (i + x, full is not None and l[x] or None)
217 yield (i + x, full is not None and l[x] or None)
218 if i == 0:
218 if i == 0:
219 break
219 break
220
220
221 # calculate and return the reachability bitmask for sha
221 # calculate and return the reachability bitmask for sha
222 def is_reachable(ar, reachable, sha):
222 def is_reachable(ar, reachable, sha):
223 if len(ar) == 0:
223 if len(ar) == 0:
224 return 1
224 return 1
225 mask = 0
225 mask = 0
226 for i in xrange(len(ar)):
226 for i in xrange(len(ar)):
227 if sha in reachable[i]:
227 if sha in reachable[i]:
228 mask |= 1 << i
228 mask |= 1 << i
229
229
230 return mask
230 return mask
231
231
232 reachable = []
232 reachable = []
233 stop_sha1 = []
233 stop_sha1 = []
234 want_sha1 = []
234 want_sha1 = []
235 count = 0
235 count = 0
236
236
237 # figure out which commits they are asking for and which ones they
237 # figure out which commits they are asking for and which ones they
238 # want us to stop on
238 # want us to stop on
239 for i, arg in enumerate(args):
239 for i, arg in enumerate(args):
240 if arg.startswith('^'):
240 if arg.startswith('^'):
241 s = repo.lookup(arg[1:])
241 s = repo.lookup(arg[1:])
242 stop_sha1.append(s)
242 stop_sha1.append(s)
243 want_sha1.append(s)
243 want_sha1.append(s)
244 elif arg != 'HEAD':
244 elif arg != 'HEAD':
245 want_sha1.append(repo.lookup(arg))
245 want_sha1.append(repo.lookup(arg))
246
246
247 # calculate the graph for the supplied commits
247 # calculate the graph for the supplied commits
248 for i, n in enumerate(want_sha1):
248 for i, n in enumerate(want_sha1):
249 reachable.append(set())
249 reachable.append(set())
250 visit = [n]
250 visit = [n]
251 reachable[i].add(n)
251 reachable[i].add(n)
252 while visit:
252 while visit:
253 n = visit.pop(0)
253 n = visit.pop(0)
254 if n in stop_sha1:
254 if n in stop_sha1:
255 continue
255 continue
256 for p in repo.changelog.parents(n):
256 for p in repo.changelog.parents(n):
257 if p not in reachable[i]:
257 if p not in reachable[i]:
258 reachable[i].add(p)
258 reachable[i].add(p)
259 visit.append(p)
259 visit.append(p)
260 if p in stop_sha1:
260 if p in stop_sha1:
261 continue
261 continue
262
262
263 # walk the repository looking for commits that are in our
263 # walk the repository looking for commits that are in our
264 # reachability graph
264 # reachability graph
265 for i, ctx in chlogwalk():
265 for i, ctx in chlogwalk():
266 if i not in repo:
266 if i not in repo:
267 continue
267 continue
268 n = repo.changelog.node(i)
268 n = repo.changelog.node(i)
269 mask = is_reachable(want_sha1, reachable, n)
269 mask = is_reachable(want_sha1, reachable, n)
270 if mask:
270 if mask:
271 parentstr = ""
271 parentstr = ""
272 if parents:
272 if parents:
273 pp = repo.changelog.parents(n)
273 pp = repo.changelog.parents(n)
274 if pp[0] != nullid:
274 if pp[0] != nullid:
275 parentstr += " " + short(pp[0])
275 parentstr += " " + short(pp[0])
276 if pp[1] != nullid:
276 if pp[1] != nullid:
277 parentstr += " " + short(pp[1])
277 parentstr += " " + short(pp[1])
278 if not full:
278 if not full:
279 ui.write("%s%s\n" % (short(n), parentstr))
279 ui.write("%s%s\n" % (short(n), parentstr))
280 elif full == "commit":
280 elif full == "commit":
281 ui.write("%s%s\n" % (short(n), parentstr))
281 ui.write("%s%s\n" % (short(n), parentstr))
282 catcommit(ui, repo, n, ' ', ctx)
282 catcommit(ui, repo, n, ' ', ctx)
283 else:
283 else:
284 (p1, p2) = repo.changelog.parents(n)
284 (p1, p2) = repo.changelog.parents(n)
285 (h, h1, h2) = map(short, (n, p1, p2))
285 (h, h1, h2) = map(short, (n, p1, p2))
286 (i1, i2) = map(repo.changelog.rev, (p1, p2))
286 (i1, i2) = map(repo.changelog.rev, (p1, p2))
287
287
288 date = ctx.date()[0]
288 date = ctx.date()[0]
289 ui.write("%s %s:%s" % (date, h, mask))
289 ui.write("%s %s:%s" % (date, h, mask))
290 mask = is_reachable(want_sha1, reachable, p1)
290 mask = is_reachable(want_sha1, reachable, p1)
291 if i1 != nullrev and mask > 0:
291 if i1 != nullrev and mask > 0:
292 ui.write("%s:%s " % (h1, mask)),
292 ui.write("%s:%s " % (h1, mask)),
293 mask = is_reachable(want_sha1, reachable, p2)
293 mask = is_reachable(want_sha1, reachable, p2)
294 if i2 != nullrev and mask > 0:
294 if i2 != nullrev and mask > 0:
295 ui.write("%s:%s " % (h2, mask))
295 ui.write("%s:%s " % (h2, mask))
296 ui.write("\n")
296 ui.write("\n")
297 if maxnr and count >= maxnr:
297 if maxnr and count >= maxnr:
298 break
298 break
299 count += 1
299 count += 1
300
300
301 @command('debug-rev-parse',
301 @command('debug-rev-parse',
302 [('', 'default', '', _('ignored'))],
302 [('', 'default', '', _('ignored'))],
303 _('hg debug-rev-parse REV'))
303 _('REV'))
304 def revparse(ui, repo, *revs, **opts):
304 def revparse(ui, repo, *revs, **opts):
305 """parse given revisions"""
305 """parse given revisions"""
306 def revstr(rev):
306 def revstr(rev):
307 if rev == 'HEAD':
307 if rev == 'HEAD':
308 rev = 'tip'
308 rev = 'tip'
309 return revlog.hex(repo.lookup(rev))
309 return revlog.hex(repo.lookup(rev))
310
310
311 for r in revs:
311 for r in revs:
312 revrange = r.split(':', 1)
312 revrange = r.split(':', 1)
313 ui.write('%s\n' % revstr(revrange[0]))
313 ui.write('%s\n' % revstr(revrange[0]))
314 if len(revrange) == 2:
314 if len(revrange) == 2:
315 ui.write('^%s\n' % revstr(revrange[1]))
315 ui.write('^%s\n' % revstr(revrange[1]))
316
316
317 # git rev-list tries to order things by date, and has the ability to stop
317 # git rev-list tries to order things by date, and has the ability to stop
318 # at a given commit without walking the whole repo. TODO add the stop
318 # at a given commit without walking the whole repo. TODO add the stop
319 # parameter
319 # parameter
320 @command('debug-rev-list',
320 @command('debug-rev-list',
321 [('H', 'header', None, _('header')),
321 [('H', 'header', None, _('header')),
322 ('t', 'topo-order', None, _('topo-order')),
322 ('t', 'topo-order', None, _('topo-order')),
323 ('p', 'parents', None, _('parents')),
323 ('p', 'parents', None, _('parents')),
324 ('n', 'max-count', 0, _('max-count'))],
324 ('n', 'max-count', 0, _('max-count'))],
325 ('hg debug-rev-list [OPTION]... REV...'))
325 ('[OPTION]... REV...'))
326 def revlist(ui, repo, *revs, **opts):
326 def revlist(ui, repo, *revs, **opts):
327 """print revisions"""
327 """print revisions"""
328 if opts['header']:
328 if opts['header']:
329 full = "commit"
329 full = "commit"
330 else:
330 else:
331 full = None
331 full = None
332 copy = [x for x in revs]
332 copy = [x for x in revs]
333 revtree(ui, copy, repo, full, opts['max_count'], opts['parents'])
333 revtree(ui, copy, repo, full, opts['max_count'], opts['parents'])
334
334
335 @command('debug-config', [], _('hg debug-config'))
335 @command('debug-config', [], _('hg debug-config'))
336 def config(ui, repo, **opts):
336 def config(ui, repo, **opts):
337 """print extension options"""
337 """print extension options"""
338 def writeopt(name, value):
338 def writeopt(name, value):
339 ui.write(('k=%s\nv=%s\n' % (name, value)))
339 ui.write(('k=%s\nv=%s\n' % (name, value)))
340
340
341 writeopt('vdiff', ui.config('hgk', 'vdiff', ''))
341 writeopt('vdiff', ui.config('hgk', 'vdiff', ''))
342
342
343
343
344 @command('view',
344 @command('view',
345 [('l', 'limit', '',
345 [('l', 'limit', '',
346 _('limit number of changes displayed'), _('NUM'))],
346 _('limit number of changes displayed'), _('NUM'))],
347 _('hg view [-l LIMIT] [REVRANGE]'))
347 _('[-l LIMIT] [REVRANGE]'))
348 def view(ui, repo, *etc, **opts):
348 def view(ui, repo, *etc, **opts):
349 "start interactive history viewer"
349 "start interactive history viewer"
350 os.chdir(repo.root)
350 os.chdir(repo.root)
351 optstr = ' '.join(['--%s %s' % (k, v) for k, v in opts.iteritems() if v])
351 optstr = ' '.join(['--%s %s' % (k, v) for k, v in opts.iteritems() if v])
352 cmd = ui.config("hgk", "path", "hgk") + " %s %s" % (optstr, " ".join(etc))
352 cmd = ui.config("hgk", "path", "hgk") + " %s %s" % (optstr, " ".join(etc))
353 ui.debug("running %s\n" % cmd)
353 ui.debug("running %s\n" % cmd)
354 ui.system(cmd)
354 ui.system(cmd)
General Comments 0
You need to be logged in to leave comments. Login now