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