##// END OF EJS Templates
avoid to copy more than one file to the same destination file
Robin Farine -
r1514:faf46d81 default
parent child Browse files
Show More
@@ -1,2626 +1,2633 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 targets = {}
793
794
794 def okaytocopy(abs, rel, exact):
795 def okaytocopy(abs, rel, exact):
795 reasons = {'?': _('is not managed'),
796 reasons = {'?': _('is not managed'),
796 'a': _('has been marked for add')}
797 'a': _('has been marked for add')}
797 reason = reasons.get(repo.dirstate.state(abs))
798 reason = reasons.get(repo.dirstate.state(abs))
798 if reason:
799 if reason:
799 if exact: ui.warn(_('%s: not copying - file %s\n') % (rel, reason))
800 if exact: ui.warn(_('%s: not copying - file %s\n') % (rel, reason))
800 else:
801 else:
801 return True
802 return True
802
803
803 def copy(abssrc, relsrc, target, exact):
804 def copy(abssrc, relsrc, target, exact):
804 abstarget = util.canonpath(repo.root, cwd, target)
805 abstarget = util.canonpath(repo.root, cwd, target)
805 reltarget = util.pathto(cwd, abstarget)
806 reltarget = util.pathto(cwd, abstarget)
806 if os.path.exists(reltarget):
807 prevsrc = targets.get(abstarget)
808 if prevsrc is not None:
809 ui.warn(_('%s: not overwriting - %s collides with %s\n') %
810 (reltarget, abssrc, prevsrc))
811 return
812 elif os.path.exists(reltarget):
807 if opts['force']:
813 if opts['force']:
808 os.unlink(reltarget)
814 os.unlink(reltarget)
809 else:
815 else:
810 ui.warn(_('%s: not overwriting - file exists\n') %
816 ui.warn(_('%s: not overwriting - file exists\n') %
811 reltarget)
817 reltarget)
812 return
818 return
813 if ui.verbose or not exact:
819 if ui.verbose or not exact:
814 ui.status(_('copying %s to %s\n') % (relsrc, reltarget))
820 ui.status(_('copying %s to %s\n') % (relsrc, reltarget))
815 if not opts['after']:
821 if not opts['after']:
816 targetdir = os.path.dirname(reltarget) or '.'
822 targetdir = os.path.dirname(reltarget) or '.'
817 if not os.path.isdir(targetdir):
823 if not os.path.isdir(targetdir):
818 os.makedirs(targetdir)
824 os.makedirs(targetdir)
819 try:
825 try:
820 shutil.copyfile(relsrc, reltarget)
826 shutil.copyfile(relsrc, reltarget)
821 shutil.copymode(relsrc, reltarget)
827 shutil.copymode(relsrc, reltarget)
822 except shutil.Error, inst:
828 except shutil.Error, inst:
823 raise util.Abort(str(inst))
829 raise util.Abort(str(inst))
824 except IOError, inst:
830 except IOError, inst:
825 if inst.errno == errno.ENOENT:
831 if inst.errno == errno.ENOENT:
826 ui.warn(_('%s: deleted in working copy\n') % relsrc)
832 ui.warn(_('%s: deleted in working copy\n') % relsrc)
827 else:
833 else:
828 ui.warn(_('%s: cannot copy - %s\n') %
834 ui.warn(_('%s: cannot copy - %s\n') %
829 (relsrc, inst.strerror))
835 (relsrc, inst.strerror))
830 errors += 1
836 errors += 1
831 return
837 return
838 targets[abstarget] = abssrc
832 repo.copy(abssrc, abstarget)
839 repo.copy(abssrc, abstarget)
833 copied.append((abssrc, relsrc, exact))
840 copied.append((abssrc, relsrc, exact))
834
841
835 pats = list(pats)
842 pats = list(pats)
836 if not pats:
843 if not pats:
837 raise util.Abort(_('no source or destination specified'))
844 raise util.Abort(_('no source or destination specified'))
838 if len(pats) == 1:
845 if len(pats) == 1:
839 raise util.Abort(_('no destination specified'))
846 raise util.Abort(_('no destination specified'))
840 dest = pats.pop()
847 dest = pats.pop()
841 destdirexists = os.path.isdir(dest)
848 destdirexists = os.path.isdir(dest)
842 if (len(pats) > 1 or not os.path.exists(pats[0])) and not destdirexists:
849 if (len(pats) > 1 or not os.path.exists(pats[0])) and not destdirexists:
843 raise util.Abort(_('with multiple sources, destination must be an '
850 raise util.Abort(_('with multiple sources, destination must be an '
844 'existing directory'))
851 'existing directory'))
845
852
846 for pat in pats:
853 for pat in pats:
847 if os.path.isdir(pat):
854 if os.path.isdir(pat):
848 if destdirexists:
855 if destdirexists:
849 striplen = len(os.path.split(pat)[0])
856 striplen = len(os.path.split(pat)[0])
850 else:
857 else:
851 striplen = len(pat)
858 striplen = len(pat)
852 if striplen:
859 if striplen:
853 striplen += len(os.sep)
860 striplen += len(os.sep)
854 targetpath = lambda p: os.path.join(dest, p[striplen:])
861 targetpath = lambda p: os.path.join(dest, p[striplen:])
855 elif destdirexists:
862 elif destdirexists:
856 targetpath = lambda p: os.path.join(dest, os.path.basename(p))
863 targetpath = lambda p: os.path.join(dest, os.path.basename(p))
857 else:
864 else:
858 targetpath = lambda p: dest
865 targetpath = lambda p: dest
859 for tag, abssrc, relsrc, exact in walk(repo, [pat], opts):
866 for tag, abssrc, relsrc, exact in walk(repo, [pat], opts):
860 if okaytocopy(abssrc, relsrc, exact):
867 if okaytocopy(abssrc, relsrc, exact):
861 copy(abssrc, relsrc, targetpath(abssrc), exact)
868 copy(abssrc, relsrc, targetpath(abssrc), exact)
862
869
863 if errors:
870 if errors:
864 ui.warn(_('(consider using --after)\n'))
871 ui.warn(_('(consider using --after)\n'))
865 if len(copied) == 0:
872 if len(copied) == 0:
866 raise util.Abort(_('no files to copy'))
873 raise util.Abort(_('no files to copy'))
867 return errors, copied
874 return errors, copied
868
875
869 def copy(ui, repo, *pats, **opts):
876 def copy(ui, repo, *pats, **opts):
870 """mark files as copied for the next commit
877 """mark files as copied for the next commit
871
878
872 Mark dest as having copies of source files. If dest is a
879 Mark dest as having copies of source files. If dest is a
873 directory, copies are put in that directory. If dest is a file,
880 directory, copies are put in that directory. If dest is a file,
874 there can only be one source.
881 there can only be one source.
875
882
876 By default, this command copies the contents of files as they
883 By default, this command copies the contents of files as they
877 stand in the working directory. If invoked with --after, the
884 stand in the working directory. If invoked with --after, the
878 operation is recorded, but no copying is performed.
885 operation is recorded, but no copying is performed.
879
886
880 This command takes effect in the next commit.
887 This command takes effect in the next commit.
881
888
882 NOTE: This command should be treated as experimental. While it
889 NOTE: This command should be treated as experimental. While it
883 should properly record copied files, this information is not yet
890 should properly record copied files, this information is not yet
884 fully used by merge, nor fully reported by log.
891 fully used by merge, nor fully reported by log.
885 """
892 """
886 errs, copied = docopy(ui, repo, pats, opts)
893 errs, copied = docopy(ui, repo, pats, opts)
887 return errs
894 return errs
888
895
889 def debugancestor(ui, index, rev1, rev2):
896 def debugancestor(ui, index, rev1, rev2):
890 """find the ancestor revision of two revisions in a given index"""
897 """find the ancestor revision of two revisions in a given index"""
891 r = revlog.revlog(util.opener(os.getcwd()), index, "")
898 r = revlog.revlog(util.opener(os.getcwd()), index, "")
892 a = r.ancestor(r.lookup(rev1), r.lookup(rev2))
899 a = r.ancestor(r.lookup(rev1), r.lookup(rev2))
893 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
900 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
894
901
895 def debugcheckstate(ui, repo):
902 def debugcheckstate(ui, repo):
896 """validate the correctness of the current dirstate"""
903 """validate the correctness of the current dirstate"""
897 parent1, parent2 = repo.dirstate.parents()
904 parent1, parent2 = repo.dirstate.parents()
898 repo.dirstate.read()
905 repo.dirstate.read()
899 dc = repo.dirstate.map
906 dc = repo.dirstate.map
900 keys = dc.keys()
907 keys = dc.keys()
901 keys.sort()
908 keys.sort()
902 m1n = repo.changelog.read(parent1)[0]
909 m1n = repo.changelog.read(parent1)[0]
903 m2n = repo.changelog.read(parent2)[0]
910 m2n = repo.changelog.read(parent2)[0]
904 m1 = repo.manifest.read(m1n)
911 m1 = repo.manifest.read(m1n)
905 m2 = repo.manifest.read(m2n)
912 m2 = repo.manifest.read(m2n)
906 errors = 0
913 errors = 0
907 for f in dc:
914 for f in dc:
908 state = repo.dirstate.state(f)
915 state = repo.dirstate.state(f)
909 if state in "nr" and f not in m1:
916 if state in "nr" and f not in m1:
910 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
917 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
911 errors += 1
918 errors += 1
912 if state in "a" and f in m1:
919 if state in "a" and f in m1:
913 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
920 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
914 errors += 1
921 errors += 1
915 if state in "m" and f not in m1 and f not in m2:
922 if state in "m" and f not in m1 and f not in m2:
916 ui.warn(_("%s in state %s, but not in either manifest\n") %
923 ui.warn(_("%s in state %s, but not in either manifest\n") %
917 (f, state))
924 (f, state))
918 errors += 1
925 errors += 1
919 for f in m1:
926 for f in m1:
920 state = repo.dirstate.state(f)
927 state = repo.dirstate.state(f)
921 if state not in "nrm":
928 if state not in "nrm":
922 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
929 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
923 errors += 1
930 errors += 1
924 if errors:
931 if errors:
925 raise util.Abort(_(".hg/dirstate inconsistent with current parent's manifest"))
932 raise util.Abort(_(".hg/dirstate inconsistent with current parent's manifest"))
926
933
927 def debugconfig(ui):
934 def debugconfig(ui):
928 """show combined config settings from all hgrc files"""
935 """show combined config settings from all hgrc files"""
929 try:
936 try:
930 repo = hg.repository(ui)
937 repo = hg.repository(ui)
931 except hg.RepoError:
938 except hg.RepoError:
932 pass
939 pass
933 for section, name, value in ui.walkconfig():
940 for section, name, value in ui.walkconfig():
934 ui.write('%s.%s=%s\n' % (section, name, value))
941 ui.write('%s.%s=%s\n' % (section, name, value))
935
942
936 def debugsetparents(ui, repo, rev1, rev2=None):
943 def debugsetparents(ui, repo, rev1, rev2=None):
937 """manually set the parents of the current working directory
944 """manually set the parents of the current working directory
938
945
939 This is useful for writing repository conversion tools, but should
946 This is useful for writing repository conversion tools, but should
940 be used with care.
947 be used with care.
941 """
948 """
942
949
943 if not rev2:
950 if not rev2:
944 rev2 = hex(nullid)
951 rev2 = hex(nullid)
945
952
946 repo.dirstate.setparents(repo.lookup(rev1), repo.lookup(rev2))
953 repo.dirstate.setparents(repo.lookup(rev1), repo.lookup(rev2))
947
954
948 def debugstate(ui, repo):
955 def debugstate(ui, repo):
949 """show the contents of the current dirstate"""
956 """show the contents of the current dirstate"""
950 repo.dirstate.read()
957 repo.dirstate.read()
951 dc = repo.dirstate.map
958 dc = repo.dirstate.map
952 keys = dc.keys()
959 keys = dc.keys()
953 keys.sort()
960 keys.sort()
954 for file_ in keys:
961 for file_ in keys:
955 ui.write("%c %3o %10d %s %s\n"
962 ui.write("%c %3o %10d %s %s\n"
956 % (dc[file_][0], dc[file_][1] & 0777, dc[file_][2],
963 % (dc[file_][0], dc[file_][1] & 0777, dc[file_][2],
957 time.strftime("%x %X",
964 time.strftime("%x %X",
958 time.localtime(dc[file_][3])), file_))
965 time.localtime(dc[file_][3])), file_))
959 for f in repo.dirstate.copies:
966 for f in repo.dirstate.copies:
960 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copies[f], f))
967 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copies[f], f))
961
968
962 def debugdata(ui, file_, rev):
969 def debugdata(ui, file_, rev):
963 """dump the contents of an data file revision"""
970 """dump the contents of an data file revision"""
964 r = revlog.revlog(util.opener(os.getcwd()), file_[:-2] + ".i", file_)
971 r = revlog.revlog(util.opener(os.getcwd()), file_[:-2] + ".i", file_)
965 try:
972 try:
966 ui.write(r.revision(r.lookup(rev)))
973 ui.write(r.revision(r.lookup(rev)))
967 except KeyError:
974 except KeyError:
968 raise util.Abort(_('invalid revision identifier %s'), rev)
975 raise util.Abort(_('invalid revision identifier %s'), rev)
969
976
970 def debugindex(ui, file_):
977 def debugindex(ui, file_):
971 """dump the contents of an index file"""
978 """dump the contents of an index file"""
972 r = revlog.revlog(util.opener(os.getcwd()), file_, "")
979 r = revlog.revlog(util.opener(os.getcwd()), file_, "")
973 ui.write(" rev offset length base linkrev" +
980 ui.write(" rev offset length base linkrev" +
974 " nodeid p1 p2\n")
981 " nodeid p1 p2\n")
975 for i in range(r.count()):
982 for i in range(r.count()):
976 e = r.index[i]
983 e = r.index[i]
977 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
984 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
978 i, e[0], e[1], e[2], e[3],
985 i, e[0], e[1], e[2], e[3],
979 short(e[6]), short(e[4]), short(e[5])))
986 short(e[6]), short(e[4]), short(e[5])))
980
987
981 def debugindexdot(ui, file_):
988 def debugindexdot(ui, file_):
982 """dump an index DAG as a .dot file"""
989 """dump an index DAG as a .dot file"""
983 r = revlog.revlog(util.opener(os.getcwd()), file_, "")
990 r = revlog.revlog(util.opener(os.getcwd()), file_, "")
984 ui.write("digraph G {\n")
991 ui.write("digraph G {\n")
985 for i in range(r.count()):
992 for i in range(r.count()):
986 e = r.index[i]
993 e = r.index[i]
987 ui.write("\t%d -> %d\n" % (r.rev(e[4]), i))
994 ui.write("\t%d -> %d\n" % (r.rev(e[4]), i))
988 if e[5] != nullid:
995 if e[5] != nullid:
989 ui.write("\t%d -> %d\n" % (r.rev(e[5]), i))
996 ui.write("\t%d -> %d\n" % (r.rev(e[5]), i))
990 ui.write("}\n")
997 ui.write("}\n")
991
998
992 def debugrename(ui, repo, file, rev=None):
999 def debugrename(ui, repo, file, rev=None):
993 """dump rename information"""
1000 """dump rename information"""
994 r = repo.file(relpath(repo, [file])[0])
1001 r = repo.file(relpath(repo, [file])[0])
995 if rev:
1002 if rev:
996 try:
1003 try:
997 # assume all revision numbers are for changesets
1004 # assume all revision numbers are for changesets
998 n = repo.lookup(rev)
1005 n = repo.lookup(rev)
999 change = repo.changelog.read(n)
1006 change = repo.changelog.read(n)
1000 m = repo.manifest.read(change[0])
1007 m = repo.manifest.read(change[0])
1001 n = m[relpath(repo, [file])[0]]
1008 n = m[relpath(repo, [file])[0]]
1002 except hg.RepoError, KeyError:
1009 except hg.RepoError, KeyError:
1003 n = r.lookup(rev)
1010 n = r.lookup(rev)
1004 else:
1011 else:
1005 n = r.tip()
1012 n = r.tip()
1006 m = r.renamed(n)
1013 m = r.renamed(n)
1007 if m:
1014 if m:
1008 ui.write(_("renamed from %s:%s\n") % (m[0], hex(m[1])))
1015 ui.write(_("renamed from %s:%s\n") % (m[0], hex(m[1])))
1009 else:
1016 else:
1010 ui.write(_("not renamed\n"))
1017 ui.write(_("not renamed\n"))
1011
1018
1012 def debugwalk(ui, repo, *pats, **opts):
1019 def debugwalk(ui, repo, *pats, **opts):
1013 """show how files match on given patterns"""
1020 """show how files match on given patterns"""
1014 items = list(walk(repo, pats, opts))
1021 items = list(walk(repo, pats, opts))
1015 if not items:
1022 if not items:
1016 return
1023 return
1017 fmt = '%%s %%-%ds %%-%ds %%s' % (
1024 fmt = '%%s %%-%ds %%-%ds %%s' % (
1018 max([len(abs) for (src, abs, rel, exact) in items]),
1025 max([len(abs) for (src, abs, rel, exact) in items]),
1019 max([len(rel) for (src, abs, rel, exact) in items]))
1026 max([len(rel) for (src, abs, rel, exact) in items]))
1020 for src, abs, rel, exact in items:
1027 for src, abs, rel, exact in items:
1021 line = fmt % (src, abs, rel, exact and 'exact' or '')
1028 line = fmt % (src, abs, rel, exact and 'exact' or '')
1022 ui.write("%s\n" % line.rstrip())
1029 ui.write("%s\n" % line.rstrip())
1023
1030
1024 def diff(ui, repo, *pats, **opts):
1031 def diff(ui, repo, *pats, **opts):
1025 """diff working directory (or selected files)
1032 """diff working directory (or selected files)
1026
1033
1027 Show differences between revisions for the specified files.
1034 Show differences between revisions for the specified files.
1028
1035
1029 Differences between files are shown using the unified diff format.
1036 Differences between files are shown using the unified diff format.
1030
1037
1031 When two revision arguments are given, then changes are shown
1038 When two revision arguments are given, then changes are shown
1032 between those revisions. If only one revision is specified then
1039 between those revisions. If only one revision is specified then
1033 that revision is compared to the working directory, and, when no
1040 that revision is compared to the working directory, and, when no
1034 revisions are specified, the working directory files are compared
1041 revisions are specified, the working directory files are compared
1035 to its parent.
1042 to its parent.
1036
1043
1037 Without the -a option, diff will avoid generating diffs of files
1044 Without the -a option, diff will avoid generating diffs of files
1038 it detects as binary. With -a, diff will generate a diff anyway,
1045 it detects as binary. With -a, diff will generate a diff anyway,
1039 probably with undesirable results.
1046 probably with undesirable results.
1040 """
1047 """
1041 node1, node2 = None, None
1048 node1, node2 = None, None
1042 revs = [repo.lookup(x) for x in opts['rev']]
1049 revs = [repo.lookup(x) for x in opts['rev']]
1043
1050
1044 if len(revs) > 0:
1051 if len(revs) > 0:
1045 node1 = revs[0]
1052 node1 = revs[0]
1046 if len(revs) > 1:
1053 if len(revs) > 1:
1047 node2 = revs[1]
1054 node2 = revs[1]
1048 if len(revs) > 2:
1055 if len(revs) > 2:
1049 raise util.Abort(_("too many revisions to diff"))
1056 raise util.Abort(_("too many revisions to diff"))
1050
1057
1051 fns, matchfn, anypats = matchpats(repo, repo.getcwd(), pats, opts)
1058 fns, matchfn, anypats = matchpats(repo, repo.getcwd(), pats, opts)
1052
1059
1053 dodiff(sys.stdout, ui, repo, node1, node2, fns, match=matchfn,
1060 dodiff(sys.stdout, ui, repo, node1, node2, fns, match=matchfn,
1054 text=opts['text'])
1061 text=opts['text'])
1055
1062
1056 def doexport(ui, repo, changeset, seqno, total, revwidth, opts):
1063 def doexport(ui, repo, changeset, seqno, total, revwidth, opts):
1057 node = repo.lookup(changeset)
1064 node = repo.lookup(changeset)
1058 prev, other = repo.changelog.parents(node)
1065 prev, other = repo.changelog.parents(node)
1059 change = repo.changelog.read(node)
1066 change = repo.changelog.read(node)
1060
1067
1061 fp = make_file(repo, repo.changelog, opts['output'],
1068 fp = make_file(repo, repo.changelog, opts['output'],
1062 node=node, total=total, seqno=seqno,
1069 node=node, total=total, seqno=seqno,
1063 revwidth=revwidth)
1070 revwidth=revwidth)
1064 if fp != sys.stdout:
1071 if fp != sys.stdout:
1065 ui.note("%s\n" % fp.name)
1072 ui.note("%s\n" % fp.name)
1066
1073
1067 fp.write("# HG changeset patch\n")
1074 fp.write("# HG changeset patch\n")
1068 fp.write("# User %s\n" % change[1])
1075 fp.write("# User %s\n" % change[1])
1069 fp.write("# Node ID %s\n" % hex(node))
1076 fp.write("# Node ID %s\n" % hex(node))
1070 fp.write("# Parent %s\n" % hex(prev))
1077 fp.write("# Parent %s\n" % hex(prev))
1071 if other != nullid:
1078 if other != nullid:
1072 fp.write("# Parent %s\n" % hex(other))
1079 fp.write("# Parent %s\n" % hex(other))
1073 fp.write(change[4].rstrip())
1080 fp.write(change[4].rstrip())
1074 fp.write("\n\n")
1081 fp.write("\n\n")
1075
1082
1076 dodiff(fp, ui, repo, prev, node, text=opts['text'])
1083 dodiff(fp, ui, repo, prev, node, text=opts['text'])
1077 if fp != sys.stdout:
1084 if fp != sys.stdout:
1078 fp.close()
1085 fp.close()
1079
1086
1080 def export(ui, repo, *changesets, **opts):
1087 def export(ui, repo, *changesets, **opts):
1081 """dump the header and diffs for one or more changesets
1088 """dump the header and diffs for one or more changesets
1082
1089
1083 Print the changeset header and diffs for one or more revisions.
1090 Print the changeset header and diffs for one or more revisions.
1084
1091
1085 The information shown in the changeset header is: author,
1092 The information shown in the changeset header is: author,
1086 changeset hash, parent and commit comment.
1093 changeset hash, parent and commit comment.
1087
1094
1088 Output may be to a file, in which case the name of the file is
1095 Output may be to a file, in which case the name of the file is
1089 given using a format string. The formatting rules are as follows:
1096 given using a format string. The formatting rules are as follows:
1090
1097
1091 %% literal "%" character
1098 %% literal "%" character
1092 %H changeset hash (40 bytes of hexadecimal)
1099 %H changeset hash (40 bytes of hexadecimal)
1093 %N number of patches being generated
1100 %N number of patches being generated
1094 %R changeset revision number
1101 %R changeset revision number
1095 %b basename of the exporting repository
1102 %b basename of the exporting repository
1096 %h short-form changeset hash (12 bytes of hexadecimal)
1103 %h short-form changeset hash (12 bytes of hexadecimal)
1097 %n zero-padded sequence number, starting at 1
1104 %n zero-padded sequence number, starting at 1
1098 %r zero-padded changeset revision number
1105 %r zero-padded changeset revision number
1099
1106
1100 Without the -a option, export will avoid generating diffs of files
1107 Without the -a option, export will avoid generating diffs of files
1101 it detects as binary. With -a, export will generate a diff anyway,
1108 it detects as binary. With -a, export will generate a diff anyway,
1102 probably with undesirable results.
1109 probably with undesirable results.
1103 """
1110 """
1104 if not changesets:
1111 if not changesets:
1105 raise util.Abort(_("export requires at least one changeset"))
1112 raise util.Abort(_("export requires at least one changeset"))
1106 seqno = 0
1113 seqno = 0
1107 revs = list(revrange(ui, repo, changesets))
1114 revs = list(revrange(ui, repo, changesets))
1108 total = len(revs)
1115 total = len(revs)
1109 revwidth = max(map(len, revs))
1116 revwidth = max(map(len, revs))
1110 ui.note(len(revs) > 1 and _("Exporting patches:\n") or _("Exporting patch:\n"))
1117 ui.note(len(revs) > 1 and _("Exporting patches:\n") or _("Exporting patch:\n"))
1111 for cset in revs:
1118 for cset in revs:
1112 seqno += 1
1119 seqno += 1
1113 doexport(ui, repo, cset, seqno, total, revwidth, opts)
1120 doexport(ui, repo, cset, seqno, total, revwidth, opts)
1114
1121
1115 def forget(ui, repo, *pats, **opts):
1122 def forget(ui, repo, *pats, **opts):
1116 """don't add the specified files on the next commit
1123 """don't add the specified files on the next commit
1117
1124
1118 Undo an 'hg add' scheduled for the next commit.
1125 Undo an 'hg add' scheduled for the next commit.
1119 """
1126 """
1120 forget = []
1127 forget = []
1121 for src, abs, rel, exact in walk(repo, pats, opts):
1128 for src, abs, rel, exact in walk(repo, pats, opts):
1122 if repo.dirstate.state(abs) == 'a':
1129 if repo.dirstate.state(abs) == 'a':
1123 forget.append(abs)
1130 forget.append(abs)
1124 if ui.verbose or not exact:
1131 if ui.verbose or not exact:
1125 ui.status(_('forgetting %s\n') % rel)
1132 ui.status(_('forgetting %s\n') % rel)
1126 repo.forget(forget)
1133 repo.forget(forget)
1127
1134
1128 def grep(ui, repo, pattern, *pats, **opts):
1135 def grep(ui, repo, pattern, *pats, **opts):
1129 """search for a pattern in specified files and revisions
1136 """search for a pattern in specified files and revisions
1130
1137
1131 Search revisions of files for a regular expression.
1138 Search revisions of files for a regular expression.
1132
1139
1133 This command behaves differently than Unix grep. It only accepts
1140 This command behaves differently than Unix grep. It only accepts
1134 Python/Perl regexps. It searches repository history, not the
1141 Python/Perl regexps. It searches repository history, not the
1135 working directory. It always prints the revision number in which
1142 working directory. It always prints the revision number in which
1136 a match appears.
1143 a match appears.
1137
1144
1138 By default, grep only prints output for the first revision of a
1145 By default, grep only prints output for the first revision of a
1139 file in which it finds a match. To get it to print every revision
1146 file in which it finds a match. To get it to print every revision
1140 that contains a change in match status ("-" for a match that
1147 that contains a change in match status ("-" for a match that
1141 becomes a non-match, or "+" for a non-match that becomes a match),
1148 becomes a non-match, or "+" for a non-match that becomes a match),
1142 use the --all flag.
1149 use the --all flag.
1143 """
1150 """
1144 reflags = 0
1151 reflags = 0
1145 if opts['ignore_case']:
1152 if opts['ignore_case']:
1146 reflags |= re.I
1153 reflags |= re.I
1147 regexp = re.compile(pattern, reflags)
1154 regexp = re.compile(pattern, reflags)
1148 sep, eol = ':', '\n'
1155 sep, eol = ':', '\n'
1149 if opts['print0']:
1156 if opts['print0']:
1150 sep = eol = '\0'
1157 sep = eol = '\0'
1151
1158
1152 fcache = {}
1159 fcache = {}
1153 def getfile(fn):
1160 def getfile(fn):
1154 if fn not in fcache:
1161 if fn not in fcache:
1155 fcache[fn] = repo.file(fn)
1162 fcache[fn] = repo.file(fn)
1156 return fcache[fn]
1163 return fcache[fn]
1157
1164
1158 def matchlines(body):
1165 def matchlines(body):
1159 begin = 0
1166 begin = 0
1160 linenum = 0
1167 linenum = 0
1161 while True:
1168 while True:
1162 match = regexp.search(body, begin)
1169 match = regexp.search(body, begin)
1163 if not match:
1170 if not match:
1164 break
1171 break
1165 mstart, mend = match.span()
1172 mstart, mend = match.span()
1166 linenum += body.count('\n', begin, mstart) + 1
1173 linenum += body.count('\n', begin, mstart) + 1
1167 lstart = body.rfind('\n', begin, mstart) + 1 or begin
1174 lstart = body.rfind('\n', begin, mstart) + 1 or begin
1168 lend = body.find('\n', mend)
1175 lend = body.find('\n', mend)
1169 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
1176 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
1170 begin = lend + 1
1177 begin = lend + 1
1171
1178
1172 class linestate:
1179 class linestate:
1173 def __init__(self, line, linenum, colstart, colend):
1180 def __init__(self, line, linenum, colstart, colend):
1174 self.line = line
1181 self.line = line
1175 self.linenum = linenum
1182 self.linenum = linenum
1176 self.colstart = colstart
1183 self.colstart = colstart
1177 self.colend = colend
1184 self.colend = colend
1178 def __eq__(self, other):
1185 def __eq__(self, other):
1179 return self.line == other.line
1186 return self.line == other.line
1180 def __hash__(self):
1187 def __hash__(self):
1181 return hash(self.line)
1188 return hash(self.line)
1182
1189
1183 matches = {}
1190 matches = {}
1184 def grepbody(fn, rev, body):
1191 def grepbody(fn, rev, body):
1185 matches[rev].setdefault(fn, {})
1192 matches[rev].setdefault(fn, {})
1186 m = matches[rev][fn]
1193 m = matches[rev][fn]
1187 for lnum, cstart, cend, line in matchlines(body):
1194 for lnum, cstart, cend, line in matchlines(body):
1188 s = linestate(line, lnum, cstart, cend)
1195 s = linestate(line, lnum, cstart, cend)
1189 m[s] = s
1196 m[s] = s
1190
1197
1191 prev = {}
1198 prev = {}
1192 ucache = {}
1199 ucache = {}
1193 def display(fn, rev, states, prevstates):
1200 def display(fn, rev, states, prevstates):
1194 diff = list(sets.Set(states).symmetric_difference(sets.Set(prevstates)))
1201 diff = list(sets.Set(states).symmetric_difference(sets.Set(prevstates)))
1195 diff.sort(lambda x, y: cmp(x.linenum, y.linenum))
1202 diff.sort(lambda x, y: cmp(x.linenum, y.linenum))
1196 counts = {'-': 0, '+': 0}
1203 counts = {'-': 0, '+': 0}
1197 filerevmatches = {}
1204 filerevmatches = {}
1198 for l in diff:
1205 for l in diff:
1199 if incrementing or not opts['all']:
1206 if incrementing or not opts['all']:
1200 change = ((l in prevstates) and '-') or '+'
1207 change = ((l in prevstates) and '-') or '+'
1201 r = rev
1208 r = rev
1202 else:
1209 else:
1203 change = ((l in states) and '-') or '+'
1210 change = ((l in states) and '-') or '+'
1204 r = prev[fn]
1211 r = prev[fn]
1205 cols = [fn, str(rev)]
1212 cols = [fn, str(rev)]
1206 if opts['line_number']: cols.append(str(l.linenum))
1213 if opts['line_number']: cols.append(str(l.linenum))
1207 if opts['all']: cols.append(change)
1214 if opts['all']: cols.append(change)
1208 if opts['user']: cols.append(trimuser(ui, getchange(rev)[1], rev,
1215 if opts['user']: cols.append(trimuser(ui, getchange(rev)[1], rev,
1209 ucache))
1216 ucache))
1210 if opts['files_with_matches']:
1217 if opts['files_with_matches']:
1211 c = (fn, rev)
1218 c = (fn, rev)
1212 if c in filerevmatches: continue
1219 if c in filerevmatches: continue
1213 filerevmatches[c] = 1
1220 filerevmatches[c] = 1
1214 else:
1221 else:
1215 cols.append(l.line)
1222 cols.append(l.line)
1216 ui.write(sep.join(cols), eol)
1223 ui.write(sep.join(cols), eol)
1217 counts[change] += 1
1224 counts[change] += 1
1218 return counts['+'], counts['-']
1225 return counts['+'], counts['-']
1219
1226
1220 fstate = {}
1227 fstate = {}
1221 skip = {}
1228 skip = {}
1222 changeiter, getchange = walkchangerevs(ui, repo, repo.getcwd(), pats, opts)
1229 changeiter, getchange = walkchangerevs(ui, repo, repo.getcwd(), pats, opts)
1223 count = 0
1230 count = 0
1224 incrementing = False
1231 incrementing = False
1225 for st, rev, fns in changeiter:
1232 for st, rev, fns in changeiter:
1226 if st == 'window':
1233 if st == 'window':
1227 incrementing = rev
1234 incrementing = rev
1228 matches.clear()
1235 matches.clear()
1229 elif st == 'add':
1236 elif st == 'add':
1230 change = repo.changelog.read(repo.lookup(str(rev)))
1237 change = repo.changelog.read(repo.lookup(str(rev)))
1231 mf = repo.manifest.read(change[0])
1238 mf = repo.manifest.read(change[0])
1232 matches[rev] = {}
1239 matches[rev] = {}
1233 for fn in fns:
1240 for fn in fns:
1234 if fn in skip: continue
1241 if fn in skip: continue
1235 fstate.setdefault(fn, {})
1242 fstate.setdefault(fn, {})
1236 try:
1243 try:
1237 grepbody(fn, rev, getfile(fn).read(mf[fn]))
1244 grepbody(fn, rev, getfile(fn).read(mf[fn]))
1238 except KeyError:
1245 except KeyError:
1239 pass
1246 pass
1240 elif st == 'iter':
1247 elif st == 'iter':
1241 states = matches[rev].items()
1248 states = matches[rev].items()
1242 states.sort()
1249 states.sort()
1243 for fn, m in states:
1250 for fn, m in states:
1244 if fn in skip: continue
1251 if fn in skip: continue
1245 if incrementing or not opts['all'] or fstate[fn]:
1252 if incrementing or not opts['all'] or fstate[fn]:
1246 pos, neg = display(fn, rev, m, fstate[fn])
1253 pos, neg = display(fn, rev, m, fstate[fn])
1247 count += pos + neg
1254 count += pos + neg
1248 if pos and not opts['all']:
1255 if pos and not opts['all']:
1249 skip[fn] = True
1256 skip[fn] = True
1250 fstate[fn] = m
1257 fstate[fn] = m
1251 prev[fn] = rev
1258 prev[fn] = rev
1252
1259
1253 if not incrementing:
1260 if not incrementing:
1254 fstate = fstate.items()
1261 fstate = fstate.items()
1255 fstate.sort()
1262 fstate.sort()
1256 for fn, state in fstate:
1263 for fn, state in fstate:
1257 if fn in skip: continue
1264 if fn in skip: continue
1258 display(fn, rev, {}, state)
1265 display(fn, rev, {}, state)
1259 return (count == 0 and 1) or 0
1266 return (count == 0 and 1) or 0
1260
1267
1261 def heads(ui, repo, **opts):
1268 def heads(ui, repo, **opts):
1262 """show current repository heads
1269 """show current repository heads
1263
1270
1264 Show all repository head changesets.
1271 Show all repository head changesets.
1265
1272
1266 Repository "heads" are changesets that don't have children
1273 Repository "heads" are changesets that don't have children
1267 changesets. They are where development generally takes place and
1274 changesets. They are where development generally takes place and
1268 are the usual targets for update and merge operations.
1275 are the usual targets for update and merge operations.
1269 """
1276 """
1270 heads = repo.changelog.heads()
1277 heads = repo.changelog.heads()
1271 br = None
1278 br = None
1272 if opts['branches']:
1279 if opts['branches']:
1273 br = repo.branchlookup(heads)
1280 br = repo.branchlookup(heads)
1274 for n in repo.changelog.heads():
1281 for n in repo.changelog.heads():
1275 show_changeset(ui, repo, changenode=n, brinfo=br)
1282 show_changeset(ui, repo, changenode=n, brinfo=br)
1276
1283
1277 def identify(ui, repo):
1284 def identify(ui, repo):
1278 """print information about the working copy
1285 """print information about the working copy
1279
1286
1280 Print a short summary of the current state of the repo.
1287 Print a short summary of the current state of the repo.
1281
1288
1282 This summary identifies the repository state using one or two parent
1289 This summary identifies the repository state using one or two parent
1283 hash identifiers, followed by a "+" if there are uncommitted changes
1290 hash identifiers, followed by a "+" if there are uncommitted changes
1284 in the working directory, followed by a list of tags for this revision.
1291 in the working directory, followed by a list of tags for this revision.
1285 """
1292 """
1286 parents = [p for p in repo.dirstate.parents() if p != nullid]
1293 parents = [p for p in repo.dirstate.parents() if p != nullid]
1287 if not parents:
1294 if not parents:
1288 ui.write(_("unknown\n"))
1295 ui.write(_("unknown\n"))
1289 return
1296 return
1290
1297
1291 hexfunc = ui.verbose and hex or short
1298 hexfunc = ui.verbose and hex or short
1292 (c, a, d, u) = repo.changes()
1299 (c, a, d, u) = repo.changes()
1293 output = ["%s%s" % ('+'.join([hexfunc(parent) for parent in parents]),
1300 output = ["%s%s" % ('+'.join([hexfunc(parent) for parent in parents]),
1294 (c or a or d) and "+" or "")]
1301 (c or a or d) and "+" or "")]
1295
1302
1296 if not ui.quiet:
1303 if not ui.quiet:
1297 # multiple tags for a single parent separated by '/'
1304 # multiple tags for a single parent separated by '/'
1298 parenttags = ['/'.join(tags)
1305 parenttags = ['/'.join(tags)
1299 for tags in map(repo.nodetags, parents) if tags]
1306 for tags in map(repo.nodetags, parents) if tags]
1300 # tags for multiple parents separated by ' + '
1307 # tags for multiple parents separated by ' + '
1301 if parenttags:
1308 if parenttags:
1302 output.append(' + '.join(parenttags))
1309 output.append(' + '.join(parenttags))
1303
1310
1304 ui.write("%s\n" % ' '.join(output))
1311 ui.write("%s\n" % ' '.join(output))
1305
1312
1306 def import_(ui, repo, patch1, *patches, **opts):
1313 def import_(ui, repo, patch1, *patches, **opts):
1307 """import an ordered set of patches
1314 """import an ordered set of patches
1308
1315
1309 Import a list of patches and commit them individually.
1316 Import a list of patches and commit them individually.
1310
1317
1311 If there are outstanding changes in the working directory, import
1318 If there are outstanding changes in the working directory, import
1312 will abort unless given the -f flag.
1319 will abort unless given the -f flag.
1313
1320
1314 If a patch looks like a mail message (its first line starts with
1321 If a patch looks like a mail message (its first line starts with
1315 "From " or looks like an RFC822 header), it will not be applied
1322 "From " or looks like an RFC822 header), it will not be applied
1316 unless the -f option is used. The importer neither parses nor
1323 unless the -f option is used. The importer neither parses nor
1317 discards mail headers, so use -f only to override the "mailness"
1324 discards mail headers, so use -f only to override the "mailness"
1318 safety check, not to import a real mail message.
1325 safety check, not to import a real mail message.
1319 """
1326 """
1320 patches = (patch1,) + patches
1327 patches = (patch1,) + patches
1321
1328
1322 if not opts['force']:
1329 if not opts['force']:
1323 (c, a, d, u) = repo.changes()
1330 (c, a, d, u) = repo.changes()
1324 if c or a or d:
1331 if c or a or d:
1325 raise util.Abort(_("outstanding uncommitted changes"))
1332 raise util.Abort(_("outstanding uncommitted changes"))
1326
1333
1327 d = opts["base"]
1334 d = opts["base"]
1328 strip = opts["strip"]
1335 strip = opts["strip"]
1329
1336
1330 mailre = re.compile(r'(?:From |[\w-]+:)')
1337 mailre = re.compile(r'(?:From |[\w-]+:)')
1331
1338
1332 # attempt to detect the start of a patch
1339 # attempt to detect the start of a patch
1333 # (this heuristic is borrowed from quilt)
1340 # (this heuristic is borrowed from quilt)
1334 diffre = re.compile(r'(?:Index:[ \t]|diff[ \t]|RCS file: |' +
1341 diffre = re.compile(r'(?:Index:[ \t]|diff[ \t]|RCS file: |' +
1335 'retrieving revision [0-9]+(\.[0-9]+)*$|' +
1342 'retrieving revision [0-9]+(\.[0-9]+)*$|' +
1336 '(---|\*\*\*)[ \t])')
1343 '(---|\*\*\*)[ \t])')
1337
1344
1338 for patch in patches:
1345 for patch in patches:
1339 ui.status(_("applying %s\n") % patch)
1346 ui.status(_("applying %s\n") % patch)
1340 pf = os.path.join(d, patch)
1347 pf = os.path.join(d, patch)
1341
1348
1342 message = []
1349 message = []
1343 user = None
1350 user = None
1344 hgpatch = False
1351 hgpatch = False
1345 for line in file(pf):
1352 for line in file(pf):
1346 line = line.rstrip()
1353 line = line.rstrip()
1347 if (not message and not hgpatch and
1354 if (not message and not hgpatch and
1348 mailre.match(line) and not opts['force']):
1355 mailre.match(line) and not opts['force']):
1349 if len(line) > 35: line = line[:32] + '...'
1356 if len(line) > 35: line = line[:32] + '...'
1350 raise util.Abort(_('first line looks like a '
1357 raise util.Abort(_('first line looks like a '
1351 'mail header: ') + line)
1358 'mail header: ') + line)
1352 if diffre.match(line):
1359 if diffre.match(line):
1353 break
1360 break
1354 elif hgpatch:
1361 elif hgpatch:
1355 # parse values when importing the result of an hg export
1362 # parse values when importing the result of an hg export
1356 if line.startswith("# User "):
1363 if line.startswith("# User "):
1357 user = line[7:]
1364 user = line[7:]
1358 ui.debug(_('User: %s\n') % user)
1365 ui.debug(_('User: %s\n') % user)
1359 elif not line.startswith("# ") and line:
1366 elif not line.startswith("# ") and line:
1360 message.append(line)
1367 message.append(line)
1361 hgpatch = False
1368 hgpatch = False
1362 elif line == '# HG changeset patch':
1369 elif line == '# HG changeset patch':
1363 hgpatch = True
1370 hgpatch = True
1364 message = [] # We may have collected garbage
1371 message = [] # We may have collected garbage
1365 else:
1372 else:
1366 message.append(line)
1373 message.append(line)
1367
1374
1368 # make sure message isn't empty
1375 # make sure message isn't empty
1369 if not message:
1376 if not message:
1370 message = _("imported patch %s\n") % patch
1377 message = _("imported patch %s\n") % patch
1371 else:
1378 else:
1372 message = "%s\n" % '\n'.join(message)
1379 message = "%s\n" % '\n'.join(message)
1373 ui.debug(_('message:\n%s\n') % message)
1380 ui.debug(_('message:\n%s\n') % message)
1374
1381
1375 files = util.patch(strip, pf, ui)
1382 files = util.patch(strip, pf, ui)
1376
1383
1377 if len(files) > 0:
1384 if len(files) > 0:
1378 addremove(ui, repo, *files)
1385 addremove(ui, repo, *files)
1379 repo.commit(files, message, user)
1386 repo.commit(files, message, user)
1380
1387
1381 def incoming(ui, repo, source="default", **opts):
1388 def incoming(ui, repo, source="default", **opts):
1382 """show new changesets found in source
1389 """show new changesets found in source
1383
1390
1384 Show new changesets found in the specified repo or the default
1391 Show new changesets found in the specified repo or the default
1385 pull repo. These are the changesets that would be pulled if a pull
1392 pull repo. These are the changesets that would be pulled if a pull
1386 was requested.
1393 was requested.
1387
1394
1388 Currently only local repositories are supported.
1395 Currently only local repositories are supported.
1389 """
1396 """
1390 source = ui.expandpath(source, repo.root)
1397 source = ui.expandpath(source, repo.root)
1391 other = hg.repository(ui, source)
1398 other = hg.repository(ui, source)
1392 if not other.local():
1399 if not other.local():
1393 raise util.Abort(_("incoming doesn't work for remote repositories yet"))
1400 raise util.Abort(_("incoming doesn't work for remote repositories yet"))
1394 o = repo.findincoming(other)
1401 o = repo.findincoming(other)
1395 if not o:
1402 if not o:
1396 return
1403 return
1397 o = other.changelog.nodesbetween(o)[0]
1404 o = other.changelog.nodesbetween(o)[0]
1398 if opts['newest_first']:
1405 if opts['newest_first']:
1399 o.reverse()
1406 o.reverse()
1400 for n in o:
1407 for n in o:
1401 parents = [p for p in other.changelog.parents(n) if p != nullid]
1408 parents = [p for p in other.changelog.parents(n) if p != nullid]
1402 if opts['no_merges'] and len(parents) == 2:
1409 if opts['no_merges'] and len(parents) == 2:
1403 continue
1410 continue
1404 show_changeset(ui, other, changenode=n)
1411 show_changeset(ui, other, changenode=n)
1405 if opts['patch']:
1412 if opts['patch']:
1406 prev = (parents and parents[0]) or nullid
1413 prev = (parents and parents[0]) or nullid
1407 dodiff(ui, ui, other, prev, n)
1414 dodiff(ui, ui, other, prev, n)
1408 ui.write("\n")
1415 ui.write("\n")
1409
1416
1410 def init(ui, dest="."):
1417 def init(ui, dest="."):
1411 """create a new repository in the given directory
1418 """create a new repository in the given directory
1412
1419
1413 Initialize a new repository in the given directory. If the given
1420 Initialize a new repository in the given directory. If the given
1414 directory does not exist, it is created.
1421 directory does not exist, it is created.
1415
1422
1416 If no directory is given, the current directory is used.
1423 If no directory is given, the current directory is used.
1417 """
1424 """
1418 if not os.path.exists(dest):
1425 if not os.path.exists(dest):
1419 os.mkdir(dest)
1426 os.mkdir(dest)
1420 hg.repository(ui, dest, create=1)
1427 hg.repository(ui, dest, create=1)
1421
1428
1422 def locate(ui, repo, *pats, **opts):
1429 def locate(ui, repo, *pats, **opts):
1423 """locate files matching specific patterns
1430 """locate files matching specific patterns
1424
1431
1425 Print all files under Mercurial control whose names match the
1432 Print all files under Mercurial control whose names match the
1426 given patterns.
1433 given patterns.
1427
1434
1428 This command searches the current directory and its
1435 This command searches the current directory and its
1429 subdirectories. To search an entire repository, move to the root
1436 subdirectories. To search an entire repository, move to the root
1430 of the repository.
1437 of the repository.
1431
1438
1432 If no patterns are given to match, this command prints all file
1439 If no patterns are given to match, this command prints all file
1433 names.
1440 names.
1434
1441
1435 If you want to feed the output of this command into the "xargs"
1442 If you want to feed the output of this command into the "xargs"
1436 command, use the "-0" option to both this command and "xargs".
1443 command, use the "-0" option to both this command and "xargs".
1437 This will avoid the problem of "xargs" treating single filenames
1444 This will avoid the problem of "xargs" treating single filenames
1438 that contain white space as multiple filenames.
1445 that contain white space as multiple filenames.
1439 """
1446 """
1440 end = opts['print0'] and '\0' or '\n'
1447 end = opts['print0'] and '\0' or '\n'
1441
1448
1442 for src, abs, rel, exact in walk(repo, pats, opts, '(?:.*/|)'):
1449 for src, abs, rel, exact in walk(repo, pats, opts, '(?:.*/|)'):
1443 if repo.dirstate.state(abs) == '?':
1450 if repo.dirstate.state(abs) == '?':
1444 continue
1451 continue
1445 if opts['fullpath']:
1452 if opts['fullpath']:
1446 ui.write(os.path.join(repo.root, abs), end)
1453 ui.write(os.path.join(repo.root, abs), end)
1447 else:
1454 else:
1448 ui.write(rel, end)
1455 ui.write(rel, end)
1449
1456
1450 def log(ui, repo, *pats, **opts):
1457 def log(ui, repo, *pats, **opts):
1451 """show revision history of entire repository or files
1458 """show revision history of entire repository or files
1452
1459
1453 Print the revision history of the specified files or the entire project.
1460 Print the revision history of the specified files or the entire project.
1454
1461
1455 By default this command outputs: changeset id and hash, tags,
1462 By default this command outputs: changeset id and hash, tags,
1456 parents, user, date and time, and a summary for each commit. The
1463 parents, user, date and time, and a summary for each commit. The
1457 -v switch adds some more detail, such as changed files, manifest
1464 -v switch adds some more detail, such as changed files, manifest
1458 hashes or message signatures.
1465 hashes or message signatures.
1459 """
1466 """
1460 class dui:
1467 class dui:
1461 # Implement and delegate some ui protocol. Save hunks of
1468 # Implement and delegate some ui protocol. Save hunks of
1462 # output for later display in the desired order.
1469 # output for later display in the desired order.
1463 def __init__(self, ui):
1470 def __init__(self, ui):
1464 self.ui = ui
1471 self.ui = ui
1465 self.hunk = {}
1472 self.hunk = {}
1466 def bump(self, rev):
1473 def bump(self, rev):
1467 self.rev = rev
1474 self.rev = rev
1468 self.hunk[rev] = []
1475 self.hunk[rev] = []
1469 def note(self, *args):
1476 def note(self, *args):
1470 if self.verbose:
1477 if self.verbose:
1471 self.write(*args)
1478 self.write(*args)
1472 def status(self, *args):
1479 def status(self, *args):
1473 if not self.quiet:
1480 if not self.quiet:
1474 self.write(*args)
1481 self.write(*args)
1475 def write(self, *args):
1482 def write(self, *args):
1476 self.hunk[self.rev].append(args)
1483 self.hunk[self.rev].append(args)
1477 def debug(self, *args):
1484 def debug(self, *args):
1478 if self.debugflag:
1485 if self.debugflag:
1479 self.write(*args)
1486 self.write(*args)
1480 def __getattr__(self, key):
1487 def __getattr__(self, key):
1481 return getattr(self.ui, key)
1488 return getattr(self.ui, key)
1482 cwd = repo.getcwd()
1489 cwd = repo.getcwd()
1483 if not pats and cwd:
1490 if not pats and cwd:
1484 opts['include'] = [os.path.join(cwd, i) for i in opts['include']]
1491 opts['include'] = [os.path.join(cwd, i) for i in opts['include']]
1485 opts['exclude'] = [os.path.join(cwd, x) for x in opts['exclude']]
1492 opts['exclude'] = [os.path.join(cwd, x) for x in opts['exclude']]
1486 changeiter, getchange = walkchangerevs(ui, repo, (pats and cwd) or '',
1493 changeiter, getchange = walkchangerevs(ui, repo, (pats and cwd) or '',
1487 pats, opts)
1494 pats, opts)
1488 for st, rev, fns in changeiter:
1495 for st, rev, fns in changeiter:
1489 if st == 'window':
1496 if st == 'window':
1490 du = dui(ui)
1497 du = dui(ui)
1491 elif st == 'add':
1498 elif st == 'add':
1492 du.bump(rev)
1499 du.bump(rev)
1493 changenode = repo.changelog.node(rev)
1500 changenode = repo.changelog.node(rev)
1494 parents = [p for p in repo.changelog.parents(changenode)
1501 parents = [p for p in repo.changelog.parents(changenode)
1495 if p != nullid]
1502 if p != nullid]
1496 if opts['no_merges'] and len(parents) == 2:
1503 if opts['no_merges'] and len(parents) == 2:
1497 continue
1504 continue
1498 if opts['only_merges'] and len(parents) != 2:
1505 if opts['only_merges'] and len(parents) != 2:
1499 continue
1506 continue
1500
1507
1501 br = None
1508 br = None
1502 if opts['keyword']:
1509 if opts['keyword']:
1503 changes = repo.changelog.read(repo.changelog.node(rev))
1510 changes = repo.changelog.read(repo.changelog.node(rev))
1504 miss = 0
1511 miss = 0
1505 for k in [kw.lower() for kw in opts['keyword']]:
1512 for k in [kw.lower() for kw in opts['keyword']]:
1506 if not (k in changes[1].lower() or
1513 if not (k in changes[1].lower() or
1507 k in changes[4].lower() or
1514 k in changes[4].lower() or
1508 k in " ".join(changes[3][:20]).lower()):
1515 k in " ".join(changes[3][:20]).lower()):
1509 miss = 1
1516 miss = 1
1510 break
1517 break
1511 if miss:
1518 if miss:
1512 continue
1519 continue
1513
1520
1514 if opts['branch']:
1521 if opts['branch']:
1515 br = repo.branchlookup([repo.changelog.node(rev)])
1522 br = repo.branchlookup([repo.changelog.node(rev)])
1516
1523
1517 show_changeset(du, repo, rev, brinfo=br)
1524 show_changeset(du, repo, rev, brinfo=br)
1518 if opts['patch']:
1525 if opts['patch']:
1519 prev = (parents and parents[0]) or nullid
1526 prev = (parents and parents[0]) or nullid
1520 dodiff(du, du, repo, prev, changenode, fns)
1527 dodiff(du, du, repo, prev, changenode, fns)
1521 du.write("\n\n")
1528 du.write("\n\n")
1522 elif st == 'iter':
1529 elif st == 'iter':
1523 for args in du.hunk[rev]:
1530 for args in du.hunk[rev]:
1524 ui.write(*args)
1531 ui.write(*args)
1525
1532
1526 def manifest(ui, repo, rev=None):
1533 def manifest(ui, repo, rev=None):
1527 """output the latest or given revision of the project manifest
1534 """output the latest or given revision of the project manifest
1528
1535
1529 Print a list of version controlled files for the given revision.
1536 Print a list of version controlled files for the given revision.
1530
1537
1531 The manifest is the list of files being version controlled. If no revision
1538 The manifest is the list of files being version controlled. If no revision
1532 is given then the tip is used.
1539 is given then the tip is used.
1533 """
1540 """
1534 if rev:
1541 if rev:
1535 try:
1542 try:
1536 # assume all revision numbers are for changesets
1543 # assume all revision numbers are for changesets
1537 n = repo.lookup(rev)
1544 n = repo.lookup(rev)
1538 change = repo.changelog.read(n)
1545 change = repo.changelog.read(n)
1539 n = change[0]
1546 n = change[0]
1540 except hg.RepoError:
1547 except hg.RepoError:
1541 n = repo.manifest.lookup(rev)
1548 n = repo.manifest.lookup(rev)
1542 else:
1549 else:
1543 n = repo.manifest.tip()
1550 n = repo.manifest.tip()
1544 m = repo.manifest.read(n)
1551 m = repo.manifest.read(n)
1545 mf = repo.manifest.readflags(n)
1552 mf = repo.manifest.readflags(n)
1546 files = m.keys()
1553 files = m.keys()
1547 files.sort()
1554 files.sort()
1548
1555
1549 for f in files:
1556 for f in files:
1550 ui.write("%40s %3s %s\n" % (hex(m[f]), mf[f] and "755" or "644", f))
1557 ui.write("%40s %3s %s\n" % (hex(m[f]), mf[f] and "755" or "644", f))
1551
1558
1552 def outgoing(ui, repo, dest="default-push", **opts):
1559 def outgoing(ui, repo, dest="default-push", **opts):
1553 """show changesets not found in destination
1560 """show changesets not found in destination
1554
1561
1555 Show changesets not found in the specified destination repo or the
1562 Show changesets not found in the specified destination repo or the
1556 default push repo. These are the changesets that would be pushed
1563 default push repo. These are the changesets that would be pushed
1557 if a push was requested.
1564 if a push was requested.
1558 """
1565 """
1559 dest = ui.expandpath(dest, repo.root)
1566 dest = ui.expandpath(dest, repo.root)
1560 other = hg.repository(ui, dest)
1567 other = hg.repository(ui, dest)
1561 o = repo.findoutgoing(other)
1568 o = repo.findoutgoing(other)
1562 o = repo.changelog.nodesbetween(o)[0]
1569 o = repo.changelog.nodesbetween(o)[0]
1563 if opts['newest_first']:
1570 if opts['newest_first']:
1564 o.reverse()
1571 o.reverse()
1565 for n in o:
1572 for n in o:
1566 parents = [p for p in repo.changelog.parents(n) if p != nullid]
1573 parents = [p for p in repo.changelog.parents(n) if p != nullid]
1567 if opts['no_merges'] and len(parents) == 2:
1574 if opts['no_merges'] and len(parents) == 2:
1568 continue
1575 continue
1569 show_changeset(ui, repo, changenode=n)
1576 show_changeset(ui, repo, changenode=n)
1570 if opts['patch']:
1577 if opts['patch']:
1571 prev = (parents and parents[0]) or nullid
1578 prev = (parents and parents[0]) or nullid
1572 dodiff(ui, ui, repo, prev, n)
1579 dodiff(ui, ui, repo, prev, n)
1573 ui.write("\n")
1580 ui.write("\n")
1574
1581
1575 def parents(ui, repo, rev=None):
1582 def parents(ui, repo, rev=None):
1576 """show the parents of the working dir or revision
1583 """show the parents of the working dir or revision
1577
1584
1578 Print the working directory's parent revisions.
1585 Print the working directory's parent revisions.
1579 """
1586 """
1580 if rev:
1587 if rev:
1581 p = repo.changelog.parents(repo.lookup(rev))
1588 p = repo.changelog.parents(repo.lookup(rev))
1582 else:
1589 else:
1583 p = repo.dirstate.parents()
1590 p = repo.dirstate.parents()
1584
1591
1585 for n in p:
1592 for n in p:
1586 if n != nullid:
1593 if n != nullid:
1587 show_changeset(ui, repo, changenode=n)
1594 show_changeset(ui, repo, changenode=n)
1588
1595
1589 def paths(ui, search=None):
1596 def paths(ui, search=None):
1590 """show definition of symbolic path names
1597 """show definition of symbolic path names
1591
1598
1592 Show definition of symbolic path name NAME. If no name is given, show
1599 Show definition of symbolic path name NAME. If no name is given, show
1593 definition of available names.
1600 definition of available names.
1594
1601
1595 Path names are defined in the [paths] section of /etc/mercurial/hgrc
1602 Path names are defined in the [paths] section of /etc/mercurial/hgrc
1596 and $HOME/.hgrc. If run inside a repository, .hg/hgrc is used, too.
1603 and $HOME/.hgrc. If run inside a repository, .hg/hgrc is used, too.
1597 """
1604 """
1598 try:
1605 try:
1599 repo = hg.repository(ui=ui)
1606 repo = hg.repository(ui=ui)
1600 except hg.RepoError:
1607 except hg.RepoError:
1601 pass
1608 pass
1602
1609
1603 if search:
1610 if search:
1604 for name, path in ui.configitems("paths"):
1611 for name, path in ui.configitems("paths"):
1605 if name == search:
1612 if name == search:
1606 ui.write("%s\n" % path)
1613 ui.write("%s\n" % path)
1607 return
1614 return
1608 ui.warn(_("not found!\n"))
1615 ui.warn(_("not found!\n"))
1609 return 1
1616 return 1
1610 else:
1617 else:
1611 for name, path in ui.configitems("paths"):
1618 for name, path in ui.configitems("paths"):
1612 ui.write("%s = %s\n" % (name, path))
1619 ui.write("%s = %s\n" % (name, path))
1613
1620
1614 def pull(ui, repo, source="default", **opts):
1621 def pull(ui, repo, source="default", **opts):
1615 """pull changes from the specified source
1622 """pull changes from the specified source
1616
1623
1617 Pull changes from a remote repository to a local one.
1624 Pull changes from a remote repository to a local one.
1618
1625
1619 This finds all changes from the repository at the specified path
1626 This finds all changes from the repository at the specified path
1620 or URL and adds them to the local repository. By default, this
1627 or URL and adds them to the local repository. By default, this
1621 does not update the copy of the project in the working directory.
1628 does not update the copy of the project in the working directory.
1622
1629
1623 Valid URLs are of the form:
1630 Valid URLs are of the form:
1624
1631
1625 local/filesystem/path
1632 local/filesystem/path
1626 http://[user@]host[:port][/path]
1633 http://[user@]host[:port][/path]
1627 https://[user@]host[:port][/path]
1634 https://[user@]host[:port][/path]
1628 ssh://[user@]host[:port][/path]
1635 ssh://[user@]host[:port][/path]
1629
1636
1630 SSH requires an accessible shell account on the destination machine
1637 SSH requires an accessible shell account on the destination machine
1631 and a copy of hg in the remote path. With SSH, paths are relative
1638 and a copy of hg in the remote path. With SSH, paths are relative
1632 to the remote user's home directory by default; use two slashes at
1639 to the remote user's home directory by default; use two slashes at
1633 the start of a path to specify it as relative to the filesystem root.
1640 the start of a path to specify it as relative to the filesystem root.
1634 """
1641 """
1635 source = ui.expandpath(source, repo.root)
1642 source = ui.expandpath(source, repo.root)
1636 ui.status(_('pulling from %s\n') % (source))
1643 ui.status(_('pulling from %s\n') % (source))
1637
1644
1638 if opts['ssh']:
1645 if opts['ssh']:
1639 ui.setconfig("ui", "ssh", opts['ssh'])
1646 ui.setconfig("ui", "ssh", opts['ssh'])
1640 if opts['remotecmd']:
1647 if opts['remotecmd']:
1641 ui.setconfig("ui", "remotecmd", opts['remotecmd'])
1648 ui.setconfig("ui", "remotecmd", opts['remotecmd'])
1642
1649
1643 other = hg.repository(ui, source)
1650 other = hg.repository(ui, source)
1644 revs = None
1651 revs = None
1645 if opts['rev'] and not other.local():
1652 if opts['rev'] and not other.local():
1646 raise util.Abort("pull -r doesn't work for remote repositories yet")
1653 raise util.Abort("pull -r doesn't work for remote repositories yet")
1647 elif opts['rev']:
1654 elif opts['rev']:
1648 revs = [other.lookup(rev) for rev in opts['rev']]
1655 revs = [other.lookup(rev) for rev in opts['rev']]
1649 r = repo.pull(other, heads=revs)
1656 r = repo.pull(other, heads=revs)
1650 if not r:
1657 if not r:
1651 if opts['update']:
1658 if opts['update']:
1652 return update(ui, repo)
1659 return update(ui, repo)
1653 else:
1660 else:
1654 ui.status(_("(run 'hg update' to get a working copy)\n"))
1661 ui.status(_("(run 'hg update' to get a working copy)\n"))
1655
1662
1656 return r
1663 return r
1657
1664
1658 def push(ui, repo, dest="default-push", force=False, ssh=None, remotecmd=None):
1665 def push(ui, repo, dest="default-push", force=False, ssh=None, remotecmd=None):
1659 """push changes to the specified destination
1666 """push changes to the specified destination
1660
1667
1661 Push changes from the local repository to the given destination.
1668 Push changes from the local repository to the given destination.
1662
1669
1663 This is the symmetrical operation for pull. It helps to move
1670 This is the symmetrical operation for pull. It helps to move
1664 changes from the current repository to a different one. If the
1671 changes from the current repository to a different one. If the
1665 destination is local this is identical to a pull in that directory
1672 destination is local this is identical to a pull in that directory
1666 from the current one.
1673 from the current one.
1667
1674
1668 By default, push will refuse to run if it detects the result would
1675 By default, push will refuse to run if it detects the result would
1669 increase the number of remote heads. This generally indicates the
1676 increase the number of remote heads. This generally indicates the
1670 the client has forgotten to sync and merge before pushing.
1677 the client has forgotten to sync and merge before pushing.
1671
1678
1672 Valid URLs are of the form:
1679 Valid URLs are of the form:
1673
1680
1674 local/filesystem/path
1681 local/filesystem/path
1675 ssh://[user@]host[:port][/path]
1682 ssh://[user@]host[:port][/path]
1676
1683
1677 SSH requires an accessible shell account on the destination
1684 SSH requires an accessible shell account on the destination
1678 machine and a copy of hg in the remote path.
1685 machine and a copy of hg in the remote path.
1679 """
1686 """
1680 dest = ui.expandpath(dest, repo.root)
1687 dest = ui.expandpath(dest, repo.root)
1681 ui.status('pushing to %s\n' % (dest))
1688 ui.status('pushing to %s\n' % (dest))
1682
1689
1683 if ssh:
1690 if ssh:
1684 ui.setconfig("ui", "ssh", ssh)
1691 ui.setconfig("ui", "ssh", ssh)
1685 if remotecmd:
1692 if remotecmd:
1686 ui.setconfig("ui", "remotecmd", remotecmd)
1693 ui.setconfig("ui", "remotecmd", remotecmd)
1687
1694
1688 other = hg.repository(ui, dest)
1695 other = hg.repository(ui, dest)
1689 r = repo.push(other, force)
1696 r = repo.push(other, force)
1690 return r
1697 return r
1691
1698
1692 def rawcommit(ui, repo, *flist, **rc):
1699 def rawcommit(ui, repo, *flist, **rc):
1693 """raw commit interface
1700 """raw commit interface
1694
1701
1695 Lowlevel commit, for use in helper scripts.
1702 Lowlevel commit, for use in helper scripts.
1696
1703
1697 This command is not intended to be used by normal users, as it is
1704 This command is not intended to be used by normal users, as it is
1698 primarily useful for importing from other SCMs.
1705 primarily useful for importing from other SCMs.
1699 """
1706 """
1700 message = rc['message']
1707 message = rc['message']
1701 if not message and rc['logfile']:
1708 if not message and rc['logfile']:
1702 try:
1709 try:
1703 message = open(rc['logfile']).read()
1710 message = open(rc['logfile']).read()
1704 except IOError:
1711 except IOError:
1705 pass
1712 pass
1706 if not message and not rc['logfile']:
1713 if not message and not rc['logfile']:
1707 raise util.Abort(_("missing commit message"))
1714 raise util.Abort(_("missing commit message"))
1708
1715
1709 files = relpath(repo, list(flist))
1716 files = relpath(repo, list(flist))
1710 if rc['files']:
1717 if rc['files']:
1711 files += open(rc['files']).read().splitlines()
1718 files += open(rc['files']).read().splitlines()
1712
1719
1713 rc['parent'] = map(repo.lookup, rc['parent'])
1720 rc['parent'] = map(repo.lookup, rc['parent'])
1714
1721
1715 try:
1722 try:
1716 repo.rawcommit(files, message, rc['user'], rc['date'], *rc['parent'])
1723 repo.rawcommit(files, message, rc['user'], rc['date'], *rc['parent'])
1717 except ValueError, inst:
1724 except ValueError, inst:
1718 raise util.Abort(str(inst))
1725 raise util.Abort(str(inst))
1719
1726
1720 def recover(ui, repo):
1727 def recover(ui, repo):
1721 """roll back an interrupted transaction
1728 """roll back an interrupted transaction
1722
1729
1723 Recover from an interrupted commit or pull.
1730 Recover from an interrupted commit or pull.
1724
1731
1725 This command tries to fix the repository status after an interrupted
1732 This command tries to fix the repository status after an interrupted
1726 operation. It should only be necessary when Mercurial suggests it.
1733 operation. It should only be necessary when Mercurial suggests it.
1727 """
1734 """
1728 repo.recover()
1735 repo.recover()
1729
1736
1730 def remove(ui, repo, pat, *pats, **opts):
1737 def remove(ui, repo, pat, *pats, **opts):
1731 """remove the specified files on the next commit
1738 """remove the specified files on the next commit
1732
1739
1733 Schedule the indicated files for removal from the repository.
1740 Schedule the indicated files for removal from the repository.
1734
1741
1735 This command schedules the files to be removed at the next commit.
1742 This command schedules the files to be removed at the next commit.
1736 This only removes files from the current branch, not from the
1743 This only removes files from the current branch, not from the
1737 entire project history. If the files still exist in the working
1744 entire project history. If the files still exist in the working
1738 directory, they will be deleted from it.
1745 directory, they will be deleted from it.
1739 """
1746 """
1740 names = []
1747 names = []
1741 def okaytoremove(abs, rel, exact):
1748 def okaytoremove(abs, rel, exact):
1742 c, a, d, u = repo.changes(files = [abs])
1749 c, a, d, u = repo.changes(files = [abs])
1743 reason = None
1750 reason = None
1744 if c: reason = _('is modified')
1751 if c: reason = _('is modified')
1745 elif a: reason = _('has been marked for add')
1752 elif a: reason = _('has been marked for add')
1746 elif u: reason = _('is not managed')
1753 elif u: reason = _('is not managed')
1747 if reason:
1754 if reason:
1748 if exact: ui.warn(_('not removing %s: file %s\n') % (rel, reason))
1755 if exact: ui.warn(_('not removing %s: file %s\n') % (rel, reason))
1749 else:
1756 else:
1750 return True
1757 return True
1751 for src, abs, rel, exact in walk(repo, (pat,) + pats, opts):
1758 for src, abs, rel, exact in walk(repo, (pat,) + pats, opts):
1752 if okaytoremove(abs, rel, exact):
1759 if okaytoremove(abs, rel, exact):
1753 if ui.verbose or not exact: ui.status(_('removing %s\n') % rel)
1760 if ui.verbose or not exact: ui.status(_('removing %s\n') % rel)
1754 names.append(abs)
1761 names.append(abs)
1755 repo.remove(names, unlink=True)
1762 repo.remove(names, unlink=True)
1756
1763
1757 def rename(ui, repo, *pats, **opts):
1764 def rename(ui, repo, *pats, **opts):
1758 """rename files; equivalent of copy + remove
1765 """rename files; equivalent of copy + remove
1759
1766
1760 Mark dest as copies of sources; mark sources for deletion. If
1767 Mark dest as copies of sources; mark sources for deletion. If
1761 dest is a directory, copies are put in that directory. If dest is
1768 dest is a directory, copies are put in that directory. If dest is
1762 a file, there can only be one source.
1769 a file, there can only be one source.
1763
1770
1764 By default, this command copies the contents of files as they
1771 By default, this command copies the contents of files as they
1765 stand in the working directory. If invoked with --after, the
1772 stand in the working directory. If invoked with --after, the
1766 operation is recorded, but no copying is performed.
1773 operation is recorded, but no copying is performed.
1767
1774
1768 This command takes effect in the next commit.
1775 This command takes effect in the next commit.
1769
1776
1770 NOTE: This command should be treated as experimental. While it
1777 NOTE: This command should be treated as experimental. While it
1771 should properly record rename files, this information is not yet
1778 should properly record rename files, this information is not yet
1772 fully used by merge, nor fully reported by log.
1779 fully used by merge, nor fully reported by log.
1773 """
1780 """
1774 errs, copied = docopy(ui, repo, pats, opts)
1781 errs, copied = docopy(ui, repo, pats, opts)
1775 names = []
1782 names = []
1776 for abs, rel, exact in copied:
1783 for abs, rel, exact in copied:
1777 if ui.verbose or not exact: ui.status(_('removing %s\n') % rel)
1784 if ui.verbose or not exact: ui.status(_('removing %s\n') % rel)
1778 names.append(abs)
1785 names.append(abs)
1779 repo.remove(names, unlink=True)
1786 repo.remove(names, unlink=True)
1780 return errs
1787 return errs
1781
1788
1782 def revert(ui, repo, *pats, **opts):
1789 def revert(ui, repo, *pats, **opts):
1783 """revert modified files or dirs back to their unmodified states
1790 """revert modified files or dirs back to their unmodified states
1784
1791
1785 Revert any uncommitted modifications made to the named files or
1792 Revert any uncommitted modifications made to the named files or
1786 directories. This restores the contents of the affected files to
1793 directories. This restores the contents of the affected files to
1787 an unmodified state.
1794 an unmodified state.
1788
1795
1789 If a file has been deleted, it is recreated. If the executable
1796 If a file has been deleted, it is recreated. If the executable
1790 mode of a file was changed, it is reset.
1797 mode of a file was changed, it is reset.
1791
1798
1792 If names are given, all files matching the names are reverted.
1799 If names are given, all files matching the names are reverted.
1793
1800
1794 If no names are given, all files in the current directory and
1801 If no names are given, all files in the current directory and
1795 its subdirectories are reverted.
1802 its subdirectories are reverted.
1796 """
1803 """
1797 node = opts['rev'] and repo.lookup(opts['rev']) or \
1804 node = opts['rev'] and repo.lookup(opts['rev']) or \
1798 repo.dirstate.parents()[0]
1805 repo.dirstate.parents()[0]
1799
1806
1800 files, choose, anypats = matchpats(repo, repo.getcwd(), pats, opts)
1807 files, choose, anypats = matchpats(repo, repo.getcwd(), pats, opts)
1801 (c, a, d, u) = repo.changes(match=choose)
1808 (c, a, d, u) = repo.changes(match=choose)
1802 repo.forget(a)
1809 repo.forget(a)
1803 repo.undelete(d)
1810 repo.undelete(d)
1804
1811
1805 return repo.update(node, False, True, choose, False)
1812 return repo.update(node, False, True, choose, False)
1806
1813
1807 def root(ui, repo):
1814 def root(ui, repo):
1808 """print the root (top) of the current working dir
1815 """print the root (top) of the current working dir
1809
1816
1810 Print the root directory of the current repository.
1817 Print the root directory of the current repository.
1811 """
1818 """
1812 ui.write(repo.root + "\n")
1819 ui.write(repo.root + "\n")
1813
1820
1814 def serve(ui, repo, **opts):
1821 def serve(ui, repo, **opts):
1815 """export the repository via HTTP
1822 """export the repository via HTTP
1816
1823
1817 Start a local HTTP repository browser and pull server.
1824 Start a local HTTP repository browser and pull server.
1818
1825
1819 By default, the server logs accesses to stdout and errors to
1826 By default, the server logs accesses to stdout and errors to
1820 stderr. Use the "-A" and "-E" options to log to files.
1827 stderr. Use the "-A" and "-E" options to log to files.
1821 """
1828 """
1822
1829
1823 if opts["stdio"]:
1830 if opts["stdio"]:
1824 fin, fout = sys.stdin, sys.stdout
1831 fin, fout = sys.stdin, sys.stdout
1825 sys.stdout = sys.stderr
1832 sys.stdout = sys.stderr
1826
1833
1827 # Prevent insertion/deletion of CRs
1834 # Prevent insertion/deletion of CRs
1828 util.set_binary(fin)
1835 util.set_binary(fin)
1829 util.set_binary(fout)
1836 util.set_binary(fout)
1830
1837
1831 def getarg():
1838 def getarg():
1832 argline = fin.readline()[:-1]
1839 argline = fin.readline()[:-1]
1833 arg, l = argline.split()
1840 arg, l = argline.split()
1834 val = fin.read(int(l))
1841 val = fin.read(int(l))
1835 return arg, val
1842 return arg, val
1836 def respond(v):
1843 def respond(v):
1837 fout.write("%d\n" % len(v))
1844 fout.write("%d\n" % len(v))
1838 fout.write(v)
1845 fout.write(v)
1839 fout.flush()
1846 fout.flush()
1840
1847
1841 lock = None
1848 lock = None
1842
1849
1843 while 1:
1850 while 1:
1844 cmd = fin.readline()[:-1]
1851 cmd = fin.readline()[:-1]
1845 if cmd == '':
1852 if cmd == '':
1846 return
1853 return
1847 if cmd == "heads":
1854 if cmd == "heads":
1848 h = repo.heads()
1855 h = repo.heads()
1849 respond(" ".join(map(hex, h)) + "\n")
1856 respond(" ".join(map(hex, h)) + "\n")
1850 if cmd == "lock":
1857 if cmd == "lock":
1851 lock = repo.lock()
1858 lock = repo.lock()
1852 respond("")
1859 respond("")
1853 if cmd == "unlock":
1860 if cmd == "unlock":
1854 if lock:
1861 if lock:
1855 lock.release()
1862 lock.release()
1856 lock = None
1863 lock = None
1857 respond("")
1864 respond("")
1858 elif cmd == "branches":
1865 elif cmd == "branches":
1859 arg, nodes = getarg()
1866 arg, nodes = getarg()
1860 nodes = map(bin, nodes.split(" "))
1867 nodes = map(bin, nodes.split(" "))
1861 r = []
1868 r = []
1862 for b in repo.branches(nodes):
1869 for b in repo.branches(nodes):
1863 r.append(" ".join(map(hex, b)) + "\n")
1870 r.append(" ".join(map(hex, b)) + "\n")
1864 respond("".join(r))
1871 respond("".join(r))
1865 elif cmd == "between":
1872 elif cmd == "between":
1866 arg, pairs = getarg()
1873 arg, pairs = getarg()
1867 pairs = [map(bin, p.split("-")) for p in pairs.split(" ")]
1874 pairs = [map(bin, p.split("-")) for p in pairs.split(" ")]
1868 r = []
1875 r = []
1869 for b in repo.between(pairs):
1876 for b in repo.between(pairs):
1870 r.append(" ".join(map(hex, b)) + "\n")
1877 r.append(" ".join(map(hex, b)) + "\n")
1871 respond("".join(r))
1878 respond("".join(r))
1872 elif cmd == "changegroup":
1879 elif cmd == "changegroup":
1873 nodes = []
1880 nodes = []
1874 arg, roots = getarg()
1881 arg, roots = getarg()
1875 nodes = map(bin, roots.split(" "))
1882 nodes = map(bin, roots.split(" "))
1876
1883
1877 cg = repo.changegroup(nodes)
1884 cg = repo.changegroup(nodes)
1878 while 1:
1885 while 1:
1879 d = cg.read(4096)
1886 d = cg.read(4096)
1880 if not d:
1887 if not d:
1881 break
1888 break
1882 fout.write(d)
1889 fout.write(d)
1883
1890
1884 fout.flush()
1891 fout.flush()
1885
1892
1886 elif cmd == "addchangegroup":
1893 elif cmd == "addchangegroup":
1887 if not lock:
1894 if not lock:
1888 respond("not locked")
1895 respond("not locked")
1889 continue
1896 continue
1890 respond("")
1897 respond("")
1891
1898
1892 r = repo.addchangegroup(fin)
1899 r = repo.addchangegroup(fin)
1893 respond("")
1900 respond("")
1894
1901
1895 optlist = "name templates style address port ipv6 accesslog errorlog"
1902 optlist = "name templates style address port ipv6 accesslog errorlog"
1896 for o in optlist.split():
1903 for o in optlist.split():
1897 if opts[o]:
1904 if opts[o]:
1898 ui.setconfig("web", o, opts[o])
1905 ui.setconfig("web", o, opts[o])
1899
1906
1900 try:
1907 try:
1901 httpd = hgweb.create_server(repo)
1908 httpd = hgweb.create_server(repo)
1902 except socket.error, inst:
1909 except socket.error, inst:
1903 raise util.Abort('cannot start server: ' + inst.args[1])
1910 raise util.Abort('cannot start server: ' + inst.args[1])
1904
1911
1905 if ui.verbose:
1912 if ui.verbose:
1906 addr, port = httpd.socket.getsockname()
1913 addr, port = httpd.socket.getsockname()
1907 if addr == '0.0.0.0':
1914 if addr == '0.0.0.0':
1908 addr = socket.gethostname()
1915 addr = socket.gethostname()
1909 else:
1916 else:
1910 try:
1917 try:
1911 addr = socket.gethostbyaddr(addr)[0]
1918 addr = socket.gethostbyaddr(addr)[0]
1912 except socket.error:
1919 except socket.error:
1913 pass
1920 pass
1914 if port != 80:
1921 if port != 80:
1915 ui.status(_('listening at http://%s:%d/\n') % (addr, port))
1922 ui.status(_('listening at http://%s:%d/\n') % (addr, port))
1916 else:
1923 else:
1917 ui.status(_('listening at http://%s/\n') % addr)
1924 ui.status(_('listening at http://%s/\n') % addr)
1918 httpd.serve_forever()
1925 httpd.serve_forever()
1919
1926
1920 def status(ui, repo, *pats, **opts):
1927 def status(ui, repo, *pats, **opts):
1921 """show changed files in the working directory
1928 """show changed files in the working directory
1922
1929
1923 Show changed files in the working directory. If no names are
1930 Show changed files in the working directory. If no names are
1924 given, all files are shown. Otherwise, only files matching the
1931 given, all files are shown. Otherwise, only files matching the
1925 given names are shown.
1932 given names are shown.
1926
1933
1927 The codes used to show the status of files are:
1934 The codes used to show the status of files are:
1928 M = modified
1935 M = modified
1929 A = added
1936 A = added
1930 R = removed
1937 R = removed
1931 ? = not tracked
1938 ? = not tracked
1932 """
1939 """
1933
1940
1934 cwd = repo.getcwd()
1941 cwd = repo.getcwd()
1935 files, matchfn, anypats = matchpats(repo, cwd, pats, opts)
1942 files, matchfn, anypats = matchpats(repo, cwd, pats, opts)
1936 (c, a, d, u) = [[util.pathto(cwd, x) for x in n]
1943 (c, a, d, u) = [[util.pathto(cwd, x) for x in n]
1937 for n in repo.changes(files=files, match=matchfn)]
1944 for n in repo.changes(files=files, match=matchfn)]
1938
1945
1939 changetypes = [(_('modified'), 'M', c),
1946 changetypes = [(_('modified'), 'M', c),
1940 (_('added'), 'A', a),
1947 (_('added'), 'A', a),
1941 (_('removed'), 'R', d),
1948 (_('removed'), 'R', d),
1942 (_('unknown'), '?', u)]
1949 (_('unknown'), '?', u)]
1943
1950
1944 end = opts['print0'] and '\0' or '\n'
1951 end = opts['print0'] and '\0' or '\n'
1945
1952
1946 for opt, char, changes in ([ct for ct in changetypes if opts[ct[0]]]
1953 for opt, char, changes in ([ct for ct in changetypes if opts[ct[0]]]
1947 or changetypes):
1954 or changetypes):
1948 if opts['no_status']:
1955 if opts['no_status']:
1949 format = "%%s%s" % end
1956 format = "%%s%s" % end
1950 else:
1957 else:
1951 format = "%s %%s%s" % (char, end);
1958 format = "%s %%s%s" % (char, end);
1952
1959
1953 for f in changes:
1960 for f in changes:
1954 ui.write(format % f)
1961 ui.write(format % f)
1955
1962
1956 def tag(ui, repo, name, rev=None, **opts):
1963 def tag(ui, repo, name, rev=None, **opts):
1957 """add a tag for the current tip or a given revision
1964 """add a tag for the current tip or a given revision
1958
1965
1959 Name a particular revision using <name>.
1966 Name a particular revision using <name>.
1960
1967
1961 Tags are used to name particular revisions of the repository and are
1968 Tags are used to name particular revisions of the repository and are
1962 very useful to compare different revision, to go back to significant
1969 very useful to compare different revision, to go back to significant
1963 earlier versions or to mark branch points as releases, etc.
1970 earlier versions or to mark branch points as releases, etc.
1964
1971
1965 If no revision is given, the tip is used.
1972 If no revision is given, the tip is used.
1966
1973
1967 To facilitate version control, distribution, and merging of tags,
1974 To facilitate version control, distribution, and merging of tags,
1968 they are stored as a file named ".hgtags" which is managed
1975 they are stored as a file named ".hgtags" which is managed
1969 similarly to other project files and can be hand-edited if
1976 similarly to other project files and can be hand-edited if
1970 necessary.
1977 necessary.
1971 """
1978 """
1972 if name == "tip":
1979 if name == "tip":
1973 raise util.Abort(_("the name 'tip' is reserved"))
1980 raise util.Abort(_("the name 'tip' is reserved"))
1974 if 'rev' in opts:
1981 if 'rev' in opts:
1975 rev = opts['rev']
1982 rev = opts['rev']
1976 if rev:
1983 if rev:
1977 r = hex(repo.lookup(rev))
1984 r = hex(repo.lookup(rev))
1978 else:
1985 else:
1979 r = hex(repo.changelog.tip())
1986 r = hex(repo.changelog.tip())
1980
1987
1981 if name.find(revrangesep) >= 0:
1988 if name.find(revrangesep) >= 0:
1982 raise util.Abort(_("'%s' cannot be used in a tag name") % revrangesep)
1989 raise util.Abort(_("'%s' cannot be used in a tag name") % revrangesep)
1983
1990
1984 if opts['local']:
1991 if opts['local']:
1985 repo.opener("localtags", "a").write("%s %s\n" % (r, name))
1992 repo.opener("localtags", "a").write("%s %s\n" % (r, name))
1986 return
1993 return
1987
1994
1988 (c, a, d, u) = repo.changes()
1995 (c, a, d, u) = repo.changes()
1989 for x in (c, a, d, u):
1996 for x in (c, a, d, u):
1990 if ".hgtags" in x:
1997 if ".hgtags" in x:
1991 raise util.Abort(_("working copy of .hgtags is changed "
1998 raise util.Abort(_("working copy of .hgtags is changed "
1992 "(please commit .hgtags manually)"))
1999 "(please commit .hgtags manually)"))
1993
2000
1994 repo.wfile(".hgtags", "ab").write("%s %s\n" % (r, name))
2001 repo.wfile(".hgtags", "ab").write("%s %s\n" % (r, name))
1995 if repo.dirstate.state(".hgtags") == '?':
2002 if repo.dirstate.state(".hgtags") == '?':
1996 repo.add([".hgtags"])
2003 repo.add([".hgtags"])
1997
2004
1998 message = (opts['message'] or
2005 message = (opts['message'] or
1999 _("Added tag %s for changeset %s") % (name, r))
2006 _("Added tag %s for changeset %s") % (name, r))
2000 try:
2007 try:
2001 repo.commit([".hgtags"], message, opts['user'], opts['date'])
2008 repo.commit([".hgtags"], message, opts['user'], opts['date'])
2002 except ValueError, inst:
2009 except ValueError, inst:
2003 raise util.Abort(str(inst))
2010 raise util.Abort(str(inst))
2004
2011
2005 def tags(ui, repo):
2012 def tags(ui, repo):
2006 """list repository tags
2013 """list repository tags
2007
2014
2008 List the repository tags.
2015 List the repository tags.
2009
2016
2010 This lists both regular and local tags.
2017 This lists both regular and local tags.
2011 """
2018 """
2012
2019
2013 l = repo.tagslist()
2020 l = repo.tagslist()
2014 l.reverse()
2021 l.reverse()
2015 for t, n in l:
2022 for t, n in l:
2016 try:
2023 try:
2017 r = "%5d:%s" % (repo.changelog.rev(n), hex(n))
2024 r = "%5d:%s" % (repo.changelog.rev(n), hex(n))
2018 except KeyError:
2025 except KeyError:
2019 r = " ?:?"
2026 r = " ?:?"
2020 ui.write("%-30s %s\n" % (t, r))
2027 ui.write("%-30s %s\n" % (t, r))
2021
2028
2022 def tip(ui, repo):
2029 def tip(ui, repo):
2023 """show the tip revision
2030 """show the tip revision
2024
2031
2025 Show the tip revision.
2032 Show the tip revision.
2026 """
2033 """
2027 n = repo.changelog.tip()
2034 n = repo.changelog.tip()
2028 show_changeset(ui, repo, changenode=n)
2035 show_changeset(ui, repo, changenode=n)
2029
2036
2030 def unbundle(ui, repo, fname):
2037 def unbundle(ui, repo, fname):
2031 """apply a changegroup file
2038 """apply a changegroup file
2032
2039
2033 Apply a compressed changegroup file generated by the bundle
2040 Apply a compressed changegroup file generated by the bundle
2034 command.
2041 command.
2035 """
2042 """
2036 f = urllib.urlopen(fname)
2043 f = urllib.urlopen(fname)
2037
2044
2038 if f.read(4) != "HG10":
2045 if f.read(4) != "HG10":
2039 raise util.Abort(_("%s: not a Mercurial bundle file") % fname)
2046 raise util.Abort(_("%s: not a Mercurial bundle file") % fname)
2040
2047
2041 def bzgenerator(f):
2048 def bzgenerator(f):
2042 zd = bz2.BZ2Decompressor()
2049 zd = bz2.BZ2Decompressor()
2043 for chunk in f:
2050 for chunk in f:
2044 yield zd.decompress(chunk)
2051 yield zd.decompress(chunk)
2045
2052
2046 bzgen = bzgenerator(util.filechunkiter(f, 4096))
2053 bzgen = bzgenerator(util.filechunkiter(f, 4096))
2047 repo.addchangegroup(util.chunkbuffer(bzgen))
2054 repo.addchangegroup(util.chunkbuffer(bzgen))
2048
2055
2049 def undo(ui, repo):
2056 def undo(ui, repo):
2050 """undo the last commit or pull
2057 """undo the last commit or pull
2051
2058
2052 Roll back the last pull or commit transaction on the
2059 Roll back the last pull or commit transaction on the
2053 repository, restoring the project to its earlier state.
2060 repository, restoring the project to its earlier state.
2054
2061
2055 This command should be used with care. There is only one level of
2062 This command should be used with care. There is only one level of
2056 undo and there is no redo.
2063 undo and there is no redo.
2057
2064
2058 This command is not intended for use on public repositories. Once
2065 This command is not intended for use on public repositories. Once
2059 a change is visible for pull by other users, undoing it locally is
2066 a change is visible for pull by other users, undoing it locally is
2060 ineffective.
2067 ineffective.
2061 """
2068 """
2062 repo.undo()
2069 repo.undo()
2063
2070
2064 def update(ui, repo, node=None, merge=False, clean=False, branch=None):
2071 def update(ui, repo, node=None, merge=False, clean=False, branch=None):
2065 """update or merge working directory
2072 """update or merge working directory
2066
2073
2067 Update the working directory to the specified revision.
2074 Update the working directory to the specified revision.
2068
2075
2069 If there are no outstanding changes in the working directory and
2076 If there are no outstanding changes in the working directory and
2070 there is a linear relationship between the current version and the
2077 there is a linear relationship between the current version and the
2071 requested version, the result is the requested version.
2078 requested version, the result is the requested version.
2072
2079
2073 Otherwise the result is a merge between the contents of the
2080 Otherwise the result is a merge between the contents of the
2074 current working directory and the requested version. Files that
2081 current working directory and the requested version. Files that
2075 changed between either parent are marked as changed for the next
2082 changed between either parent are marked as changed for the next
2076 commit and a commit must be performed before any further updates
2083 commit and a commit must be performed before any further updates
2077 are allowed.
2084 are allowed.
2078
2085
2079 By default, update will refuse to run if doing so would require
2086 By default, update will refuse to run if doing so would require
2080 merging or discarding local changes.
2087 merging or discarding local changes.
2081 """
2088 """
2082 if branch:
2089 if branch:
2083 br = repo.branchlookup(branch=branch)
2090 br = repo.branchlookup(branch=branch)
2084 found = []
2091 found = []
2085 for x in br:
2092 for x in br:
2086 if branch in br[x]:
2093 if branch in br[x]:
2087 found.append(x)
2094 found.append(x)
2088 if len(found) > 1:
2095 if len(found) > 1:
2089 ui.warn(_("Found multiple heads for %s\n") % branch)
2096 ui.warn(_("Found multiple heads for %s\n") % branch)
2090 for x in found:
2097 for x in found:
2091 show_changeset(ui, repo, changenode=x, brinfo=br)
2098 show_changeset(ui, repo, changenode=x, brinfo=br)
2092 return 1
2099 return 1
2093 if len(found) == 1:
2100 if len(found) == 1:
2094 node = found[0]
2101 node = found[0]
2095 ui.warn(_("Using head %s for branch %s\n") % (short(node), branch))
2102 ui.warn(_("Using head %s for branch %s\n") % (short(node), branch))
2096 else:
2103 else:
2097 ui.warn(_("branch %s not found\n") % (branch))
2104 ui.warn(_("branch %s not found\n") % (branch))
2098 return 1
2105 return 1
2099 else:
2106 else:
2100 node = node and repo.lookup(node) or repo.changelog.tip()
2107 node = node and repo.lookup(node) or repo.changelog.tip()
2101 return repo.update(node, allow=merge, force=clean)
2108 return repo.update(node, allow=merge, force=clean)
2102
2109
2103 def verify(ui, repo):
2110 def verify(ui, repo):
2104 """verify the integrity of the repository
2111 """verify the integrity of the repository
2105
2112
2106 Verify the integrity of the current repository.
2113 Verify the integrity of the current repository.
2107
2114
2108 This will perform an extensive check of the repository's
2115 This will perform an extensive check of the repository's
2109 integrity, validating the hashes and checksums of each entry in
2116 integrity, validating the hashes and checksums of each entry in
2110 the changelog, manifest, and tracked files, as well as the
2117 the changelog, manifest, and tracked files, as well as the
2111 integrity of their crosslinks and indices.
2118 integrity of their crosslinks and indices.
2112 """
2119 """
2113 return repo.verify()
2120 return repo.verify()
2114
2121
2115 # Command options and aliases are listed here, alphabetically
2122 # Command options and aliases are listed here, alphabetically
2116
2123
2117 table = {
2124 table = {
2118 "^add":
2125 "^add":
2119 (add,
2126 (add,
2120 [('I', 'include', [], _('include names matching the given patterns')),
2127 [('I', 'include', [], _('include names matching the given patterns')),
2121 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2128 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2122 "hg add [OPTION]... [FILE]..."),
2129 "hg add [OPTION]... [FILE]..."),
2123 "addremove":
2130 "addremove":
2124 (addremove,
2131 (addremove,
2125 [('I', 'include', [], _('include names matching the given patterns')),
2132 [('I', 'include', [], _('include names matching the given patterns')),
2126 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2133 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2127 "hg addremove [OPTION]... [FILE]..."),
2134 "hg addremove [OPTION]... [FILE]..."),
2128 "^annotate":
2135 "^annotate":
2129 (annotate,
2136 (annotate,
2130 [('r', 'rev', '', _('annotate the specified revision')),
2137 [('r', 'rev', '', _('annotate the specified revision')),
2131 ('a', 'text', None, _('treat all files as text')),
2138 ('a', 'text', None, _('treat all files as text')),
2132 ('u', 'user', None, _('list the author')),
2139 ('u', 'user', None, _('list the author')),
2133 ('n', 'number', None, _('list the revision number (default)')),
2140 ('n', 'number', None, _('list the revision number (default)')),
2134 ('c', 'changeset', None, _('list the changeset')),
2141 ('c', 'changeset', None, _('list the changeset')),
2135 ('I', 'include', [], _('include names matching the given patterns')),
2142 ('I', 'include', [], _('include names matching the given patterns')),
2136 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2143 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2137 _('hg annotate [OPTION]... FILE...')),
2144 _('hg annotate [OPTION]... FILE...')),
2138 "bundle":
2145 "bundle":
2139 (bundle,
2146 (bundle,
2140 [],
2147 [],
2141 _('hg bundle FILE DEST')),
2148 _('hg bundle FILE DEST')),
2142 "cat":
2149 "cat":
2143 (cat,
2150 (cat,
2144 [('I', 'include', [], _('include names matching the given patterns')),
2151 [('I', 'include', [], _('include names matching the given patterns')),
2145 ('X', 'exclude', [], _('exclude names matching the given patterns')),
2152 ('X', 'exclude', [], _('exclude names matching the given patterns')),
2146 ('o', 'output', "", _('print output to file with formatted name')),
2153 ('o', 'output', "", _('print output to file with formatted name')),
2147 ('r', 'rev', '', _('print the given revision'))],
2154 ('r', 'rev', '', _('print the given revision'))],
2148 _('hg cat [OPTION]... FILE...')),
2155 _('hg cat [OPTION]... FILE...')),
2149 "^clone":
2156 "^clone":
2150 (clone,
2157 (clone,
2151 [('U', 'noupdate', None, _('do not update the new working directory')),
2158 [('U', 'noupdate', None, _('do not update the new working directory')),
2152 ('e', 'ssh', "", _('specify ssh command to use')),
2159 ('e', 'ssh', "", _('specify ssh command to use')),
2153 ('', 'pull', None, _('use pull protocol to copy metadata')),
2160 ('', 'pull', None, _('use pull protocol to copy metadata')),
2154 ('r', 'rev', [], _('a changeset you would like to have after cloning')),
2161 ('r', 'rev', [], _('a changeset you would like to have after cloning')),
2155 ('', 'remotecmd', "", _('specify hg command to run on the remote side'))],
2162 ('', 'remotecmd', "", _('specify hg command to run on the remote side'))],
2156 _('hg clone [OPTION]... SOURCE [DEST]')),
2163 _('hg clone [OPTION]... SOURCE [DEST]')),
2157 "^commit|ci":
2164 "^commit|ci":
2158 (commit,
2165 (commit,
2159 [('A', 'addremove', None, _('run addremove during commit')),
2166 [('A', 'addremove', None, _('run addremove during commit')),
2160 ('I', 'include', [], _('include names matching the given patterns')),
2167 ('I', 'include', [], _('include names matching the given patterns')),
2161 ('X', 'exclude', [], _('exclude names matching the given patterns')),
2168 ('X', 'exclude', [], _('exclude names matching the given patterns')),
2162 ('m', 'message', "", _('use <text> as commit message')),
2169 ('m', 'message', "", _('use <text> as commit message')),
2163 ('l', 'logfile', "", _('read the commit message from <file>')),
2170 ('l', 'logfile', "", _('read the commit message from <file>')),
2164 ('d', 'date', "", _('record datecode as commit date')),
2171 ('d', 'date', "", _('record datecode as commit date')),
2165 ('u', 'user', "", _('record user as commiter'))],
2172 ('u', 'user', "", _('record user as commiter'))],
2166 _('hg commit [OPTION]... [FILE]...')),
2173 _('hg commit [OPTION]... [FILE]...')),
2167 "copy|cp": (copy,
2174 "copy|cp": (copy,
2168 [('I', 'include', [], _('include names matching the given patterns')),
2175 [('I', 'include', [], _('include names matching the given patterns')),
2169 ('X', 'exclude', [], _('exclude names matching the given patterns')),
2176 ('X', 'exclude', [], _('exclude names matching the given patterns')),
2170 ('A', 'after', None, _('record a copy that has already occurred')),
2177 ('A', 'after', None, _('record a copy that has already occurred')),
2171 ('f', 'force', None, _('forcibly copy over an existing managed file'))],
2178 ('f', 'force', None, _('forcibly copy over an existing managed file'))],
2172 _('hg copy [OPTION]... [SOURCE]... DEST')),
2179 _('hg copy [OPTION]... [SOURCE]... DEST')),
2173 "debugancestor": (debugancestor, [], _('debugancestor INDEX REV1 REV2')),
2180 "debugancestor": (debugancestor, [], _('debugancestor INDEX REV1 REV2')),
2174 "debugcheckstate": (debugcheckstate, [], _('debugcheckstate')),
2181 "debugcheckstate": (debugcheckstate, [], _('debugcheckstate')),
2175 "debugconfig": (debugconfig, [], _('debugconfig')),
2182 "debugconfig": (debugconfig, [], _('debugconfig')),
2176 "debugsetparents": (debugsetparents, [], _('debugsetparents REV1 [REV2]')),
2183 "debugsetparents": (debugsetparents, [], _('debugsetparents REV1 [REV2]')),
2177 "debugstate": (debugstate, [], _('debugstate')),
2184 "debugstate": (debugstate, [], _('debugstate')),
2178 "debugdata": (debugdata, [], _('debugdata FILE REV')),
2185 "debugdata": (debugdata, [], _('debugdata FILE REV')),
2179 "debugindex": (debugindex, [], _('debugindex FILE')),
2186 "debugindex": (debugindex, [], _('debugindex FILE')),
2180 "debugindexdot": (debugindexdot, [], _('debugindexdot FILE')),
2187 "debugindexdot": (debugindexdot, [], _('debugindexdot FILE')),
2181 "debugrename": (debugrename, [], _('debugrename FILE [REV]')),
2188 "debugrename": (debugrename, [], _('debugrename FILE [REV]')),
2182 "debugwalk":
2189 "debugwalk":
2183 (debugwalk,
2190 (debugwalk,
2184 [('I', 'include', [], _('include names matching the given patterns')),
2191 [('I', 'include', [], _('include names matching the given patterns')),
2185 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2192 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2186 _('debugwalk [OPTION]... [FILE]...')),
2193 _('debugwalk [OPTION]... [FILE]...')),
2187 "^diff":
2194 "^diff":
2188 (diff,
2195 (diff,
2189 [('r', 'rev', [], _('revision')),
2196 [('r', 'rev', [], _('revision')),
2190 ('a', 'text', None, _('treat all files as text')),
2197 ('a', 'text', None, _('treat all files as text')),
2191 ('I', 'include', [], _('include names matching the given patterns')),
2198 ('I', 'include', [], _('include names matching the given patterns')),
2192 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2199 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2193 _('hg diff [-a] [-I] [-X] [-r REV1 [-r REV2]] [FILE]...')),
2200 _('hg diff [-a] [-I] [-X] [-r REV1 [-r REV2]] [FILE]...')),
2194 "^export":
2201 "^export":
2195 (export,
2202 (export,
2196 [('o', 'output', "", _('print output to file with formatted name')),
2203 [('o', 'output', "", _('print output to file with formatted name')),
2197 ('a', 'text', None, _('treat all files as text'))],
2204 ('a', 'text', None, _('treat all files as text'))],
2198 "hg export [-a] [-o OUTFILE] REV..."),
2205 "hg export [-a] [-o OUTFILE] REV..."),
2199 "forget":
2206 "forget":
2200 (forget,
2207 (forget,
2201 [('I', 'include', [], _('include names matching the given patterns')),
2208 [('I', 'include', [], _('include names matching the given patterns')),
2202 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2209 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2203 "hg forget [OPTION]... FILE..."),
2210 "hg forget [OPTION]... FILE..."),
2204 "grep":
2211 "grep":
2205 (grep,
2212 (grep,
2206 [('0', 'print0', None, _('end fields with NUL')),
2213 [('0', 'print0', None, _('end fields with NUL')),
2207 ('I', 'include', [], _('include names matching the given patterns')),
2214 ('I', 'include', [], _('include names matching the given patterns')),
2208 ('X', 'exclude', [], _('exclude names matching the given patterns')),
2215 ('X', 'exclude', [], _('exclude names matching the given patterns')),
2209 ('', 'all', None, _('print all revisions that match')),
2216 ('', 'all', None, _('print all revisions that match')),
2210 ('i', 'ignore-case', None, _('ignore case when matching')),
2217 ('i', 'ignore-case', None, _('ignore case when matching')),
2211 ('l', 'files-with-matches', None, _('print only filenames and revs that match')),
2218 ('l', 'files-with-matches', None, _('print only filenames and revs that match')),
2212 ('n', 'line-number', None, _('print matching line numbers')),
2219 ('n', 'line-number', None, _('print matching line numbers')),
2213 ('r', 'rev', [], _('search in given revision range')),
2220 ('r', 'rev', [], _('search in given revision range')),
2214 ('u', 'user', None, _('print user who committed change'))],
2221 ('u', 'user', None, _('print user who committed change'))],
2215 "hg grep [OPTION]... PATTERN [FILE]..."),
2222 "hg grep [OPTION]... PATTERN [FILE]..."),
2216 "heads":
2223 "heads":
2217 (heads,
2224 (heads,
2218 [('b', 'branches', None, _('find branch info'))],
2225 [('b', 'branches', None, _('find branch info'))],
2219 _('hg heads [-b]')),
2226 _('hg heads [-b]')),
2220 "help": (help_, [], _('hg help [COMMAND]')),
2227 "help": (help_, [], _('hg help [COMMAND]')),
2221 "identify|id": (identify, [], _('hg identify')),
2228 "identify|id": (identify, [], _('hg identify')),
2222 "import|patch":
2229 "import|patch":
2223 (import_,
2230 (import_,
2224 [('p', 'strip', 1, _('directory strip option for patch. This has the same\n') +
2231 [('p', 'strip', 1, _('directory strip option for patch. This has the same\n') +
2225 _('meaning as the corresponding patch option')),
2232 _('meaning as the corresponding patch option')),
2226 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
2233 ('f', 'force', None, _('skip check for outstanding uncommitted changes')),
2227 ('b', 'base', "", _('base path'))],
2234 ('b', 'base', "", _('base path'))],
2228 "hg import [-f] [-p NUM] [-b BASE] PATCH..."),
2235 "hg import [-f] [-p NUM] [-b BASE] PATCH..."),
2229 "incoming|in": (incoming,
2236 "incoming|in": (incoming,
2230 [('M', 'no-merges', None, _("do not show merges")),
2237 [('M', 'no-merges', None, _("do not show merges")),
2231 ('p', 'patch', None, _('show patch')),
2238 ('p', 'patch', None, _('show patch')),
2232 ('n', 'newest-first', None, _('show newest record first'))],
2239 ('n', 'newest-first', None, _('show newest record first'))],
2233 _('hg incoming [-p] [-n] [-M] [SOURCE]')),
2240 _('hg incoming [-p] [-n] [-M] [SOURCE]')),
2234 "^init": (init, [], _('hg init [DEST]')),
2241 "^init": (init, [], _('hg init [DEST]')),
2235 "locate":
2242 "locate":
2236 (locate,
2243 (locate,
2237 [('r', 'rev', '', _('search the repository as it stood at rev')),
2244 [('r', 'rev', '', _('search the repository as it stood at rev')),
2238 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
2245 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
2239 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
2246 ('f', 'fullpath', None, _('print complete paths from the filesystem root')),
2240 ('I', 'include', [], _('include names matching the given patterns')),
2247 ('I', 'include', [], _('include names matching the given patterns')),
2241 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2248 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2242 _('hg locate [OPTION]... [PATTERN]...')),
2249 _('hg locate [OPTION]... [PATTERN]...')),
2243 "^log|history":
2250 "^log|history":
2244 (log,
2251 (log,
2245 [('I', 'include', [], _('include names matching the given patterns')),
2252 [('I', 'include', [], _('include names matching the given patterns')),
2246 ('X', 'exclude', [], _('exclude names matching the given patterns')),
2253 ('X', 'exclude', [], _('exclude names matching the given patterns')),
2247 ('b', 'branch', None, _('show branches')),
2254 ('b', 'branch', None, _('show branches')),
2248 ('k', 'keyword', [], _('search for a keyword')),
2255 ('k', 'keyword', [], _('search for a keyword')),
2249 ('r', 'rev', [], _('show the specified revision or range')),
2256 ('r', 'rev', [], _('show the specified revision or range')),
2250 ('M', 'no-merges', None, _("do not show merges")),
2257 ('M', 'no-merges', None, _("do not show merges")),
2251 ('m', 'only-merges', None, _("show only merges")),
2258 ('m', 'only-merges', None, _("show only merges")),
2252 ('p', 'patch', None, _('show patch'))],
2259 ('p', 'patch', None, _('show patch'))],
2253 _('hg log [-I] [-X] [-r REV]... [-p] [FILE]')),
2260 _('hg log [-I] [-X] [-r REV]... [-p] [FILE]')),
2254 "manifest": (manifest, [], _('hg manifest [REV]')),
2261 "manifest": (manifest, [], _('hg manifest [REV]')),
2255 "outgoing|out": (outgoing,
2262 "outgoing|out": (outgoing,
2256 [('M', 'no-merges', None, _("do not show merges")),
2263 [('M', 'no-merges', None, _("do not show merges")),
2257 ('p', 'patch', None, _('show patch')),
2264 ('p', 'patch', None, _('show patch')),
2258 ('n', 'newest-first', None, _('show newest record first'))],
2265 ('n', 'newest-first', None, _('show newest record first'))],
2259 _('hg outgoing [-p] [-n] [-M] [DEST]')),
2266 _('hg outgoing [-p] [-n] [-M] [DEST]')),
2260 "^parents": (parents, [], _('hg parents [REV]')),
2267 "^parents": (parents, [], _('hg parents [REV]')),
2261 "paths": (paths, [], _('hg paths [NAME]')),
2268 "paths": (paths, [], _('hg paths [NAME]')),
2262 "^pull":
2269 "^pull":
2263 (pull,
2270 (pull,
2264 [('u', 'update', None, _('update the working directory to tip after pull')),
2271 [('u', 'update', None, _('update the working directory to tip after pull')),
2265 ('e', 'ssh', "", _('specify ssh command to use')),
2272 ('e', 'ssh', "", _('specify ssh command to use')),
2266 ('r', 'rev', [], _('a specific revision you would like to pull')),
2273 ('r', 'rev', [], _('a specific revision you would like to pull')),
2267 ('', 'remotecmd', "", _('specify hg command to run on the remote side'))],
2274 ('', 'remotecmd', "", _('specify hg command to run on the remote side'))],
2268 _('hg pull [-u] [-e FILE] [-r rev] [--remotecmd FILE] [SOURCE]')),
2275 _('hg pull [-u] [-e FILE] [-r rev] [--remotecmd FILE] [SOURCE]')),
2269 "^push":
2276 "^push":
2270 (push,
2277 (push,
2271 [('f', 'force', None, _('force push')),
2278 [('f', 'force', None, _('force push')),
2272 ('e', 'ssh', "", _('specify ssh command to use')),
2279 ('e', 'ssh', "", _('specify ssh command to use')),
2273 ('', 'remotecmd', "", _('specify hg command to run on the remote side'))],
2280 ('', 'remotecmd', "", _('specify hg command to run on the remote side'))],
2274 _('hg push [-f] [-e FILE] [--remotecmd FILE] [DEST]')),
2281 _('hg push [-f] [-e FILE] [--remotecmd FILE] [DEST]')),
2275 "rawcommit":
2282 "rawcommit":
2276 (rawcommit,
2283 (rawcommit,
2277 [('p', 'parent', [], _('parent')),
2284 [('p', 'parent', [], _('parent')),
2278 ('d', 'date', "", _('date code')),
2285 ('d', 'date', "", _('date code')),
2279 ('u', 'user', "", _('user')),
2286 ('u', 'user', "", _('user')),
2280 ('F', 'files', "", _('file list')),
2287 ('F', 'files', "", _('file list')),
2281 ('m', 'message', "", _('commit message')),
2288 ('m', 'message', "", _('commit message')),
2282 ('l', 'logfile', "", _('commit message file'))],
2289 ('l', 'logfile', "", _('commit message file'))],
2283 _('hg rawcommit [OPTION]... [FILE]...')),
2290 _('hg rawcommit [OPTION]... [FILE]...')),
2284 "recover": (recover, [], _("hg recover")),
2291 "recover": (recover, [], _("hg recover")),
2285 "^remove|rm": (remove,
2292 "^remove|rm": (remove,
2286 [('I', 'include', [], _('include names matching the given patterns')),
2293 [('I', 'include', [], _('include names matching the given patterns')),
2287 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2294 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2288 _("hg remove [OPTION]... FILE...")),
2295 _("hg remove [OPTION]... FILE...")),
2289 "rename|mv": (rename,
2296 "rename|mv": (rename,
2290 [('I', 'include', [], _('include names matching the given patterns')),
2297 [('I', 'include', [], _('include names matching the given patterns')),
2291 ('X', 'exclude', [], _('exclude names matching the given patterns')),
2298 ('X', 'exclude', [], _('exclude names matching the given patterns')),
2292 ('A', 'after', None, _('record a rename that has already occurred')),
2299 ('A', 'after', None, _('record a rename that has already occurred')),
2293 ('f', 'force', None, _('forcibly copy over an existing managed file'))],
2300 ('f', 'force', None, _('forcibly copy over an existing managed file'))],
2294 _('hg rename [OPTION]... [SOURCE]... DEST')),
2301 _('hg rename [OPTION]... [SOURCE]... DEST')),
2295 "^revert":
2302 "^revert":
2296 (revert,
2303 (revert,
2297 [('I', 'include', [], _('include names matching the given patterns')),
2304 [('I', 'include', [], _('include names matching the given patterns')),
2298 ('X', 'exclude', [], _('exclude names matching the given patterns')),
2305 ('X', 'exclude', [], _('exclude names matching the given patterns')),
2299 ("r", "rev", "", _("revision to revert to"))],
2306 ("r", "rev", "", _("revision to revert to"))],
2300 _("hg revert [-n] [-r REV] [NAME]...")),
2307 _("hg revert [-n] [-r REV] [NAME]...")),
2301 "root": (root, [], _("hg root")),
2308 "root": (root, [], _("hg root")),
2302 "^serve":
2309 "^serve":
2303 (serve,
2310 (serve,
2304 [('A', 'accesslog', '', _('name of access log file to write to')),
2311 [('A', 'accesslog', '', _('name of access log file to write to')),
2305 ('E', 'errorlog', '', _('name of error log file to write to')),
2312 ('E', 'errorlog', '', _('name of error log file to write to')),
2306 ('p', 'port', 0, _('port to use (default: 8000)')),
2313 ('p', 'port', 0, _('port to use (default: 8000)')),
2307 ('a', 'address', '', _('address to use')),
2314 ('a', 'address', '', _('address to use')),
2308 ('n', 'name', "", _('name to show in web pages (default: working dir)')),
2315 ('n', 'name', "", _('name to show in web pages (default: working dir)')),
2309 ('', 'stdio', None, _('for remote clients')),
2316 ('', 'stdio', None, _('for remote clients')),
2310 ('t', 'templates', "", _('web templates to use')),
2317 ('t', 'templates', "", _('web templates to use')),
2311 ('', 'style', "", _('template style to use')),
2318 ('', 'style', "", _('template style to use')),
2312 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4'))],
2319 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4'))],
2313 _("hg serve [OPTION]...")),
2320 _("hg serve [OPTION]...")),
2314 "^status|st":
2321 "^status|st":
2315 (status,
2322 (status,
2316 [('m', 'modified', None, _('show only modified files')),
2323 [('m', 'modified', None, _('show only modified files')),
2317 ('a', 'added', None, _('show only added files')),
2324 ('a', 'added', None, _('show only added files')),
2318 ('r', 'removed', None, _('show only removed files')),
2325 ('r', 'removed', None, _('show only removed files')),
2319 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
2326 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
2320 ('n', 'no-status', None, _('hide status prefix')),
2327 ('n', 'no-status', None, _('hide status prefix')),
2321 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
2328 ('0', 'print0', None, _('end filenames with NUL, for use with xargs')),
2322 ('I', 'include', [], _('include names matching the given patterns')),
2329 ('I', 'include', [], _('include names matching the given patterns')),
2323 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2330 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2324 _("hg status [OPTION]... [FILE]...")),
2331 _("hg status [OPTION]... [FILE]...")),
2325 "tag":
2332 "tag":
2326 (tag,
2333 (tag,
2327 [('l', 'local', None, _('make the tag local')),
2334 [('l', 'local', None, _('make the tag local')),
2328 ('m', 'message', "", _('message for tag commit log entry')),
2335 ('m', 'message', "", _('message for tag commit log entry')),
2329 ('d', 'date', "", _('record datecode as commit date')),
2336 ('d', 'date', "", _('record datecode as commit date')),
2330 ('u', 'user', "", _('record user as commiter')),
2337 ('u', 'user', "", _('record user as commiter')),
2331 ('r', 'rev', "", _('revision to tag'))],
2338 ('r', 'rev', "", _('revision to tag'))],
2332 _('hg tag [OPTION]... NAME [REV]')),
2339 _('hg tag [OPTION]... NAME [REV]')),
2333 "tags": (tags, [], _('hg tags')),
2340 "tags": (tags, [], _('hg tags')),
2334 "tip": (tip, [], _('hg tip')),
2341 "tip": (tip, [], _('hg tip')),
2335 "unbundle":
2342 "unbundle":
2336 (unbundle,
2343 (unbundle,
2337 [],
2344 [],
2338 _('hg unbundle FILE')),
2345 _('hg unbundle FILE')),
2339 "undo": (undo, [], _('hg undo')),
2346 "undo": (undo, [], _('hg undo')),
2340 "^update|up|checkout|co":
2347 "^update|up|checkout|co":
2341 (update,
2348 (update,
2342 [('b', 'branch', "", _('checkout the head of a specific branch')),
2349 [('b', 'branch', "", _('checkout the head of a specific branch')),
2343 ('m', 'merge', None, _('allow merging of branches')),
2350 ('m', 'merge', None, _('allow merging of branches')),
2344 ('C', 'clean', None, _('overwrite locally modified files'))],
2351 ('C', 'clean', None, _('overwrite locally modified files'))],
2345 _('hg update [-b TAG] [-m] [-C] [REV]')),
2352 _('hg update [-b TAG] [-m] [-C] [REV]')),
2346 "verify": (verify, [], _('hg verify')),
2353 "verify": (verify, [], _('hg verify')),
2347 "version": (show_version, [], _('hg version')),
2354 "version": (show_version, [], _('hg version')),
2348 }
2355 }
2349
2356
2350 globalopts = [
2357 globalopts = [
2351 ('R', 'repository', "", _("repository root directory")),
2358 ('R', 'repository', "", _("repository root directory")),
2352 ('', 'cwd', '', _("change working directory")),
2359 ('', 'cwd', '', _("change working directory")),
2353 ('y', 'noninteractive', None, _("do not prompt, assume 'yes' for any required answers")),
2360 ('y', 'noninteractive', None, _("do not prompt, assume 'yes' for any required answers")),
2354 ('q', 'quiet', None, _("suppress output")),
2361 ('q', 'quiet', None, _("suppress output")),
2355 ('v', 'verbose', None, _("enable additional output")),
2362 ('v', 'verbose', None, _("enable additional output")),
2356 ('', 'debug', None, _("enable debugging output")),
2363 ('', 'debug', None, _("enable debugging output")),
2357 ('', 'debugger', None, _("start debugger")),
2364 ('', 'debugger', None, _("start debugger")),
2358 ('', 'traceback', None, _("print traceback on exception")),
2365 ('', 'traceback', None, _("print traceback on exception")),
2359 ('', 'time', None, _("time how long the command takes")),
2366 ('', 'time', None, _("time how long the command takes")),
2360 ('', 'profile', None, _("print command execution profile")),
2367 ('', 'profile', None, _("print command execution profile")),
2361 ('', 'version', None, _("output version information and exit")),
2368 ('', 'version', None, _("output version information and exit")),
2362 ('h', 'help', None, _("display help and exit")),
2369 ('h', 'help', None, _("display help and exit")),
2363 ]
2370 ]
2364
2371
2365 norepo = ("clone init version help debugancestor debugconfig debugdata"
2372 norepo = ("clone init version help debugancestor debugconfig debugdata"
2366 " debugindex debugindexdot paths")
2373 " debugindex debugindexdot paths")
2367
2374
2368 def find(cmd):
2375 def find(cmd):
2369 choice = []
2376 choice = []
2370 for e in table.keys():
2377 for e in table.keys():
2371 aliases = e.lstrip("^").split("|")
2378 aliases = e.lstrip("^").split("|")
2372 if cmd in aliases:
2379 if cmd in aliases:
2373 return e, table[e]
2380 return e, table[e]
2374 for a in aliases:
2381 for a in aliases:
2375 if a.startswith(cmd):
2382 if a.startswith(cmd):
2376 choice.append(e)
2383 choice.append(e)
2377 if len(choice) == 1:
2384 if len(choice) == 1:
2378 e = choice[0]
2385 e = choice[0]
2379 return e, table[e]
2386 return e, table[e]
2380
2387
2381 raise UnknownCommand(cmd)
2388 raise UnknownCommand(cmd)
2382
2389
2383 class SignalInterrupt(Exception):
2390 class SignalInterrupt(Exception):
2384 """Exception raised on SIGTERM and SIGHUP."""
2391 """Exception raised on SIGTERM and SIGHUP."""
2385
2392
2386 def catchterm(*args):
2393 def catchterm(*args):
2387 raise SignalInterrupt
2394 raise SignalInterrupt
2388
2395
2389 def run():
2396 def run():
2390 sys.exit(dispatch(sys.argv[1:]))
2397 sys.exit(dispatch(sys.argv[1:]))
2391
2398
2392 class ParseError(Exception):
2399 class ParseError(Exception):
2393 """Exception raised on errors in parsing the command line."""
2400 """Exception raised on errors in parsing the command line."""
2394
2401
2395 def parse(ui, args):
2402 def parse(ui, args):
2396 options = {}
2403 options = {}
2397 cmdoptions = {}
2404 cmdoptions = {}
2398
2405
2399 try:
2406 try:
2400 args = fancyopts.fancyopts(args, globalopts, options)
2407 args = fancyopts.fancyopts(args, globalopts, options)
2401 except fancyopts.getopt.GetoptError, inst:
2408 except fancyopts.getopt.GetoptError, inst:
2402 raise ParseError(None, inst)
2409 raise ParseError(None, inst)
2403
2410
2404 if args:
2411 if args:
2405 cmd, args = args[0], args[1:]
2412 cmd, args = args[0], args[1:]
2406 defaults = ui.config("defaults", cmd)
2413 defaults = ui.config("defaults", cmd)
2407 if defaults:
2414 if defaults:
2408 # reparse with command defaults added
2415 # reparse with command defaults added
2409 args = [cmd] + defaults.split() + args
2416 args = [cmd] + defaults.split() + args
2410 try:
2417 try:
2411 args = fancyopts.fancyopts(args, globalopts, options)
2418 args = fancyopts.fancyopts(args, globalopts, options)
2412 except fancyopts.getopt.GetoptError, inst:
2419 except fancyopts.getopt.GetoptError, inst:
2413 raise ParseError(None, inst)
2420 raise ParseError(None, inst)
2414
2421
2415 cmd, args = args[0], args[1:]
2422 cmd, args = args[0], args[1:]
2416
2423
2417 i = find(cmd)[1]
2424 i = find(cmd)[1]
2418 c = list(i[1])
2425 c = list(i[1])
2419 else:
2426 else:
2420 cmd = None
2427 cmd = None
2421 c = []
2428 c = []
2422
2429
2423 # combine global options into local
2430 # combine global options into local
2424 for o in globalopts:
2431 for o in globalopts:
2425 c.append((o[0], o[1], options[o[1]], o[3]))
2432 c.append((o[0], o[1], options[o[1]], o[3]))
2426
2433
2427 try:
2434 try:
2428 args = fancyopts.fancyopts(args, c, cmdoptions)
2435 args = fancyopts.fancyopts(args, c, cmdoptions)
2429 except fancyopts.getopt.GetoptError, inst:
2436 except fancyopts.getopt.GetoptError, inst:
2430 raise ParseError(cmd, inst)
2437 raise ParseError(cmd, inst)
2431
2438
2432 # separate global options back out
2439 # separate global options back out
2433 for o in globalopts:
2440 for o in globalopts:
2434 n = o[1]
2441 n = o[1]
2435 options[n] = cmdoptions[n]
2442 options[n] = cmdoptions[n]
2436 del cmdoptions[n]
2443 del cmdoptions[n]
2437
2444
2438 return (cmd, cmd and i[0] or None, args, options, cmdoptions)
2445 return (cmd, cmd and i[0] or None, args, options, cmdoptions)
2439
2446
2440 def dispatch(args):
2447 def dispatch(args):
2441 signal.signal(signal.SIGTERM, catchterm)
2448 signal.signal(signal.SIGTERM, catchterm)
2442 try:
2449 try:
2443 signal.signal(signal.SIGHUP, catchterm)
2450 signal.signal(signal.SIGHUP, catchterm)
2444 except AttributeError:
2451 except AttributeError:
2445 pass
2452 pass
2446
2453
2447 try:
2454 try:
2448 u = ui.ui()
2455 u = ui.ui()
2449 except util.Abort, inst:
2456 except util.Abort, inst:
2450 sys.stderr.write(_("abort: %s\n") % inst)
2457 sys.stderr.write(_("abort: %s\n") % inst)
2451 sys.exit(1)
2458 sys.exit(1)
2452
2459
2453 external = []
2460 external = []
2454 for x in u.extensions():
2461 for x in u.extensions():
2455 def on_exception(Exception, inst):
2462 def on_exception(Exception, inst):
2456 u.warn(_("*** failed to import extension %s\n") % x[1])
2463 u.warn(_("*** failed to import extension %s\n") % x[1])
2457 u.warn("%s\n" % inst)
2464 u.warn("%s\n" % inst)
2458 if "--traceback" in sys.argv[1:]:
2465 if "--traceback" in sys.argv[1:]:
2459 traceback.print_exc()
2466 traceback.print_exc()
2460 if x[1]:
2467 if x[1]:
2461 try:
2468 try:
2462 mod = imp.load_source(x[0], x[1])
2469 mod = imp.load_source(x[0], x[1])
2463 except Exception, inst:
2470 except Exception, inst:
2464 on_exception(Exception, inst)
2471 on_exception(Exception, inst)
2465 continue
2472 continue
2466 else:
2473 else:
2467 def importh(name):
2474 def importh(name):
2468 mod = __import__(name)
2475 mod = __import__(name)
2469 components = name.split('.')
2476 components = name.split('.')
2470 for comp in components[1:]:
2477 for comp in components[1:]:
2471 mod = getattr(mod, comp)
2478 mod = getattr(mod, comp)
2472 return mod
2479 return mod
2473 try:
2480 try:
2474 mod = importh(x[0])
2481 mod = importh(x[0])
2475 except Exception, inst:
2482 except Exception, inst:
2476 on_exception(Exception, inst)
2483 on_exception(Exception, inst)
2477 continue
2484 continue
2478
2485
2479 external.append(mod)
2486 external.append(mod)
2480 for x in external:
2487 for x in external:
2481 cmdtable = getattr(x, 'cmdtable', {})
2488 cmdtable = getattr(x, 'cmdtable', {})
2482 for t in cmdtable:
2489 for t in cmdtable:
2483 if t in table:
2490 if t in table:
2484 u.warn(_("module %s overrides %s\n") % (x.__name__, t))
2491 u.warn(_("module %s overrides %s\n") % (x.__name__, t))
2485 table.update(cmdtable)
2492 table.update(cmdtable)
2486
2493
2487 try:
2494 try:
2488 cmd, func, args, options, cmdoptions = parse(u, args)
2495 cmd, func, args, options, cmdoptions = parse(u, args)
2489 except ParseError, inst:
2496 except ParseError, inst:
2490 if inst.args[0]:
2497 if inst.args[0]:
2491 u.warn(_("hg %s: %s\n") % (inst.args[0], inst.args[1]))
2498 u.warn(_("hg %s: %s\n") % (inst.args[0], inst.args[1]))
2492 help_(u, inst.args[0])
2499 help_(u, inst.args[0])
2493 else:
2500 else:
2494 u.warn(_("hg: %s\n") % inst.args[1])
2501 u.warn(_("hg: %s\n") % inst.args[1])
2495 help_(u, 'shortlist')
2502 help_(u, 'shortlist')
2496 sys.exit(-1)
2503 sys.exit(-1)
2497 except UnknownCommand, inst:
2504 except UnknownCommand, inst:
2498 u.warn(_("hg: unknown command '%s'\n") % inst.args[0])
2505 u.warn(_("hg: unknown command '%s'\n") % inst.args[0])
2499 help_(u, 'shortlist')
2506 help_(u, 'shortlist')
2500 sys.exit(1)
2507 sys.exit(1)
2501
2508
2502 if options["time"]:
2509 if options["time"]:
2503 def get_times():
2510 def get_times():
2504 t = os.times()
2511 t = os.times()
2505 if t[4] == 0.0: # Windows leaves this as zero, so use time.clock()
2512 if t[4] == 0.0: # Windows leaves this as zero, so use time.clock()
2506 t = (t[0], t[1], t[2], t[3], time.clock())
2513 t = (t[0], t[1], t[2], t[3], time.clock())
2507 return t
2514 return t
2508 s = get_times()
2515 s = get_times()
2509 def print_time():
2516 def print_time():
2510 t = get_times()
2517 t = get_times()
2511 u.warn(_("Time: real %.3f secs (user %.3f+%.3f sys %.3f+%.3f)\n") %
2518 u.warn(_("Time: real %.3f secs (user %.3f+%.3f sys %.3f+%.3f)\n") %
2512 (t[4]-s[4], t[0]-s[0], t[2]-s[2], t[1]-s[1], t[3]-s[3]))
2519 (t[4]-s[4], t[0]-s[0], t[2]-s[2], t[1]-s[1], t[3]-s[3]))
2513 atexit.register(print_time)
2520 atexit.register(print_time)
2514
2521
2515 u.updateopts(options["verbose"], options["debug"], options["quiet"],
2522 u.updateopts(options["verbose"], options["debug"], options["quiet"],
2516 not options["noninteractive"])
2523 not options["noninteractive"])
2517
2524
2518 # enter the debugger before command execution
2525 # enter the debugger before command execution
2519 if options['debugger']:
2526 if options['debugger']:
2520 pdb.set_trace()
2527 pdb.set_trace()
2521
2528
2522 try:
2529 try:
2523 try:
2530 try:
2524 if options['help']:
2531 if options['help']:
2525 help_(u, cmd, options['version'])
2532 help_(u, cmd, options['version'])
2526 sys.exit(0)
2533 sys.exit(0)
2527 elif options['version']:
2534 elif options['version']:
2528 show_version(u)
2535 show_version(u)
2529 sys.exit(0)
2536 sys.exit(0)
2530 elif not cmd:
2537 elif not cmd:
2531 help_(u, 'shortlist')
2538 help_(u, 'shortlist')
2532 sys.exit(0)
2539 sys.exit(0)
2533
2540
2534 if options['cwd']:
2541 if options['cwd']:
2535 try:
2542 try:
2536 os.chdir(options['cwd'])
2543 os.chdir(options['cwd'])
2537 except OSError, inst:
2544 except OSError, inst:
2538 raise util.Abort('%s: %s' %
2545 raise util.Abort('%s: %s' %
2539 (options['cwd'], inst.strerror))
2546 (options['cwd'], inst.strerror))
2540
2547
2541 if cmd not in norepo.split():
2548 if cmd not in norepo.split():
2542 path = options["repository"] or ""
2549 path = options["repository"] or ""
2543 repo = hg.repository(ui=u, path=path)
2550 repo = hg.repository(ui=u, path=path)
2544 for x in external:
2551 for x in external:
2545 if hasattr(x, 'reposetup'): x.reposetup(u, repo)
2552 if hasattr(x, 'reposetup'): x.reposetup(u, repo)
2546 d = lambda: func(u, repo, *args, **cmdoptions)
2553 d = lambda: func(u, repo, *args, **cmdoptions)
2547 else:
2554 else:
2548 d = lambda: func(u, *args, **cmdoptions)
2555 d = lambda: func(u, *args, **cmdoptions)
2549
2556
2550 if options['profile']:
2557 if options['profile']:
2551 import hotshot, hotshot.stats
2558 import hotshot, hotshot.stats
2552 prof = hotshot.Profile("hg.prof")
2559 prof = hotshot.Profile("hg.prof")
2553 r = prof.runcall(d)
2560 r = prof.runcall(d)
2554 prof.close()
2561 prof.close()
2555 stats = hotshot.stats.load("hg.prof")
2562 stats = hotshot.stats.load("hg.prof")
2556 stats.strip_dirs()
2563 stats.strip_dirs()
2557 stats.sort_stats('time', 'calls')
2564 stats.sort_stats('time', 'calls')
2558 stats.print_stats(40)
2565 stats.print_stats(40)
2559 return r
2566 return r
2560 else:
2567 else:
2561 return d()
2568 return d()
2562 except:
2569 except:
2563 # enter the debugger when we hit an exception
2570 # enter the debugger when we hit an exception
2564 if options['debugger']:
2571 if options['debugger']:
2565 pdb.post_mortem(sys.exc_info()[2])
2572 pdb.post_mortem(sys.exc_info()[2])
2566 if options['traceback']:
2573 if options['traceback']:
2567 traceback.print_exc()
2574 traceback.print_exc()
2568 raise
2575 raise
2569 except hg.RepoError, inst:
2576 except hg.RepoError, inst:
2570 u.warn(_("abort: "), inst, "!\n")
2577 u.warn(_("abort: "), inst, "!\n")
2571 except revlog.RevlogError, inst:
2578 except revlog.RevlogError, inst:
2572 u.warn(_("abort: "), inst, "!\n")
2579 u.warn(_("abort: "), inst, "!\n")
2573 except SignalInterrupt:
2580 except SignalInterrupt:
2574 u.warn(_("killed!\n"))
2581 u.warn(_("killed!\n"))
2575 except KeyboardInterrupt:
2582 except KeyboardInterrupt:
2576 try:
2583 try:
2577 u.warn(_("interrupted!\n"))
2584 u.warn(_("interrupted!\n"))
2578 except IOError, inst:
2585 except IOError, inst:
2579 if inst.errno == errno.EPIPE:
2586 if inst.errno == errno.EPIPE:
2580 if u.debugflag:
2587 if u.debugflag:
2581 u.warn(_("\nbroken pipe\n"))
2588 u.warn(_("\nbroken pipe\n"))
2582 else:
2589 else:
2583 raise
2590 raise
2584 except IOError, inst:
2591 except IOError, inst:
2585 if hasattr(inst, "code"):
2592 if hasattr(inst, "code"):
2586 u.warn(_("abort: %s\n") % inst)
2593 u.warn(_("abort: %s\n") % inst)
2587 elif hasattr(inst, "reason"):
2594 elif hasattr(inst, "reason"):
2588 u.warn(_("abort: error: %s\n") % inst.reason[1])
2595 u.warn(_("abort: error: %s\n") % inst.reason[1])
2589 elif hasattr(inst, "args") and inst[0] == errno.EPIPE:
2596 elif hasattr(inst, "args") and inst[0] == errno.EPIPE:
2590 if u.debugflag:
2597 if u.debugflag:
2591 u.warn(_("broken pipe\n"))
2598 u.warn(_("broken pipe\n"))
2592 elif getattr(inst, "strerror", None):
2599 elif getattr(inst, "strerror", None):
2593 if getattr(inst, "filename", None):
2600 if getattr(inst, "filename", None):
2594 u.warn(_("abort: %s - %s\n") % (inst.strerror, inst.filename))
2601 u.warn(_("abort: %s - %s\n") % (inst.strerror, inst.filename))
2595 else:
2602 else:
2596 u.warn(_("abort: %s\n") % inst.strerror)
2603 u.warn(_("abort: %s\n") % inst.strerror)
2597 else:
2604 else:
2598 raise
2605 raise
2599 except OSError, inst:
2606 except OSError, inst:
2600 if hasattr(inst, "filename"):
2607 if hasattr(inst, "filename"):
2601 u.warn(_("abort: %s: %s\n") % (inst.strerror, inst.filename))
2608 u.warn(_("abort: %s: %s\n") % (inst.strerror, inst.filename))
2602 else:
2609 else:
2603 u.warn(_("abort: %s\n") % inst.strerror)
2610 u.warn(_("abort: %s\n") % inst.strerror)
2604 except util.Abort, inst:
2611 except util.Abort, inst:
2605 u.warn(_('abort: '), inst.args[0] % inst.args[1:], '\n')
2612 u.warn(_('abort: '), inst.args[0] % inst.args[1:], '\n')
2606 sys.exit(1)
2613 sys.exit(1)
2607 except TypeError, inst:
2614 except TypeError, inst:
2608 # was this an argument error?
2615 # was this an argument error?
2609 tb = traceback.extract_tb(sys.exc_info()[2])
2616 tb = traceback.extract_tb(sys.exc_info()[2])
2610 if len(tb) > 2: # no
2617 if len(tb) > 2: # no
2611 raise
2618 raise
2612 u.debug(inst, "\n")
2619 u.debug(inst, "\n")
2613 u.warn(_("%s: invalid arguments\n") % cmd)
2620 u.warn(_("%s: invalid arguments\n") % cmd)
2614 help_(u, cmd)
2621 help_(u, cmd)
2615 except UnknownCommand, inst:
2622 except UnknownCommand, inst:
2616 u.warn(_("hg: unknown command '%s'\n") % inst.args[0])
2623 u.warn(_("hg: unknown command '%s'\n") % inst.args[0])
2617 help_(u, 'shortlist')
2624 help_(u, 'shortlist')
2618 except SystemExit:
2625 except SystemExit:
2619 # don't catch this in the catch-all below
2626 # don't catch this in the catch-all below
2620 raise
2627 raise
2621 except:
2628 except:
2622 u.warn(_("** unknown exception encountered, details follow\n"))
2629 u.warn(_("** unknown exception encountered, details follow\n"))
2623 u.warn(_("** report bug details to mercurial@selenic.com\n"))
2630 u.warn(_("** report bug details to mercurial@selenic.com\n"))
2624 raise
2631 raise
2625
2632
2626 sys.exit(-1)
2633 sys.exit(-1)
@@ -1,78 +1,84 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
61
62 echo "# attempt to overwrite an existing file"
62 echo "# attempt to overwrite an existing file"
63 echo "ca" > d1/ca
63 echo "ca" > d1/ca
64 hg rename d1/ba d1/ca
64 hg rename d1/ba d1/ca
65 hg status
65 hg status
66 hg update -C
66 hg update -C
67
67
68 echo "# forced overwrite of an existing file"
68 echo "# forced overwrite of an existing file"
69 echo "ca" > d1/ca
69 echo "ca" > d1/ca
70 hg rename --force d1/ba d1/ca
70 hg rename --force d1/ba d1/ca
71 hg status
71 hg status
72 hg update -C
72 hg update -C
73
73
74 echo "# replace a symlink with a file"
74 echo "# replace a symlink with a file"
75 ln -s ba d1/ca
75 ln -s ba d1/ca
76 hg rename --force d1/ba d1/ca
76 hg rename --force d1/ba d1/ca
77 hg status
77 hg status
78 hg update -C
78 hg update -C
79
80 echo "# do not copy more than one source file to the same destination file"
81 mkdir d3
82 hg rename d1/* d2/* d3
83 hg status
84 hg update -C
@@ -1,103 +1,115 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 exists
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
94 # attempt to overwrite an existing file
95 d1/ca: not overwriting - file exists
95 d1/ca: not overwriting - file exists
96 abort: no files to copy
96 abort: no files to copy
97 ? d1/ca
97 ? d1/ca
98 # forced overwrite of an existing file
98 # forced overwrite of an existing file
99 A d1/ca
99 A d1/ca
100 R d1/ba
100 R d1/ba
101 # replace a symlink with a file
101 # replace a symlink with a file
102 A d1/ca
102 A d1/ca
103 R d1/ba
103 R d1/ba
104 # do not copy more than one source file to the same destination file
105 copying d1/d11/a1 to d3/d11/a1
106 d3/b: not overwriting - d2/b collides with d1/b
107 removing d1/d11/a1
108 A d3/a
109 A d3/b
110 A d3/ba
111 A d3/d11/a1
112 R d1/a
113 R d1/b
114 R d1/ba
115 R d1/d11/a1
General Comments 0
You need to be logged in to leave comments. Login now