##// END OF EJS Templates
copy & rename don't overwrite unless --force is specified
Robin Farine -
r1513:5c3b93b2 default
parent child Browse files
Show More
@@ -1,2623 +1,2626 b''
1 # commands.py - command processing for mercurial
1 # commands.py - command processing for mercurial
2 #
2 #
3 # Copyright 2005 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms
5 # This software may be used and distributed according to the terms
6 # of the GNU General Public License, incorporated herein by reference.
6 # of the GNU General Public License, incorporated herein by reference.
7
7
8 from demandload import demandload
8 from demandload import demandload
9 from node import *
9 from node import *
10 from i18n import gettext as _
10 from i18n import gettext as _
11 demandload(globals(), "os re sys signal shutil imp urllib pdb")
11 demandload(globals(), "os re sys signal shutil imp urllib pdb")
12 demandload(globals(), "fancyopts ui hg util lock revlog")
12 demandload(globals(), "fancyopts ui hg util lock revlog")
13 demandload(globals(), "fnmatch hgweb mdiff random signal time traceback")
13 demandload(globals(), "fnmatch hgweb mdiff random signal time traceback")
14 demandload(globals(), "errno socket version struct atexit sets bz2")
14 demandload(globals(), "errno socket version struct atexit sets bz2")
15
15
16 class UnknownCommand(Exception):
16 class UnknownCommand(Exception):
17 """Exception raised if command is not in the command table."""
17 """Exception raised if command is not in the command table."""
18
18
19 def filterfiles(filters, files):
19 def filterfiles(filters, files):
20 l = [x for x in files if x in filters]
20 l = [x for x in files if x in filters]
21
21
22 for t in filters:
22 for t in filters:
23 if t and t[-1] != "/":
23 if t and t[-1] != "/":
24 t += "/"
24 t += "/"
25 l += [x for x in files if x.startswith(t)]
25 l += [x for x in files if x.startswith(t)]
26 return l
26 return l
27
27
28 def relpath(repo, args):
28 def relpath(repo, args):
29 cwd = repo.getcwd()
29 cwd = repo.getcwd()
30 if cwd:
30 if cwd:
31 return [util.normpath(os.path.join(cwd, x)) for x in args]
31 return [util.normpath(os.path.join(cwd, x)) for x in args]
32 return args
32 return args
33
33
34 def matchpats(repo, cwd, pats=[], opts={}, head=''):
34 def matchpats(repo, cwd, pats=[], opts={}, head=''):
35 return util.cmdmatcher(repo.root, cwd, pats or ['.'], opts.get('include'),
35 return util.cmdmatcher(repo.root, cwd, pats or ['.'], opts.get('include'),
36 opts.get('exclude'), head)
36 opts.get('exclude'), head)
37
37
38 def makewalk(repo, pats, opts, head=''):
38 def makewalk(repo, pats, opts, head=''):
39 cwd = repo.getcwd()
39 cwd = repo.getcwd()
40 files, matchfn, anypats = matchpats(repo, cwd, pats, opts, head)
40 files, matchfn, anypats = matchpats(repo, cwd, pats, opts, head)
41 exact = dict(zip(files, files))
41 exact = dict(zip(files, files))
42 def walk():
42 def walk():
43 for src, fn in repo.walk(files=files, match=matchfn):
43 for src, fn in repo.walk(files=files, match=matchfn):
44 yield src, fn, util.pathto(cwd, fn), fn in exact
44 yield src, fn, util.pathto(cwd, fn), fn in exact
45 return files, matchfn, walk()
45 return files, matchfn, walk()
46
46
47 def walk(repo, pats, opts, head=''):
47 def walk(repo, pats, opts, head=''):
48 files, matchfn, results = makewalk(repo, pats, opts, head)
48 files, matchfn, results = makewalk(repo, pats, opts, head)
49 for r in results:
49 for r in results:
50 yield r
50 yield r
51
51
52 def walkchangerevs(ui, repo, cwd, pats, opts):
52 def walkchangerevs(ui, repo, cwd, pats, opts):
53 '''Iterate over files and the revs they changed in.
53 '''Iterate over files and the revs they changed in.
54
54
55 Callers most commonly need to iterate backwards over the history
55 Callers most commonly need to iterate backwards over the history
56 it is interested in. Doing so has awful (quadratic-looking)
56 it is interested in. Doing so has awful (quadratic-looking)
57 performance, so we use iterators in a "windowed" way.
57 performance, so we use iterators in a "windowed" way.
58
58
59 We walk a window of revisions in the desired order. Within the
59 We walk a window of revisions in the desired order. Within the
60 window, we first walk forwards to gather data, then in the desired
60 window, we first walk forwards to gather data, then in the desired
61 order (usually backwards) to display it.
61 order (usually backwards) to display it.
62
62
63 This function returns an (iterator, getchange) pair. The
63 This function returns an (iterator, getchange) pair. The
64 getchange function returns the changelog entry for a numeric
64 getchange function returns the changelog entry for a numeric
65 revision. The iterator yields 3-tuples. They will be of one of
65 revision. The iterator yields 3-tuples. They will be of one of
66 the following forms:
66 the following forms:
67
67
68 "window", incrementing, lastrev: stepping through a window,
68 "window", incrementing, lastrev: stepping through a window,
69 positive if walking forwards through revs, last rev in the
69 positive if walking forwards through revs, last rev in the
70 sequence iterated over - use to reset state for the current window
70 sequence iterated over - use to reset state for the current window
71
71
72 "add", rev, fns: out-of-order traversal of the given file names
72 "add", rev, fns: out-of-order traversal of the given file names
73 fns, which changed during revision rev - use to gather data for
73 fns, which changed during revision rev - use to gather data for
74 possible display
74 possible display
75
75
76 "iter", rev, None: in-order traversal of the revs earlier iterated
76 "iter", rev, None: in-order traversal of the revs earlier iterated
77 over with "add" - use to display data'''
77 over with "add" - use to display data'''
78
78
79 if repo.changelog.count() == 0:
79 if repo.changelog.count() == 0:
80 return [], False
80 return [], False
81
81
82 cwd = repo.getcwd()
82 cwd = repo.getcwd()
83 if not pats and cwd:
83 if not pats and cwd:
84 opts['include'] = [os.path.join(cwd, i) for i in opts['include']]
84 opts['include'] = [os.path.join(cwd, i) for i in opts['include']]
85 opts['exclude'] = [os.path.join(cwd, x) for x in opts['exclude']]
85 opts['exclude'] = [os.path.join(cwd, x) for x in opts['exclude']]
86 files, matchfn, anypats = matchpats(repo, (pats and cwd) or '',
86 files, matchfn, anypats = matchpats(repo, (pats and cwd) or '',
87 pats, opts)
87 pats, opts)
88 revs = map(int, revrange(ui, repo, opts['rev'] or ['tip:0']))
88 revs = map(int, revrange(ui, repo, opts['rev'] or ['tip:0']))
89 wanted = {}
89 wanted = {}
90 slowpath = anypats
90 slowpath = anypats
91 window = 300
91 window = 300
92 fncache = {}
92 fncache = {}
93
93
94 chcache = {}
94 chcache = {}
95 def getchange(rev):
95 def getchange(rev):
96 ch = chcache.get(rev)
96 ch = chcache.get(rev)
97 if ch is None:
97 if ch is None:
98 chcache[rev] = ch = repo.changelog.read(repo.lookup(str(rev)))
98 chcache[rev] = ch = repo.changelog.read(repo.lookup(str(rev)))
99 return ch
99 return ch
100
100
101 if not slowpath and not files:
101 if not slowpath and not files:
102 # No files, no patterns. Display all revs.
102 # No files, no patterns. Display all revs.
103 wanted = dict(zip(revs, revs))
103 wanted = dict(zip(revs, revs))
104 if not slowpath:
104 if not slowpath:
105 # Only files, no patterns. Check the history of each file.
105 # Only files, no patterns. Check the history of each file.
106 def filerevgen(filelog):
106 def filerevgen(filelog):
107 for i in xrange(filelog.count() - 1, -1, -window):
107 for i in xrange(filelog.count() - 1, -1, -window):
108 revs = []
108 revs = []
109 for j in xrange(max(0, i - window), i + 1):
109 for j in xrange(max(0, i - window), i + 1):
110 revs.append(filelog.linkrev(filelog.node(j)))
110 revs.append(filelog.linkrev(filelog.node(j)))
111 revs.reverse()
111 revs.reverse()
112 for rev in revs:
112 for rev in revs:
113 yield rev
113 yield rev
114
114
115 minrev, maxrev = min(revs), max(revs)
115 minrev, maxrev = min(revs), max(revs)
116 for file in files:
116 for file in files:
117 filelog = repo.file(file)
117 filelog = repo.file(file)
118 # A zero count may be a directory or deleted file, so
118 # A zero count may be a directory or deleted file, so
119 # try to find matching entries on the slow path.
119 # try to find matching entries on the slow path.
120 if filelog.count() == 0:
120 if filelog.count() == 0:
121 slowpath = True
121 slowpath = True
122 break
122 break
123 for rev in filerevgen(filelog):
123 for rev in filerevgen(filelog):
124 if rev <= maxrev:
124 if rev <= maxrev:
125 if rev < minrev:
125 if rev < minrev:
126 break
126 break
127 fncache.setdefault(rev, [])
127 fncache.setdefault(rev, [])
128 fncache[rev].append(file)
128 fncache[rev].append(file)
129 wanted[rev] = 1
129 wanted[rev] = 1
130 if slowpath:
130 if slowpath:
131 # The slow path checks files modified in every changeset.
131 # The slow path checks files modified in every changeset.
132 def changerevgen():
132 def changerevgen():
133 for i in xrange(repo.changelog.count() - 1, -1, -window):
133 for i in xrange(repo.changelog.count() - 1, -1, -window):
134 for j in xrange(max(0, i - window), i + 1):
134 for j in xrange(max(0, i - window), i + 1):
135 yield j, getchange(j)[3]
135 yield j, getchange(j)[3]
136
136
137 for rev, changefiles in changerevgen():
137 for rev, changefiles in changerevgen():
138 matches = filter(matchfn, changefiles)
138 matches = filter(matchfn, changefiles)
139 if matches:
139 if matches:
140 fncache[rev] = matches
140 fncache[rev] = matches
141 wanted[rev] = 1
141 wanted[rev] = 1
142
142
143 def iterate():
143 def iterate():
144 for i in xrange(0, len(revs), window):
144 for i in xrange(0, len(revs), window):
145 yield 'window', revs[0] < revs[-1], revs[-1]
145 yield 'window', revs[0] < revs[-1], revs[-1]
146 nrevs = [rev for rev in revs[i:min(i+window, len(revs))]
146 nrevs = [rev for rev in revs[i:min(i+window, len(revs))]
147 if rev in wanted]
147 if rev in wanted]
148 srevs = list(nrevs)
148 srevs = list(nrevs)
149 srevs.sort()
149 srevs.sort()
150 for rev in srevs:
150 for rev in srevs:
151 fns = fncache.get(rev) or filter(matchfn, getchange(rev)[3])
151 fns = fncache.get(rev) or filter(matchfn, getchange(rev)[3])
152 yield 'add', rev, fns
152 yield 'add', rev, fns
153 for rev in nrevs:
153 for rev in nrevs:
154 yield 'iter', rev, None
154 yield 'iter', rev, None
155 return iterate(), getchange
155 return iterate(), getchange
156
156
157 revrangesep = ':'
157 revrangesep = ':'
158
158
159 def revrange(ui, repo, revs, revlog=None):
159 def revrange(ui, repo, revs, revlog=None):
160 """Yield revision as strings from a list of revision specifications."""
160 """Yield revision as strings from a list of revision specifications."""
161 if revlog is None:
161 if revlog is None:
162 revlog = repo.changelog
162 revlog = repo.changelog
163 revcount = revlog.count()
163 revcount = revlog.count()
164 def fix(val, defval):
164 def fix(val, defval):
165 if not val:
165 if not val:
166 return defval
166 return defval
167 try:
167 try:
168 num = int(val)
168 num = int(val)
169 if str(num) != val:
169 if str(num) != val:
170 raise ValueError
170 raise ValueError
171 if num < 0: num += revcount
171 if num < 0: num += revcount
172 if num < 0: num = 0
172 if num < 0: num = 0
173 elif num >= revcount:
173 elif num >= revcount:
174 raise ValueError
174 raise ValueError
175 except ValueError:
175 except ValueError:
176 try:
176 try:
177 num = repo.changelog.rev(repo.lookup(val))
177 num = repo.changelog.rev(repo.lookup(val))
178 except KeyError:
178 except KeyError:
179 try:
179 try:
180 num = revlog.rev(revlog.lookup(val))
180 num = revlog.rev(revlog.lookup(val))
181 except KeyError:
181 except KeyError:
182 raise util.Abort(_('invalid revision identifier %s'), val)
182 raise util.Abort(_('invalid revision identifier %s'), val)
183 return num
183 return num
184 seen = {}
184 seen = {}
185 for spec in revs:
185 for spec in revs:
186 if spec.find(revrangesep) >= 0:
186 if spec.find(revrangesep) >= 0:
187 start, end = spec.split(revrangesep, 1)
187 start, end = spec.split(revrangesep, 1)
188 start = fix(start, 0)
188 start = fix(start, 0)
189 end = fix(end, revcount - 1)
189 end = fix(end, revcount - 1)
190 step = start > end and -1 or 1
190 step = start > end and -1 or 1
191 for rev in xrange(start, end+step, step):
191 for rev in xrange(start, end+step, step):
192 if rev in seen: continue
192 if rev in seen: continue
193 seen[rev] = 1
193 seen[rev] = 1
194 yield str(rev)
194 yield str(rev)
195 else:
195 else:
196 rev = fix(spec, None)
196 rev = fix(spec, None)
197 if rev in seen: continue
197 if rev in seen: continue
198 seen[rev] = 1
198 seen[rev] = 1
199 yield str(rev)
199 yield str(rev)
200
200
201 def make_filename(repo, r, pat, node=None,
201 def make_filename(repo, r, pat, node=None,
202 total=None, seqno=None, revwidth=None, pathname=None):
202 total=None, seqno=None, revwidth=None, pathname=None):
203 node_expander = {
203 node_expander = {
204 'H': lambda: hex(node),
204 'H': lambda: hex(node),
205 'R': lambda: str(r.rev(node)),
205 'R': lambda: str(r.rev(node)),
206 'h': lambda: short(node),
206 'h': lambda: short(node),
207 }
207 }
208 expander = {
208 expander = {
209 '%': lambda: '%',
209 '%': lambda: '%',
210 'b': lambda: os.path.basename(repo.root),
210 'b': lambda: os.path.basename(repo.root),
211 }
211 }
212
212
213 try:
213 try:
214 if node:
214 if node:
215 expander.update(node_expander)
215 expander.update(node_expander)
216 if node and revwidth is not None:
216 if node and revwidth is not None:
217 expander['r'] = lambda: str(r.rev(node)).zfill(revwidth)
217 expander['r'] = lambda: str(r.rev(node)).zfill(revwidth)
218 if total is not None:
218 if total is not None:
219 expander['N'] = lambda: str(total)
219 expander['N'] = lambda: str(total)
220 if seqno is not None:
220 if seqno is not None:
221 expander['n'] = lambda: str(seqno)
221 expander['n'] = lambda: str(seqno)
222 if total is not None and seqno is not None:
222 if total is not None and seqno is not None:
223 expander['n'] = lambda:str(seqno).zfill(len(str(total)))
223 expander['n'] = lambda:str(seqno).zfill(len(str(total)))
224 if pathname is not None:
224 if pathname is not None:
225 expander['s'] = lambda: os.path.basename(pathname)
225 expander['s'] = lambda: os.path.basename(pathname)
226 expander['d'] = lambda: os.path.dirname(pathname) or '.'
226 expander['d'] = lambda: os.path.dirname(pathname) or '.'
227 expander['p'] = lambda: pathname
227 expander['p'] = lambda: pathname
228
228
229 newname = []
229 newname = []
230 patlen = len(pat)
230 patlen = len(pat)
231 i = 0
231 i = 0
232 while i < patlen:
232 while i < patlen:
233 c = pat[i]
233 c = pat[i]
234 if c == '%':
234 if c == '%':
235 i += 1
235 i += 1
236 c = pat[i]
236 c = pat[i]
237 c = expander[c]()
237 c = expander[c]()
238 newname.append(c)
238 newname.append(c)
239 i += 1
239 i += 1
240 return ''.join(newname)
240 return ''.join(newname)
241 except KeyError, inst:
241 except KeyError, inst:
242 raise util.Abort(_("invalid format spec '%%%s' in output file name"),
242 raise util.Abort(_("invalid format spec '%%%s' in output file name"),
243 inst.args[0])
243 inst.args[0])
244
244
245 def make_file(repo, r, pat, node=None,
245 def make_file(repo, r, pat, node=None,
246 total=None, seqno=None, revwidth=None, mode='wb', pathname=None):
246 total=None, seqno=None, revwidth=None, mode='wb', pathname=None):
247 if not pat or pat == '-':
247 if not pat or pat == '-':
248 return 'w' in mode and sys.stdout or sys.stdin
248 return 'w' in mode and sys.stdout or sys.stdin
249 if hasattr(pat, 'write') and 'w' in mode:
249 if hasattr(pat, 'write') and 'w' in mode:
250 return pat
250 return pat
251 if hasattr(pat, 'read') and 'r' in mode:
251 if hasattr(pat, 'read') and 'r' in mode:
252 return pat
252 return pat
253 return open(make_filename(repo, r, pat, node, total, seqno, revwidth,
253 return open(make_filename(repo, r, pat, node, total, seqno, revwidth,
254 pathname),
254 pathname),
255 mode)
255 mode)
256
256
257 def dodiff(fp, ui, repo, node1, node2, files=None, match=util.always,
257 def dodiff(fp, ui, repo, node1, node2, files=None, match=util.always,
258 changes=None, text=False):
258 changes=None, text=False):
259 if not changes:
259 if not changes:
260 (c, a, d, u) = repo.changes(node1, node2, files, match=match)
260 (c, a, d, u) = repo.changes(node1, node2, files, match=match)
261 else:
261 else:
262 (c, a, d, u) = changes
262 (c, a, d, u) = changes
263 if files:
263 if files:
264 c, a, d = map(lambda x: filterfiles(files, x), (c, a, d))
264 c, a, d = map(lambda x: filterfiles(files, x), (c, a, d))
265
265
266 if not c and not a and not d:
266 if not c and not a and not d:
267 return
267 return
268
268
269 if node2:
269 if node2:
270 change = repo.changelog.read(node2)
270 change = repo.changelog.read(node2)
271 mmap2 = repo.manifest.read(change[0])
271 mmap2 = repo.manifest.read(change[0])
272 date2 = util.datestr(change[2])
272 date2 = util.datestr(change[2])
273 def read(f):
273 def read(f):
274 return repo.file(f).read(mmap2[f])
274 return repo.file(f).read(mmap2[f])
275 else:
275 else:
276 date2 = util.datestr()
276 date2 = util.datestr()
277 if not node1:
277 if not node1:
278 node1 = repo.dirstate.parents()[0]
278 node1 = repo.dirstate.parents()[0]
279 def read(f):
279 def read(f):
280 return repo.wfile(f).read()
280 return repo.wfile(f).read()
281
281
282 if ui.quiet:
282 if ui.quiet:
283 r = None
283 r = None
284 else:
284 else:
285 hexfunc = ui.verbose and hex or short
285 hexfunc = ui.verbose and hex or short
286 r = [hexfunc(node) for node in [node1, node2] if node]
286 r = [hexfunc(node) for node in [node1, node2] if node]
287
287
288 change = repo.changelog.read(node1)
288 change = repo.changelog.read(node1)
289 mmap = repo.manifest.read(change[0])
289 mmap = repo.manifest.read(change[0])
290 date1 = util.datestr(change[2])
290 date1 = util.datestr(change[2])
291
291
292 for f in c:
292 for f in c:
293 to = None
293 to = None
294 if f in mmap:
294 if f in mmap:
295 to = repo.file(f).read(mmap[f])
295 to = repo.file(f).read(mmap[f])
296 tn = read(f)
296 tn = read(f)
297 fp.write(mdiff.unidiff(to, date1, tn, date2, f, r, text=text))
297 fp.write(mdiff.unidiff(to, date1, tn, date2, f, r, text=text))
298 for f in a:
298 for f in a:
299 to = None
299 to = None
300 tn = read(f)
300 tn = read(f)
301 fp.write(mdiff.unidiff(to, date1, tn, date2, f, r, text=text))
301 fp.write(mdiff.unidiff(to, date1, tn, date2, f, r, text=text))
302 for f in d:
302 for f in d:
303 to = repo.file(f).read(mmap[f])
303 to = repo.file(f).read(mmap[f])
304 tn = None
304 tn = None
305 fp.write(mdiff.unidiff(to, date1, tn, date2, f, r, text=text))
305 fp.write(mdiff.unidiff(to, date1, tn, date2, f, r, text=text))
306
306
307 def trimuser(ui, name, rev, revcache):
307 def trimuser(ui, name, rev, revcache):
308 """trim the name of the user who committed a change"""
308 """trim the name of the user who committed a change"""
309 user = revcache.get(rev)
309 user = revcache.get(rev)
310 if user is None:
310 if user is None:
311 user = revcache[rev] = ui.shortuser(name)
311 user = revcache[rev] = ui.shortuser(name)
312 return user
312 return user
313
313
314 def show_changeset(ui, repo, rev=0, changenode=None, brinfo=None):
314 def show_changeset(ui, repo, rev=0, changenode=None, brinfo=None):
315 """show a single changeset or file revision"""
315 """show a single changeset or file revision"""
316 log = repo.changelog
316 log = repo.changelog
317 if changenode is None:
317 if changenode is None:
318 changenode = log.node(rev)
318 changenode = log.node(rev)
319 elif not rev:
319 elif not rev:
320 rev = log.rev(changenode)
320 rev = log.rev(changenode)
321
321
322 if ui.quiet:
322 if ui.quiet:
323 ui.write("%d:%s\n" % (rev, short(changenode)))
323 ui.write("%d:%s\n" % (rev, short(changenode)))
324 return
324 return
325
325
326 changes = log.read(changenode)
326 changes = log.read(changenode)
327 date = util.datestr(changes[2])
327 date = util.datestr(changes[2])
328
328
329 parents = [(log.rev(p), ui.verbose and hex(p) or short(p))
329 parents = [(log.rev(p), ui.verbose and hex(p) or short(p))
330 for p in log.parents(changenode)
330 for p in log.parents(changenode)
331 if ui.debugflag or p != nullid]
331 if ui.debugflag or p != nullid]
332 if not ui.debugflag and len(parents) == 1 and parents[0][0] == rev-1:
332 if not ui.debugflag and len(parents) == 1 and parents[0][0] == rev-1:
333 parents = []
333 parents = []
334
334
335 if ui.verbose:
335 if ui.verbose:
336 ui.write(_("changeset: %d:%s\n") % (rev, hex(changenode)))
336 ui.write(_("changeset: %d:%s\n") % (rev, hex(changenode)))
337 else:
337 else:
338 ui.write(_("changeset: %d:%s\n") % (rev, short(changenode)))
338 ui.write(_("changeset: %d:%s\n") % (rev, short(changenode)))
339
339
340 for tag in repo.nodetags(changenode):
340 for tag in repo.nodetags(changenode):
341 ui.status(_("tag: %s\n") % tag)
341 ui.status(_("tag: %s\n") % tag)
342 for parent in parents:
342 for parent in parents:
343 ui.write(_("parent: %d:%s\n") % parent)
343 ui.write(_("parent: %d:%s\n") % parent)
344
344
345 if brinfo and changenode in brinfo:
345 if brinfo and changenode in brinfo:
346 br = brinfo[changenode]
346 br = brinfo[changenode]
347 ui.write(_("branch: %s\n") % " ".join(br))
347 ui.write(_("branch: %s\n") % " ".join(br))
348
348
349 ui.debug(_("manifest: %d:%s\n") % (repo.manifest.rev(changes[0]),
349 ui.debug(_("manifest: %d:%s\n") % (repo.manifest.rev(changes[0]),
350 hex(changes[0])))
350 hex(changes[0])))
351 ui.status(_("user: %s\n") % changes[1])
351 ui.status(_("user: %s\n") % changes[1])
352 ui.status(_("date: %s\n") % date)
352 ui.status(_("date: %s\n") % date)
353
353
354 if ui.debugflag:
354 if ui.debugflag:
355 files = repo.changes(log.parents(changenode)[0], changenode)
355 files = repo.changes(log.parents(changenode)[0], changenode)
356 for key, value in zip([_("files:"), _("files+:"), _("files-:")], files):
356 for key, value in zip([_("files:"), _("files+:"), _("files-:")], files):
357 if value:
357 if value:
358 ui.note("%-12s %s\n" % (key, " ".join(value)))
358 ui.note("%-12s %s\n" % (key, " ".join(value)))
359 else:
359 else:
360 ui.note(_("files: %s\n") % " ".join(changes[3]))
360 ui.note(_("files: %s\n") % " ".join(changes[3]))
361
361
362 description = changes[4].strip()
362 description = changes[4].strip()
363 if description:
363 if description:
364 if ui.verbose:
364 if ui.verbose:
365 ui.status(_("description:\n"))
365 ui.status(_("description:\n"))
366 ui.status(description)
366 ui.status(description)
367 ui.status("\n\n")
367 ui.status("\n\n")
368 else:
368 else:
369 ui.status(_("summary: %s\n") % description.splitlines()[0])
369 ui.status(_("summary: %s\n") % description.splitlines()[0])
370 ui.status("\n")
370 ui.status("\n")
371
371
372 def show_version(ui):
372 def show_version(ui):
373 """output version and copyright information"""
373 """output version and copyright information"""
374 ui.write(_("Mercurial Distributed SCM (version %s)\n")
374 ui.write(_("Mercurial Distributed SCM (version %s)\n")
375 % version.get_version())
375 % version.get_version())
376 ui.status(_(
376 ui.status(_(
377 "\nCopyright (C) 2005 Matt Mackall <mpm@selenic.com>\n"
377 "\nCopyright (C) 2005 Matt Mackall <mpm@selenic.com>\n"
378 "This is free software; see the source for copying conditions. "
378 "This is free software; see the source for copying conditions. "
379 "There is NO\nwarranty; "
379 "There is NO\nwarranty; "
380 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
380 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
381 ))
381 ))
382
382
383 def help_(ui, cmd=None, with_version=False):
383 def help_(ui, cmd=None, with_version=False):
384 """show help for a given command or all commands"""
384 """show help for a given command or all commands"""
385 option_lists = []
385 option_lists = []
386 if cmd and cmd != 'shortlist':
386 if cmd and cmd != 'shortlist':
387 if with_version:
387 if with_version:
388 show_version(ui)
388 show_version(ui)
389 ui.write('\n')
389 ui.write('\n')
390 key, i = find(cmd)
390 key, i = find(cmd)
391 # synopsis
391 # synopsis
392 ui.write("%s\n\n" % i[2])
392 ui.write("%s\n\n" % i[2])
393
393
394 # description
394 # description
395 doc = i[0].__doc__
395 doc = i[0].__doc__
396 if ui.quiet:
396 if ui.quiet:
397 doc = doc.splitlines(0)[0]
397 doc = doc.splitlines(0)[0]
398 ui.write("%s\n" % doc.rstrip())
398 ui.write("%s\n" % doc.rstrip())
399
399
400 if not ui.quiet:
400 if not ui.quiet:
401 # aliases
401 # aliases
402 aliases = ', '.join(key.split('|')[1:])
402 aliases = ', '.join(key.split('|')[1:])
403 if aliases:
403 if aliases:
404 ui.write(_("\naliases: %s\n") % aliases)
404 ui.write(_("\naliases: %s\n") % aliases)
405
405
406 # options
406 # options
407 if i[1]:
407 if i[1]:
408 option_lists.append(("options", i[1]))
408 option_lists.append(("options", i[1]))
409
409
410 else:
410 else:
411 # program name
411 # program name
412 if ui.verbose or with_version:
412 if ui.verbose or with_version:
413 show_version(ui)
413 show_version(ui)
414 else:
414 else:
415 ui.status(_("Mercurial Distributed SCM\n"))
415 ui.status(_("Mercurial Distributed SCM\n"))
416 ui.status('\n')
416 ui.status('\n')
417
417
418 # list of commands
418 # list of commands
419 if cmd == "shortlist":
419 if cmd == "shortlist":
420 ui.status(_('basic commands (use "hg help" '
420 ui.status(_('basic commands (use "hg help" '
421 'for the full list or option "-v" for details):\n\n'))
421 'for the full list or option "-v" for details):\n\n'))
422 elif ui.verbose:
422 elif ui.verbose:
423 ui.status(_('list of commands:\n\n'))
423 ui.status(_('list of commands:\n\n'))
424 else:
424 else:
425 ui.status(_('list of commands (use "hg help -v" '
425 ui.status(_('list of commands (use "hg help -v" '
426 'to show aliases and global options):\n\n'))
426 'to show aliases and global options):\n\n'))
427
427
428 h = {}
428 h = {}
429 cmds = {}
429 cmds = {}
430 for c, e in table.items():
430 for c, e in table.items():
431 f = c.split("|")[0]
431 f = c.split("|")[0]
432 if cmd == "shortlist" and not f.startswith("^"):
432 if cmd == "shortlist" and not f.startswith("^"):
433 continue
433 continue
434 f = f.lstrip("^")
434 f = f.lstrip("^")
435 if not ui.debugflag and f.startswith("debug"):
435 if not ui.debugflag and f.startswith("debug"):
436 continue
436 continue
437 d = ""
437 d = ""
438 if e[0].__doc__:
438 if e[0].__doc__:
439 d = e[0].__doc__.splitlines(0)[0].rstrip()
439 d = e[0].__doc__.splitlines(0)[0].rstrip()
440 h[f] = d
440 h[f] = d
441 cmds[f]=c.lstrip("^")
441 cmds[f]=c.lstrip("^")
442
442
443 fns = h.keys()
443 fns = h.keys()
444 fns.sort()
444 fns.sort()
445 m = max(map(len, fns))
445 m = max(map(len, fns))
446 for f in fns:
446 for f in fns:
447 if ui.verbose:
447 if ui.verbose:
448 commands = cmds[f].replace("|",", ")
448 commands = cmds[f].replace("|",", ")
449 ui.write(" %s:\n %s\n"%(commands,h[f]))
449 ui.write(" %s:\n %s\n"%(commands,h[f]))
450 else:
450 else:
451 ui.write(' %-*s %s\n' % (m, f, h[f]))
451 ui.write(' %-*s %s\n' % (m, f, h[f]))
452
452
453 # global options
453 # global options
454 if ui.verbose:
454 if ui.verbose:
455 option_lists.append(("global options", globalopts))
455 option_lists.append(("global options", globalopts))
456
456
457 # list all option lists
457 # list all option lists
458 opt_output = []
458 opt_output = []
459 for title, options in option_lists:
459 for title, options in option_lists:
460 opt_output.append(("\n%s:\n" % title, None))
460 opt_output.append(("\n%s:\n" % title, None))
461 for shortopt, longopt, default, desc in options:
461 for shortopt, longopt, default, desc in options:
462 opt_output.append(("%2s%s" % (shortopt and "-%s" % shortopt,
462 opt_output.append(("%2s%s" % (shortopt and "-%s" % shortopt,
463 longopt and " --%s" % longopt),
463 longopt and " --%s" % longopt),
464 "%s%s" % (desc,
464 "%s%s" % (desc,
465 default and _(" (default: %s)") % default
465 default and _(" (default: %s)") % default
466 or "")))
466 or "")))
467
467
468 if opt_output:
468 if opt_output:
469 opts_len = max([len(line[0]) for line in opt_output if line[1]])
469 opts_len = max([len(line[0]) for line in opt_output if line[1]])
470 for first, second in opt_output:
470 for first, second in opt_output:
471 if second:
471 if second:
472 ui.write(" %-*s %s\n" % (opts_len, first, second))
472 ui.write(" %-*s %s\n" % (opts_len, first, second))
473 else:
473 else:
474 ui.write("%s\n" % first)
474 ui.write("%s\n" % first)
475
475
476 # Commands start here, listed alphabetically
476 # Commands start here, listed alphabetically
477
477
478 def add(ui, repo, *pats, **opts):
478 def add(ui, repo, *pats, **opts):
479 """add the specified files on the next commit
479 """add the specified files on the next commit
480
480
481 Schedule files to be version controlled and added to the repository.
481 Schedule files to be version controlled and added to the repository.
482
482
483 The files will be added to the repository at the next commit.
483 The files will be added to the repository at the next commit.
484
484
485 If no names are given, add all files in the current directory and
485 If no names are given, add all files in the current directory and
486 its subdirectories.
486 its subdirectories.
487 """
487 """
488
488
489 names = []
489 names = []
490 for src, abs, rel, exact in walk(repo, pats, opts):
490 for src, abs, rel, exact in walk(repo, pats, opts):
491 if exact:
491 if exact:
492 if ui.verbose: ui.status(_('adding %s\n') % rel)
492 if ui.verbose: ui.status(_('adding %s\n') % rel)
493 names.append(abs)
493 names.append(abs)
494 elif repo.dirstate.state(abs) == '?':
494 elif repo.dirstate.state(abs) == '?':
495 ui.status(_('adding %s\n') % rel)
495 ui.status(_('adding %s\n') % rel)
496 names.append(abs)
496 names.append(abs)
497 repo.add(names)
497 repo.add(names)
498
498
499 def addremove(ui, repo, *pats, **opts):
499 def addremove(ui, repo, *pats, **opts):
500 """add all new files, delete all missing files
500 """add all new files, delete all missing files
501
501
502 Add all new files and remove all missing files from the repository.
502 Add all new files and remove all missing files from the repository.
503
503
504 New files are ignored if they match any of the patterns in .hgignore. As
504 New files are ignored if they match any of the patterns in .hgignore. As
505 with add, these changes take effect at the next commit.
505 with add, these changes take effect at the next commit.
506 """
506 """
507 add, remove = [], []
507 add, remove = [], []
508 for src, abs, rel, exact in walk(repo, pats, opts):
508 for src, abs, rel, exact in walk(repo, pats, opts):
509 if src == 'f' and repo.dirstate.state(abs) == '?':
509 if src == 'f' and repo.dirstate.state(abs) == '?':
510 add.append(abs)
510 add.append(abs)
511 if ui.verbose or not exact:
511 if ui.verbose or not exact:
512 ui.status(_('adding %s\n') % rel)
512 ui.status(_('adding %s\n') % rel)
513 if repo.dirstate.state(abs) != 'r' and not os.path.exists(rel):
513 if repo.dirstate.state(abs) != 'r' and not os.path.exists(rel):
514 remove.append(abs)
514 remove.append(abs)
515 if ui.verbose or not exact:
515 if ui.verbose or not exact:
516 ui.status(_('removing %s\n') % rel)
516 ui.status(_('removing %s\n') % rel)
517 repo.add(add)
517 repo.add(add)
518 repo.remove(remove)
518 repo.remove(remove)
519
519
520 def annotate(ui, repo, *pats, **opts):
520 def annotate(ui, repo, *pats, **opts):
521 """show changeset information per file line
521 """show changeset information per file line
522
522
523 List changes in files, showing the revision id responsible for each line
523 List changes in files, showing the revision id responsible for each line
524
524
525 This command is useful to discover who did a change or when a change took
525 This command is useful to discover who did a change or when a change took
526 place.
526 place.
527
527
528 Without the -a option, annotate will avoid processing files it
528 Without the -a option, annotate will avoid processing files it
529 detects as binary. With -a, annotate will generate an annotation
529 detects as binary. With -a, annotate will generate an annotation
530 anyway, probably with undesirable results.
530 anyway, probably with undesirable results.
531 """
531 """
532 def getnode(rev):
532 def getnode(rev):
533 return short(repo.changelog.node(rev))
533 return short(repo.changelog.node(rev))
534
534
535 ucache = {}
535 ucache = {}
536 def getname(rev):
536 def getname(rev):
537 cl = repo.changelog.read(repo.changelog.node(rev))
537 cl = repo.changelog.read(repo.changelog.node(rev))
538 return trimuser(ui, cl[1], rev, ucache)
538 return trimuser(ui, cl[1], rev, ucache)
539
539
540 if not pats:
540 if not pats:
541 raise util.Abort(_('at least one file name or pattern required'))
541 raise util.Abort(_('at least one file name or pattern required'))
542
542
543 opmap = [['user', getname], ['number', str], ['changeset', getnode]]
543 opmap = [['user', getname], ['number', str], ['changeset', getnode]]
544 if not opts['user'] and not opts['changeset']:
544 if not opts['user'] and not opts['changeset']:
545 opts['number'] = 1
545 opts['number'] = 1
546
546
547 if opts['rev']:
547 if opts['rev']:
548 node = repo.changelog.lookup(opts['rev'])
548 node = repo.changelog.lookup(opts['rev'])
549 else:
549 else:
550 node = repo.dirstate.parents()[0]
550 node = repo.dirstate.parents()[0]
551 change = repo.changelog.read(node)
551 change = repo.changelog.read(node)
552 mmap = repo.manifest.read(change[0])
552 mmap = repo.manifest.read(change[0])
553
553
554 for src, abs, rel, exact in walk(repo, pats, opts):
554 for src, abs, rel, exact in walk(repo, pats, opts):
555 if abs not in mmap:
555 if abs not in mmap:
556 ui.warn(_("warning: %s is not in the repository!\n") % rel)
556 ui.warn(_("warning: %s is not in the repository!\n") % rel)
557 continue
557 continue
558
558
559 f = repo.file(abs)
559 f = repo.file(abs)
560 if not opts['text'] and util.binary(f.read(mmap[abs])):
560 if not opts['text'] and util.binary(f.read(mmap[abs])):
561 ui.write(_("%s: binary file\n") % rel)
561 ui.write(_("%s: binary file\n") % rel)
562 continue
562 continue
563
563
564 lines = f.annotate(mmap[abs])
564 lines = f.annotate(mmap[abs])
565 pieces = []
565 pieces = []
566
566
567 for o, f in opmap:
567 for o, f in opmap:
568 if opts[o]:
568 if opts[o]:
569 l = [f(n) for n, dummy in lines]
569 l = [f(n) for n, dummy in lines]
570 if l:
570 if l:
571 m = max(map(len, l))
571 m = max(map(len, l))
572 pieces.append(["%*s" % (m, x) for x in l])
572 pieces.append(["%*s" % (m, x) for x in l])
573
573
574 if pieces:
574 if pieces:
575 for p, l in zip(zip(*pieces), lines):
575 for p, l in zip(zip(*pieces), lines):
576 ui.write("%s: %s" % (" ".join(p), l[1]))
576 ui.write("%s: %s" % (" ".join(p), l[1]))
577
577
578 def bundle(ui, repo, fname, dest="default-push", **opts):
578 def bundle(ui, repo, fname, dest="default-push", **opts):
579 """create a changegroup file
579 """create a changegroup file
580
580
581 Generate a compressed changegroup file collecting all changesets
581 Generate a compressed changegroup file collecting all changesets
582 not found in the other repository.
582 not found in the other repository.
583
583
584 This file can then be transferred using conventional means and
584 This file can then be transferred using conventional means and
585 applied to another repository with the unbundle command. This is
585 applied to another repository with the unbundle command. This is
586 useful when native push and pull are not available or when
586 useful when native push and pull are not available or when
587 exporting an entire repository is undesirable. The standard file
587 exporting an entire repository is undesirable. The standard file
588 extension is ".hg".
588 extension is ".hg".
589
589
590 Unlike import/export, this exactly preserves all changeset
590 Unlike import/export, this exactly preserves all changeset
591 contents including permissions, rename data, and revision history.
591 contents including permissions, rename data, and revision history.
592 """
592 """
593 f = open(fname, "wb")
593 f = open(fname, "wb")
594 dest = ui.expandpath(dest, repo.root)
594 dest = ui.expandpath(dest, repo.root)
595 other = hg.repository(ui, dest)
595 other = hg.repository(ui, dest)
596 o = repo.findoutgoing(other)
596 o = repo.findoutgoing(other)
597 cg = repo.changegroup(o)
597 cg = repo.changegroup(o)
598
598
599 try:
599 try:
600 f.write("HG10")
600 f.write("HG10")
601 z = bz2.BZ2Compressor(9)
601 z = bz2.BZ2Compressor(9)
602 while 1:
602 while 1:
603 chunk = cg.read(4096)
603 chunk = cg.read(4096)
604 if not chunk:
604 if not chunk:
605 break
605 break
606 f.write(z.compress(chunk))
606 f.write(z.compress(chunk))
607 f.write(z.flush())
607 f.write(z.flush())
608 except:
608 except:
609 os.unlink(fname)
609 os.unlink(fname)
610 raise
610 raise
611
611
612 def cat(ui, repo, file1, *pats, **opts):
612 def cat(ui, repo, file1, *pats, **opts):
613 """output the latest or given revisions of files
613 """output the latest or given revisions of files
614
614
615 Print the specified files as they were at the given revision.
615 Print the specified files as they were at the given revision.
616 If no revision is given then the tip is used.
616 If no revision is given then the tip is used.
617
617
618 Output may be to a file, in which case the name of the file is
618 Output may be to a file, in which case the name of the file is
619 given using a format string. The formatting rules are the same as
619 given using a format string. The formatting rules are the same as
620 for the export command, with the following additions:
620 for the export command, with the following additions:
621
621
622 %s basename of file being printed
622 %s basename of file being printed
623 %d dirname of file being printed, or '.' if in repo root
623 %d dirname of file being printed, or '.' if in repo root
624 %p root-relative path name of file being printed
624 %p root-relative path name of file being printed
625 """
625 """
626 mf = {}
626 mf = {}
627 if opts['rev']:
627 if opts['rev']:
628 change = repo.changelog.read(repo.lookup(opts['rev']))
628 change = repo.changelog.read(repo.lookup(opts['rev']))
629 mf = repo.manifest.read(change[0])
629 mf = repo.manifest.read(change[0])
630 for src, abs, rel, exact in walk(repo, (file1,) + pats, opts):
630 for src, abs, rel, exact in walk(repo, (file1,) + pats, opts):
631 r = repo.file(abs)
631 r = repo.file(abs)
632 if opts['rev']:
632 if opts['rev']:
633 try:
633 try:
634 n = mf[abs]
634 n = mf[abs]
635 except (hg.RepoError, KeyError):
635 except (hg.RepoError, KeyError):
636 try:
636 try:
637 n = r.lookup(rev)
637 n = r.lookup(rev)
638 except KeyError, inst:
638 except KeyError, inst:
639 raise util.Abort(_('cannot find file %s in rev %s'), rel, rev)
639 raise util.Abort(_('cannot find file %s in rev %s'), rel, rev)
640 else:
640 else:
641 n = r.tip()
641 n = r.tip()
642 fp = make_file(repo, r, opts['output'], node=n, pathname=abs)
642 fp = make_file(repo, r, opts['output'], node=n, pathname=abs)
643 fp.write(r.read(n))
643 fp.write(r.read(n))
644
644
645 def clone(ui, source, dest=None, **opts):
645 def clone(ui, source, dest=None, **opts):
646 """make a copy of an existing repository
646 """make a copy of an existing repository
647
647
648 Create a copy of an existing repository in a new directory.
648 Create a copy of an existing repository in a new directory.
649
649
650 If no destination directory name is specified, it defaults to the
650 If no destination directory name is specified, it defaults to the
651 basename of the source.
651 basename of the source.
652
652
653 The location of the source is added to the new repository's
653 The location of the source is added to the new repository's
654 .hg/hgrc file, as the default to be used for future pulls.
654 .hg/hgrc file, as the default to be used for future pulls.
655
655
656 For efficiency, hardlinks are used for cloning whenever the source
656 For efficiency, hardlinks are used for cloning whenever the source
657 and destination are on the same filesystem. Some filesystems,
657 and destination are on the same filesystem. Some filesystems,
658 such as AFS, implement hardlinking incorrectly, but do not report
658 such as AFS, implement hardlinking incorrectly, but do not report
659 errors. In these cases, use the --pull option to avoid
659 errors. In these cases, use the --pull option to avoid
660 hardlinking.
660 hardlinking.
661 """
661 """
662 if dest is None:
662 if dest is None:
663 dest = os.path.basename(os.path.normpath(source))
663 dest = os.path.basename(os.path.normpath(source))
664
664
665 if os.path.exists(dest):
665 if os.path.exists(dest):
666 raise util.Abort(_("destination '%s' already exists"), dest)
666 raise util.Abort(_("destination '%s' already exists"), dest)
667
667
668 dest = os.path.realpath(dest)
668 dest = os.path.realpath(dest)
669
669
670 class Dircleanup:
670 class Dircleanup:
671 def __init__(self, dir_):
671 def __init__(self, dir_):
672 self.rmtree = shutil.rmtree
672 self.rmtree = shutil.rmtree
673 self.dir_ = dir_
673 self.dir_ = dir_
674 os.mkdir(dir_)
674 os.mkdir(dir_)
675 def close(self):
675 def close(self):
676 self.dir_ = None
676 self.dir_ = None
677 def __del__(self):
677 def __del__(self):
678 if self.dir_:
678 if self.dir_:
679 self.rmtree(self.dir_, True)
679 self.rmtree(self.dir_, True)
680
680
681 if opts['ssh']:
681 if opts['ssh']:
682 ui.setconfig("ui", "ssh", opts['ssh'])
682 ui.setconfig("ui", "ssh", opts['ssh'])
683 if opts['remotecmd']:
683 if opts['remotecmd']:
684 ui.setconfig("ui", "remotecmd", opts['remotecmd'])
684 ui.setconfig("ui", "remotecmd", opts['remotecmd'])
685
685
686 if not os.path.exists(source):
686 if not os.path.exists(source):
687 source = ui.expandpath(source)
687 source = ui.expandpath(source)
688
688
689 d = Dircleanup(dest)
689 d = Dircleanup(dest)
690 abspath = source
690 abspath = source
691 other = hg.repository(ui, source)
691 other = hg.repository(ui, source)
692
692
693 copy = False
693 copy = False
694 if other.dev() != -1:
694 if other.dev() != -1:
695 abspath = os.path.abspath(source)
695 abspath = os.path.abspath(source)
696 if not opts['pull'] and not opts['rev']:
696 if not opts['pull'] and not opts['rev']:
697 copy = True
697 copy = True
698
698
699 if copy:
699 if copy:
700 try:
700 try:
701 # we use a lock here because if we race with commit, we
701 # we use a lock here because if we race with commit, we
702 # can end up with extra data in the cloned revlogs that's
702 # can end up with extra data in the cloned revlogs that's
703 # not pointed to by changesets, thus causing verify to
703 # not pointed to by changesets, thus causing verify to
704 # fail
704 # fail
705 l1 = lock.lock(os.path.join(source, ".hg", "lock"))
705 l1 = lock.lock(os.path.join(source, ".hg", "lock"))
706 except OSError:
706 except OSError:
707 copy = False
707 copy = False
708
708
709 if copy:
709 if copy:
710 # we lock here to avoid premature writing to the target
710 # we lock here to avoid premature writing to the target
711 os.mkdir(os.path.join(dest, ".hg"))
711 os.mkdir(os.path.join(dest, ".hg"))
712 l2 = lock.lock(os.path.join(dest, ".hg", "lock"))
712 l2 = lock.lock(os.path.join(dest, ".hg", "lock"))
713
713
714 files = "data 00manifest.d 00manifest.i 00changelog.d 00changelog.i"
714 files = "data 00manifest.d 00manifest.i 00changelog.d 00changelog.i"
715 for f in files.split():
715 for f in files.split():
716 src = os.path.join(source, ".hg", f)
716 src = os.path.join(source, ".hg", f)
717 dst = os.path.join(dest, ".hg", f)
717 dst = os.path.join(dest, ".hg", f)
718 try:
718 try:
719 util.copyfiles(src, dst)
719 util.copyfiles(src, dst)
720 except OSError, inst:
720 except OSError, inst:
721 if inst.errno != errno.ENOENT: raise
721 if inst.errno != errno.ENOENT: raise
722
722
723 repo = hg.repository(ui, dest)
723 repo = hg.repository(ui, dest)
724
724
725 else:
725 else:
726 revs = None
726 revs = None
727 if opts['rev']:
727 if opts['rev']:
728 if not other.local():
728 if not other.local():
729 raise util.Abort("clone -r not supported yet for remote repositories.")
729 raise util.Abort("clone -r not supported yet for remote repositories.")
730 else:
730 else:
731 revs = [other.lookup(rev) for rev in opts['rev']]
731 revs = [other.lookup(rev) for rev in opts['rev']]
732 repo = hg.repository(ui, dest, create=1)
732 repo = hg.repository(ui, dest, create=1)
733 repo.pull(other, heads = revs)
733 repo.pull(other, heads = revs)
734
734
735 f = repo.opener("hgrc", "w", text=True)
735 f = repo.opener("hgrc", "w", text=True)
736 f.write("[paths]\n")
736 f.write("[paths]\n")
737 f.write("default = %s\n" % abspath)
737 f.write("default = %s\n" % abspath)
738
738
739 if not opts['noupdate']:
739 if not opts['noupdate']:
740 update(ui, repo)
740 update(ui, repo)
741
741
742 d.close()
742 d.close()
743
743
744 def commit(ui, repo, *pats, **opts):
744 def commit(ui, repo, *pats, **opts):
745 """commit the specified files or all outstanding changes
745 """commit the specified files or all outstanding changes
746
746
747 Commit changes to the given files into the repository.
747 Commit changes to the given files into the repository.
748
748
749 If a list of files is omitted, all changes reported by "hg status"
749 If a list of files is omitted, all changes reported by "hg status"
750 from the root of the repository will be commited.
750 from the root of the repository will be commited.
751
751
752 The HGEDITOR or EDITOR environment variables are used to start an
752 The HGEDITOR or EDITOR environment variables are used to start an
753 editor to add a commit comment.
753 editor to add a commit comment.
754 """
754 """
755 message = opts['message']
755 message = opts['message']
756 logfile = opts['logfile']
756 logfile = opts['logfile']
757
757
758 if message and logfile:
758 if message and logfile:
759 raise util.Abort(_('options --message and --logfile are mutually '
759 raise util.Abort(_('options --message and --logfile are mutually '
760 'exclusive'))
760 'exclusive'))
761 if not message and logfile:
761 if not message and logfile:
762 try:
762 try:
763 if logfile == '-':
763 if logfile == '-':
764 message = sys.stdin.read()
764 message = sys.stdin.read()
765 else:
765 else:
766 message = open(logfile).read()
766 message = open(logfile).read()
767 except IOError, inst:
767 except IOError, inst:
768 raise util.Abort(_("can't read commit message '%s': %s") %
768 raise util.Abort(_("can't read commit message '%s': %s") %
769 (logfile, inst.strerror))
769 (logfile, inst.strerror))
770
770
771 if opts['addremove']:
771 if opts['addremove']:
772 addremove(ui, repo, *pats, **opts)
772 addremove(ui, repo, *pats, **opts)
773 cwd = repo.getcwd()
773 cwd = repo.getcwd()
774 if not pats and cwd:
774 if not pats and cwd:
775 opts['include'] = [os.path.join(cwd, i) for i in opts['include']]
775 opts['include'] = [os.path.join(cwd, i) for i in opts['include']]
776 opts['exclude'] = [os.path.join(cwd, x) for x in opts['exclude']]
776 opts['exclude'] = [os.path.join(cwd, x) for x in opts['exclude']]
777 fns, match, anypats = matchpats(repo, (pats and repo.getcwd()) or '',
777 fns, match, anypats = matchpats(repo, (pats and repo.getcwd()) or '',
778 pats, opts)
778 pats, opts)
779 if pats:
779 if pats:
780 c, a, d, u = repo.changes(files=fns, match=match)
780 c, a, d, u = repo.changes(files=fns, match=match)
781 files = c + a + [fn for fn in d if repo.dirstate.state(fn) == 'r']
781 files = c + a + [fn for fn in d if repo.dirstate.state(fn) == 'r']
782 else:
782 else:
783 files = []
783 files = []
784 try:
784 try:
785 repo.commit(files, message, opts['user'], opts['date'], match)
785 repo.commit(files, message, opts['user'], opts['date'], match)
786 except ValueError, inst:
786 except ValueError, inst:
787 raise util.Abort(str(inst))
787 raise util.Abort(str(inst))
788
788
789 def docopy(ui, repo, pats, opts):
789 def docopy(ui, repo, pats, opts):
790 cwd = repo.getcwd()
790 cwd = repo.getcwd()
791 errors = 0
791 errors = 0
792 copied = []
792 copied = []
793
793
794 def okaytocopy(abs, rel, exact):
794 def okaytocopy(abs, rel, exact):
795 reasons = {'?': _('is not managed'),
795 reasons = {'?': _('is not managed'),
796 'a': _('has been marked for add')}
796 'a': _('has been marked for add')}
797 reason = reasons.get(repo.dirstate.state(abs))
797 reason = reasons.get(repo.dirstate.state(abs))
798 if reason:
798 if reason:
799 if exact: ui.warn(_('%s: not copying - file %s\n') % (rel, reason))
799 if exact: ui.warn(_('%s: not copying - file %s\n') % (rel, reason))
800 else:
800 else:
801 return True
801 return True
802
802
803 def copy(abssrc, relsrc, target, exact):
803 def copy(abssrc, relsrc, target, exact):
804 abstarget = util.canonpath(repo.root, cwd, target)
804 abstarget = util.canonpath(repo.root, cwd, target)
805 reltarget = util.pathto(cwd, abstarget)
805 reltarget = util.pathto(cwd, abstarget)
806 if not opts['force'] and repo.dirstate.state(abstarget) not in 'a?':
806 if os.path.exists(reltarget):
807 ui.warn(_('%s: not overwriting - file already managed\n') %
807 if opts['force']:
808 os.unlink(reltarget)
809 else:
810 ui.warn(_('%s: not overwriting - file exists\n') %
808 reltarget)
811 reltarget)
809 return
812 return
810 if ui.verbose or not exact:
813 if ui.verbose or not exact:
811 ui.status(_('copying %s to %s\n') % (relsrc, reltarget))
814 ui.status(_('copying %s to %s\n') % (relsrc, reltarget))
812 if not opts['after']:
815 if not opts['after']:
813 targetdir = os.path.dirname(reltarget) or '.'
816 targetdir = os.path.dirname(reltarget) or '.'
814 if not os.path.isdir(targetdir):
817 if not os.path.isdir(targetdir):
815 os.makedirs(targetdir)
818 os.makedirs(targetdir)
816 try:
819 try:
817 shutil.copyfile(relsrc, reltarget)
820 shutil.copyfile(relsrc, reltarget)
818 shutil.copymode(relsrc, reltarget)
821 shutil.copymode(relsrc, reltarget)
819 except shutil.Error, inst:
822 except shutil.Error, inst:
820 raise util.Abort(str(inst))
823 raise util.Abort(str(inst))
821 except IOError, inst:
824 except IOError, inst:
822 if inst.errno == errno.ENOENT:
825 if inst.errno == errno.ENOENT:
823 ui.warn(_('%s: deleted in working copy\n') % relsrc)
826 ui.warn(_('%s: deleted in working copy\n') % relsrc)
824 else:
827 else:
825 ui.warn(_('%s: cannot copy - %s\n') %
828 ui.warn(_('%s: cannot copy - %s\n') %
826 (relsrc, inst.strerror))
829 (relsrc, inst.strerror))
827 errors += 1
830 errors += 1
828 return
831 return
829 repo.copy(abssrc, abstarget)
832 repo.copy(abssrc, abstarget)
830 copied.append((abssrc, relsrc, exact))
833 copied.append((abssrc, relsrc, exact))
831
834
832 pats = list(pats)
835 pats = list(pats)
833 if not pats:
836 if not pats:
834 raise util.Abort(_('no source or destination specified'))
837 raise util.Abort(_('no source or destination specified'))
835 if len(pats) == 1:
838 if len(pats) == 1:
836 raise util.Abort(_('no destination specified'))
839 raise util.Abort(_('no destination specified'))
837 dest = pats.pop()
840 dest = pats.pop()
838 destdirexists = os.path.isdir(dest)
841 destdirexists = os.path.isdir(dest)
839 if (len(pats) > 1 or not os.path.exists(pats[0])) and not destdirexists:
842 if (len(pats) > 1 or not os.path.exists(pats[0])) and not destdirexists:
840 raise util.Abort(_('with multiple sources, destination must be an '
843 raise util.Abort(_('with multiple sources, destination must be an '
841 'existing directory'))
844 'existing directory'))
842
845
843 for pat in pats:
846 for pat in pats:
844 if os.path.isdir(pat):
847 if os.path.isdir(pat):
845 if destdirexists:
848 if destdirexists:
846 striplen = len(os.path.split(pat)[0])
849 striplen = len(os.path.split(pat)[0])
847 else:
850 else:
848 striplen = len(pat)
851 striplen = len(pat)
849 if striplen:
852 if striplen:
850 striplen += len(os.sep)
853 striplen += len(os.sep)
851 targetpath = lambda p: os.path.join(dest, p[striplen:])
854 targetpath = lambda p: os.path.join(dest, p[striplen:])
852 elif destdirexists:
855 elif destdirexists:
853 targetpath = lambda p: os.path.join(dest, os.path.basename(p))
856 targetpath = lambda p: os.path.join(dest, os.path.basename(p))
854 else:
857 else:
855 targetpath = lambda p: dest
858 targetpath = lambda p: dest
856 for tag, abssrc, relsrc, exact in walk(repo, [pat], opts):
859 for tag, abssrc, relsrc, exact in walk(repo, [pat], opts):
857 if okaytocopy(abssrc, relsrc, exact):
860 if okaytocopy(abssrc, relsrc, exact):
858 copy(abssrc, relsrc, targetpath(abssrc), exact)
861 copy(abssrc, relsrc, targetpath(abssrc), exact)
859
862
860 if errors:
863 if errors:
861 ui.warn(_('(consider using --after)\n'))
864 ui.warn(_('(consider using --after)\n'))
862 if len(copied) == 0:
865 if len(copied) == 0:
863 raise util.Abort(_('no files to copy'))
866 raise util.Abort(_('no files to copy'))
864 return errors, copied
867 return errors, copied
865
868
866 def copy(ui, repo, *pats, **opts):
869 def copy(ui, repo, *pats, **opts):
867 """mark files as copied for the next commit
870 """mark files as copied for the next commit
868
871
869 Mark dest as having copies of source files. If dest is a
872 Mark dest as having copies of source files. If dest is a
870 directory, copies are put in that directory. If dest is a file,
873 directory, copies are put in that directory. If dest is a file,
871 there can only be one source.
874 there can only be one source.
872
875
873 By default, this command copies the contents of files as they
876 By default, this command copies the contents of files as they
874 stand in the working directory. If invoked with --after, the
877 stand in the working directory. If invoked with --after, the
875 operation is recorded, but no copying is performed.
878 operation is recorded, but no copying is performed.
876
879
877 This command takes effect in the next commit.
880 This command takes effect in the next commit.
878
881
879 NOTE: This command should be treated as experimental. While it
882 NOTE: This command should be treated as experimental. While it
880 should properly record copied files, this information is not yet
883 should properly record copied files, this information is not yet
881 fully used by merge, nor fully reported by log.
884 fully used by merge, nor fully reported by log.
882 """
885 """
883 errs, copied = docopy(ui, repo, pats, opts)
886 errs, copied = docopy(ui, repo, pats, opts)
884 return errs
887 return errs
885
888
886 def debugancestor(ui, index, rev1, rev2):
889 def debugancestor(ui, index, rev1, rev2):
887 """find the ancestor revision of two revisions in a given index"""
890 """find the ancestor revision of two revisions in a given index"""
888 r = revlog.revlog(util.opener(os.getcwd()), index, "")
891 r = revlog.revlog(util.opener(os.getcwd()), index, "")
889 a = r.ancestor(r.lookup(rev1), r.lookup(rev2))
892 a = r.ancestor(r.lookup(rev1), r.lookup(rev2))
890 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
893 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
891
894
892 def debugcheckstate(ui, repo):
895 def debugcheckstate(ui, repo):
893 """validate the correctness of the current dirstate"""
896 """validate the correctness of the current dirstate"""
894 parent1, parent2 = repo.dirstate.parents()
897 parent1, parent2 = repo.dirstate.parents()
895 repo.dirstate.read()
898 repo.dirstate.read()
896 dc = repo.dirstate.map
899 dc = repo.dirstate.map
897 keys = dc.keys()
900 keys = dc.keys()
898 keys.sort()
901 keys.sort()
899 m1n = repo.changelog.read(parent1)[0]
902 m1n = repo.changelog.read(parent1)[0]
900 m2n = repo.changelog.read(parent2)[0]
903 m2n = repo.changelog.read(parent2)[0]
901 m1 = repo.manifest.read(m1n)
904 m1 = repo.manifest.read(m1n)
902 m2 = repo.manifest.read(m2n)
905 m2 = repo.manifest.read(m2n)
903 errors = 0
906 errors = 0
904 for f in dc:
907 for f in dc:
905 state = repo.dirstate.state(f)
908 state = repo.dirstate.state(f)
906 if state in "nr" and f not in m1:
909 if state in "nr" and f not in m1:
907 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
910 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
908 errors += 1
911 errors += 1
909 if state in "a" and f in m1:
912 if state in "a" and f in m1:
910 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
913 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
911 errors += 1
914 errors += 1
912 if state in "m" and f not in m1 and f not in m2:
915 if state in "m" and f not in m1 and f not in m2:
913 ui.warn(_("%s in state %s, but not in either manifest\n") %
916 ui.warn(_("%s in state %s, but not in either manifest\n") %
914 (f, state))
917 (f, state))
915 errors += 1
918 errors += 1
916 for f in m1:
919 for f in m1:
917 state = repo.dirstate.state(f)
920 state = repo.dirstate.state(f)
918 if state not in "nrm":
921 if state not in "nrm":
919 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
922 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
920 errors += 1
923 errors += 1
921 if errors:
924 if errors:
922 raise util.Abort(_(".hg/dirstate inconsistent with current parent's manifest"))
925 raise util.Abort(_(".hg/dirstate inconsistent with current parent's manifest"))
923
926
924 def debugconfig(ui):
927 def debugconfig(ui):
925 """show combined config settings from all hgrc files"""
928 """show combined config settings from all hgrc files"""
926 try:
929 try:
927 repo = hg.repository(ui)
930 repo = hg.repository(ui)
928 except hg.RepoError:
931 except hg.RepoError:
929 pass
932 pass
930 for section, name, value in ui.walkconfig():
933 for section, name, value in ui.walkconfig():
931 ui.write('%s.%s=%s\n' % (section, name, value))
934 ui.write('%s.%s=%s\n' % (section, name, value))
932
935
933 def debugsetparents(ui, repo, rev1, rev2=None):
936 def debugsetparents(ui, repo, rev1, rev2=None):
934 """manually set the parents of the current working directory
937 """manually set the parents of the current working directory
935
938
936 This is useful for writing repository conversion tools, but should
939 This is useful for writing repository conversion tools, but should
937 be used with care.
940 be used with care.
938 """
941 """
939
942
940 if not rev2:
943 if not rev2:
941 rev2 = hex(nullid)
944 rev2 = hex(nullid)
942
945
943 repo.dirstate.setparents(repo.lookup(rev1), repo.lookup(rev2))
946 repo.dirstate.setparents(repo.lookup(rev1), repo.lookup(rev2))
944
947
945 def debugstate(ui, repo):
948 def debugstate(ui, repo):
946 """show the contents of the current dirstate"""
949 """show the contents of the current dirstate"""
947 repo.dirstate.read()
950 repo.dirstate.read()
948 dc = repo.dirstate.map
951 dc = repo.dirstate.map
949 keys = dc.keys()
952 keys = dc.keys()
950 keys.sort()
953 keys.sort()
951 for file_ in keys:
954 for file_ in keys:
952 ui.write("%c %3o %10d %s %s\n"
955 ui.write("%c %3o %10d %s %s\n"
953 % (dc[file_][0], dc[file_][1] & 0777, dc[file_][2],
956 % (dc[file_][0], dc[file_][1] & 0777, dc[file_][2],
954 time.strftime("%x %X",
957 time.strftime("%x %X",
955 time.localtime(dc[file_][3])), file_))
958 time.localtime(dc[file_][3])), file_))
956 for f in repo.dirstate.copies:
959 for f in repo.dirstate.copies:
957 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copies[f], f))
960 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copies[f], f))
958
961
959 def debugdata(ui, file_, rev):
962 def debugdata(ui, file_, rev):
960 """dump the contents of an data file revision"""
963 """dump the contents of an data file revision"""
961 r = revlog.revlog(util.opener(os.getcwd()), file_[:-2] + ".i", file_)
964 r = revlog.revlog(util.opener(os.getcwd()), file_[:-2] + ".i", file_)
962 try:
965 try:
963 ui.write(r.revision(r.lookup(rev)))
966 ui.write(r.revision(r.lookup(rev)))
964 except KeyError:
967 except KeyError:
965 raise util.Abort(_('invalid revision identifier %s'), rev)
968 raise util.Abort(_('invalid revision identifier %s'), rev)
966
969
967 def debugindex(ui, file_):
970 def debugindex(ui, file_):
968 """dump the contents of an index file"""
971 """dump the contents of an index file"""
969 r = revlog.revlog(util.opener(os.getcwd()), file_, "")
972 r = revlog.revlog(util.opener(os.getcwd()), file_, "")
970 ui.write(" rev offset length base linkrev" +
973 ui.write(" rev offset length base linkrev" +
971 " nodeid p1 p2\n")
974 " nodeid p1 p2\n")
972 for i in range(r.count()):
975 for i in range(r.count()):
973 e = r.index[i]
976 e = r.index[i]
974 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
977 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
975 i, e[0], e[1], e[2], e[3],
978 i, e[0], e[1], e[2], e[3],
976 short(e[6]), short(e[4]), short(e[5])))
979 short(e[6]), short(e[4]), short(e[5])))
977
980
978 def debugindexdot(ui, file_):
981 def debugindexdot(ui, file_):
979 """dump an index DAG as a .dot file"""
982 """dump an index DAG as a .dot file"""
980 r = revlog.revlog(util.opener(os.getcwd()), file_, "")
983 r = revlog.revlog(util.opener(os.getcwd()), file_, "")
981 ui.write("digraph G {\n")
984 ui.write("digraph G {\n")
982 for i in range(r.count()):
985 for i in range(r.count()):
983 e = r.index[i]
986 e = r.index[i]
984 ui.write("\t%d -> %d\n" % (r.rev(e[4]), i))
987 ui.write("\t%d -> %d\n" % (r.rev(e[4]), i))
985 if e[5] != nullid:
988 if e[5] != nullid:
986 ui.write("\t%d -> %d\n" % (r.rev(e[5]), i))
989 ui.write("\t%d -> %d\n" % (r.rev(e[5]), i))
987 ui.write("}\n")
990 ui.write("}\n")
988
991
989 def debugrename(ui, repo, file, rev=None):
992 def debugrename(ui, repo, file, rev=None):
990 """dump rename information"""
993 """dump rename information"""
991 r = repo.file(relpath(repo, [file])[0])
994 r = repo.file(relpath(repo, [file])[0])
992 if rev:
995 if rev:
993 try:
996 try:
994 # assume all revision numbers are for changesets
997 # assume all revision numbers are for changesets
995 n = repo.lookup(rev)
998 n = repo.lookup(rev)
996 change = repo.changelog.read(n)
999 change = repo.changelog.read(n)
997 m = repo.manifest.read(change[0])
1000 m = repo.manifest.read(change[0])
998 n = m[relpath(repo, [file])[0]]
1001 n = m[relpath(repo, [file])[0]]
999 except hg.RepoError, KeyError:
1002 except hg.RepoError, KeyError:
1000 n = r.lookup(rev)
1003 n = r.lookup(rev)
1001 else:
1004 else:
1002 n = r.tip()
1005 n = r.tip()
1003 m = r.renamed(n)
1006 m = r.renamed(n)
1004 if m:
1007 if m:
1005 ui.write(_("renamed from %s:%s\n") % (m[0], hex(m[1])))
1008 ui.write(_("renamed from %s:%s\n") % (m[0], hex(m[1])))
1006 else:
1009 else:
1007 ui.write(_("not renamed\n"))
1010 ui.write(_("not renamed\n"))
1008
1011
1009 def debugwalk(ui, repo, *pats, **opts):
1012 def debugwalk(ui, repo, *pats, **opts):
1010 """show how files match on given patterns"""
1013 """show how files match on given patterns"""
1011 items = list(walk(repo, pats, opts))
1014 items = list(walk(repo, pats, opts))
1012 if not items:
1015 if not items:
1013 return
1016 return
1014 fmt = '%%s %%-%ds %%-%ds %%s' % (
1017 fmt = '%%s %%-%ds %%-%ds %%s' % (
1015 max([len(abs) for (src, abs, rel, exact) in items]),
1018 max([len(abs) for (src, abs, rel, exact) in items]),
1016 max([len(rel) for (src, abs, rel, exact) in items]))
1019 max([len(rel) for (src, abs, rel, exact) in items]))
1017 for src, abs, rel, exact in items:
1020 for src, abs, rel, exact in items:
1018 line = fmt % (src, abs, rel, exact and 'exact' or '')
1021 line = fmt % (src, abs, rel, exact and 'exact' or '')
1019 ui.write("%s\n" % line.rstrip())
1022 ui.write("%s\n" % line.rstrip())
1020
1023
1021 def diff(ui, repo, *pats, **opts):
1024 def diff(ui, repo, *pats, **opts):
1022 """diff working directory (or selected files)
1025 """diff working directory (or selected files)
1023
1026
1024 Show differences between revisions for the specified files.
1027 Show differences between revisions for the specified files.
1025
1028
1026 Differences between files are shown using the unified diff format.
1029 Differences between files are shown using the unified diff format.
1027
1030
1028 When two revision arguments are given, then changes are shown
1031 When two revision arguments are given, then changes are shown
1029 between those revisions. If only one revision is specified then
1032 between those revisions. If only one revision is specified then
1030 that revision is compared to the working directory, and, when no
1033 that revision is compared to the working directory, and, when no
1031 revisions are specified, the working directory files are compared
1034 revisions are specified, the working directory files are compared
1032 to its parent.
1035 to its parent.
1033
1036
1034 Without the -a option, diff will avoid generating diffs of files
1037 Without the -a option, diff will avoid generating diffs of files
1035 it detects as binary. With -a, diff will generate a diff anyway,
1038 it detects as binary. With -a, diff will generate a diff anyway,
1036 probably with undesirable results.
1039 probably with undesirable results.
1037 """
1040 """
1038 node1, node2 = None, None
1041 node1, node2 = None, None
1039 revs = [repo.lookup(x) for x in opts['rev']]
1042 revs = [repo.lookup(x) for x in opts['rev']]
1040
1043
1041 if len(revs) > 0:
1044 if len(revs) > 0:
1042 node1 = revs[0]
1045 node1 = revs[0]
1043 if len(revs) > 1:
1046 if len(revs) > 1:
1044 node2 = revs[1]
1047 node2 = revs[1]
1045 if len(revs) > 2:
1048 if len(revs) > 2:
1046 raise util.Abort(_("too many revisions to diff"))
1049 raise util.Abort(_("too many revisions to diff"))
1047
1050
1048 fns, matchfn, anypats = matchpats(repo, repo.getcwd(), pats, opts)
1051 fns, matchfn, anypats = matchpats(repo, repo.getcwd(), pats, opts)
1049
1052
1050 dodiff(sys.stdout, ui, repo, node1, node2, fns, match=matchfn,
1053 dodiff(sys.stdout, ui, repo, node1, node2, fns, match=matchfn,
1051 text=opts['text'])
1054 text=opts['text'])
1052
1055
1053 def doexport(ui, repo, changeset, seqno, total, revwidth, opts):
1056 def doexport(ui, repo, changeset, seqno, total, revwidth, opts):
1054 node = repo.lookup(changeset)
1057 node = repo.lookup(changeset)
1055 prev, other = repo.changelog.parents(node)
1058 prev, other = repo.changelog.parents(node)
1056 change = repo.changelog.read(node)
1059 change = repo.changelog.read(node)
1057
1060
1058 fp = make_file(repo, repo.changelog, opts['output'],
1061 fp = make_file(repo, repo.changelog, opts['output'],
1059 node=node, total=total, seqno=seqno,
1062 node=node, total=total, seqno=seqno,
1060 revwidth=revwidth)
1063 revwidth=revwidth)
1061 if fp != sys.stdout:
1064 if fp != sys.stdout:
1062 ui.note("%s\n" % fp.name)
1065 ui.note("%s\n" % fp.name)
1063
1066
1064 fp.write("# HG changeset patch\n")
1067 fp.write("# HG changeset patch\n")
1065 fp.write("# User %s\n" % change[1])
1068 fp.write("# User %s\n" % change[1])
1066 fp.write("# Node ID %s\n" % hex(node))
1069 fp.write("# Node ID %s\n" % hex(node))
1067 fp.write("# Parent %s\n" % hex(prev))
1070 fp.write("# Parent %s\n" % hex(prev))
1068 if other != nullid:
1071 if other != nullid:
1069 fp.write("# Parent %s\n" % hex(other))
1072 fp.write("# Parent %s\n" % hex(other))
1070 fp.write(change[4].rstrip())
1073 fp.write(change[4].rstrip())
1071 fp.write("\n\n")
1074 fp.write("\n\n")
1072
1075
1073 dodiff(fp, ui, repo, prev, node, text=opts['text'])
1076 dodiff(fp, ui, repo, prev, node, text=opts['text'])
1074 if fp != sys.stdout:
1077 if fp != sys.stdout:
1075 fp.close()
1078 fp.close()
1076
1079
1077 def export(ui, repo, *changesets, **opts):
1080 def export(ui, repo, *changesets, **opts):
1078 """dump the header and diffs for one or more changesets
1081 """dump the header and diffs for one or more changesets
1079
1082
1080 Print the changeset header and diffs for one or more revisions.
1083 Print the changeset header and diffs for one or more revisions.
1081
1084
1082 The information shown in the changeset header is: author,
1085 The information shown in the changeset header is: author,
1083 changeset hash, parent and commit comment.
1086 changeset hash, parent and commit comment.
1084
1087
1085 Output may be to a file, in which case the name of the file is
1088 Output may be to a file, in which case the name of the file is
1086 given using a format string. The formatting rules are as follows:
1089 given using a format string. The formatting rules are as follows:
1087
1090
1088 %% literal "%" character
1091 %% literal "%" character
1089 %H changeset hash (40 bytes of hexadecimal)
1092 %H changeset hash (40 bytes of hexadecimal)
1090 %N number of patches being generated
1093 %N number of patches being generated
1091 %R changeset revision number
1094 %R changeset revision number
1092 %b basename of the exporting repository
1095 %b basename of the exporting repository
1093 %h short-form changeset hash (12 bytes of hexadecimal)
1096 %h short-form changeset hash (12 bytes of hexadecimal)
1094 %n zero-padded sequence number, starting at 1
1097 %n zero-padded sequence number, starting at 1
1095 %r zero-padded changeset revision number
1098 %r zero-padded changeset revision number
1096
1099
1097 Without the -a option, export will avoid generating diffs of files
1100 Without the -a option, export will avoid generating diffs of files
1098 it detects as binary. With -a, export will generate a diff anyway,
1101 it detects as binary. With -a, export will generate a diff anyway,
1099 probably with undesirable results.
1102 probably with undesirable results.
1100 """
1103 """
1101 if not changesets:
1104 if not changesets:
1102 raise util.Abort(_("export requires at least one changeset"))
1105 raise util.Abort(_("export requires at least one changeset"))
1103 seqno = 0
1106 seqno = 0
1104 revs = list(revrange(ui, repo, changesets))
1107 revs = list(revrange(ui, repo, changesets))
1105 total = len(revs)
1108 total = len(revs)
1106 revwidth = max(map(len, revs))
1109 revwidth = max(map(len, revs))
1107 ui.note(len(revs) > 1 and _("Exporting patches:\n") or _("Exporting patch:\n"))
1110 ui.note(len(revs) > 1 and _("Exporting patches:\n") or _("Exporting patch:\n"))
1108 for cset in revs:
1111 for cset in revs:
1109 seqno += 1
1112 seqno += 1
1110 doexport(ui, repo, cset, seqno, total, revwidth, opts)
1113 doexport(ui, repo, cset, seqno, total, revwidth, opts)
1111
1114
1112 def forget(ui, repo, *pats, **opts):
1115 def forget(ui, repo, *pats, **opts):
1113 """don't add the specified files on the next commit
1116 """don't add the specified files on the next commit
1114
1117
1115 Undo an 'hg add' scheduled for the next commit.
1118 Undo an 'hg add' scheduled for the next commit.
1116 """
1119 """
1117 forget = []
1120 forget = []
1118 for src, abs, rel, exact in walk(repo, pats, opts):
1121 for src, abs, rel, exact in walk(repo, pats, opts):
1119 if repo.dirstate.state(abs) == 'a':
1122 if repo.dirstate.state(abs) == 'a':
1120 forget.append(abs)
1123 forget.append(abs)
1121 if ui.verbose or not exact:
1124 if ui.verbose or not exact:
1122 ui.status(_('forgetting %s\n') % rel)
1125 ui.status(_('forgetting %s\n') % rel)
1123 repo.forget(forget)
1126 repo.forget(forget)
1124
1127
1125 def grep(ui, repo, pattern, *pats, **opts):
1128 def grep(ui, repo, pattern, *pats, **opts):
1126 """search for a pattern in specified files and revisions
1129 """search for a pattern in specified files and revisions
1127
1130
1128 Search revisions of files for a regular expression.
1131 Search revisions of files for a regular expression.
1129
1132
1130 This command behaves differently than Unix grep. It only accepts
1133 This command behaves differently than Unix grep. It only accepts
1131 Python/Perl regexps. It searches repository history, not the
1134 Python/Perl regexps. It searches repository history, not the
1132 working directory. It always prints the revision number in which
1135 working directory. It always prints the revision number in which
1133 a match appears.
1136 a match appears.
1134
1137
1135 By default, grep only prints output for the first revision of a
1138 By default, grep only prints output for the first revision of a
1136 file in which it finds a match. To get it to print every revision
1139 file in which it finds a match. To get it to print every revision
1137 that contains a change in match status ("-" for a match that
1140 that contains a change in match status ("-" for a match that
1138 becomes a non-match, or "+" for a non-match that becomes a match),
1141 becomes a non-match, or "+" for a non-match that becomes a match),
1139 use the --all flag.
1142 use the --all flag.
1140 """
1143 """
1141 reflags = 0
1144 reflags = 0
1142 if opts['ignore_case']:
1145 if opts['ignore_case']:
1143 reflags |= re.I
1146 reflags |= re.I
1144 regexp = re.compile(pattern, reflags)
1147 regexp = re.compile(pattern, reflags)
1145 sep, eol = ':', '\n'
1148 sep, eol = ':', '\n'
1146 if opts['print0']:
1149 if opts['print0']:
1147 sep = eol = '\0'
1150 sep = eol = '\0'
1148
1151
1149 fcache = {}
1152 fcache = {}
1150 def getfile(fn):
1153 def getfile(fn):
1151 if fn not in fcache:
1154 if fn not in fcache:
1152 fcache[fn] = repo.file(fn)
1155 fcache[fn] = repo.file(fn)
1153 return fcache[fn]
1156 return fcache[fn]
1154
1157
1155 def matchlines(body):
1158 def matchlines(body):
1156 begin = 0
1159 begin = 0
1157 linenum = 0
1160 linenum = 0
1158 while True:
1161 while True:
1159 match = regexp.search(body, begin)
1162 match = regexp.search(body, begin)
1160 if not match:
1163 if not match:
1161 break
1164 break
1162 mstart, mend = match.span()
1165 mstart, mend = match.span()
1163 linenum += body.count('\n', begin, mstart) + 1
1166 linenum += body.count('\n', begin, mstart) + 1
1164 lstart = body.rfind('\n', begin, mstart) + 1 or begin
1167 lstart = body.rfind('\n', begin, mstart) + 1 or begin
1165 lend = body.find('\n', mend)
1168 lend = body.find('\n', mend)
1166 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
1169 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
1167 begin = lend + 1
1170 begin = lend + 1
1168
1171
1169 class linestate:
1172 class linestate:
1170 def __init__(self, line, linenum, colstart, colend):
1173 def __init__(self, line, linenum, colstart, colend):
1171 self.line = line
1174 self.line = line
1172 self.linenum = linenum
1175 self.linenum = linenum
1173 self.colstart = colstart
1176 self.colstart = colstart
1174 self.colend = colend
1177 self.colend = colend
1175 def __eq__(self, other):
1178 def __eq__(self, other):
1176 return self.line == other.line
1179 return self.line == other.line
1177 def __hash__(self):
1180 def __hash__(self):
1178 return hash(self.line)
1181 return hash(self.line)
1179
1182
1180 matches = {}
1183 matches = {}
1181 def grepbody(fn, rev, body):
1184 def grepbody(fn, rev, body):
1182 matches[rev].setdefault(fn, {})
1185 matches[rev].setdefault(fn, {})
1183 m = matches[rev][fn]
1186 m = matches[rev][fn]
1184 for lnum, cstart, cend, line in matchlines(body):
1187 for lnum, cstart, cend, line in matchlines(body):
1185 s = linestate(line, lnum, cstart, cend)
1188 s = linestate(line, lnum, cstart, cend)
1186 m[s] = s
1189 m[s] = s
1187
1190
1188 prev = {}
1191 prev = {}
1189 ucache = {}
1192 ucache = {}
1190 def display(fn, rev, states, prevstates):
1193 def display(fn, rev, states, prevstates):
1191 diff = list(sets.Set(states).symmetric_difference(sets.Set(prevstates)))
1194 diff = list(sets.Set(states).symmetric_difference(sets.Set(prevstates)))
1192 diff.sort(lambda x, y: cmp(x.linenum, y.linenum))
1195 diff.sort(lambda x, y: cmp(x.linenum, y.linenum))
1193 counts = {'-': 0, '+': 0}
1196 counts = {'-': 0, '+': 0}
1194 filerevmatches = {}
1197 filerevmatches = {}
1195 for l in diff:
1198 for l in diff:
1196 if incrementing or not opts['all']:
1199 if incrementing or not opts['all']:
1197 change = ((l in prevstates) and '-') or '+'
1200 change = ((l in prevstates) and '-') or '+'
1198 r = rev
1201 r = rev
1199 else:
1202 else:
1200 change = ((l in states) and '-') or '+'
1203 change = ((l in states) and '-') or '+'
1201 r = prev[fn]
1204 r = prev[fn]
1202 cols = [fn, str(rev)]
1205 cols = [fn, str(rev)]
1203 if opts['line_number']: cols.append(str(l.linenum))
1206 if opts['line_number']: cols.append(str(l.linenum))
1204 if opts['all']: cols.append(change)
1207 if opts['all']: cols.append(change)
1205 if opts['user']: cols.append(trimuser(ui, getchange(rev)[1], rev,
1208 if opts['user']: cols.append(trimuser(ui, getchange(rev)[1], rev,
1206 ucache))
1209 ucache))
1207 if opts['files_with_matches']:
1210 if opts['files_with_matches']:
1208 c = (fn, rev)
1211 c = (fn, rev)
1209 if c in filerevmatches: continue
1212 if c in filerevmatches: continue
1210 filerevmatches[c] = 1
1213 filerevmatches[c] = 1
1211 else:
1214 else:
1212 cols.append(l.line)
1215 cols.append(l.line)
1213 ui.write(sep.join(cols), eol)
1216 ui.write(sep.join(cols), eol)
1214 counts[change] += 1
1217 counts[change] += 1
1215 return counts['+'], counts['-']
1218 return counts['+'], counts['-']
1216
1219
1217 fstate = {}
1220 fstate = {}
1218 skip = {}
1221 skip = {}
1219 changeiter, getchange = walkchangerevs(ui, repo, repo.getcwd(), pats, opts)
1222 changeiter, getchange = walkchangerevs(ui, repo, repo.getcwd(), pats, opts)
1220 count = 0
1223 count = 0
1221 incrementing = False
1224 incrementing = False
1222 for st, rev, fns in changeiter:
1225 for st, rev, fns in changeiter:
1223 if st == 'window':
1226 if st == 'window':
1224 incrementing = rev
1227 incrementing = rev
1225 matches.clear()
1228 matches.clear()
1226 elif st == 'add':
1229 elif st == 'add':
1227 change = repo.changelog.read(repo.lookup(str(rev)))
1230 change = repo.changelog.read(repo.lookup(str(rev)))
1228 mf = repo.manifest.read(change[0])
1231 mf = repo.manifest.read(change[0])
1229 matches[rev] = {}
1232 matches[rev] = {}
1230 for fn in fns:
1233 for fn in fns:
1231 if fn in skip: continue
1234 if fn in skip: continue
1232 fstate.setdefault(fn, {})
1235 fstate.setdefault(fn, {})
1233 try:
1236 try:
1234 grepbody(fn, rev, getfile(fn).read(mf[fn]))
1237 grepbody(fn, rev, getfile(fn).read(mf[fn]))
1235 except KeyError:
1238 except KeyError:
1236 pass
1239 pass
1237 elif st == 'iter':
1240 elif st == 'iter':
1238 states = matches[rev].items()
1241 states = matches[rev].items()
1239 states.sort()
1242 states.sort()
1240 for fn, m in states:
1243 for fn, m in states:
1241 if fn in skip: continue
1244 if fn in skip: continue
1242 if incrementing or not opts['all'] or fstate[fn]:
1245 if incrementing or not opts['all'] or fstate[fn]:
1243 pos, neg = display(fn, rev, m, fstate[fn])
1246 pos, neg = display(fn, rev, m, fstate[fn])
1244 count += pos + neg
1247 count += pos + neg
1245 if pos and not opts['all']:
1248 if pos and not opts['all']:
1246 skip[fn] = True
1249 skip[fn] = True
1247 fstate[fn] = m
1250 fstate[fn] = m
1248 prev[fn] = rev
1251 prev[fn] = rev
1249
1252
1250 if not incrementing:
1253 if not incrementing:
1251 fstate = fstate.items()
1254 fstate = fstate.items()
1252 fstate.sort()
1255 fstate.sort()
1253 for fn, state in fstate:
1256 for fn, state in fstate:
1254 if fn in skip: continue
1257 if fn in skip: continue
1255 display(fn, rev, {}, state)
1258 display(fn, rev, {}, state)
1256 return (count == 0 and 1) or 0
1259 return (count == 0 and 1) or 0
1257
1260
1258 def heads(ui, repo, **opts):
1261 def heads(ui, repo, **opts):
1259 """show current repository heads
1262 """show current repository heads
1260
1263
1261 Show all repository head changesets.
1264 Show all repository head changesets.
1262
1265
1263 Repository "heads" are changesets that don't have children
1266 Repository "heads" are changesets that don't have children
1264 changesets. They are where development generally takes place and
1267 changesets. They are where development generally takes place and
1265 are the usual targets for update and merge operations.
1268 are the usual targets for update and merge operations.
1266 """
1269 """
1267 heads = repo.changelog.heads()
1270 heads = repo.changelog.heads()
1268 br = None
1271 br = None
1269 if opts['branches']:
1272 if opts['branches']:
1270 br = repo.branchlookup(heads)
1273 br = repo.branchlookup(heads)
1271 for n in repo.changelog.heads():
1274 for n in repo.changelog.heads():
1272 show_changeset(ui, repo, changenode=n, brinfo=br)
1275 show_changeset(ui, repo, changenode=n, brinfo=br)
1273
1276
1274 def identify(ui, repo):
1277 def identify(ui, repo):
1275 """print information about the working copy
1278 """print information about the working copy
1276
1279
1277 Print a short summary of the current state of the repo.
1280 Print a short summary of the current state of the repo.
1278
1281
1279 This summary identifies the repository state using one or two parent
1282 This summary identifies the repository state using one or two parent
1280 hash identifiers, followed by a "+" if there are uncommitted changes
1283 hash identifiers, followed by a "+" if there are uncommitted changes
1281 in the working directory, followed by a list of tags for this revision.
1284 in the working directory, followed by a list of tags for this revision.
1282 """
1285 """
1283 parents = [p for p in repo.dirstate.parents() if p != nullid]
1286 parents = [p for p in repo.dirstate.parents() if p != nullid]
1284 if not parents:
1287 if not parents:
1285 ui.write(_("unknown\n"))
1288 ui.write(_("unknown\n"))
1286 return
1289 return
1287
1290
1288 hexfunc = ui.verbose and hex or short
1291 hexfunc = ui.verbose and hex or short
1289 (c, a, d, u) = repo.changes()
1292 (c, a, d, u) = repo.changes()
1290 output = ["%s%s" % ('+'.join([hexfunc(parent) for parent in parents]),
1293 output = ["%s%s" % ('+'.join([hexfunc(parent) for parent in parents]),
1291 (c or a or d) and "+" or "")]
1294 (c or a or d) and "+" or "")]
1292
1295
1293 if not ui.quiet:
1296 if not ui.quiet:
1294 # multiple tags for a single parent separated by '/'
1297 # multiple tags for a single parent separated by '/'
1295 parenttags = ['/'.join(tags)
1298 parenttags = ['/'.join(tags)
1296 for tags in map(repo.nodetags, parents) if tags]
1299 for tags in map(repo.nodetags, parents) if tags]
1297 # tags for multiple parents separated by ' + '
1300 # tags for multiple parents separated by ' + '
1298 if parenttags:
1301 if parenttags:
1299 output.append(' + '.join(parenttags))
1302 output.append(' + '.join(parenttags))
1300
1303
1301 ui.write("%s\n" % ' '.join(output))
1304 ui.write("%s\n" % ' '.join(output))
1302
1305
1303 def import_(ui, repo, patch1, *patches, **opts):
1306 def import_(ui, repo, patch1, *patches, **opts):
1304 """import an ordered set of patches
1307 """import an ordered set of patches
1305
1308
1306 Import a list of patches and commit them individually.
1309 Import a list of patches and commit them individually.
1307
1310
1308 If there are outstanding changes in the working directory, import
1311 If there are outstanding changes in the working directory, import
1309 will abort unless given the -f flag.
1312 will abort unless given the -f flag.
1310
1313
1311 If a patch looks like a mail message (its first line starts with
1314 If a patch looks like a mail message (its first line starts with
1312 "From " or looks like an RFC822 header), it will not be applied
1315 "From " or looks like an RFC822 header), it will not be applied
1313 unless the -f option is used. The importer neither parses nor
1316 unless the -f option is used. The importer neither parses nor
1314 discards mail headers, so use -f only to override the "mailness"
1317 discards mail headers, so use -f only to override the "mailness"
1315 safety check, not to import a real mail message.
1318 safety check, not to import a real mail message.
1316 """
1319 """
1317 patches = (patch1,) + patches
1320 patches = (patch1,) + patches
1318
1321
1319 if not opts['force']:
1322 if not opts['force']:
1320 (c, a, d, u) = repo.changes()
1323 (c, a, d, u) = repo.changes()
1321 if c or a or d:
1324 if c or a or d:
1322 raise util.Abort(_("outstanding uncommitted changes"))
1325 raise util.Abort(_("outstanding uncommitted changes"))
1323
1326
1324 d = opts["base"]
1327 d = opts["base"]
1325 strip = opts["strip"]
1328 strip = opts["strip"]
1326
1329
1327 mailre = re.compile(r'(?:From |[\w-]+:)')
1330 mailre = re.compile(r'(?:From |[\w-]+:)')
1328
1331
1329 # attempt to detect the start of a patch
1332 # attempt to detect the start of a patch
1330 # (this heuristic is borrowed from quilt)
1333 # (this heuristic is borrowed from quilt)
1331 diffre = re.compile(r'(?:Index:[ \t]|diff[ \t]|RCS file: |' +
1334 diffre = re.compile(r'(?:Index:[ \t]|diff[ \t]|RCS file: |' +
1332 'retrieving revision [0-9]+(\.[0-9]+)*$|' +
1335 'retrieving revision [0-9]+(\.[0-9]+)*$|' +
1333 '(---|\*\*\*)[ \t])')
1336 '(---|\*\*\*)[ \t])')
1334
1337
1335 for patch in patches:
1338 for patch in patches:
1336 ui.status(_("applying %s\n") % patch)
1339 ui.status(_("applying %s\n") % patch)
1337 pf = os.path.join(d, patch)
1340 pf = os.path.join(d, patch)
1338
1341
1339 message = []
1342 message = []
1340 user = None
1343 user = None
1341 hgpatch = False
1344 hgpatch = False
1342 for line in file(pf):
1345 for line in file(pf):
1343 line = line.rstrip()
1346 line = line.rstrip()
1344 if (not message and not hgpatch and
1347 if (not message and not hgpatch and
1345 mailre.match(line) and not opts['force']):
1348 mailre.match(line) and not opts['force']):
1346 if len(line) > 35: line = line[:32] + '...'
1349 if len(line) > 35: line = line[:32] + '...'
1347 raise util.Abort(_('first line looks like a '
1350 raise util.Abort(_('first line looks like a '
1348 'mail header: ') + line)
1351 'mail header: ') + line)
1349 if diffre.match(line):
1352 if diffre.match(line):
1350 break
1353 break
1351 elif hgpatch:
1354 elif hgpatch:
1352 # parse values when importing the result of an hg export
1355 # parse values when importing the result of an hg export
1353 if line.startswith("# User "):
1356 if line.startswith("# User "):
1354 user = line[7:]
1357 user = line[7:]
1355 ui.debug(_('User: %s\n') % user)
1358 ui.debug(_('User: %s\n') % user)
1356 elif not line.startswith("# ") and line:
1359 elif not line.startswith("# ") and line:
1357 message.append(line)
1360 message.append(line)
1358 hgpatch = False
1361 hgpatch = False
1359 elif line == '# HG changeset patch':
1362 elif line == '# HG changeset patch':
1360 hgpatch = True
1363 hgpatch = True
1361 message = [] # We may have collected garbage
1364 message = [] # We may have collected garbage
1362 else:
1365 else:
1363 message.append(line)
1366 message.append(line)
1364
1367
1365 # make sure message isn't empty
1368 # make sure message isn't empty
1366 if not message:
1369 if not message:
1367 message = _("imported patch %s\n") % patch
1370 message = _("imported patch %s\n") % patch
1368 else:
1371 else:
1369 message = "%s\n" % '\n'.join(message)
1372 message = "%s\n" % '\n'.join(message)
1370 ui.debug(_('message:\n%s\n') % message)
1373 ui.debug(_('message:\n%s\n') % message)
1371
1374
1372 files = util.patch(strip, pf, ui)
1375 files = util.patch(strip, pf, ui)
1373
1376
1374 if len(files) > 0:
1377 if len(files) > 0:
1375 addremove(ui, repo, *files)
1378 addremove(ui, repo, *files)
1376 repo.commit(files, message, user)
1379 repo.commit(files, message, user)
1377
1380
1378 def incoming(ui, repo, source="default", **opts):
1381 def incoming(ui, repo, source="default", **opts):
1379 """show new changesets found in source
1382 """show new changesets found in source
1380
1383
1381 Show new changesets found in the specified repo or the default
1384 Show new changesets found in the specified repo or the default
1382 pull repo. These are the changesets that would be pulled if a pull
1385 pull repo. These are the changesets that would be pulled if a pull
1383 was requested.
1386 was requested.
1384
1387
1385 Currently only local repositories are supported.
1388 Currently only local repositories are supported.
1386 """
1389 """
1387 source = ui.expandpath(source, repo.root)
1390 source = ui.expandpath(source, repo.root)
1388 other = hg.repository(ui, source)
1391 other = hg.repository(ui, source)
1389 if not other.local():
1392 if not other.local():
1390 raise util.Abort(_("incoming doesn't work for remote repositories yet"))
1393 raise util.Abort(_("incoming doesn't work for remote repositories yet"))
1391 o = repo.findincoming(other)
1394 o = repo.findincoming(other)
1392 if not o:
1395 if not o:
1393 return
1396 return
1394 o = other.changelog.nodesbetween(o)[0]
1397 o = other.changelog.nodesbetween(o)[0]
1395 if opts['newest_first']:
1398 if opts['newest_first']:
1396 o.reverse()
1399 o.reverse()
1397 for n in o:
1400 for n in o:
1398 parents = [p for p in other.changelog.parents(n) if p != nullid]
1401 parents = [p for p in other.changelog.parents(n) if p != nullid]
1399 if opts['no_merges'] and len(parents) == 2:
1402 if opts['no_merges'] and len(parents) == 2:
1400 continue
1403 continue
1401 show_changeset(ui, other, changenode=n)
1404 show_changeset(ui, other, changenode=n)
1402 if opts['patch']:
1405 if opts['patch']:
1403 prev = (parents and parents[0]) or nullid
1406 prev = (parents and parents[0]) or nullid
1404 dodiff(ui, ui, other, prev, n)
1407 dodiff(ui, ui, other, prev, n)
1405 ui.write("\n")
1408 ui.write("\n")
1406
1409
1407 def init(ui, dest="."):
1410 def init(ui, dest="."):
1408 """create a new repository in the given directory
1411 """create a new repository in the given directory
1409
1412
1410 Initialize a new repository in the given directory. If the given
1413 Initialize a new repository in the given directory. If the given
1411 directory does not exist, it is created.
1414 directory does not exist, it is created.
1412
1415
1413 If no directory is given, the current directory is used.
1416 If no directory is given, the current directory is used.
1414 """
1417 """
1415 if not os.path.exists(dest):
1418 if not os.path.exists(dest):
1416 os.mkdir(dest)
1419 os.mkdir(dest)
1417 hg.repository(ui, dest, create=1)
1420 hg.repository(ui, dest, create=1)
1418
1421
1419 def locate(ui, repo, *pats, **opts):
1422 def locate(ui, repo, *pats, **opts):
1420 """locate files matching specific patterns
1423 """locate files matching specific patterns
1421
1424
1422 Print all files under Mercurial control whose names match the
1425 Print all files under Mercurial control whose names match the
1423 given patterns.
1426 given patterns.
1424
1427
1425 This command searches the current directory and its
1428 This command searches the current directory and its
1426 subdirectories. To search an entire repository, move to the root
1429 subdirectories. To search an entire repository, move to the root
1427 of the repository.
1430 of the repository.
1428
1431
1429 If no patterns are given to match, this command prints all file
1432 If no patterns are given to match, this command prints all file
1430 names.
1433 names.
1431
1434
1432 If you want to feed the output of this command into the "xargs"
1435 If you want to feed the output of this command into the "xargs"
1433 command, use the "-0" option to both this command and "xargs".
1436 command, use the "-0" option to both this command and "xargs".
1434 This will avoid the problem of "xargs" treating single filenames
1437 This will avoid the problem of "xargs" treating single filenames
1435 that contain white space as multiple filenames.
1438 that contain white space as multiple filenames.
1436 """
1439 """
1437 end = opts['print0'] and '\0' or '\n'
1440 end = opts['print0'] and '\0' or '\n'
1438
1441
1439 for src, abs, rel, exact in walk(repo, pats, opts, '(?:.*/|)'):
1442 for src, abs, rel, exact in walk(repo, pats, opts, '(?:.*/|)'):
1440 if repo.dirstate.state(abs) == '?':
1443 if repo.dirstate.state(abs) == '?':
1441 continue
1444 continue
1442 if opts['fullpath']:
1445 if opts['fullpath']:
1443 ui.write(os.path.join(repo.root, abs), end)
1446 ui.write(os.path.join(repo.root, abs), end)
1444 else:
1447 else:
1445 ui.write(rel, end)
1448 ui.write(rel, end)
1446
1449
1447 def log(ui, repo, *pats, **opts):
1450 def log(ui, repo, *pats, **opts):
1448 """show revision history of entire repository or files
1451 """show revision history of entire repository or files
1449
1452
1450 Print the revision history of the specified files or the entire project.
1453 Print the revision history of the specified files or the entire project.
1451
1454
1452 By default this command outputs: changeset id and hash, tags,
1455 By default this command outputs: changeset id and hash, tags,
1453 parents, user, date and time, and a summary for each commit. The
1456 parents, user, date and time, and a summary for each commit. The
1454 -v switch adds some more detail, such as changed files, manifest
1457 -v switch adds some more detail, such as changed files, manifest
1455 hashes or message signatures.
1458 hashes or message signatures.
1456 """
1459 """
1457 class dui:
1460 class dui:
1458 # Implement and delegate some ui protocol. Save hunks of
1461 # Implement and delegate some ui protocol. Save hunks of
1459 # output for later display in the desired order.
1462 # output for later display in the desired order.
1460 def __init__(self, ui):
1463 def __init__(self, ui):
1461 self.ui = ui
1464 self.ui = ui
1462 self.hunk = {}
1465 self.hunk = {}
1463 def bump(self, rev):
1466 def bump(self, rev):
1464 self.rev = rev
1467 self.rev = rev
1465 self.hunk[rev] = []
1468 self.hunk[rev] = []
1466 def note(self, *args):
1469 def note(self, *args):
1467 if self.verbose:
1470 if self.verbose:
1468 self.write(*args)
1471 self.write(*args)
1469 def status(self, *args):
1472 def status(self, *args):
1470 if not self.quiet:
1473 if not self.quiet:
1471 self.write(*args)
1474 self.write(*args)
1472 def write(self, *args):
1475 def write(self, *args):
1473 self.hunk[self.rev].append(args)
1476 self.hunk[self.rev].append(args)
1474 def debug(self, *args):
1477 def debug(self, *args):
1475 if self.debugflag:
1478 if self.debugflag:
1476 self.write(*args)
1479 self.write(*args)
1477 def __getattr__(self, key):
1480 def __getattr__(self, key):
1478 return getattr(self.ui, key)
1481 return getattr(self.ui, key)
1479 cwd = repo.getcwd()
1482 cwd = repo.getcwd()
1480 if not pats and cwd:
1483 if not pats and cwd:
1481 opts['include'] = [os.path.join(cwd, i) for i in opts['include']]
1484 opts['include'] = [os.path.join(cwd, i) for i in opts['include']]
1482 opts['exclude'] = [os.path.join(cwd, x) for x in opts['exclude']]
1485 opts['exclude'] = [os.path.join(cwd, x) for x in opts['exclude']]
1483 changeiter, getchange = walkchangerevs(ui, repo, (pats and cwd) or '',
1486 changeiter, getchange = walkchangerevs(ui, repo, (pats and cwd) or '',
1484 pats, opts)
1487 pats, opts)
1485 for st, rev, fns in changeiter:
1488 for st, rev, fns in changeiter:
1486 if st == 'window':
1489 if st == 'window':
1487 du = dui(ui)
1490 du = dui(ui)
1488 elif st == 'add':
1491 elif st == 'add':
1489 du.bump(rev)
1492 du.bump(rev)
1490 changenode = repo.changelog.node(rev)
1493 changenode = repo.changelog.node(rev)
1491 parents = [p for p in repo.changelog.parents(changenode)
1494 parents = [p for p in repo.changelog.parents(changenode)
1492 if p != nullid]
1495 if p != nullid]
1493 if opts['no_merges'] and len(parents) == 2:
1496 if opts['no_merges'] and len(parents) == 2:
1494 continue
1497 continue
1495 if opts['only_merges'] and len(parents) != 2:
1498 if opts['only_merges'] and len(parents) != 2:
1496 continue
1499 continue
1497
1500
1498 br = None
1501 br = None
1499 if opts['keyword']:
1502 if opts['keyword']:
1500 changes = repo.changelog.read(repo.changelog.node(rev))
1503 changes = repo.changelog.read(repo.changelog.node(rev))
1501 miss = 0
1504 miss = 0
1502 for k in [kw.lower() for kw in opts['keyword']]:
1505 for k in [kw.lower() for kw in opts['keyword']]:
1503 if not (k in changes[1].lower() or
1506 if not (k in changes[1].lower() or
1504 k in changes[4].lower() or
1507 k in changes[4].lower() or
1505 k in " ".join(changes[3][:20]).lower()):
1508 k in " ".join(changes[3][:20]).lower()):
1506 miss = 1
1509 miss = 1
1507 break
1510 break
1508 if miss:
1511 if miss:
1509 continue
1512 continue
1510
1513
1511 if opts['branch']:
1514 if opts['branch']:
1512 br = repo.branchlookup([repo.changelog.node(rev)])
1515 br = repo.branchlookup([repo.changelog.node(rev)])
1513
1516
1514 show_changeset(du, repo, rev, brinfo=br)
1517 show_changeset(du, repo, rev, brinfo=br)
1515 if opts['patch']:
1518 if opts['patch']:
1516 prev = (parents and parents[0]) or nullid
1519 prev = (parents and parents[0]) or nullid
1517 dodiff(du, du, repo, prev, changenode, fns)
1520 dodiff(du, du, repo, prev, changenode, fns)
1518 du.write("\n\n")
1521 du.write("\n\n")
1519 elif st == 'iter':
1522 elif st == 'iter':
1520 for args in du.hunk[rev]:
1523 for args in du.hunk[rev]:
1521 ui.write(*args)
1524 ui.write(*args)
1522
1525
1523 def manifest(ui, repo, rev=None):
1526 def manifest(ui, repo, rev=None):
1524 """output the latest or given revision of the project manifest
1527 """output the latest or given revision of the project manifest
1525
1528
1526 Print a list of version controlled files for the given revision.
1529 Print a list of version controlled files for the given revision.
1527
1530
1528 The manifest is the list of files being version controlled. If no revision
1531 The manifest is the list of files being version controlled. If no revision
1529 is given then the tip is used.
1532 is given then the tip is used.
1530 """
1533 """
1531 if rev:
1534 if rev:
1532 try:
1535 try:
1533 # assume all revision numbers are for changesets
1536 # assume all revision numbers are for changesets
1534 n = repo.lookup(rev)
1537 n = repo.lookup(rev)
1535 change = repo.changelog.read(n)
1538 change = repo.changelog.read(n)
1536 n = change[0]
1539 n = change[0]
1537 except hg.RepoError:
1540 except hg.RepoError:
1538 n = repo.manifest.lookup(rev)
1541 n = repo.manifest.lookup(rev)
1539 else:
1542 else:
1540 n = repo.manifest.tip()
1543 n = repo.manifest.tip()
1541 m = repo.manifest.read(n)
1544 m = repo.manifest.read(n)
1542 mf = repo.manifest.readflags(n)
1545 mf = repo.manifest.readflags(n)
1543 files = m.keys()
1546 files = m.keys()
1544 files.sort()
1547 files.sort()
1545
1548
1546 for f in files:
1549 for f in files:
1547 ui.write("%40s %3s %s\n" % (hex(m[f]), mf[f] and "755" or "644", f))
1550 ui.write("%40s %3s %s\n" % (hex(m[f]), mf[f] and "755" or "644", f))
1548
1551
1549 def outgoing(ui, repo, dest="default-push", **opts):
1552 def outgoing(ui, repo, dest="default-push", **opts):
1550 """show changesets not found in destination
1553 """show changesets not found in destination
1551
1554
1552 Show changesets not found in the specified destination repo or the
1555 Show changesets not found in the specified destination repo or the
1553 default push repo. These are the changesets that would be pushed
1556 default push repo. These are the changesets that would be pushed
1554 if a push was requested.
1557 if a push was requested.
1555 """
1558 """
1556 dest = ui.expandpath(dest, repo.root)
1559 dest = ui.expandpath(dest, repo.root)
1557 other = hg.repository(ui, dest)
1560 other = hg.repository(ui, dest)
1558 o = repo.findoutgoing(other)
1561 o = repo.findoutgoing(other)
1559 o = repo.changelog.nodesbetween(o)[0]
1562 o = repo.changelog.nodesbetween(o)[0]
1560 if opts['newest_first']:
1563 if opts['newest_first']:
1561 o.reverse()
1564 o.reverse()
1562 for n in o:
1565 for n in o:
1563 parents = [p for p in repo.changelog.parents(n) if p != nullid]
1566 parents = [p for p in repo.changelog.parents(n) if p != nullid]
1564 if opts['no_merges'] and len(parents) == 2:
1567 if opts['no_merges'] and len(parents) == 2:
1565 continue
1568 continue
1566 show_changeset(ui, repo, changenode=n)
1569 show_changeset(ui, repo, changenode=n)
1567 if opts['patch']:
1570 if opts['patch']:
1568 prev = (parents and parents[0]) or nullid
1571 prev = (parents and parents[0]) or nullid
1569 dodiff(ui, ui, repo, prev, n)
1572 dodiff(ui, ui, repo, prev, n)
1570 ui.write("\n")
1573 ui.write("\n")
1571
1574
1572 def parents(ui, repo, rev=None):
1575 def parents(ui, repo, rev=None):
1573 """show the parents of the working dir or revision
1576 """show the parents of the working dir or revision
1574
1577
1575 Print the working directory's parent revisions.
1578 Print the working directory's parent revisions.
1576 """
1579 """
1577 if rev:
1580 if rev:
1578 p = repo.changelog.parents(repo.lookup(rev))
1581 p = repo.changelog.parents(repo.lookup(rev))
1579 else:
1582 else:
1580 p = repo.dirstate.parents()
1583 p = repo.dirstate.parents()
1581
1584
1582 for n in p:
1585 for n in p:
1583 if n != nullid:
1586 if n != nullid:
1584 show_changeset(ui, repo, changenode=n)
1587 show_changeset(ui, repo, changenode=n)
1585
1588
1586 def paths(ui, search=None):
1589 def paths(ui, search=None):
1587 """show definition of symbolic path names
1590 """show definition of symbolic path names
1588
1591
1589 Show definition of symbolic path name NAME. If no name is given, show
1592 Show definition of symbolic path name NAME. If no name is given, show
1590 definition of available names.
1593 definition of available names.
1591
1594
1592 Path names are defined in the [paths] section of /etc/mercurial/hgrc
1595 Path names are defined in the [paths] section of /etc/mercurial/hgrc
1593 and $HOME/.hgrc. If run inside a repository, .hg/hgrc is used, too.
1596 and $HOME/.hgrc. If run inside a repository, .hg/hgrc is used, too.
1594 """
1597 """
1595 try:
1598 try:
1596 repo = hg.repository(ui=ui)
1599 repo = hg.repository(ui=ui)
1597 except hg.RepoError:
1600 except hg.RepoError:
1598 pass
1601 pass
1599
1602
1600 if search:
1603 if search:
1601 for name, path in ui.configitems("paths"):
1604 for name, path in ui.configitems("paths"):
1602 if name == search:
1605 if name == search:
1603 ui.write("%s\n" % path)
1606 ui.write("%s\n" % path)
1604 return
1607 return
1605 ui.warn(_("not found!\n"))
1608 ui.warn(_("not found!\n"))
1606 return 1
1609 return 1
1607 else:
1610 else:
1608 for name, path in ui.configitems("paths"):
1611 for name, path in ui.configitems("paths"):
1609 ui.write("%s = %s\n" % (name, path))
1612 ui.write("%s = %s\n" % (name, path))
1610
1613
1611 def pull(ui, repo, source="default", **opts):
1614 def pull(ui, repo, source="default", **opts):
1612 """pull changes from the specified source
1615 """pull changes from the specified source
1613
1616
1614 Pull changes from a remote repository to a local one.
1617 Pull changes from a remote repository to a local one.
1615
1618
1616 This finds all changes from the repository at the specified path
1619 This finds all changes from the repository at the specified path
1617 or URL and adds them to the local repository. By default, this
1620 or URL and adds them to the local repository. By default, this
1618 does not update the copy of the project in the working directory.
1621 does not update the copy of the project in the working directory.
1619
1622
1620 Valid URLs are of the form:
1623 Valid URLs are of the form:
1621
1624
1622 local/filesystem/path
1625 local/filesystem/path
1623 http://[user@]host[:port][/path]
1626 http://[user@]host[:port][/path]
1624 https://[user@]host[:port][/path]
1627 https://[user@]host[:port][/path]
1625 ssh://[user@]host[:port][/path]
1628 ssh://[user@]host[:port][/path]
1626
1629
1627 SSH requires an accessible shell account on the destination machine
1630 SSH requires an accessible shell account on the destination machine
1628 and a copy of hg in the remote path. With SSH, paths are relative
1631 and a copy of hg in the remote path. With SSH, paths are relative
1629 to the remote user's home directory by default; use two slashes at
1632 to the remote user's home directory by default; use two slashes at
1630 the start of a path to specify it as relative to the filesystem root.
1633 the start of a path to specify it as relative to the filesystem root.
1631 """
1634 """
1632 source = ui.expandpath(source, repo.root)
1635 source = ui.expandpath(source, repo.root)
1633 ui.status(_('pulling from %s\n') % (source))
1636 ui.status(_('pulling from %s\n') % (source))
1634
1637
1635 if opts['ssh']:
1638 if opts['ssh']:
1636 ui.setconfig("ui", "ssh", opts['ssh'])
1639 ui.setconfig("ui", "ssh", opts['ssh'])
1637 if opts['remotecmd']:
1640 if opts['remotecmd']:
1638 ui.setconfig("ui", "remotecmd", opts['remotecmd'])
1641 ui.setconfig("ui", "remotecmd", opts['remotecmd'])
1639
1642
1640 other = hg.repository(ui, source)
1643 other = hg.repository(ui, source)
1641 revs = None
1644 revs = None
1642 if opts['rev'] and not other.local():
1645 if opts['rev'] and not other.local():
1643 raise util.Abort("pull -r doesn't work for remote repositories yet")
1646 raise util.Abort("pull -r doesn't work for remote repositories yet")
1644 elif opts['rev']:
1647 elif opts['rev']:
1645 revs = [other.lookup(rev) for rev in opts['rev']]
1648 revs = [other.lookup(rev) for rev in opts['rev']]
1646 r = repo.pull(other, heads=revs)
1649 r = repo.pull(other, heads=revs)
1647 if not r:
1650 if not r:
1648 if opts['update']:
1651 if opts['update']:
1649 return update(ui, repo)
1652 return update(ui, repo)
1650 else:
1653 else:
1651 ui.status(_("(run 'hg update' to get a working copy)\n"))
1654 ui.status(_("(run 'hg update' to get a working copy)\n"))
1652
1655
1653 return r
1656 return r
1654
1657
1655 def push(ui, repo, dest="default-push", force=False, ssh=None, remotecmd=None):
1658 def push(ui, repo, dest="default-push", force=False, ssh=None, remotecmd=None):
1656 """push changes to the specified destination
1659 """push changes to the specified destination
1657
1660
1658 Push changes from the local repository to the given destination.
1661 Push changes from the local repository to the given destination.
1659
1662
1660 This is the symmetrical operation for pull. It helps to move
1663 This is the symmetrical operation for pull. It helps to move
1661 changes from the current repository to a different one. If the
1664 changes from the current repository to a different one. If the
1662 destination is local this is identical to a pull in that directory
1665 destination is local this is identical to a pull in that directory
1663 from the current one.
1666 from the current one.
1664
1667
1665 By default, push will refuse to run if it detects the result would
1668 By default, push will refuse to run if it detects the result would
1666 increase the number of remote heads. This generally indicates the
1669 increase the number of remote heads. This generally indicates the
1667 the client has forgotten to sync and merge before pushing.
1670 the client has forgotten to sync and merge before pushing.
1668
1671
1669 Valid URLs are of the form:
1672 Valid URLs are of the form:
1670
1673
1671 local/filesystem/path
1674 local/filesystem/path
1672 ssh://[user@]host[:port][/path]
1675 ssh://[user@]host[:port][/path]
1673
1676
1674 SSH requires an accessible shell account on the destination
1677 SSH requires an accessible shell account on the destination
1675 machine and a copy of hg in the remote path.
1678 machine and a copy of hg in the remote path.
1676 """
1679 """
1677 dest = ui.expandpath(dest, repo.root)
1680 dest = ui.expandpath(dest, repo.root)
1678 ui.status('pushing to %s\n' % (dest))
1681 ui.status('pushing to %s\n' % (dest))
1679
1682
1680 if ssh:
1683 if ssh:
1681 ui.setconfig("ui", "ssh", ssh)
1684 ui.setconfig("ui", "ssh", ssh)
1682 if remotecmd:
1685 if remotecmd:
1683 ui.setconfig("ui", "remotecmd", remotecmd)
1686 ui.setconfig("ui", "remotecmd", remotecmd)
1684
1687
1685 other = hg.repository(ui, dest)
1688 other = hg.repository(ui, dest)
1686 r = repo.push(other, force)
1689 r = repo.push(other, force)
1687 return r
1690 return r
1688
1691
1689 def rawcommit(ui, repo, *flist, **rc):
1692 def rawcommit(ui, repo, *flist, **rc):
1690 """raw commit interface
1693 """raw commit interface
1691
1694
1692 Lowlevel commit, for use in helper scripts.
1695 Lowlevel commit, for use in helper scripts.
1693
1696
1694 This command is not intended to be used by normal users, as it is
1697 This command is not intended to be used by normal users, as it is
1695 primarily useful for importing from other SCMs.
1698 primarily useful for importing from other SCMs.
1696 """
1699 """
1697 message = rc['message']
1700 message = rc['message']
1698 if not message and rc['logfile']:
1701 if not message and rc['logfile']:
1699 try:
1702 try:
1700 message = open(rc['logfile']).read()
1703 message = open(rc['logfile']).read()
1701 except IOError:
1704 except IOError:
1702 pass
1705 pass
1703 if not message and not rc['logfile']:
1706 if not message and not rc['logfile']:
1704 raise util.Abort(_("missing commit message"))
1707 raise util.Abort(_("missing commit message"))
1705
1708
1706 files = relpath(repo, list(flist))
1709 files = relpath(repo, list(flist))
1707 if rc['files']:
1710 if rc['files']:
1708 files += open(rc['files']).read().splitlines()
1711 files += open(rc['files']).read().splitlines()
1709
1712
1710 rc['parent'] = map(repo.lookup, rc['parent'])
1713 rc['parent'] = map(repo.lookup, rc['parent'])
1711
1714
1712 try:
1715 try:
1713 repo.rawcommit(files, message, rc['user'], rc['date'], *rc['parent'])
1716 repo.rawcommit(files, message, rc['user'], rc['date'], *rc['parent'])
1714 except ValueError, inst:
1717 except ValueError, inst:
1715 raise util.Abort(str(inst))
1718 raise util.Abort(str(inst))
1716
1719
1717 def recover(ui, repo):
1720 def recover(ui, repo):
1718 """roll back an interrupted transaction
1721 """roll back an interrupted transaction
1719
1722
1720 Recover from an interrupted commit or pull.
1723 Recover from an interrupted commit or pull.
1721
1724
1722 This command tries to fix the repository status after an interrupted
1725 This command tries to fix the repository status after an interrupted
1723 operation. It should only be necessary when Mercurial suggests it.
1726 operation. It should only be necessary when Mercurial suggests it.
1724 """
1727 """
1725 repo.recover()
1728 repo.recover()
1726
1729
1727 def remove(ui, repo, pat, *pats, **opts):
1730 def remove(ui, repo, pat, *pats, **opts):
1728 """remove the specified files on the next commit
1731 """remove the specified files on the next commit
1729
1732
1730 Schedule the indicated files for removal from the repository.
1733 Schedule the indicated files for removal from the repository.
1731
1734
1732 This command schedules the files to be removed at the next commit.
1735 This command schedules the files to be removed at the next commit.
1733 This only removes files from the current branch, not from the
1736 This only removes files from the current branch, not from the
1734 entire project history. If the files still exist in the working
1737 entire project history. If the files still exist in the working
1735 directory, they will be deleted from it.
1738 directory, they will be deleted from it.
1736 """
1739 """
1737 names = []
1740 names = []
1738 def okaytoremove(abs, rel, exact):
1741 def okaytoremove(abs, rel, exact):
1739 c, a, d, u = repo.changes(files = [abs])
1742 c, a, d, u = repo.changes(files = [abs])
1740 reason = None
1743 reason = None
1741 if c: reason = _('is modified')
1744 if c: reason = _('is modified')
1742 elif a: reason = _('has been marked for add')
1745 elif a: reason = _('has been marked for add')
1743 elif u: reason = _('is not managed')
1746 elif u: reason = _('is not managed')
1744 if reason:
1747 if reason:
1745 if exact: ui.warn(_('not removing %s: file %s\n') % (rel, reason))
1748 if exact: ui.warn(_('not removing %s: file %s\n') % (rel, reason))
1746 else:
1749 else:
1747 return True
1750 return True
1748 for src, abs, rel, exact in walk(repo, (pat,) + pats, opts):
1751 for src, abs, rel, exact in walk(repo, (pat,) + pats, opts):
1749 if okaytoremove(abs, rel, exact):
1752 if okaytoremove(abs, rel, exact):
1750 if ui.verbose or not exact: ui.status(_('removing %s\n') % rel)
1753 if ui.verbose or not exact: ui.status(_('removing %s\n') % rel)
1751 names.append(abs)
1754 names.append(abs)
1752 repo.remove(names, unlink=True)
1755 repo.remove(names, unlink=True)
1753
1756
1754 def rename(ui, repo, *pats, **opts):
1757 def rename(ui, repo, *pats, **opts):
1755 """rename files; equivalent of copy + remove
1758 """rename files; equivalent of copy + remove
1756
1759
1757 Mark dest as copies of sources; mark sources for deletion. If
1760 Mark dest as copies of sources; mark sources for deletion. If
1758 dest is a directory, copies are put in that directory. If dest is
1761 dest is a directory, copies are put in that directory. If dest is
1759 a file, there can only be one source.
1762 a file, there can only be one source.
1760
1763
1761 By default, this command copies the contents of files as they
1764 By default, this command copies the contents of files as they
1762 stand in the working directory. If invoked with --after, the
1765 stand in the working directory. If invoked with --after, the
1763 operation is recorded, but no copying is performed.
1766 operation is recorded, but no copying is performed.
1764
1767
1765 This command takes effect in the next commit.
1768 This command takes effect in the next commit.
1766
1769
1767 NOTE: This command should be treated as experimental. While it
1770 NOTE: This command should be treated as experimental. While it
1768 should properly record rename files, this information is not yet
1771 should properly record rename files, this information is not yet
1769 fully used by merge, nor fully reported by log.
1772 fully used by merge, nor fully reported by log.
1770 """
1773 """
1771 errs, copied = docopy(ui, repo, pats, opts)
1774 errs, copied = docopy(ui, repo, pats, opts)
1772 names = []
1775 names = []
1773 for abs, rel, exact in copied:
1776 for abs, rel, exact in copied:
1774 if ui.verbose or not exact: ui.status(_('removing %s\n') % rel)
1777 if ui.verbose or not exact: ui.status(_('removing %s\n') % rel)
1775 names.append(abs)
1778 names.append(abs)
1776 repo.remove(names, unlink=True)
1779 repo.remove(names, unlink=True)
1777 return errs
1780 return errs
1778
1781
1779 def revert(ui, repo, *pats, **opts):
1782 def revert(ui, repo, *pats, **opts):
1780 """revert modified files or dirs back to their unmodified states
1783 """revert modified files or dirs back to their unmodified states
1781
1784
1782 Revert any uncommitted modifications made to the named files or
1785 Revert any uncommitted modifications made to the named files or
1783 directories. This restores the contents of the affected files to
1786 directories. This restores the contents of the affected files to
1784 an unmodified state.
1787 an unmodified state.
1785
1788
1786 If a file has been deleted, it is recreated. If the executable
1789 If a file has been deleted, it is recreated. If the executable
1787 mode of a file was changed, it is reset.
1790 mode of a file was changed, it is reset.
1788
1791
1789 If names are given, all files matching the names are reverted.
1792 If names are given, all files matching the names are reverted.
1790
1793
1791 If no names are given, all files in the current directory and
1794 If no names are given, all files in the current directory and
1792 its subdirectories are reverted.
1795 its subdirectories are reverted.
1793 """
1796 """
1794 node = opts['rev'] and repo.lookup(opts['rev']) or \
1797 node = opts['rev'] and repo.lookup(opts['rev']) or \
1795 repo.dirstate.parents()[0]
1798 repo.dirstate.parents()[0]
1796
1799
1797 files, choose, anypats = matchpats(repo, repo.getcwd(), pats, opts)
1800 files, choose, anypats = matchpats(repo, repo.getcwd(), pats, opts)
1798 (c, a, d, u) = repo.changes(match=choose)
1801 (c, a, d, u) = repo.changes(match=choose)
1799 repo.forget(a)
1802 repo.forget(a)
1800 repo.undelete(d)
1803 repo.undelete(d)
1801
1804
1802 return repo.update(node, False, True, choose, False)
1805 return repo.update(node, False, True, choose, False)
1803
1806
1804 def root(ui, repo):
1807 def root(ui, repo):
1805 """print the root (top) of the current working dir
1808 """print the root (top) of the current working dir
1806
1809
1807 Print the root directory of the current repository.
1810 Print the root directory of the current repository.
1808 """
1811 """
1809 ui.write(repo.root + "\n")
1812 ui.write(repo.root + "\n")
1810
1813
1811 def serve(ui, repo, **opts):
1814 def serve(ui, repo, **opts):
1812 """export the repository via HTTP
1815 """export the repository via HTTP
1813
1816
1814 Start a local HTTP repository browser and pull server.
1817 Start a local HTTP repository browser and pull server.
1815
1818
1816 By default, the server logs accesses to stdout and errors to
1819 By default, the server logs accesses to stdout and errors to
1817 stderr. Use the "-A" and "-E" options to log to files.
1820 stderr. Use the "-A" and "-E" options to log to files.
1818 """
1821 """
1819
1822
1820 if opts["stdio"]:
1823 if opts["stdio"]:
1821 fin, fout = sys.stdin, sys.stdout
1824 fin, fout = sys.stdin, sys.stdout
1822 sys.stdout = sys.stderr
1825 sys.stdout = sys.stderr
1823
1826
1824 # Prevent insertion/deletion of CRs
1827 # Prevent insertion/deletion of CRs
1825 util.set_binary(fin)
1828 util.set_binary(fin)
1826 util.set_binary(fout)
1829 util.set_binary(fout)
1827
1830
1828 def getarg():
1831 def getarg():
1829 argline = fin.readline()[:-1]
1832 argline = fin.readline()[:-1]
1830 arg, l = argline.split()
1833 arg, l = argline.split()
1831 val = fin.read(int(l))
1834 val = fin.read(int(l))
1832 return arg, val
1835 return arg, val
1833 def respond(v):
1836 def respond(v):
1834 fout.write("%d\n" % len(v))
1837 fout.write("%d\n" % len(v))
1835 fout.write(v)
1838 fout.write(v)
1836 fout.flush()
1839 fout.flush()
1837
1840
1838 lock = None
1841 lock = None
1839
1842
1840 while 1:
1843 while 1:
1841 cmd = fin.readline()[:-1]
1844 cmd = fin.readline()[:-1]
1842 if cmd == '':
1845 if cmd == '':
1843 return
1846 return
1844 if cmd == "heads":
1847 if cmd == "heads":
1845 h = repo.heads()
1848 h = repo.heads()
1846 respond(" ".join(map(hex, h)) + "\n")
1849 respond(" ".join(map(hex, h)) + "\n")
1847 if cmd == "lock":
1850 if cmd == "lock":
1848 lock = repo.lock()
1851 lock = repo.lock()
1849 respond("")
1852 respond("")
1850 if cmd == "unlock":
1853 if cmd == "unlock":
1851 if lock:
1854 if lock:
1852 lock.release()
1855 lock.release()
1853 lock = None
1856 lock = None
1854 respond("")
1857 respond("")
1855 elif cmd == "branches":
1858 elif cmd == "branches":
1856 arg, nodes = getarg()
1859 arg, nodes = getarg()
1857 nodes = map(bin, nodes.split(" "))
1860 nodes = map(bin, nodes.split(" "))
1858 r = []
1861 r = []
1859 for b in repo.branches(nodes):
1862 for b in repo.branches(nodes):
1860 r.append(" ".join(map(hex, b)) + "\n")
1863 r.append(" ".join(map(hex, b)) + "\n")
1861 respond("".join(r))
1864 respond("".join(r))
1862 elif cmd == "between":
1865 elif cmd == "between":
1863 arg, pairs = getarg()
1866 arg, pairs = getarg()
1864 pairs = [map(bin, p.split("-")) for p in pairs.split(" ")]
1867 pairs = [map(bin, p.split("-")) for p in pairs.split(" ")]
1865 r = []
1868 r = []
1866 for b in repo.between(pairs):
1869 for b in repo.between(pairs):
1867 r.append(" ".join(map(hex, b)) + "\n")
1870 r.append(" ".join(map(hex, b)) + "\n")
1868 respond("".join(r))
1871 respond("".join(r))
1869 elif cmd == "changegroup":
1872 elif cmd == "changegroup":
1870 nodes = []
1873 nodes = []
1871 arg, roots = getarg()
1874 arg, roots = getarg()
1872 nodes = map(bin, roots.split(" "))
1875 nodes = map(bin, roots.split(" "))
1873
1876
1874 cg = repo.changegroup(nodes)
1877 cg = repo.changegroup(nodes)
1875 while 1:
1878 while 1:
1876 d = cg.read(4096)
1879 d = cg.read(4096)
1877 if not d:
1880 if not d:
1878 break
1881 break
1879 fout.write(d)
1882 fout.write(d)
1880
1883
1881 fout.flush()
1884 fout.flush()
1882
1885
1883 elif cmd == "addchangegroup":
1886 elif cmd == "addchangegroup":
1884 if not lock:
1887 if not lock:
1885 respond("not locked")
1888 respond("not locked")
1886 continue
1889 continue
1887 respond("")
1890 respond("")
1888
1891
1889 r = repo.addchangegroup(fin)
1892 r = repo.addchangegroup(fin)
1890 respond("")
1893 respond("")
1891
1894
1892 optlist = "name templates style address port ipv6 accesslog errorlog"
1895 optlist = "name templates style address port ipv6 accesslog errorlog"
1893 for o in optlist.split():
1896 for o in optlist.split():
1894 if opts[o]:
1897 if opts[o]:
1895 ui.setconfig("web", o, opts[o])
1898 ui.setconfig("web", o, opts[o])
1896
1899
1897 try:
1900 try:
1898 httpd = hgweb.create_server(repo)
1901 httpd = hgweb.create_server(repo)
1899 except socket.error, inst:
1902 except socket.error, inst:
1900 raise util.Abort('cannot start server: ' + inst.args[1])
1903 raise util.Abort('cannot start server: ' + inst.args[1])
1901
1904
1902 if ui.verbose:
1905 if ui.verbose:
1903 addr, port = httpd.socket.getsockname()
1906 addr, port = httpd.socket.getsockname()
1904 if addr == '0.0.0.0':
1907 if addr == '0.0.0.0':
1905 addr = socket.gethostname()
1908 addr = socket.gethostname()
1906 else:
1909 else:
1907 try:
1910 try:
1908 addr = socket.gethostbyaddr(addr)[0]
1911 addr = socket.gethostbyaddr(addr)[0]
1909 except socket.error:
1912 except socket.error:
1910 pass
1913 pass
1911 if port != 80:
1914 if port != 80:
1912 ui.status(_('listening at http://%s:%d/\n') % (addr, port))
1915 ui.status(_('listening at http://%s:%d/\n') % (addr, port))
1913 else:
1916 else:
1914 ui.status(_('listening at http://%s/\n') % addr)
1917 ui.status(_('listening at http://%s/\n') % addr)
1915 httpd.serve_forever()
1918 httpd.serve_forever()
1916
1919
1917 def status(ui, repo, *pats, **opts):
1920 def status(ui, repo, *pats, **opts):
1918 """show changed files in the working directory
1921 """show changed files in the working directory
1919
1922
1920 Show changed files in the working directory. If no names are
1923 Show changed files in the working directory. If no names are
1921 given, all files are shown. Otherwise, only files matching the
1924 given, all files are shown. Otherwise, only files matching the
1922 given names are shown.
1925 given names are shown.
1923
1926
1924 The codes used to show the status of files are:
1927 The codes used to show the status of files are:
1925 M = modified
1928 M = modified
1926 A = added
1929 A = added
1927 R = removed
1930 R = removed
1928 ? = not tracked
1931 ? = not tracked
1929 """
1932 """
1930
1933
1931 cwd = repo.getcwd()
1934 cwd = repo.getcwd()
1932 files, matchfn, anypats = matchpats(repo, cwd, pats, opts)
1935 files, matchfn, anypats = matchpats(repo, cwd, pats, opts)
1933 (c, a, d, u) = [[util.pathto(cwd, x) for x in n]
1936 (c, a, d, u) = [[util.pathto(cwd, x) for x in n]
1934 for n in repo.changes(files=files, match=matchfn)]
1937 for n in repo.changes(files=files, match=matchfn)]
1935
1938
1936 changetypes = [(_('modified'), 'M', c),
1939 changetypes = [(_('modified'), 'M', c),
1937 (_('added'), 'A', a),
1940 (_('added'), 'A', a),
1938 (_('removed'), 'R', d),
1941 (_('removed'), 'R', d),
1939 (_('unknown'), '?', u)]
1942 (_('unknown'), '?', u)]
1940
1943
1941 end = opts['print0'] and '\0' or '\n'
1944 end = opts['print0'] and '\0' or '\n'
1942
1945
1943 for opt, char, changes in ([ct for ct in changetypes if opts[ct[0]]]
1946 for opt, char, changes in ([ct for ct in changetypes if opts[ct[0]]]
1944 or changetypes):
1947 or changetypes):
1945 if opts['no_status']:
1948 if opts['no_status']:
1946 format = "%%s%s" % end
1949 format = "%%s%s" % end
1947 else:
1950 else:
1948 format = "%s %%s%s" % (char, end);
1951 format = "%s %%s%s" % (char, end);
1949
1952
1950 for f in changes:
1953 for f in changes:
1951 ui.write(format % f)
1954 ui.write(format % f)
1952
1955
1953 def tag(ui, repo, name, rev=None, **opts):
1956 def tag(ui, repo, name, rev=None, **opts):
1954 """add a tag for the current tip or a given revision
1957 """add a tag for the current tip or a given revision
1955
1958
1956 Name a particular revision using <name>.
1959 Name a particular revision using <name>.
1957
1960
1958 Tags are used to name particular revisions of the repository and are
1961 Tags are used to name particular revisions of the repository and are
1959 very useful to compare different revision, to go back to significant
1962 very useful to compare different revision, to go back to significant
1960 earlier versions or to mark branch points as releases, etc.
1963 earlier versions or to mark branch points as releases, etc.
1961
1964
1962 If no revision is given, the tip is used.
1965 If no revision is given, the tip is used.
1963
1966
1964 To facilitate version control, distribution, and merging of tags,
1967 To facilitate version control, distribution, and merging of tags,
1965 they are stored as a file named ".hgtags" which is managed
1968 they are stored as a file named ".hgtags" which is managed
1966 similarly to other project files and can be hand-edited if
1969 similarly to other project files and can be hand-edited if
1967 necessary.
1970 necessary.
1968 """
1971 """
1969 if name == "tip":
1972 if name == "tip":
1970 raise util.Abort(_("the name 'tip' is reserved"))
1973 raise util.Abort(_("the name 'tip' is reserved"))
1971 if 'rev' in opts:
1974 if 'rev' in opts:
1972 rev = opts['rev']
1975 rev = opts['rev']
1973 if rev:
1976 if rev:
1974 r = hex(repo.lookup(rev))
1977 r = hex(repo.lookup(rev))
1975 else:
1978 else:
1976 r = hex(repo.changelog.tip())
1979 r = hex(repo.changelog.tip())
1977
1980
1978 if name.find(revrangesep) >= 0:
1981 if name.find(revrangesep) >= 0:
1979 raise util.Abort(_("'%s' cannot be used in a tag name") % revrangesep)
1982 raise util.Abort(_("'%s' cannot be used in a tag name") % revrangesep)
1980
1983
1981 if opts['local']:
1984 if opts['local']:
1982 repo.opener("localtags", "a").write("%s %s\n" % (r, name))
1985 repo.opener("localtags", "a").write("%s %s\n" % (r, name))
1983 return
1986 return
1984
1987
1985 (c, a, d, u) = repo.changes()
1988 (c, a, d, u) = repo.changes()
1986 for x in (c, a, d, u):
1989 for x in (c, a, d, u):
1987 if ".hgtags" in x:
1990 if ".hgtags" in x:
1988 raise util.Abort(_("working copy of .hgtags is changed "
1991 raise util.Abort(_("working copy of .hgtags is changed "
1989 "(please commit .hgtags manually)"))
1992 "(please commit .hgtags manually)"))
1990
1993
1991 repo.wfile(".hgtags", "ab").write("%s %s\n" % (r, name))
1994 repo.wfile(".hgtags", "ab").write("%s %s\n" % (r, name))
1992 if repo.dirstate.state(".hgtags") == '?':
1995 if repo.dirstate.state(".hgtags") == '?':
1993 repo.add([".hgtags"])
1996 repo.add([".hgtags"])
1994
1997
1995 message = (opts['message'] or
1998 message = (opts['message'] or
1996 _("Added tag %s for changeset %s") % (name, r))
1999 _("Added tag %s for changeset %s") % (name, r))
1997 try:
2000 try:
1998 repo.commit([".hgtags"], message, opts['user'], opts['date'])
2001 repo.commit([".hgtags"], message, opts['user'], opts['date'])
1999 except ValueError, inst:
2002 except ValueError, inst:
2000 raise util.Abort(str(inst))
2003 raise util.Abort(str(inst))
2001
2004
2002 def tags(ui, repo):
2005 def tags(ui, repo):
2003 """list repository tags
2006 """list repository tags
2004
2007
2005 List the repository tags.
2008 List the repository tags.
2006
2009
2007 This lists both regular and local tags.
2010 This lists both regular and local tags.
2008 """
2011 """
2009
2012
2010 l = repo.tagslist()
2013 l = repo.tagslist()
2011 l.reverse()
2014 l.reverse()
2012 for t, n in l:
2015 for t, n in l:
2013 try:
2016 try:
2014 r = "%5d:%s" % (repo.changelog.rev(n), hex(n))
2017 r = "%5d:%s" % (repo.changelog.rev(n), hex(n))
2015 except KeyError:
2018 except KeyError:
2016 r = " ?:?"
2019 r = " ?:?"
2017 ui.write("%-30s %s\n" % (t, r))
2020 ui.write("%-30s %s\n" % (t, r))
2018
2021
2019 def tip(ui, repo):
2022 def tip(ui, repo):
2020 """show the tip revision
2023 """show the tip revision
2021
2024
2022 Show the tip revision.
2025 Show the tip revision.
2023 """
2026 """
2024 n = repo.changelog.tip()
2027 n = repo.changelog.tip()
2025 show_changeset(ui, repo, changenode=n)
2028 show_changeset(ui, repo, changenode=n)
2026
2029
2027 def unbundle(ui, repo, fname):
2030 def unbundle(ui, repo, fname):
2028 """apply a changegroup file
2031 """apply a changegroup file
2029
2032
2030 Apply a compressed changegroup file generated by the bundle
2033 Apply a compressed changegroup file generated by the bundle
2031 command.
2034 command.
2032 """
2035 """
2033 f = urllib.urlopen(fname)
2036 f = urllib.urlopen(fname)
2034
2037
2035 if f.read(4) != "HG10":
2038 if f.read(4) != "HG10":
2036 raise util.Abort(_("%s: not a Mercurial bundle file") % fname)
2039 raise util.Abort(_("%s: not a Mercurial bundle file") % fname)
2037
2040
2038 def bzgenerator(f):
2041 def bzgenerator(f):
2039 zd = bz2.BZ2Decompressor()
2042 zd = bz2.BZ2Decompressor()
2040 for chunk in f:
2043 for chunk in f:
2041 yield zd.decompress(chunk)
2044 yield zd.decompress(chunk)
2042
2045
2043 bzgen = bzgenerator(util.filechunkiter(f, 4096))
2046 bzgen = bzgenerator(util.filechunkiter(f, 4096))
2044 repo.addchangegroup(util.chunkbuffer(bzgen))
2047 repo.addchangegroup(util.chunkbuffer(bzgen))
2045
2048
2046 def undo(ui, repo):
2049 def undo(ui, repo):
2047 """undo the last commit or pull
2050 """undo the last commit or pull
2048
2051
2049 Roll back the last pull or commit transaction on the
2052 Roll back the last pull or commit transaction on the
2050 repository, restoring the project to its earlier state.
2053 repository, restoring the project to its earlier state.
2051
2054
2052 This command should be used with care. There is only one level of
2055 This command should be used with care. There is only one level of
2053 undo and there is no redo.
2056 undo and there is no redo.
2054
2057
2055 This command is not intended for use on public repositories. Once
2058 This command is not intended for use on public repositories. Once
2056 a change is visible for pull by other users, undoing it locally is
2059 a change is visible for pull by other users, undoing it locally is
2057 ineffective.
2060 ineffective.
2058 """
2061 """
2059 repo.undo()
2062 repo.undo()
2060
2063
2061 def update(ui, repo, node=None, merge=False, clean=False, branch=None):
2064 def update(ui, repo, node=None, merge=False, clean=False, branch=None):
2062 """update or merge working directory
2065 """update or merge working directory
2063
2066
2064 Update the working directory to the specified revision.
2067 Update the working directory to the specified revision.
2065
2068
2066 If there are no outstanding changes in the working directory and
2069 If there are no outstanding changes in the working directory and
2067 there is a linear relationship between the current version and the
2070 there is a linear relationship between the current version and the
2068 requested version, the result is the requested version.
2071 requested version, the result is the requested version.
2069
2072
2070 Otherwise the result is a merge between the contents of the
2073 Otherwise the result is a merge between the contents of the
2071 current working directory and the requested version. Files that
2074 current working directory and the requested version. Files that
2072 changed between either parent are marked as changed for the next
2075 changed between either parent are marked as changed for the next
2073 commit and a commit must be performed before any further updates
2076 commit and a commit must be performed before any further updates
2074 are allowed.
2077 are allowed.
2075
2078
2076 By default, update will refuse to run if doing so would require
2079 By default, update will refuse to run if doing so would require
2077 merging or discarding local changes.
2080 merging or discarding local changes.
2078 """
2081 """
2079 if branch:
2082 if branch:
2080 br = repo.branchlookup(branch=branch)
2083 br = repo.branchlookup(branch=branch)
2081 found = []
2084 found = []
2082 for x in br:
2085 for x in br:
2083 if branch in br[x]:
2086 if branch in br[x]:
2084 found.append(x)
2087 found.append(x)
2085 if len(found) > 1:
2088 if len(found) > 1:
2086 ui.warn(_("Found multiple heads for %s\n") % branch)
2089 ui.warn(_("Found multiple heads for %s\n") % branch)
2087 for x in found:
2090 for x in found:
2088 show_changeset(ui, repo, changenode=x, brinfo=br)
2091 show_changeset(ui, repo, changenode=x, brinfo=br)
2089 return 1
2092 return 1
2090 if len(found) == 1:
2093 if len(found) == 1:
2091 node = found[0]
2094 node = found[0]
2092 ui.warn(_("Using head %s for branch %s\n") % (short(node), branch))
2095 ui.warn(_("Using head %s for branch %s\n") % (short(node), branch))
2093 else:
2096 else:
2094 ui.warn(_("branch %s not found\n") % (branch))
2097 ui.warn(_("branch %s not found\n") % (branch))
2095 return 1
2098 return 1
2096 else:
2099 else:
2097 node = node and repo.lookup(node) or repo.changelog.tip()
2100 node = node and repo.lookup(node) or repo.changelog.tip()
2098 return repo.update(node, allow=merge, force=clean)
2101 return repo.update(node, allow=merge, force=clean)
2099
2102
2100 def verify(ui, repo):
2103 def verify(ui, repo):
2101 """verify the integrity of the repository
2104 """verify the integrity of the repository
2102
2105
2103 Verify the integrity of the current repository.
2106 Verify the integrity of the current repository.
2104
2107
2105 This will perform an extensive check of the repository's
2108 This will perform an extensive check of the repository's
2106 integrity, validating the hashes and checksums of each entry in
2109 integrity, validating the hashes and checksums of each entry in
2107 the changelog, manifest, and tracked files, as well as the
2110 the changelog, manifest, and tracked files, as well as the
2108 integrity of their crosslinks and indices.
2111 integrity of their crosslinks and indices.
2109 """
2112 """
2110 return repo.verify()
2113 return repo.verify()
2111
2114
2112 # Command options and aliases are listed here, alphabetically
2115 # Command options and aliases are listed here, alphabetically
2113
2116
2114 table = {
2117 table = {
2115 "^add":
2118 "^add":
2116 (add,
2119 (add,
2117 [('I', 'include', [], _('include names matching the given patterns')),
2120 [('I', 'include', [], _('include names matching the given patterns')),
2118 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2121 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2119 "hg add [OPTION]... [FILE]..."),
2122 "hg add [OPTION]... [FILE]..."),
2120 "addremove":
2123 "addremove":
2121 (addremove,
2124 (addremove,
2122 [('I', 'include', [], _('include names matching the given patterns')),
2125 [('I', 'include', [], _('include names matching the given patterns')),
2123 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2126 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2124 "hg addremove [OPTION]... [FILE]..."),
2127 "hg addremove [OPTION]... [FILE]..."),
2125 "^annotate":
2128 "^annotate":
2126 (annotate,
2129 (annotate,
2127 [('r', 'rev', '', _('annotate the specified revision')),
2130 [('r', 'rev', '', _('annotate the specified revision')),
2128 ('a', 'text', None, _('treat all files as text')),
2131 ('a', 'text', None, _('treat all files as text')),
2129 ('u', 'user', None, _('list the author')),
2132 ('u', 'user', None, _('list the author')),
2130 ('n', 'number', None, _('list the revision number (default)')),
2133 ('n', 'number', None, _('list the revision number (default)')),
2131 ('c', 'changeset', None, _('list the changeset')),
2134 ('c', 'changeset', None, _('list the changeset')),
2132 ('I', 'include', [], _('include names matching the given patterns')),
2135 ('I', 'include', [], _('include names matching the given patterns')),
2133 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2136 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2134 _('hg annotate [OPTION]... FILE...')),
2137 _('hg annotate [OPTION]... FILE...')),
2135 "bundle":
2138 "bundle":
2136 (bundle,
2139 (bundle,
2137 [],
2140 [],
2138 _('hg bundle FILE DEST')),
2141 _('hg bundle FILE DEST')),
2139 "cat":
2142 "cat":
2140 (cat,
2143 (cat,
2141 [('I', 'include', [], _('include names matching the given patterns')),
2144 [('I', 'include', [], _('include names matching the given patterns')),
2142 ('X', 'exclude', [], _('exclude names matching the given patterns')),
2145 ('X', 'exclude', [], _('exclude names matching the given patterns')),
2143 ('o', 'output', "", _('print output to file with formatted name')),
2146 ('o', 'output', "", _('print output to file with formatted name')),
2144 ('r', 'rev', '', _('print the given revision'))],
2147 ('r', 'rev', '', _('print the given revision'))],
2145 _('hg cat [OPTION]... FILE...')),
2148 _('hg cat [OPTION]... FILE...')),
2146 "^clone":
2149 "^clone":
2147 (clone,
2150 (clone,
2148 [('U', 'noupdate', None, _('do not update the new working directory')),
2151 [('U', 'noupdate', None, _('do not update the new working directory')),
2149 ('e', 'ssh', "", _('specify ssh command to use')),
2152 ('e', 'ssh', "", _('specify ssh command to use')),
2150 ('', 'pull', None, _('use pull protocol to copy metadata')),
2153 ('', 'pull', None, _('use pull protocol to copy metadata')),
2151 ('r', 'rev', [], _('a changeset you would like to have after cloning')),
2154 ('r', 'rev', [], _('a changeset you would like to have after cloning')),
2152 ('', 'remotecmd', "", _('specify hg command to run on the remote side'))],
2155 ('', 'remotecmd', "", _('specify hg command to run on the remote side'))],
2153 _('hg clone [OPTION]... SOURCE [DEST]')),
2156 _('hg clone [OPTION]... SOURCE [DEST]')),
2154 "^commit|ci":
2157 "^commit|ci":
2155 (commit,
2158 (commit,
2156 [('A', 'addremove', None, _('run addremove during commit')),
2159 [('A', 'addremove', None, _('run addremove during commit')),
2157 ('I', 'include', [], _('include names matching the given patterns')),
2160 ('I', 'include', [], _('include names matching the given patterns')),
2158 ('X', 'exclude', [], _('exclude names matching the given patterns')),
2161 ('X', 'exclude', [], _('exclude names matching the given patterns')),
2159 ('m', 'message', "", _('use <text> as commit message')),
2162 ('m', 'message', "", _('use <text> as commit message')),
2160 ('l', 'logfile', "", _('read the commit message from <file>')),
2163 ('l', 'logfile', "", _('read the commit message from <file>')),
2161 ('d', 'date', "", _('record datecode as commit date')),
2164 ('d', 'date', "", _('record datecode as commit date')),
2162 ('u', 'user', "", _('record user as commiter'))],
2165 ('u', 'user', "", _('record user as commiter'))],
2163 _('hg commit [OPTION]... [FILE]...')),
2166 _('hg commit [OPTION]... [FILE]...')),
2164 "copy|cp": (copy,
2167 "copy|cp": (copy,
2165 [('I', 'include', [], _('include names matching the given patterns')),
2168 [('I', 'include', [], _('include names matching the given patterns')),
2166 ('X', 'exclude', [], _('exclude names matching the given patterns')),
2169 ('X', 'exclude', [], _('exclude names matching the given patterns')),
2167 ('A', 'after', None, _('record a copy that has already occurred')),
2170 ('A', 'after', None, _('record a copy that has already occurred')),
2168 ('f', 'force', None, _('forcibly copy over an existing managed file'))],
2171 ('f', 'force', None, _('forcibly copy over an existing managed file'))],
2169 _('hg copy [OPTION]... [SOURCE]... DEST')),
2172 _('hg copy [OPTION]... [SOURCE]... DEST')),
2170 "debugancestor": (debugancestor, [], _('debugancestor INDEX REV1 REV2')),
2173 "debugancestor": (debugancestor, [], _('debugancestor INDEX REV1 REV2')),
2171 "debugcheckstate": (debugcheckstate, [], _('debugcheckstate')),
2174 "debugcheckstate": (debugcheckstate, [], _('debugcheckstate')),
2172 "debugconfig": (debugconfig, [], _('debugconfig')),
2175 "debugconfig": (debugconfig, [], _('debugconfig')),
2173 "debugsetparents": (debugsetparents, [], _('debugsetparents REV1 [REV2]')),
2176 "debugsetparents": (debugsetparents, [], _('debugsetparents REV1 [REV2]')),
2174 "debugstate": (debugstate, [], _('debugstate')),
2177 "debugstate": (debugstate, [], _('debugstate')),
2175 "debugdata": (debugdata, [], _('debugdata FILE REV')),
2178 "debugdata": (debugdata, [], _('debugdata FILE REV')),
2176 "debugindex": (debugindex, [], _('debugindex FILE')),
2179 "debugindex": (debugindex, [], _('debugindex FILE')),
2177 "debugindexdot": (debugindexdot, [], _('debugindexdot FILE')),
2180 "debugindexdot": (debugindexdot, [], _('debugindexdot FILE')),
2178 "debugrename": (debugrename, [], _('debugrename FILE [REV]')),
2181 "debugrename": (debugrename, [], _('debugrename FILE [REV]')),
2179 "debugwalk":
2182 "debugwalk":
2180 (debugwalk,
2183 (debugwalk,
2181 [('I', 'include', [], _('include names matching the given patterns')),
2184 [('I', 'include', [], _('include names matching the given patterns')),
2182 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2185 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2183 _('debugwalk [OPTION]... [FILE]...')),
2186 _('debugwalk [OPTION]... [FILE]...')),
2184 "^diff":
2187 "^diff":
2185 (diff,
2188 (diff,
2186 [('r', 'rev', [], _('revision')),
2189 [('r', 'rev', [], _('revision')),
2187 ('a', 'text', None, _('treat all files as text')),
2190 ('a', 'text', None, _('treat all files as text')),
2188 ('I', 'include', [], _('include names matching the given patterns')),
2191 ('I', 'include', [], _('include names matching the given patterns')),
2189 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2192 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2190 _('hg diff [-a] [-I] [-X] [-r REV1 [-r REV2]] [FILE]...')),
2193 _('hg diff [-a] [-I] [-X] [-r REV1 [-r REV2]] [FILE]...')),
2191 "^export":
2194 "^export":
2192 (export,
2195 (export,
2193 [('o', 'output', "", _('print output to file with formatted name')),
2196 [('o', 'output', "", _('print output to file with formatted name')),
2194 ('a', 'text', None, _('treat all files as text'))],
2197 ('a', 'text', None, _('treat all files as text'))],
2195 "hg export [-a] [-o OUTFILE] REV..."),
2198 "hg export [-a] [-o OUTFILE] REV..."),
2196 "forget":
2199 "forget":
2197 (forget,
2200 (forget,
2198 [('I', 'include', [], _('include names matching the given patterns')),
2201 [('I', 'include', [], _('include names matching the given patterns')),
2199 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2202 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2200 "hg forget [OPTION]... FILE..."),
2203 "hg forget [OPTION]... FILE..."),
2201 "grep":
2204 "grep":
2202 (grep,
2205 (grep,
2203 [('0', 'print0', None, _('end fields with NUL')),
2206 [('0', 'print0', None, _('end fields with NUL')),
2204 ('I', 'include', [], _('include names matching the given patterns')),
2207 ('I', 'include', [], _('include names matching the given patterns')),
2205 ('X', 'exclude', [], _('exclude names matching the given patterns')),
2208 ('X', 'exclude', [], _('exclude names matching the given patterns')),
2206 ('', 'all', None, _('print all revisions that match')),
2209 ('', 'all', None, _('print all revisions that match')),
2207 ('i', 'ignore-case', None, _('ignore case when matching')),
2210 ('i', 'ignore-case', None, _('ignore case when matching')),
2208 ('l', 'files-with-matches', None, _('print only filenames and revs that match')),
2211 ('l', 'files-with-matches', None, _('print only filenames and revs that match')),
2209 ('n', 'line-number', None, _('print matching line numbers')),
2212 ('n', 'line-number', None, _('print matching line numbers')),
2210 ('r', 'rev', [], _('search in given revision range')),
2213 ('r', 'rev', [], _('search in given revision range')),
2211 ('u', 'user', None, _('print user who committed change'))],
2214 ('u', 'user', None, _('print user who committed change'))],
2212 "hg grep [OPTION]... PATTERN [FILE]..."),
2215 "hg grep [OPTION]... PATTERN [FILE]..."),
2213 "heads":
2216 "heads":
2214 (heads,
2217 (heads,
2215 [('b', 'branches', None, _('find branch info'))],
2218 [('b', 'branches', None, _('find branch info'))],
2216 _('hg heads [-b]')),
2219 _('hg heads [-b]')),
2217 "help": (help_, [], _('hg help [COMMAND]')),
2220 "help": (help_, [], _('hg help [COMMAND]')),
2218 "identify|id": (identify, [], _('hg identify')),
2221 "identify|id": (identify, [], _('hg identify')),
2219 "import|patch":
2222 "import|patch":
2220 (import_,
2223 (import_,
2221 [('p', 'strip', 1, _('directory strip option for patch. This has the same\n') +
2224 [('p', 'strip', 1, _('directory strip option for patch. This has the same\n') +
2222 _('meaning as the corresponding patch option')),
2225 _('meaning as the corresponding patch option')),
2223 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
2226 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
2224 ('b', 'base', "", _('base path'))],
2227 ('b', 'base', "", _('base path'))],
2225 "hg import [-f] [-p NUM] [-b BASE] PATCH..."),
2228 "hg import [-f] [-p NUM] [-b BASE] PATCH..."),
2226 "incoming|in": (incoming,
2229 "incoming|in": (incoming,
2227 [('M', 'no-merges', None, _("do not show merges")),
2230 [('M', 'no-merges', None, _("do not show merges")),
2228 ('p', 'patch', None, _('show patch')),
2231 ('p', 'patch', None, _('show patch')),
2229 ('n', 'newest-first', None, _('show newest record first'))],
2232 ('n', 'newest-first', None, _('show newest record first'))],
2230 _('hg incoming [-p] [-n] [-M] [SOURCE]')),
2233 _('hg incoming [-p] [-n] [-M] [SOURCE]')),
2231 "^init": (init, [], _('hg init [DEST]')),
2234 "^init": (init, [], _('hg init [DEST]')),
2232 "locate":
2235 "locate":
2233 (locate,
2236 (locate,
2234 [('r', 'rev', '', _('search the repository as it stood at rev')),
2237 [('r', 'rev', '', _('search the repository as it stood at rev')),
2235 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
2238 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
2236 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
2239 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
2237 ('I', 'include', [], _('include names matching the given patterns')),
2240 ('I', 'include', [], _('include names matching the given patterns')),
2238 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2241 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2239 _('hg locate [OPTION]... [PATTERN]...')),
2242 _('hg locate [OPTION]... [PATTERN]...')),
2240 "^log|history":
2243 "^log|history":
2241 (log,
2244 (log,
2242 [('I', 'include', [], _('include names matching the given patterns')),
2245 [('I', 'include', [], _('include names matching the given patterns')),
2243 ('X', 'exclude', [], _('exclude names matching the given patterns')),
2246 ('X', 'exclude', [], _('exclude names matching the given patterns')),
2244 ('b', 'branch', None, _('show branches')),
2247 ('b', 'branch', None, _('show branches')),
2245 ('k', 'keyword', [], _('search for a keyword')),
2248 ('k', 'keyword', [], _('search for a keyword')),
2246 ('r', 'rev', [], _('show the specified revision or range')),
2249 ('r', 'rev', [], _('show the specified revision or range')),
2247 ('M', 'no-merges', None, _("do not show merges")),
2250 ('M', 'no-merges', None, _("do not show merges")),
2248 ('m', 'only-merges', None, _("show only merges")),
2251 ('m', 'only-merges', None, _("show only merges")),
2249 ('p', 'patch', None, _('show patch'))],
2252 ('p', 'patch', None, _('show patch'))],
2250 _('hg log [-I] [-X] [-r REV]... [-p] [FILE]')),
2253 _('hg log [-I] [-X] [-r REV]... [-p] [FILE]')),
2251 "manifest": (manifest, [], _('hg manifest [REV]')),
2254 "manifest": (manifest, [], _('hg manifest [REV]')),
2252 "outgoing|out": (outgoing,
2255 "outgoing|out": (outgoing,
2253 [('M', 'no-merges', None, _("do not show merges")),
2256 [('M', 'no-merges', None, _("do not show merges")),
2254 ('p', 'patch', None, _('show patch')),
2257 ('p', 'patch', None, _('show patch')),
2255 ('n', 'newest-first', None, _('show newest record first'))],
2258 ('n', 'newest-first', None, _('show newest record first'))],
2256 _('hg outgoing [-p] [-n] [-M] [DEST]')),
2259 _('hg outgoing [-p] [-n] [-M] [DEST]')),
2257 "^parents": (parents, [], _('hg parents [REV]')),
2260 "^parents": (parents, [], _('hg parents [REV]')),
2258 "paths": (paths, [], _('hg paths [NAME]')),
2261 "paths": (paths, [], _('hg paths [NAME]')),
2259 "^pull":
2262 "^pull":
2260 (pull,
2263 (pull,
2261 [('u', 'update', None, _('update the working directory to tip after pull')),
2264 [('u', 'update', None, _('update the working directory to tip after pull')),
2262 ('e', 'ssh', "", _('specify ssh command to use')),
2265 ('e', 'ssh', "", _('specify ssh command to use')),
2263 ('r', 'rev', [], _('a specific revision you would like to pull')),
2266 ('r', 'rev', [], _('a specific revision you would like to pull')),
2264 ('', 'remotecmd', "", _('specify hg command to run on the remote side'))],
2267 ('', 'remotecmd', "", _('specify hg command to run on the remote side'))],
2265 _('hg pull [-u] [-e FILE] [-r rev] [--remotecmd FILE] [SOURCE]')),
2268 _('hg pull [-u] [-e FILE] [-r rev] [--remotecmd FILE] [SOURCE]')),
2266 "^push":
2269 "^push":
2267 (push,
2270 (push,
2268 [('f', 'force', None, _('force push')),
2271 [('f', 'force', None, _('force push')),
2269 ('e', 'ssh', "", _('specify ssh command to use')),
2272 ('e', 'ssh', "", _('specify ssh command to use')),
2270 ('', 'remotecmd', "", _('specify hg command to run on the remote side'))],
2273 ('', 'remotecmd', "", _('specify hg command to run on the remote side'))],
2271 _('hg push [-f] [-e FILE] [--remotecmd FILE] [DEST]')),
2274 _('hg push [-f] [-e FILE] [--remotecmd FILE] [DEST]')),
2272 "rawcommit":
2275 "rawcommit":
2273 (rawcommit,
2276 (rawcommit,
2274 [('p', 'parent', [], _('parent')),
2277 [('p', 'parent', [], _('parent')),
2275 ('d', 'date', "", _('date code')),
2278 ('d', 'date', "", _('date code')),
2276 ('u', 'user', "", _('user')),
2279 ('u', 'user', "", _('user')),
2277 ('F', 'files', "", _('file list')),
2280 ('F', 'files', "", _('file list')),
2278 ('m', 'message', "", _('commit message')),
2281 ('m', 'message', "", _('commit message')),
2279 ('l', 'logfile', "", _('commit message file'))],
2282 ('l', 'logfile', "", _('commit message file'))],
2280 _('hg rawcommit [OPTION]... [FILE]...')),
2283 _('hg rawcommit [OPTION]... [FILE]...')),
2281 "recover": (recover, [], _("hg recover")),
2284 "recover": (recover, [], _("hg recover")),
2282 "^remove|rm": (remove,
2285 "^remove|rm": (remove,
2283 [('I', 'include', [], _('include names matching the given patterns')),
2286 [('I', 'include', [], _('include names matching the given patterns')),
2284 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2287 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2285 _("hg remove [OPTION]... FILE...")),
2288 _("hg remove [OPTION]... FILE...")),
2286 "rename|mv": (rename,
2289 "rename|mv": (rename,
2287 [('I', 'include', [], _('include names matching the given patterns')),
2290 [('I', 'include', [], _('include names matching the given patterns')),
2288 ('X', 'exclude', [], _('exclude names matching the given patterns')),
2291 ('X', 'exclude', [], _('exclude names matching the given patterns')),
2289 ('A', 'after', None, _('record a rename that has already occurred')),
2292 ('A', 'after', None, _('record a rename that has already occurred')),
2290 ('f', 'force', None, _('forcibly copy over an existing managed file'))],
2293 ('f', 'force', None, _('forcibly copy over an existing managed file'))],
2291 _('hg rename [OPTION]... [SOURCE]... DEST')),
2294 _('hg rename [OPTION]... [SOURCE]... DEST')),
2292 "^revert":
2295 "^revert":
2293 (revert,
2296 (revert,
2294 [('I', 'include', [], _('include names matching the given patterns')),
2297 [('I', 'include', [], _('include names matching the given patterns')),
2295 ('X', 'exclude', [], _('exclude names matching the given patterns')),
2298 ('X', 'exclude', [], _('exclude names matching the given patterns')),
2296 ("r", "rev", "", _("revision to revert to"))],
2299 ("r", "rev", "", _("revision to revert to"))],
2297 _("hg revert [-n] [-r REV] [NAME]...")),
2300 _("hg revert [-n] [-r REV] [NAME]...")),
2298 "root": (root, [], _("hg root")),
2301 "root": (root, [], _("hg root")),
2299 "^serve":
2302 "^serve":
2300 (serve,
2303 (serve,
2301 [('A', 'accesslog', '', _('name of access log file to write to')),
2304 [('A', 'accesslog', '', _('name of access log file to write to')),
2302 ('E', 'errorlog', '', _('name of error log file to write to')),
2305 ('E', 'errorlog', '', _('name of error log file to write to')),
2303 ('p', 'port', 0, _('port to use (default: 8000)')),
2306 ('p', 'port', 0, _('port to use (default: 8000)')),
2304 ('a', 'address', '', _('address to use')),
2307 ('a', 'address', '', _('address to use')),
2305 ('n', 'name', "", _('name to show in web pages (default: working dir)')),
2308 ('n', 'name', "", _('name to show in web pages (default: working dir)')),
2306 ('', 'stdio', None, _('for remote clients')),
2309 ('', 'stdio', None, _('for remote clients')),
2307 ('t', 'templates', "", _('web templates to use')),
2310 ('t', 'templates', "", _('web templates to use')),
2308 ('', 'style', "", _('template style to use')),
2311 ('', 'style', "", _('template style to use')),
2309 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4'))],
2312 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4'))],
2310 _("hg serve [OPTION]...")),
2313 _("hg serve [OPTION]...")),
2311 "^status|st":
2314 "^status|st":
2312 (status,
2315 (status,
2313 [('m', 'modified', None, _('show only modified files')),
2316 [('m', 'modified', None, _('show only modified files')),
2314 ('a', 'added', None, _('show only added files')),
2317 ('a', 'added', None, _('show only added files')),
2315 ('r', 'removed', None, _('show only removed files')),
2318 ('r', 'removed', None, _('show only removed files')),
2316 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
2319 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
2317 ('n', 'no-status', None, _('hide status prefix')),
2320 ('n', 'no-status', None, _('hide status prefix')),
2318 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
2321 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
2319 ('I', 'include', [], _('include names matching the given patterns')),
2322 ('I', 'include', [], _('include names matching the given patterns')),
2320 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2323 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2321 _("hg status [OPTION]... [FILE]...")),
2324 _("hg status [OPTION]... [FILE]...")),
2322 "tag":
2325 "tag":
2323 (tag,
2326 (tag,
2324 [('l', 'local', None, _('make the tag local')),
2327 [('l', 'local', None, _('make the tag local')),
2325 ('m', 'message', "", _('message for tag commit log entry')),
2328 ('m', 'message', "", _('message for tag commit log entry')),
2326 ('d', 'date', "", _('record datecode as commit date')),
2329 ('d', 'date', "", _('record datecode as commit date')),
2327 ('u', 'user', "", _('record user as commiter')),
2330 ('u', 'user', "", _('record user as commiter')),
2328 ('r', 'rev', "", _('revision to tag'))],
2331 ('r', 'rev', "", _('revision to tag'))],
2329 _('hg tag [OPTION]... NAME [REV]')),
2332 _('hg tag [OPTION]... NAME [REV]')),
2330 "tags": (tags, [], _('hg tags')),
2333 "tags": (tags, [], _('hg tags')),
2331 "tip": (tip, [], _('hg tip')),
2334 "tip": (tip, [], _('hg tip')),
2332 "unbundle":
2335 "unbundle":
2333 (unbundle,
2336 (unbundle,
2334 [],
2337 [],
2335 _('hg unbundle FILE')),
2338 _('hg unbundle FILE')),
2336 "undo": (undo, [], _('hg undo')),
2339 "undo": (undo, [], _('hg undo')),
2337 "^update|up|checkout|co":
2340 "^update|up|checkout|co":
2338 (update,
2341 (update,
2339 [('b', 'branch', "", _('checkout the head of a specific branch')),
2342 [('b', 'branch', "", _('checkout the head of a specific branch')),
2340 ('m', 'merge', None, _('allow merging of branches')),
2343 ('m', 'merge', None, _('allow merging of branches')),
2341 ('C', 'clean', None, _('overwrite locally modified files'))],
2344 ('C', 'clean', None, _('overwrite locally modified files'))],
2342 _('hg update [-b TAG] [-m] [-C] [REV]')),
2345 _('hg update [-b TAG] [-m] [-C] [REV]')),
2343 "verify": (verify, [], _('hg verify')),
2346 "verify": (verify, [], _('hg verify')),
2344 "version": (show_version, [], _('hg version')),
2347 "version": (show_version, [], _('hg version')),
2345 }
2348 }
2346
2349
2347 globalopts = [
2350 globalopts = [
2348 ('R', 'repository', "", _("repository root directory")),
2351 ('R', 'repository', "", _("repository root directory")),
2349 ('', 'cwd', '', _("change working directory")),
2352 ('', 'cwd', '', _("change working directory")),
2350 ('y', 'noninteractive', None, _("do not prompt, assume 'yes' for any required answers")),
2353 ('y', 'noninteractive', None, _("do not prompt, assume 'yes' for any required answers")),
2351 ('q', 'quiet', None, _("suppress output")),
2354 ('q', 'quiet', None, _("suppress output")),
2352 ('v', 'verbose', None, _("enable additional output")),
2355 ('v', 'verbose', None, _("enable additional output")),
2353 ('', 'debug', None, _("enable debugging output")),
2356 ('', 'debug', None, _("enable debugging output")),
2354 ('', 'debugger', None, _("start debugger")),
2357 ('', 'debugger', None, _("start debugger")),
2355 ('', 'traceback', None, _("print traceback on exception")),
2358 ('', 'traceback', None, _("print traceback on exception")),
2356 ('', 'time', None, _("time how long the command takes")),
2359 ('', 'time', None, _("time how long the command takes")),
2357 ('', 'profile', None, _("print command execution profile")),
2360 ('', 'profile', None, _("print command execution profile")),
2358 ('', 'version', None, _("output version information and exit")),
2361 ('', 'version', None, _("output version information and exit")),
2359 ('h', 'help', None, _("display help and exit")),
2362 ('h', 'help', None, _("display help and exit")),
2360 ]
2363 ]
2361
2364
2362 norepo = ("clone init version help debugancestor debugconfig debugdata"
2365 norepo = ("clone init version help debugancestor debugconfig debugdata"
2363 " debugindex debugindexdot paths")
2366 " debugindex debugindexdot paths")
2364
2367
2365 def find(cmd):
2368 def find(cmd):
2366 choice = []
2369 choice = []
2367 for e in table.keys():
2370 for e in table.keys():
2368 aliases = e.lstrip("^").split("|")
2371 aliases = e.lstrip("^").split("|")
2369 if cmd in aliases:
2372 if cmd in aliases:
2370 return e, table[e]
2373 return e, table[e]
2371 for a in aliases:
2374 for a in aliases:
2372 if a.startswith(cmd):
2375 if a.startswith(cmd):
2373 choice.append(e)
2376 choice.append(e)
2374 if len(choice) == 1:
2377 if len(choice) == 1:
2375 e = choice[0]
2378 e = choice[0]
2376 return e, table[e]
2379 return e, table[e]
2377
2380
2378 raise UnknownCommand(cmd)
2381 raise UnknownCommand(cmd)
2379
2382
2380 class SignalInterrupt(Exception):
2383 class SignalInterrupt(Exception):
2381 """Exception raised on SIGTERM and SIGHUP."""
2384 """Exception raised on SIGTERM and SIGHUP."""
2382
2385
2383 def catchterm(*args):
2386 def catchterm(*args):
2384 raise SignalInterrupt
2387 raise SignalInterrupt
2385
2388
2386 def run():
2389 def run():
2387 sys.exit(dispatch(sys.argv[1:]))
2390 sys.exit(dispatch(sys.argv[1:]))
2388
2391
2389 class ParseError(Exception):
2392 class ParseError(Exception):
2390 """Exception raised on errors in parsing the command line."""
2393 """Exception raised on errors in parsing the command line."""
2391
2394
2392 def parse(ui, args):
2395 def parse(ui, args):
2393 options = {}
2396 options = {}
2394 cmdoptions = {}
2397 cmdoptions = {}
2395
2398
2396 try:
2399 try:
2397 args = fancyopts.fancyopts(args, globalopts, options)
2400 args = fancyopts.fancyopts(args, globalopts, options)
2398 except fancyopts.getopt.GetoptError, inst:
2401 except fancyopts.getopt.GetoptError, inst:
2399 raise ParseError(None, inst)
2402 raise ParseError(None, inst)
2400
2403
2401 if args:
2404 if args:
2402 cmd, args = args[0], args[1:]
2405 cmd, args = args[0], args[1:]
2403 defaults = ui.config("defaults", cmd)
2406 defaults = ui.config("defaults", cmd)
2404 if defaults:
2407 if defaults:
2405 # reparse with command defaults added
2408 # reparse with command defaults added
2406 args = [cmd] + defaults.split() + args
2409 args = [cmd] + defaults.split() + args
2407 try:
2410 try:
2408 args = fancyopts.fancyopts(args, globalopts, options)
2411 args = fancyopts.fancyopts(args, globalopts, options)
2409 except fancyopts.getopt.GetoptError, inst:
2412 except fancyopts.getopt.GetoptError, inst:
2410 raise ParseError(None, inst)
2413 raise ParseError(None, inst)
2411
2414
2412 cmd, args = args[0], args[1:]
2415 cmd, args = args[0], args[1:]
2413
2416
2414 i = find(cmd)[1]
2417 i = find(cmd)[1]
2415 c = list(i[1])
2418 c = list(i[1])
2416 else:
2419 else:
2417 cmd = None
2420 cmd = None
2418 c = []
2421 c = []
2419
2422
2420 # combine global options into local
2423 # combine global options into local
2421 for o in globalopts:
2424 for o in globalopts:
2422 c.append((o[0], o[1], options[o[1]], o[3]))
2425 c.append((o[0], o[1], options[o[1]], o[3]))
2423
2426
2424 try:
2427 try:
2425 args = fancyopts.fancyopts(args, c, cmdoptions)
2428 args = fancyopts.fancyopts(args, c, cmdoptions)
2426 except fancyopts.getopt.GetoptError, inst:
2429 except fancyopts.getopt.GetoptError, inst:
2427 raise ParseError(cmd, inst)
2430 raise ParseError(cmd, inst)
2428
2431
2429 # separate global options back out
2432 # separate global options back out
2430 for o in globalopts:
2433 for o in globalopts:
2431 n = o[1]
2434 n = o[1]
2432 options[n] = cmdoptions[n]
2435 options[n] = cmdoptions[n]
2433 del cmdoptions[n]
2436 del cmdoptions[n]
2434
2437
2435 return (cmd, cmd and i[0] or None, args, options, cmdoptions)
2438 return (cmd, cmd and i[0] or None, args, options, cmdoptions)
2436
2439
2437 def dispatch(args):
2440 def dispatch(args):
2438 signal.signal(signal.SIGTERM, catchterm)
2441 signal.signal(signal.SIGTERM, catchterm)
2439 try:
2442 try:
2440 signal.signal(signal.SIGHUP, catchterm)
2443 signal.signal(signal.SIGHUP, catchterm)
2441 except AttributeError:
2444 except AttributeError:
2442 pass
2445 pass
2443
2446
2444 try:
2447 try:
2445 u = ui.ui()
2448 u = ui.ui()
2446 except util.Abort, inst:
2449 except util.Abort, inst:
2447 sys.stderr.write(_("abort: %s\n") % inst)
2450 sys.stderr.write(_("abort: %s\n") % inst)
2448 sys.exit(1)
2451 sys.exit(1)
2449
2452
2450 external = []
2453 external = []
2451 for x in u.extensions():
2454 for x in u.extensions():
2452 def on_exception(Exception, inst):
2455 def on_exception(Exception, inst):
2453 u.warn(_("*** failed to import extension %s\n") % x[1])
2456 u.warn(_("*** failed to import extension %s\n") % x[1])
2454 u.warn("%s\n" % inst)
2457 u.warn("%s\n" % inst)
2455 if "--traceback" in sys.argv[1:]:
2458 if "--traceback" in sys.argv[1:]:
2456 traceback.print_exc()
2459 traceback.print_exc()
2457 if x[1]:
2460 if x[1]:
2458 try:
2461 try:
2459 mod = imp.load_source(x[0], x[1])
2462 mod = imp.load_source(x[0], x[1])
2460 except Exception, inst:
2463 except Exception, inst:
2461 on_exception(Exception, inst)
2464 on_exception(Exception, inst)
2462 continue
2465 continue
2463 else:
2466 else:
2464 def importh(name):
2467 def importh(name):
2465 mod = __import__(name)
2468 mod = __import__(name)
2466 components = name.split('.')
2469 components = name.split('.')
2467 for comp in components[1:]:
2470 for comp in components[1:]:
2468 mod = getattr(mod, comp)
2471 mod = getattr(mod, comp)
2469 return mod
2472 return mod
2470 try:
2473 try:
2471 mod = importh(x[0])
2474 mod = importh(x[0])
2472 except Exception, inst:
2475 except Exception, inst:
2473 on_exception(Exception, inst)
2476 on_exception(Exception, inst)
2474 continue
2477 continue
2475
2478
2476 external.append(mod)
2479 external.append(mod)
2477 for x in external:
2480 for x in external:
2478 cmdtable = getattr(x, 'cmdtable', {})
2481 cmdtable = getattr(x, 'cmdtable', {})
2479 for t in cmdtable:
2482 for t in cmdtable:
2480 if t in table:
2483 if t in table:
2481 u.warn(_("module %s overrides %s\n") % (x.__name__, t))
2484 u.warn(_("module %s overrides %s\n") % (x.__name__, t))
2482 table.update(cmdtable)
2485 table.update(cmdtable)
2483
2486
2484 try:
2487 try:
2485 cmd, func, args, options, cmdoptions = parse(u, args)
2488 cmd, func, args, options, cmdoptions = parse(u, args)
2486 except ParseError, inst:
2489 except ParseError, inst:
2487 if inst.args[0]:
2490 if inst.args[0]:
2488 u.warn(_("hg %s: %s\n") % (inst.args[0], inst.args[1]))
2491 u.warn(_("hg %s: %s\n") % (inst.args[0], inst.args[1]))
2489 help_(u, inst.args[0])
2492 help_(u, inst.args[0])
2490 else:
2493 else:
2491 u.warn(_("hg: %s\n") % inst.args[1])
2494 u.warn(_("hg: %s\n") % inst.args[1])
2492 help_(u, 'shortlist')
2495 help_(u, 'shortlist')
2493 sys.exit(-1)
2496 sys.exit(-1)
2494 except UnknownCommand, inst:
2497 except UnknownCommand, inst:
2495 u.warn(_("hg: unknown command '%s'\n") % inst.args[0])
2498 u.warn(_("hg: unknown command '%s'\n") % inst.args[0])
2496 help_(u, 'shortlist')
2499 help_(u, 'shortlist')
2497 sys.exit(1)
2500 sys.exit(1)
2498
2501
2499 if options["time"]:
2502 if options["time"]:
2500 def get_times():
2503 def get_times():
2501 t = os.times()
2504 t = os.times()
2502 if t[4] == 0.0: # Windows leaves this as zero, so use time.clock()
2505 if t[4] == 0.0: # Windows leaves this as zero, so use time.clock()
2503 t = (t[0], t[1], t[2], t[3], time.clock())
2506 t = (t[0], t[1], t[2], t[3], time.clock())
2504 return t
2507 return t
2505 s = get_times()
2508 s = get_times()
2506 def print_time():
2509 def print_time():
2507 t = get_times()
2510 t = get_times()
2508 u.warn(_("Time: real %.3f secs (user %.3f+%.3f sys %.3f+%.3f)\n") %
2511 u.warn(_("Time: real %.3f secs (user %.3f+%.3f sys %.3f+%.3f)\n") %
2509 (t[4]-s[4], t[0]-s[0], t[2]-s[2], t[1]-s[1], t[3]-s[3]))
2512 (t[4]-s[4], t[0]-s[0], t[2]-s[2], t[1]-s[1], t[3]-s[3]))
2510 atexit.register(print_time)
2513 atexit.register(print_time)
2511
2514
2512 u.updateopts(options["verbose"], options["debug"], options["quiet"],
2515 u.updateopts(options["verbose"], options["debug"], options["quiet"],
2513 not options["noninteractive"])
2516 not options["noninteractive"])
2514
2517
2515 # enter the debugger before command execution
2518 # enter the debugger before command execution
2516 if options['debugger']:
2519 if options['debugger']:
2517 pdb.set_trace()
2520 pdb.set_trace()
2518
2521
2519 try:
2522 try:
2520 try:
2523 try:
2521 if options['help']:
2524 if options['help']:
2522 help_(u, cmd, options['version'])
2525 help_(u, cmd, options['version'])
2523 sys.exit(0)
2526 sys.exit(0)
2524 elif options['version']:
2527 elif options['version']:
2525 show_version(u)
2528 show_version(u)
2526 sys.exit(0)
2529 sys.exit(0)
2527 elif not cmd:
2530 elif not cmd:
2528 help_(u, 'shortlist')
2531 help_(u, 'shortlist')
2529 sys.exit(0)
2532 sys.exit(0)
2530
2533
2531 if options['cwd']:
2534 if options['cwd']:
2532 try:
2535 try:
2533 os.chdir(options['cwd'])
2536 os.chdir(options['cwd'])
2534 except OSError, inst:
2537 except OSError, inst:
2535 raise util.Abort('%s: %s' %
2538 raise util.Abort('%s: %s' %
2536 (options['cwd'], inst.strerror))
2539 (options['cwd'], inst.strerror))
2537
2540
2538 if cmd not in norepo.split():
2541 if cmd not in norepo.split():
2539 path = options["repository"] or ""
2542 path = options["repository"] or ""
2540 repo = hg.repository(ui=u, path=path)
2543 repo = hg.repository(ui=u, path=path)
2541 for x in external:
2544 for x in external:
2542 if hasattr(x, 'reposetup'): x.reposetup(u, repo)
2545 if hasattr(x, 'reposetup'): x.reposetup(u, repo)
2543 d = lambda: func(u, repo, *args, **cmdoptions)
2546 d = lambda: func(u, repo, *args, **cmdoptions)
2544 else:
2547 else:
2545 d = lambda: func(u, *args, **cmdoptions)
2548 d = lambda: func(u, *args, **cmdoptions)
2546
2549
2547 if options['profile']:
2550 if options['profile']:
2548 import hotshot, hotshot.stats
2551 import hotshot, hotshot.stats
2549 prof = hotshot.Profile("hg.prof")
2552 prof = hotshot.Profile("hg.prof")
2550 r = prof.runcall(d)
2553 r = prof.runcall(d)
2551 prof.close()
2554 prof.close()
2552 stats = hotshot.stats.load("hg.prof")
2555 stats = hotshot.stats.load("hg.prof")
2553 stats.strip_dirs()
2556 stats.strip_dirs()
2554 stats.sort_stats('time', 'calls')
2557 stats.sort_stats('time', 'calls')
2555 stats.print_stats(40)
2558 stats.print_stats(40)
2556 return r
2559 return r
2557 else:
2560 else:
2558 return d()
2561 return d()
2559 except:
2562 except:
2560 # enter the debugger when we hit an exception
2563 # enter the debugger when we hit an exception
2561 if options['debugger']:
2564 if options['debugger']:
2562 pdb.post_mortem(sys.exc_info()[2])
2565 pdb.post_mortem(sys.exc_info()[2])
2563 if options['traceback']:
2566 if options['traceback']:
2564 traceback.print_exc()
2567 traceback.print_exc()
2565 raise
2568 raise
2566 except hg.RepoError, inst:
2569 except hg.RepoError, inst:
2567 u.warn(_("abort: "), inst, "!\n")
2570 u.warn(_("abort: "), inst, "!\n")
2568 except revlog.RevlogError, inst:
2571 except revlog.RevlogError, inst:
2569 u.warn(_("abort: "), inst, "!\n")
2572 u.warn(_("abort: "), inst, "!\n")
2570 except SignalInterrupt:
2573 except SignalInterrupt:
2571 u.warn(_("killed!\n"))
2574 u.warn(_("killed!\n"))
2572 except KeyboardInterrupt:
2575 except KeyboardInterrupt:
2573 try:
2576 try:
2574 u.warn(_("interrupted!\n"))
2577 u.warn(_("interrupted!\n"))
2575 except IOError, inst:
2578 except IOError, inst:
2576 if inst.errno == errno.EPIPE:
2579 if inst.errno == errno.EPIPE:
2577 if u.debugflag:
2580 if u.debugflag:
2578 u.warn(_("\nbroken pipe\n"))
2581 u.warn(_("\nbroken pipe\n"))
2579 else:
2582 else:
2580 raise
2583 raise
2581 except IOError, inst:
2584 except IOError, inst:
2582 if hasattr(inst, "code"):
2585 if hasattr(inst, "code"):
2583 u.warn(_("abort: %s\n") % inst)
2586 u.warn(_("abort: %s\n") % inst)
2584 elif hasattr(inst, "reason"):
2587 elif hasattr(inst, "reason"):
2585 u.warn(_("abort: error: %s\n") % inst.reason[1])
2588 u.warn(_("abort: error: %s\n") % inst.reason[1])
2586 elif hasattr(inst, "args") and inst[0] == errno.EPIPE:
2589 elif hasattr(inst, "args") and inst[0] == errno.EPIPE:
2587 if u.debugflag:
2590 if u.debugflag:
2588 u.warn(_("broken pipe\n"))
2591 u.warn(_("broken pipe\n"))
2589 elif getattr(inst, "strerror", None):
2592 elif getattr(inst, "strerror", None):
2590 if getattr(inst, "filename", None):
2593 if getattr(inst, "filename", None):
2591 u.warn(_("abort: %s - %s\n") % (inst.strerror, inst.filename))
2594 u.warn(_("abort: %s - %s\n") % (inst.strerror, inst.filename))
2592 else:
2595 else:
2593 u.warn(_("abort: %s\n") % inst.strerror)
2596 u.warn(_("abort: %s\n") % inst.strerror)
2594 else:
2597 else:
2595 raise
2598 raise
2596 except OSError, inst:
2599 except OSError, inst:
2597 if hasattr(inst, "filename"):
2600 if hasattr(inst, "filename"):
2598 u.warn(_("abort: %s: %s\n") % (inst.strerror, inst.filename))
2601 u.warn(_("abort: %s: %s\n") % (inst.strerror, inst.filename))
2599 else:
2602 else:
2600 u.warn(_("abort: %s\n") % inst.strerror)
2603 u.warn(_("abort: %s\n") % inst.strerror)
2601 except util.Abort, inst:
2604 except util.Abort, inst:
2602 u.warn(_('abort: '), inst.args[0] % inst.args[1:], '\n')
2605 u.warn(_('abort: '), inst.args[0] % inst.args[1:], '\n')
2603 sys.exit(1)
2606 sys.exit(1)
2604 except TypeError, inst:
2607 except TypeError, inst:
2605 # was this an argument error?
2608 # was this an argument error?
2606 tb = traceback.extract_tb(sys.exc_info()[2])
2609 tb = traceback.extract_tb(sys.exc_info()[2])
2607 if len(tb) > 2: # no
2610 if len(tb) > 2: # no
2608 raise
2611 raise
2609 u.debug(inst, "\n")
2612 u.debug(inst, "\n")
2610 u.warn(_("%s: invalid arguments\n") % cmd)
2613 u.warn(_("%s: invalid arguments\n") % cmd)
2611 help_(u, cmd)
2614 help_(u, cmd)
2612 except UnknownCommand, inst:
2615 except UnknownCommand, inst:
2613 u.warn(_("hg: unknown command '%s'\n") % inst.args[0])
2616 u.warn(_("hg: unknown command '%s'\n") % inst.args[0])
2614 help_(u, 'shortlist')
2617 help_(u, 'shortlist')
2615 except SystemExit:
2618 except SystemExit:
2616 # don't catch this in the catch-all below
2619 # don't catch this in the catch-all below
2617 raise
2620 raise
2618 except:
2621 except:
2619 u.warn(_("** unknown exception encountered, details follow\n"))
2622 u.warn(_("** unknown exception encountered, details follow\n"))
2620 u.warn(_("** report bug details to mercurial@selenic.com\n"))
2623 u.warn(_("** report bug details to mercurial@selenic.com\n"))
2621 raise
2624 raise
2622
2625
2623 sys.exit(-1)
2626 sys.exit(-1)
@@ -1,60 +1,78 b''
1 #!/bin/sh
1 #!/bin/sh
2
2
3 hg init
3 hg init
4 mkdir d1 d1/d11 d2
4 mkdir d1 d1/d11 d2
5 echo d1/a > d1/a
5 echo d1/a > d1/a
6 echo d1/ba > d1/ba
6 echo d1/ba > d1/ba
7 echo d1/a1 > d1/d11/a1
7 echo d1/a1 > d1/d11/a1
8 echo d1/b > d1/b
8 echo d1/b > d1/b
9 echo d2/b > d2/b
9 echo d2/b > d2/b
10 hg add d1/a d1/b d1/ba d1/d11/a1 d2/b
10 hg add d1/a d1/b d1/ba d1/d11/a1 d2/b
11 hg commit -m "1" -d "0 0"
11 hg commit -m "1" -d "0 0"
12
12
13 echo "# rename a single file"
13 echo "# rename a single file"
14 hg rename d1/d11/a1 d2/c
14 hg rename d1/d11/a1 d2/c
15 hg status
15 hg status
16 hg update -C
16 hg update -C
17
17
18 echo "# move a single file to an existing directory"
18 echo "# move a single file to an existing directory"
19 hg rename d1/d11/a1 d2
19 hg rename d1/d11/a1 d2
20 hg status
20 hg status
21 hg update -C
21 hg update -C
22
22
23 echo "# rename directory d1 as d3"
23 echo "# rename directory d1 as d3"
24 hg rename d1 d3
24 hg rename d1 d3
25 hg status
25 hg status
26 hg update -C
26 hg update -C
27
27
28 echo "# move directory d1/d11 to an existing directory d2 (removes empty d1)"
28 echo "# move directory d1/d11 to an existing directory d2 (removes empty d1)"
29 hg rename d1/d11 d2
29 hg rename d1/d11 d2
30 hg status
30 hg status
31 hg update -C
31 hg update -C
32
32
33 echo "# move directories d1 and d2 to a new directory d3"
33 echo "# move directories d1 and d2 to a new directory d3"
34 mkdir d3
34 mkdir d3
35 hg rename d1 d2 d3
35 hg rename d1 d2 d3
36 hg status
36 hg status
37 hg update -C
37 hg update -C
38
38
39 echo "# move everything under directory d1 to existing directory d2, do not"
39 echo "# move everything under directory d1 to existing directory d2, do not"
40 echo "# overwrite existing files (d2/b)"
40 echo "# overwrite existing files (d2/b)"
41 hg rename d1/* d2
41 hg rename d1/* d2
42 hg status
42 hg status
43 diff d1/b d2/b
43 diff d1/b d2/b
44 hg update -C
44 hg update -C
45
45
46 echo "# attempt to move potentially more than one file into a non-existent"
46 echo "# attempt to move potentially more than one file into a non-existent"
47 echo "# directory"
47 echo "# directory"
48 hg rename 'glob:d1/**' dx
48 hg rename 'glob:d1/**' dx
49
49
50 echo "# move every file under d1 to d2/d21 (glob)"
50 echo "# move every file under d1 to d2/d21 (glob)"
51 mkdir d2/d21
51 mkdir d2/d21
52 hg rename 'glob:d1/**' d2/d21
52 hg rename 'glob:d1/**' d2/d21
53 hg status
53 hg status
54 hg update -C
54 hg update -C
55
55
56 echo "# move every file under d1 starting with an 'a' to d2/d21 (regexp)"
56 echo "# move every file under d1 starting with an 'a' to d2/d21 (regexp)"
57 mkdir d2/d21
57 mkdir d2/d21
58 hg rename 're:d1/([^a][^/]*/)*a.*' d2/d21
58 hg rename 're:d1/([^a][^/]*/)*a.*' d2/d21
59 hg status
59 hg status
60 hg update -C
60 hg update -C
61
62 echo "# attempt to overwrite an existing file"
63 echo "ca" > d1/ca
64 hg rename d1/ba d1/ca
65 hg status
66 hg update -C
67
68 echo "# forced overwrite of an existing file"
69 echo "ca" > d1/ca
70 hg rename --force d1/ba d1/ca
71 hg status
72 hg update -C
73
74 echo "# replace a symlink with a file"
75 ln -s ba d1/ca
76 hg rename --force d1/ba d1/ca
77 hg status
78 hg update -C
@@ -1,93 +1,103 b''
1 # rename a single file
1 # rename a single file
2 A d2/c
2 A d2/c
3 R d1/d11/a1
3 R d1/d11/a1
4 # move a single file to an existing directory
4 # move a single file to an existing directory
5 A d2/a1
5 A d2/a1
6 R d1/d11/a1
6 R d1/d11/a1
7 # rename directory d1 as d3
7 # rename directory d1 as d3
8 copying d1/a to d3/a
8 copying d1/a to d3/a
9 copying d1/b to d3/b
9 copying d1/b to d3/b
10 copying d1/ba to d3/ba
10 copying d1/ba to d3/ba
11 copying d1/d11/a1 to d3/d11/a1
11 copying d1/d11/a1 to d3/d11/a1
12 removing d1/a
12 removing d1/a
13 removing d1/b
13 removing d1/b
14 removing d1/ba
14 removing d1/ba
15 removing d1/d11/a1
15 removing d1/d11/a1
16 A d3/a
16 A d3/a
17 A d3/b
17 A d3/b
18 A d3/ba
18 A d3/ba
19 A d3/d11/a1
19 A d3/d11/a1
20 R d1/a
20 R d1/a
21 R d1/b
21 R d1/b
22 R d1/ba
22 R d1/ba
23 R d1/d11/a1
23 R d1/d11/a1
24 # move directory d1/d11 to an existing directory d2 (removes empty d1)
24 # move directory d1/d11 to an existing directory d2 (removes empty d1)
25 copying d1/d11/a1 to d2/d11/a1
25 copying d1/d11/a1 to d2/d11/a1
26 removing d1/d11/a1
26 removing d1/d11/a1
27 A d2/d11/a1
27 A d2/d11/a1
28 R d1/d11/a1
28 R d1/d11/a1
29 # move directories d1 and d2 to a new directory d3
29 # move directories d1 and d2 to a new directory d3
30 copying d1/a to d3/d1/a
30 copying d1/a to d3/d1/a
31 copying d1/b to d3/d1/b
31 copying d1/b to d3/d1/b
32 copying d1/ba to d3/d1/ba
32 copying d1/ba to d3/d1/ba
33 copying d1/d11/a1 to d3/d1/d11/a1
33 copying d1/d11/a1 to d3/d1/d11/a1
34 copying d2/b to d3/d2/b
34 copying d2/b to d3/d2/b
35 removing d1/a
35 removing d1/a
36 removing d1/b
36 removing d1/b
37 removing d1/ba
37 removing d1/ba
38 removing d1/d11/a1
38 removing d1/d11/a1
39 removing d2/b
39 removing d2/b
40 A d3/d1/a
40 A d3/d1/a
41 A d3/d1/b
41 A d3/d1/b
42 A d3/d1/ba
42 A d3/d1/ba
43 A d3/d1/d11/a1
43 A d3/d1/d11/a1
44 A d3/d2/b
44 A d3/d2/b
45 R d1/a
45 R d1/a
46 R d1/b
46 R d1/b
47 R d1/ba
47 R d1/ba
48 R d1/d11/a1
48 R d1/d11/a1
49 R d2/b
49 R d2/b
50 # move everything under directory d1 to existing directory d2, do not
50 # move everything under directory d1 to existing directory d2, do not
51 # overwrite existing files (d2/b)
51 # overwrite existing files (d2/b)
52 d2/b: not overwriting - file already managed
52 d2/b: not overwriting - file exists
53 copying d1/d11/a1 to d2/d11/a1
53 copying d1/d11/a1 to d2/d11/a1
54 removing d1/d11/a1
54 removing d1/d11/a1
55 A d2/a
55 A d2/a
56 A d2/ba
56 A d2/ba
57 A d2/d11/a1
57 A d2/d11/a1
58 R d1/a
58 R d1/a
59 R d1/ba
59 R d1/ba
60 R d1/d11/a1
60 R d1/d11/a1
61 1c1
61 1c1
62 < d1/b
62 < d1/b
63 ---
63 ---
64 > d2/b
64 > d2/b
65 # attempt to move potentially more than one file into a non-existent
65 # attempt to move potentially more than one file into a non-existent
66 # directory
66 # directory
67 abort: with multiple sources, destination must be an existing directory
67 abort: with multiple sources, destination must be an existing directory
68 # move every file under d1 to d2/d21 (glob)
68 # move every file under d1 to d2/d21 (glob)
69 copying d1/a to d2/d21/a
69 copying d1/a to d2/d21/a
70 copying d1/b to d2/d21/b
70 copying d1/b to d2/d21/b
71 copying d1/ba to d2/d21/ba
71 copying d1/ba to d2/d21/ba
72 copying d1/d11/a1 to d2/d21/a1
72 copying d1/d11/a1 to d2/d21/a1
73 removing d1/a
73 removing d1/a
74 removing d1/b
74 removing d1/b
75 removing d1/ba
75 removing d1/ba
76 removing d1/d11/a1
76 removing d1/d11/a1
77 A d2/d21/a
77 A d2/d21/a
78 A d2/d21/a1
78 A d2/d21/a1
79 A d2/d21/b
79 A d2/d21/b
80 A d2/d21/ba
80 A d2/d21/ba
81 R d1/a
81 R d1/a
82 R d1/b
82 R d1/b
83 R d1/ba
83 R d1/ba
84 R d1/d11/a1
84 R d1/d11/a1
85 # move every file under d1 starting with an 'a' to d2/d21 (regexp)
85 # move every file under d1 starting with an 'a' to d2/d21 (regexp)
86 copying d1/a to d2/d21/a
86 copying d1/a to d2/d21/a
87 copying d1/d11/a1 to d2/d21/a1
87 copying d1/d11/a1 to d2/d21/a1
88 removing d1/a
88 removing d1/a
89 removing d1/d11/a1
89 removing d1/d11/a1
90 A d2/d21/a
90 A d2/d21/a
91 A d2/d21/a1
91 A d2/d21/a1
92 R d1/a
92 R d1/a
93 R d1/d11/a1
93 R d1/d11/a1
94 # attempt to overwrite an existing file
95 d1/ca: not overwriting - file exists
96 abort: no files to copy
97 ? d1/ca
98 # forced overwrite of an existing file
99 A d1/ca
100 R d1/ba
101 # replace a symlink with a file
102 A d1/ca
103 R d1/ba
General Comments 0
You need to be logged in to leave comments. Login now