##// END OF EJS Templates
add -r/--rev arguments to incoming and outgoing
Benoit Boissinot -
r2521:9cceb439 default
parent child Browse files
Show More
@@ -1,3545 +1,3554 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 templater bundlerepo")
12 demandload(globals(), "fancyopts ui hg util lock revlog templater bundlerepo")
13 demandload(globals(), "fnmatch mdiff random signal tempfile time")
13 demandload(globals(), "fnmatch mdiff random signal tempfile time")
14 demandload(globals(), "traceback errno socket version struct atexit sets bz2")
14 demandload(globals(), "traceback errno socket version struct atexit sets bz2")
15 demandload(globals(), "archival cStringIO changegroup email.Parser")
15 demandload(globals(), "archival cStringIO changegroup email.Parser")
16 demandload(globals(), "hgweb.server sshserver")
16 demandload(globals(), "hgweb.server sshserver")
17
17
18 class UnknownCommand(Exception):
18 class UnknownCommand(Exception):
19 """Exception raised if command is not in the command table."""
19 """Exception raised if command is not in the command table."""
20 class AmbiguousCommand(Exception):
20 class AmbiguousCommand(Exception):
21 """Exception raised if command shortcut matches more than one command."""
21 """Exception raised if command shortcut matches more than one command."""
22
22
23 def bail_if_changed(repo):
23 def bail_if_changed(repo):
24 modified, added, removed, deleted, unknown = repo.changes()
24 modified, added, removed, deleted, unknown = repo.changes()
25 if modified or added or removed or deleted:
25 if modified or added or removed or deleted:
26 raise util.Abort(_("outstanding uncommitted changes"))
26 raise util.Abort(_("outstanding uncommitted changes"))
27
27
28 def filterfiles(filters, files):
28 def filterfiles(filters, files):
29 l = [x for x in files if x in filters]
29 l = [x for x in files if x in filters]
30
30
31 for t in filters:
31 for t in filters:
32 if t and t[-1] != "/":
32 if t and t[-1] != "/":
33 t += "/"
33 t += "/"
34 l += [x for x in files if x.startswith(t)]
34 l += [x for x in files if x.startswith(t)]
35 return l
35 return l
36
36
37 def relpath(repo, args):
37 def relpath(repo, args):
38 cwd = repo.getcwd()
38 cwd = repo.getcwd()
39 if cwd:
39 if cwd:
40 return [util.normpath(os.path.join(cwd, x)) for x in args]
40 return [util.normpath(os.path.join(cwd, x)) for x in args]
41 return args
41 return args
42
42
43 def matchpats(repo, pats=[], opts={}, head=''):
43 def matchpats(repo, pats=[], opts={}, head=''):
44 cwd = repo.getcwd()
44 cwd = repo.getcwd()
45 if not pats and cwd:
45 if not pats and cwd:
46 opts['include'] = [os.path.join(cwd, i) for i in opts['include']]
46 opts['include'] = [os.path.join(cwd, i) for i in opts['include']]
47 opts['exclude'] = [os.path.join(cwd, x) for x in opts['exclude']]
47 opts['exclude'] = [os.path.join(cwd, x) for x in opts['exclude']]
48 cwd = ''
48 cwd = ''
49 return util.cmdmatcher(repo.root, cwd, pats or ['.'], opts.get('include'),
49 return util.cmdmatcher(repo.root, cwd, pats or ['.'], opts.get('include'),
50 opts.get('exclude'), head)
50 opts.get('exclude'), head)
51
51
52 def makewalk(repo, pats, opts, node=None, head='', badmatch=None):
52 def makewalk(repo, pats, opts, node=None, head='', badmatch=None):
53 files, matchfn, anypats = matchpats(repo, pats, opts, head)
53 files, matchfn, anypats = matchpats(repo, pats, opts, head)
54 exact = dict(zip(files, files))
54 exact = dict(zip(files, files))
55 def walk():
55 def walk():
56 for src, fn in repo.walk(node=node, files=files, match=matchfn,
56 for src, fn in repo.walk(node=node, files=files, match=matchfn,
57 badmatch=badmatch):
57 badmatch=badmatch):
58 yield src, fn, util.pathto(repo.getcwd(), fn), fn in exact
58 yield src, fn, util.pathto(repo.getcwd(), fn), fn in exact
59 return files, matchfn, walk()
59 return files, matchfn, walk()
60
60
61 def walk(repo, pats, opts, node=None, head='', badmatch=None):
61 def walk(repo, pats, opts, node=None, head='', badmatch=None):
62 files, matchfn, results = makewalk(repo, pats, opts, node, head, badmatch)
62 files, matchfn, results = makewalk(repo, pats, opts, node, head, badmatch)
63 for r in results:
63 for r in results:
64 yield r
64 yield r
65
65
66 def walkchangerevs(ui, repo, pats, opts):
66 def walkchangerevs(ui, repo, pats, opts):
67 '''Iterate over files and the revs they changed in.
67 '''Iterate over files and the revs they changed in.
68
68
69 Callers most commonly need to iterate backwards over the history
69 Callers most commonly need to iterate backwards over the history
70 it is interested in. Doing so has awful (quadratic-looking)
70 it is interested in. Doing so has awful (quadratic-looking)
71 performance, so we use iterators in a "windowed" way.
71 performance, so we use iterators in a "windowed" way.
72
72
73 We walk a window of revisions in the desired order. Within the
73 We walk a window of revisions in the desired order. Within the
74 window, we first walk forwards to gather data, then in the desired
74 window, we first walk forwards to gather data, then in the desired
75 order (usually backwards) to display it.
75 order (usually backwards) to display it.
76
76
77 This function returns an (iterator, getchange, matchfn) tuple. The
77 This function returns an (iterator, getchange, matchfn) tuple. The
78 getchange function returns the changelog entry for a numeric
78 getchange function returns the changelog entry for a numeric
79 revision. The iterator yields 3-tuples. They will be of one of
79 revision. The iterator yields 3-tuples. They will be of one of
80 the following forms:
80 the following forms:
81
81
82 "window", incrementing, lastrev: stepping through a window,
82 "window", incrementing, lastrev: stepping through a window,
83 positive if walking forwards through revs, last rev in the
83 positive if walking forwards through revs, last rev in the
84 sequence iterated over - use to reset state for the current window
84 sequence iterated over - use to reset state for the current window
85
85
86 "add", rev, fns: out-of-order traversal of the given file names
86 "add", rev, fns: out-of-order traversal of the given file names
87 fns, which changed during revision rev - use to gather data for
87 fns, which changed during revision rev - use to gather data for
88 possible display
88 possible display
89
89
90 "iter", rev, None: in-order traversal of the revs earlier iterated
90 "iter", rev, None: in-order traversal of the revs earlier iterated
91 over with "add" - use to display data'''
91 over with "add" - use to display data'''
92
92
93 def increasing_windows(start, end, windowsize=8, sizelimit=512):
93 def increasing_windows(start, end, windowsize=8, sizelimit=512):
94 if start < end:
94 if start < end:
95 while start < end:
95 while start < end:
96 yield start, min(windowsize, end-start)
96 yield start, min(windowsize, end-start)
97 start += windowsize
97 start += windowsize
98 if windowsize < sizelimit:
98 if windowsize < sizelimit:
99 windowsize *= 2
99 windowsize *= 2
100 else:
100 else:
101 while start > end:
101 while start > end:
102 yield start, min(windowsize, start-end-1)
102 yield start, min(windowsize, start-end-1)
103 start -= windowsize
103 start -= windowsize
104 if windowsize < sizelimit:
104 if windowsize < sizelimit:
105 windowsize *= 2
105 windowsize *= 2
106
106
107
107
108 files, matchfn, anypats = matchpats(repo, pats, opts)
108 files, matchfn, anypats = matchpats(repo, pats, opts)
109
109
110 if repo.changelog.count() == 0:
110 if repo.changelog.count() == 0:
111 return [], False, matchfn
111 return [], False, matchfn
112
112
113 revs = map(int, revrange(ui, repo, opts['rev'] or ['tip:0']))
113 revs = map(int, revrange(ui, repo, opts['rev'] or ['tip:0']))
114 wanted = {}
114 wanted = {}
115 slowpath = anypats
115 slowpath = anypats
116 fncache = {}
116 fncache = {}
117
117
118 chcache = {}
118 chcache = {}
119 def getchange(rev):
119 def getchange(rev):
120 ch = chcache.get(rev)
120 ch = chcache.get(rev)
121 if ch is None:
121 if ch is None:
122 chcache[rev] = ch = repo.changelog.read(repo.lookup(str(rev)))
122 chcache[rev] = ch = repo.changelog.read(repo.lookup(str(rev)))
123 return ch
123 return ch
124
124
125 if not slowpath and not files:
125 if not slowpath and not files:
126 # No files, no patterns. Display all revs.
126 # No files, no patterns. Display all revs.
127 wanted = dict(zip(revs, revs))
127 wanted = dict(zip(revs, revs))
128 if not slowpath:
128 if not slowpath:
129 # Only files, no patterns. Check the history of each file.
129 # Only files, no patterns. Check the history of each file.
130 def filerevgen(filelog):
130 def filerevgen(filelog):
131 for i, window in increasing_windows(filelog.count()-1, -1):
131 for i, window in increasing_windows(filelog.count()-1, -1):
132 revs = []
132 revs = []
133 for j in xrange(i - window, i + 1):
133 for j in xrange(i - window, i + 1):
134 revs.append(filelog.linkrev(filelog.node(j)))
134 revs.append(filelog.linkrev(filelog.node(j)))
135 revs.reverse()
135 revs.reverse()
136 for rev in revs:
136 for rev in revs:
137 yield rev
137 yield rev
138
138
139 minrev, maxrev = min(revs), max(revs)
139 minrev, maxrev = min(revs), max(revs)
140 for file_ in files:
140 for file_ in files:
141 filelog = repo.file(file_)
141 filelog = repo.file(file_)
142 # A zero count may be a directory or deleted file, so
142 # A zero count may be a directory or deleted file, so
143 # try to find matching entries on the slow path.
143 # try to find matching entries on the slow path.
144 if filelog.count() == 0:
144 if filelog.count() == 0:
145 slowpath = True
145 slowpath = True
146 break
146 break
147 for rev in filerevgen(filelog):
147 for rev in filerevgen(filelog):
148 if rev <= maxrev:
148 if rev <= maxrev:
149 if rev < minrev:
149 if rev < minrev:
150 break
150 break
151 fncache.setdefault(rev, [])
151 fncache.setdefault(rev, [])
152 fncache[rev].append(file_)
152 fncache[rev].append(file_)
153 wanted[rev] = 1
153 wanted[rev] = 1
154 if slowpath:
154 if slowpath:
155 # The slow path checks files modified in every changeset.
155 # The slow path checks files modified in every changeset.
156 def changerevgen():
156 def changerevgen():
157 for i, window in increasing_windows(repo.changelog.count()-1, -1):
157 for i, window in increasing_windows(repo.changelog.count()-1, -1):
158 for j in xrange(i - window, i + 1):
158 for j in xrange(i - window, i + 1):
159 yield j, getchange(j)[3]
159 yield j, getchange(j)[3]
160
160
161 for rev, changefiles in changerevgen():
161 for rev, changefiles in changerevgen():
162 matches = filter(matchfn, changefiles)
162 matches = filter(matchfn, changefiles)
163 if matches:
163 if matches:
164 fncache[rev] = matches
164 fncache[rev] = matches
165 wanted[rev] = 1
165 wanted[rev] = 1
166
166
167 def iterate():
167 def iterate():
168 for i, window in increasing_windows(0, len(revs)):
168 for i, window in increasing_windows(0, len(revs)):
169 yield 'window', revs[0] < revs[-1], revs[-1]
169 yield 'window', revs[0] < revs[-1], revs[-1]
170 nrevs = [rev for rev in revs[i:i+window]
170 nrevs = [rev for rev in revs[i:i+window]
171 if rev in wanted]
171 if rev in wanted]
172 srevs = list(nrevs)
172 srevs = list(nrevs)
173 srevs.sort()
173 srevs.sort()
174 for rev in srevs:
174 for rev in srevs:
175 fns = fncache.get(rev) or filter(matchfn, getchange(rev)[3])
175 fns = fncache.get(rev) or filter(matchfn, getchange(rev)[3])
176 yield 'add', rev, fns
176 yield 'add', rev, fns
177 for rev in nrevs:
177 for rev in nrevs:
178 yield 'iter', rev, None
178 yield 'iter', rev, None
179 return iterate(), getchange, matchfn
179 return iterate(), getchange, matchfn
180
180
181 revrangesep = ':'
181 revrangesep = ':'
182
182
183 def revfix(repo, val, defval):
183 def revfix(repo, val, defval):
184 '''turn user-level id of changeset into rev number.
184 '''turn user-level id of changeset into rev number.
185 user-level id can be tag, changeset, rev number, or negative rev
185 user-level id can be tag, changeset, rev number, or negative rev
186 number relative to number of revs (-1 is tip, etc).'''
186 number relative to number of revs (-1 is tip, etc).'''
187 if not val:
187 if not val:
188 return defval
188 return defval
189 try:
189 try:
190 num = int(val)
190 num = int(val)
191 if str(num) != val:
191 if str(num) != val:
192 raise ValueError
192 raise ValueError
193 if num < 0:
193 if num < 0:
194 num += repo.changelog.count()
194 num += repo.changelog.count()
195 if num < 0:
195 if num < 0:
196 num = 0
196 num = 0
197 elif num >= repo.changelog.count():
197 elif num >= repo.changelog.count():
198 raise ValueError
198 raise ValueError
199 except ValueError:
199 except ValueError:
200 try:
200 try:
201 num = repo.changelog.rev(repo.lookup(val))
201 num = repo.changelog.rev(repo.lookup(val))
202 except KeyError:
202 except KeyError:
203 raise util.Abort(_('invalid revision identifier %s'), val)
203 raise util.Abort(_('invalid revision identifier %s'), val)
204 return num
204 return num
205
205
206 def revpair(ui, repo, revs):
206 def revpair(ui, repo, revs):
207 '''return pair of nodes, given list of revisions. second item can
207 '''return pair of nodes, given list of revisions. second item can
208 be None, meaning use working dir.'''
208 be None, meaning use working dir.'''
209 if not revs:
209 if not revs:
210 return repo.dirstate.parents()[0], None
210 return repo.dirstate.parents()[0], None
211 end = None
211 end = None
212 if len(revs) == 1:
212 if len(revs) == 1:
213 start = revs[0]
213 start = revs[0]
214 if revrangesep in start:
214 if revrangesep in start:
215 start, end = start.split(revrangesep, 1)
215 start, end = start.split(revrangesep, 1)
216 start = revfix(repo, start, 0)
216 start = revfix(repo, start, 0)
217 end = revfix(repo, end, repo.changelog.count() - 1)
217 end = revfix(repo, end, repo.changelog.count() - 1)
218 else:
218 else:
219 start = revfix(repo, start, None)
219 start = revfix(repo, start, None)
220 elif len(revs) == 2:
220 elif len(revs) == 2:
221 if revrangesep in revs[0] or revrangesep in revs[1]:
221 if revrangesep in revs[0] or revrangesep in revs[1]:
222 raise util.Abort(_('too many revisions specified'))
222 raise util.Abort(_('too many revisions specified'))
223 start = revfix(repo, revs[0], None)
223 start = revfix(repo, revs[0], None)
224 end = revfix(repo, revs[1], None)
224 end = revfix(repo, revs[1], None)
225 else:
225 else:
226 raise util.Abort(_('too many revisions specified'))
226 raise util.Abort(_('too many revisions specified'))
227 if end is not None: end = repo.lookup(str(end))
227 if end is not None: end = repo.lookup(str(end))
228 return repo.lookup(str(start)), end
228 return repo.lookup(str(start)), end
229
229
230 def revrange(ui, repo, revs):
230 def revrange(ui, repo, revs):
231 """Yield revision as strings from a list of revision specifications."""
231 """Yield revision as strings from a list of revision specifications."""
232 seen = {}
232 seen = {}
233 for spec in revs:
233 for spec in revs:
234 if spec.find(revrangesep) >= 0:
234 if spec.find(revrangesep) >= 0:
235 start, end = spec.split(revrangesep, 1)
235 start, end = spec.split(revrangesep, 1)
236 start = revfix(repo, start, 0)
236 start = revfix(repo, start, 0)
237 end = revfix(repo, end, repo.changelog.count() - 1)
237 end = revfix(repo, end, repo.changelog.count() - 1)
238 step = start > end and -1 or 1
238 step = start > end and -1 or 1
239 for rev in xrange(start, end+step, step):
239 for rev in xrange(start, end+step, step):
240 if rev in seen:
240 if rev in seen:
241 continue
241 continue
242 seen[rev] = 1
242 seen[rev] = 1
243 yield str(rev)
243 yield str(rev)
244 else:
244 else:
245 rev = revfix(repo, spec, None)
245 rev = revfix(repo, spec, None)
246 if rev in seen:
246 if rev in seen:
247 continue
247 continue
248 seen[rev] = 1
248 seen[rev] = 1
249 yield str(rev)
249 yield str(rev)
250
250
251 def make_filename(repo, r, pat, node=None,
251 def make_filename(repo, r, pat, node=None,
252 total=None, seqno=None, revwidth=None, pathname=None):
252 total=None, seqno=None, revwidth=None, pathname=None):
253 node_expander = {
253 node_expander = {
254 'H': lambda: hex(node),
254 'H': lambda: hex(node),
255 'R': lambda: str(r.rev(node)),
255 'R': lambda: str(r.rev(node)),
256 'h': lambda: short(node),
256 'h': lambda: short(node),
257 }
257 }
258 expander = {
258 expander = {
259 '%': lambda: '%',
259 '%': lambda: '%',
260 'b': lambda: os.path.basename(repo.root),
260 'b': lambda: os.path.basename(repo.root),
261 }
261 }
262
262
263 try:
263 try:
264 if node:
264 if node:
265 expander.update(node_expander)
265 expander.update(node_expander)
266 if node and revwidth is not None:
266 if node and revwidth is not None:
267 expander['r'] = lambda: str(r.rev(node)).zfill(revwidth)
267 expander['r'] = lambda: str(r.rev(node)).zfill(revwidth)
268 if total is not None:
268 if total is not None:
269 expander['N'] = lambda: str(total)
269 expander['N'] = lambda: str(total)
270 if seqno is not None:
270 if seqno is not None:
271 expander['n'] = lambda: str(seqno)
271 expander['n'] = lambda: str(seqno)
272 if total is not None and seqno is not None:
272 if total is not None and seqno is not None:
273 expander['n'] = lambda:str(seqno).zfill(len(str(total)))
273 expander['n'] = lambda:str(seqno).zfill(len(str(total)))
274 if pathname is not None:
274 if pathname is not None:
275 expander['s'] = lambda: os.path.basename(pathname)
275 expander['s'] = lambda: os.path.basename(pathname)
276 expander['d'] = lambda: os.path.dirname(pathname) or '.'
276 expander['d'] = lambda: os.path.dirname(pathname) or '.'
277 expander['p'] = lambda: pathname
277 expander['p'] = lambda: pathname
278
278
279 newname = []
279 newname = []
280 patlen = len(pat)
280 patlen = len(pat)
281 i = 0
281 i = 0
282 while i < patlen:
282 while i < patlen:
283 c = pat[i]
283 c = pat[i]
284 if c == '%':
284 if c == '%':
285 i += 1
285 i += 1
286 c = pat[i]
286 c = pat[i]
287 c = expander[c]()
287 c = expander[c]()
288 newname.append(c)
288 newname.append(c)
289 i += 1
289 i += 1
290 return ''.join(newname)
290 return ''.join(newname)
291 except KeyError, inst:
291 except KeyError, inst:
292 raise util.Abort(_("invalid format spec '%%%s' in output file name"),
292 raise util.Abort(_("invalid format spec '%%%s' in output file name"),
293 inst.args[0])
293 inst.args[0])
294
294
295 def make_file(repo, r, pat, node=None,
295 def make_file(repo, r, pat, node=None,
296 total=None, seqno=None, revwidth=None, mode='wb', pathname=None):
296 total=None, seqno=None, revwidth=None, mode='wb', pathname=None):
297 if not pat or pat == '-':
297 if not pat or pat == '-':
298 return 'w' in mode and sys.stdout or sys.stdin
298 return 'w' in mode and sys.stdout or sys.stdin
299 if hasattr(pat, 'write') and 'w' in mode:
299 if hasattr(pat, 'write') and 'w' in mode:
300 return pat
300 return pat
301 if hasattr(pat, 'read') and 'r' in mode:
301 if hasattr(pat, 'read') and 'r' in mode:
302 return pat
302 return pat
303 return open(make_filename(repo, r, pat, node, total, seqno, revwidth,
303 return open(make_filename(repo, r, pat, node, total, seqno, revwidth,
304 pathname),
304 pathname),
305 mode)
305 mode)
306
306
307 def write_bundle(cg, filename=None, compress=True):
307 def write_bundle(cg, filename=None, compress=True):
308 """Write a bundle file and return its filename.
308 """Write a bundle file and return its filename.
309
309
310 Existing files will not be overwritten.
310 Existing files will not be overwritten.
311 If no filename is specified, a temporary file is created.
311 If no filename is specified, a temporary file is created.
312 bz2 compression can be turned off.
312 bz2 compression can be turned off.
313 The bundle file will be deleted in case of errors.
313 The bundle file will be deleted in case of errors.
314 """
314 """
315 class nocompress(object):
315 class nocompress(object):
316 def compress(self, x):
316 def compress(self, x):
317 return x
317 return x
318 def flush(self):
318 def flush(self):
319 return ""
319 return ""
320
320
321 fh = None
321 fh = None
322 cleanup = None
322 cleanup = None
323 try:
323 try:
324 if filename:
324 if filename:
325 if os.path.exists(filename):
325 if os.path.exists(filename):
326 raise util.Abort(_("file '%s' already exists"), filename)
326 raise util.Abort(_("file '%s' already exists"), filename)
327 fh = open(filename, "wb")
327 fh = open(filename, "wb")
328 else:
328 else:
329 fd, filename = tempfile.mkstemp(prefix="hg-bundle-", suffix=".hg")
329 fd, filename = tempfile.mkstemp(prefix="hg-bundle-", suffix=".hg")
330 fh = os.fdopen(fd, "wb")
330 fh = os.fdopen(fd, "wb")
331 cleanup = filename
331 cleanup = filename
332
332
333 if compress:
333 if compress:
334 fh.write("HG10")
334 fh.write("HG10")
335 z = bz2.BZ2Compressor(9)
335 z = bz2.BZ2Compressor(9)
336 else:
336 else:
337 fh.write("HG10UN")
337 fh.write("HG10UN")
338 z = nocompress()
338 z = nocompress()
339 # parse the changegroup data, otherwise we will block
339 # parse the changegroup data, otherwise we will block
340 # in case of sshrepo because we don't know the end of the stream
340 # in case of sshrepo because we don't know the end of the stream
341
341
342 # an empty chunkiter is the end of the changegroup
342 # an empty chunkiter is the end of the changegroup
343 empty = False
343 empty = False
344 while not empty:
344 while not empty:
345 empty = True
345 empty = True
346 for chunk in changegroup.chunkiter(cg):
346 for chunk in changegroup.chunkiter(cg):
347 empty = False
347 empty = False
348 fh.write(z.compress(changegroup.genchunk(chunk)))
348 fh.write(z.compress(changegroup.genchunk(chunk)))
349 fh.write(z.compress(changegroup.closechunk()))
349 fh.write(z.compress(changegroup.closechunk()))
350 fh.write(z.flush())
350 fh.write(z.flush())
351 cleanup = None
351 cleanup = None
352 return filename
352 return filename
353 finally:
353 finally:
354 if fh is not None:
354 if fh is not None:
355 fh.close()
355 fh.close()
356 if cleanup is not None:
356 if cleanup is not None:
357 os.unlink(cleanup)
357 os.unlink(cleanup)
358
358
359 def dodiff(fp, ui, repo, node1, node2, files=None, match=util.always,
359 def dodiff(fp, ui, repo, node1, node2, files=None, match=util.always,
360 changes=None, text=False, opts={}):
360 changes=None, text=False, opts={}):
361 if not node1:
361 if not node1:
362 node1 = repo.dirstate.parents()[0]
362 node1 = repo.dirstate.parents()[0]
363 # reading the data for node1 early allows it to play nicely
363 # reading the data for node1 early allows it to play nicely
364 # with repo.changes and the revlog cache.
364 # with repo.changes and the revlog cache.
365 change = repo.changelog.read(node1)
365 change = repo.changelog.read(node1)
366 mmap = repo.manifest.read(change[0])
366 mmap = repo.manifest.read(change[0])
367 date1 = util.datestr(change[2])
367 date1 = util.datestr(change[2])
368
368
369 if not changes:
369 if not changes:
370 changes = repo.changes(node1, node2, files, match=match)
370 changes = repo.changes(node1, node2, files, match=match)
371 modified, added, removed, deleted, unknown = changes
371 modified, added, removed, deleted, unknown = changes
372 if files:
372 if files:
373 modified, added, removed = map(lambda x: filterfiles(files, x),
373 modified, added, removed = map(lambda x: filterfiles(files, x),
374 (modified, added, removed))
374 (modified, added, removed))
375
375
376 if not modified and not added and not removed:
376 if not modified and not added and not removed:
377 return
377 return
378
378
379 if node2:
379 if node2:
380 change = repo.changelog.read(node2)
380 change = repo.changelog.read(node2)
381 mmap2 = repo.manifest.read(change[0])
381 mmap2 = repo.manifest.read(change[0])
382 _date2 = util.datestr(change[2])
382 _date2 = util.datestr(change[2])
383 def date2(f):
383 def date2(f):
384 return _date2
384 return _date2
385 def read(f):
385 def read(f):
386 return repo.file(f).read(mmap2[f])
386 return repo.file(f).read(mmap2[f])
387 else:
387 else:
388 tz = util.makedate()[1]
388 tz = util.makedate()[1]
389 _date2 = util.datestr()
389 _date2 = util.datestr()
390 def date2(f):
390 def date2(f):
391 try:
391 try:
392 return util.datestr((os.lstat(repo.wjoin(f)).st_mtime, tz))
392 return util.datestr((os.lstat(repo.wjoin(f)).st_mtime, tz))
393 except OSError, err:
393 except OSError, err:
394 if err.errno != errno.ENOENT: raise
394 if err.errno != errno.ENOENT: raise
395 return _date2
395 return _date2
396 def read(f):
396 def read(f):
397 return repo.wread(f)
397 return repo.wread(f)
398
398
399 if ui.quiet:
399 if ui.quiet:
400 r = None
400 r = None
401 else:
401 else:
402 hexfunc = ui.verbose and hex or short
402 hexfunc = ui.verbose and hex or short
403 r = [hexfunc(node) for node in [node1, node2] if node]
403 r = [hexfunc(node) for node in [node1, node2] if node]
404
404
405 diffopts = ui.diffopts()
405 diffopts = ui.diffopts()
406 showfunc = opts.get('show_function') or diffopts['showfunc']
406 showfunc = opts.get('show_function') or diffopts['showfunc']
407 ignorews = opts.get('ignore_all_space') or diffopts['ignorews']
407 ignorews = opts.get('ignore_all_space') or diffopts['ignorews']
408 for f in modified:
408 for f in modified:
409 to = None
409 to = None
410 if f in mmap:
410 if f in mmap:
411 to = repo.file(f).read(mmap[f])
411 to = repo.file(f).read(mmap[f])
412 tn = read(f)
412 tn = read(f)
413 fp.write(mdiff.unidiff(to, date1, tn, date2(f), f, r, text=text,
413 fp.write(mdiff.unidiff(to, date1, tn, date2(f), f, r, text=text,
414 showfunc=showfunc, ignorews=ignorews))
414 showfunc=showfunc, ignorews=ignorews))
415 for f in added:
415 for f in added:
416 to = None
416 to = None
417 tn = read(f)
417 tn = read(f)
418 fp.write(mdiff.unidiff(to, date1, tn, date2(f), f, r, text=text,
418 fp.write(mdiff.unidiff(to, date1, tn, date2(f), f, r, text=text,
419 showfunc=showfunc, ignorews=ignorews))
419 showfunc=showfunc, ignorews=ignorews))
420 for f in removed:
420 for f in removed:
421 to = repo.file(f).read(mmap[f])
421 to = repo.file(f).read(mmap[f])
422 tn = None
422 tn = None
423 fp.write(mdiff.unidiff(to, date1, tn, date2(f), f, r, text=text,
423 fp.write(mdiff.unidiff(to, date1, tn, date2(f), f, r, text=text,
424 showfunc=showfunc, ignorews=ignorews))
424 showfunc=showfunc, ignorews=ignorews))
425
425
426 def trimuser(ui, name, rev, revcache):
426 def trimuser(ui, name, rev, revcache):
427 """trim the name of the user who committed a change"""
427 """trim the name of the user who committed a change"""
428 user = revcache.get(rev)
428 user = revcache.get(rev)
429 if user is None:
429 if user is None:
430 user = revcache[rev] = ui.shortuser(name)
430 user = revcache[rev] = ui.shortuser(name)
431 return user
431 return user
432
432
433 class changeset_printer(object):
433 class changeset_printer(object):
434 '''show changeset information when templating not requested.'''
434 '''show changeset information when templating not requested.'''
435
435
436 def __init__(self, ui, repo):
436 def __init__(self, ui, repo):
437 self.ui = ui
437 self.ui = ui
438 self.repo = repo
438 self.repo = repo
439
439
440 def show(self, rev=0, changenode=None, brinfo=None):
440 def show(self, rev=0, changenode=None, brinfo=None):
441 '''show a single changeset or file revision'''
441 '''show a single changeset or file revision'''
442 log = self.repo.changelog
442 log = self.repo.changelog
443 if changenode is None:
443 if changenode is None:
444 changenode = log.node(rev)
444 changenode = log.node(rev)
445 elif not rev:
445 elif not rev:
446 rev = log.rev(changenode)
446 rev = log.rev(changenode)
447
447
448 if self.ui.quiet:
448 if self.ui.quiet:
449 self.ui.write("%d:%s\n" % (rev, short(changenode)))
449 self.ui.write("%d:%s\n" % (rev, short(changenode)))
450 return
450 return
451
451
452 changes = log.read(changenode)
452 changes = log.read(changenode)
453 date = util.datestr(changes[2])
453 date = util.datestr(changes[2])
454
454
455 parents = [(log.rev(p), self.ui.verbose and hex(p) or short(p))
455 parents = [(log.rev(p), self.ui.verbose and hex(p) or short(p))
456 for p in log.parents(changenode)
456 for p in log.parents(changenode)
457 if self.ui.debugflag or p != nullid]
457 if self.ui.debugflag or p != nullid]
458 if (not self.ui.debugflag and len(parents) == 1 and
458 if (not self.ui.debugflag and len(parents) == 1 and
459 parents[0][0] == rev-1):
459 parents[0][0] == rev-1):
460 parents = []
460 parents = []
461
461
462 if self.ui.verbose:
462 if self.ui.verbose:
463 self.ui.write(_("changeset: %d:%s\n") % (rev, hex(changenode)))
463 self.ui.write(_("changeset: %d:%s\n") % (rev, hex(changenode)))
464 else:
464 else:
465 self.ui.write(_("changeset: %d:%s\n") % (rev, short(changenode)))
465 self.ui.write(_("changeset: %d:%s\n") % (rev, short(changenode)))
466
466
467 for tag in self.repo.nodetags(changenode):
467 for tag in self.repo.nodetags(changenode):
468 self.ui.status(_("tag: %s\n") % tag)
468 self.ui.status(_("tag: %s\n") % tag)
469 for parent in parents:
469 for parent in parents:
470 self.ui.write(_("parent: %d:%s\n") % parent)
470 self.ui.write(_("parent: %d:%s\n") % parent)
471
471
472 if brinfo and changenode in brinfo:
472 if brinfo and changenode in brinfo:
473 br = brinfo[changenode]
473 br = brinfo[changenode]
474 self.ui.write(_("branch: %s\n") % " ".join(br))
474 self.ui.write(_("branch: %s\n") % " ".join(br))
475
475
476 self.ui.debug(_("manifest: %d:%s\n") %
476 self.ui.debug(_("manifest: %d:%s\n") %
477 (self.repo.manifest.rev(changes[0]), hex(changes[0])))
477 (self.repo.manifest.rev(changes[0]), hex(changes[0])))
478 self.ui.status(_("user: %s\n") % changes[1])
478 self.ui.status(_("user: %s\n") % changes[1])
479 self.ui.status(_("date: %s\n") % date)
479 self.ui.status(_("date: %s\n") % date)
480
480
481 if self.ui.debugflag:
481 if self.ui.debugflag:
482 files = self.repo.changes(log.parents(changenode)[0], changenode)
482 files = self.repo.changes(log.parents(changenode)[0], changenode)
483 for key, value in zip([_("files:"), _("files+:"), _("files-:")],
483 for key, value in zip([_("files:"), _("files+:"), _("files-:")],
484 files):
484 files):
485 if value:
485 if value:
486 self.ui.note("%-12s %s\n" % (key, " ".join(value)))
486 self.ui.note("%-12s %s\n" % (key, " ".join(value)))
487 else:
487 else:
488 self.ui.note(_("files: %s\n") % " ".join(changes[3]))
488 self.ui.note(_("files: %s\n") % " ".join(changes[3]))
489
489
490 description = changes[4].strip()
490 description = changes[4].strip()
491 if description:
491 if description:
492 if self.ui.verbose:
492 if self.ui.verbose:
493 self.ui.status(_("description:\n"))
493 self.ui.status(_("description:\n"))
494 self.ui.status(description)
494 self.ui.status(description)
495 self.ui.status("\n\n")
495 self.ui.status("\n\n")
496 else:
496 else:
497 self.ui.status(_("summary: %s\n") %
497 self.ui.status(_("summary: %s\n") %
498 description.splitlines()[0])
498 description.splitlines()[0])
499 self.ui.status("\n")
499 self.ui.status("\n")
500
500
501 def show_changeset(ui, repo, opts):
501 def show_changeset(ui, repo, opts):
502 '''show one changeset. uses template or regular display. caller
502 '''show one changeset. uses template or regular display. caller
503 can pass in 'style' and 'template' options in opts.'''
503 can pass in 'style' and 'template' options in opts.'''
504
504
505 tmpl = opts.get('template')
505 tmpl = opts.get('template')
506 if tmpl:
506 if tmpl:
507 tmpl = templater.parsestring(tmpl, quoted=False)
507 tmpl = templater.parsestring(tmpl, quoted=False)
508 else:
508 else:
509 tmpl = ui.config('ui', 'logtemplate')
509 tmpl = ui.config('ui', 'logtemplate')
510 if tmpl: tmpl = templater.parsestring(tmpl)
510 if tmpl: tmpl = templater.parsestring(tmpl)
511 mapfile = opts.get('style') or ui.config('ui', 'style')
511 mapfile = opts.get('style') or ui.config('ui', 'style')
512 if tmpl or mapfile:
512 if tmpl or mapfile:
513 if mapfile:
513 if mapfile:
514 if not os.path.isfile(mapfile):
514 if not os.path.isfile(mapfile):
515 mapname = templater.templatepath('map-cmdline.' + mapfile)
515 mapname = templater.templatepath('map-cmdline.' + mapfile)
516 if not mapname: mapname = templater.templatepath(mapfile)
516 if not mapname: mapname = templater.templatepath(mapfile)
517 if mapname: mapfile = mapname
517 if mapname: mapfile = mapname
518 try:
518 try:
519 t = templater.changeset_templater(ui, repo, mapfile)
519 t = templater.changeset_templater(ui, repo, mapfile)
520 except SyntaxError, inst:
520 except SyntaxError, inst:
521 raise util.Abort(inst.args[0])
521 raise util.Abort(inst.args[0])
522 if tmpl: t.use_template(tmpl)
522 if tmpl: t.use_template(tmpl)
523 return t
523 return t
524 return changeset_printer(ui, repo)
524 return changeset_printer(ui, repo)
525
525
526 def show_version(ui):
526 def show_version(ui):
527 """output version and copyright information"""
527 """output version and copyright information"""
528 ui.write(_("Mercurial Distributed SCM (version %s)\n")
528 ui.write(_("Mercurial Distributed SCM (version %s)\n")
529 % version.get_version())
529 % version.get_version())
530 ui.status(_(
530 ui.status(_(
531 "\nCopyright (C) 2005 Matt Mackall <mpm@selenic.com>\n"
531 "\nCopyright (C) 2005 Matt Mackall <mpm@selenic.com>\n"
532 "This is free software; see the source for copying conditions. "
532 "This is free software; see the source for copying conditions. "
533 "There is NO\nwarranty; "
533 "There is NO\nwarranty; "
534 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
534 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
535 ))
535 ))
536
536
537 def help_(ui, cmd=None, with_version=False):
537 def help_(ui, cmd=None, with_version=False):
538 """show help for a given command or all commands"""
538 """show help for a given command or all commands"""
539 option_lists = []
539 option_lists = []
540 if cmd and cmd != 'shortlist':
540 if cmd and cmd != 'shortlist':
541 if with_version:
541 if with_version:
542 show_version(ui)
542 show_version(ui)
543 ui.write('\n')
543 ui.write('\n')
544 aliases, i = find(cmd)
544 aliases, i = find(cmd)
545 # synopsis
545 # synopsis
546 ui.write("%s\n\n" % i[2])
546 ui.write("%s\n\n" % i[2])
547
547
548 # description
548 # description
549 doc = i[0].__doc__
549 doc = i[0].__doc__
550 if not doc:
550 if not doc:
551 doc = _("(No help text available)")
551 doc = _("(No help text available)")
552 if ui.quiet:
552 if ui.quiet:
553 doc = doc.splitlines(0)[0]
553 doc = doc.splitlines(0)[0]
554 ui.write("%s\n" % doc.rstrip())
554 ui.write("%s\n" % doc.rstrip())
555
555
556 if not ui.quiet:
556 if not ui.quiet:
557 # aliases
557 # aliases
558 if len(aliases) > 1:
558 if len(aliases) > 1:
559 ui.write(_("\naliases: %s\n") % ', '.join(aliases[1:]))
559 ui.write(_("\naliases: %s\n") % ', '.join(aliases[1:]))
560
560
561 # options
561 # options
562 if i[1]:
562 if i[1]:
563 option_lists.append(("options", i[1]))
563 option_lists.append(("options", i[1]))
564
564
565 else:
565 else:
566 # program name
566 # program name
567 if ui.verbose or with_version:
567 if ui.verbose or with_version:
568 show_version(ui)
568 show_version(ui)
569 else:
569 else:
570 ui.status(_("Mercurial Distributed SCM\n"))
570 ui.status(_("Mercurial Distributed SCM\n"))
571 ui.status('\n')
571 ui.status('\n')
572
572
573 # list of commands
573 # list of commands
574 if cmd == "shortlist":
574 if cmd == "shortlist":
575 ui.status(_('basic commands (use "hg help" '
575 ui.status(_('basic commands (use "hg help" '
576 'for the full list or option "-v" for details):\n\n'))
576 'for the full list or option "-v" for details):\n\n'))
577 elif ui.verbose:
577 elif ui.verbose:
578 ui.status(_('list of commands:\n\n'))
578 ui.status(_('list of commands:\n\n'))
579 else:
579 else:
580 ui.status(_('list of commands (use "hg help -v" '
580 ui.status(_('list of commands (use "hg help -v" '
581 'to show aliases and global options):\n\n'))
581 'to show aliases and global options):\n\n'))
582
582
583 h = {}
583 h = {}
584 cmds = {}
584 cmds = {}
585 for c, e in table.items():
585 for c, e in table.items():
586 f = c.split("|")[0]
586 f = c.split("|")[0]
587 if cmd == "shortlist" and not f.startswith("^"):
587 if cmd == "shortlist" and not f.startswith("^"):
588 continue
588 continue
589 f = f.lstrip("^")
589 f = f.lstrip("^")
590 if not ui.debugflag and f.startswith("debug"):
590 if not ui.debugflag and f.startswith("debug"):
591 continue
591 continue
592 doc = e[0].__doc__
592 doc = e[0].__doc__
593 if not doc:
593 if not doc:
594 doc = _("(No help text available)")
594 doc = _("(No help text available)")
595 h[f] = doc.splitlines(0)[0].rstrip()
595 h[f] = doc.splitlines(0)[0].rstrip()
596 cmds[f] = c.lstrip("^")
596 cmds[f] = c.lstrip("^")
597
597
598 fns = h.keys()
598 fns = h.keys()
599 fns.sort()
599 fns.sort()
600 m = max(map(len, fns))
600 m = max(map(len, fns))
601 for f in fns:
601 for f in fns:
602 if ui.verbose:
602 if ui.verbose:
603 commands = cmds[f].replace("|",", ")
603 commands = cmds[f].replace("|",", ")
604 ui.write(" %s:\n %s\n"%(commands, h[f]))
604 ui.write(" %s:\n %s\n"%(commands, h[f]))
605 else:
605 else:
606 ui.write(' %-*s %s\n' % (m, f, h[f]))
606 ui.write(' %-*s %s\n' % (m, f, h[f]))
607
607
608 # global options
608 # global options
609 if ui.verbose:
609 if ui.verbose:
610 option_lists.append(("global options", globalopts))
610 option_lists.append(("global options", globalopts))
611
611
612 # list all option lists
612 # list all option lists
613 opt_output = []
613 opt_output = []
614 for title, options in option_lists:
614 for title, options in option_lists:
615 opt_output.append(("\n%s:\n" % title, None))
615 opt_output.append(("\n%s:\n" % title, None))
616 for shortopt, longopt, default, desc in options:
616 for shortopt, longopt, default, desc in options:
617 opt_output.append(("%2s%s" % (shortopt and "-%s" % shortopt,
617 opt_output.append(("%2s%s" % (shortopt and "-%s" % shortopt,
618 longopt and " --%s" % longopt),
618 longopt and " --%s" % longopt),
619 "%s%s" % (desc,
619 "%s%s" % (desc,
620 default
620 default
621 and _(" (default: %s)") % default
621 and _(" (default: %s)") % default
622 or "")))
622 or "")))
623
623
624 if opt_output:
624 if opt_output:
625 opts_len = max([len(line[0]) for line in opt_output if line[1]])
625 opts_len = max([len(line[0]) for line in opt_output if line[1]])
626 for first, second in opt_output:
626 for first, second in opt_output:
627 if second:
627 if second:
628 ui.write(" %-*s %s\n" % (opts_len, first, second))
628 ui.write(" %-*s %s\n" % (opts_len, first, second))
629 else:
629 else:
630 ui.write("%s\n" % first)
630 ui.write("%s\n" % first)
631
631
632 # Commands start here, listed alphabetically
632 # Commands start here, listed alphabetically
633
633
634 def add(ui, repo, *pats, **opts):
634 def add(ui, repo, *pats, **opts):
635 """add the specified files on the next commit
635 """add the specified files on the next commit
636
636
637 Schedule files to be version controlled and added to the repository.
637 Schedule files to be version controlled and added to the repository.
638
638
639 The files will be added to the repository at the next commit.
639 The files will be added to the repository at the next commit.
640
640
641 If no names are given, add all files in the repository.
641 If no names are given, add all files in the repository.
642 """
642 """
643
643
644 names = []
644 names = []
645 for src, abs, rel, exact in walk(repo, pats, opts):
645 for src, abs, rel, exact in walk(repo, pats, opts):
646 if exact:
646 if exact:
647 if ui.verbose:
647 if ui.verbose:
648 ui.status(_('adding %s\n') % rel)
648 ui.status(_('adding %s\n') % rel)
649 names.append(abs)
649 names.append(abs)
650 elif repo.dirstate.state(abs) == '?':
650 elif repo.dirstate.state(abs) == '?':
651 ui.status(_('adding %s\n') % rel)
651 ui.status(_('adding %s\n') % rel)
652 names.append(abs)
652 names.append(abs)
653 if not opts.get('dry_run'):
653 if not opts.get('dry_run'):
654 repo.add(names)
654 repo.add(names)
655
655
656 def addremove(ui, repo, *pats, **opts):
656 def addremove(ui, repo, *pats, **opts):
657 """add all new files, delete all missing files (DEPRECATED)
657 """add all new files, delete all missing files (DEPRECATED)
658
658
659 (DEPRECATED)
659 (DEPRECATED)
660 Add all new files and remove all missing files from the repository.
660 Add all new files and remove all missing files from the repository.
661
661
662 New files are ignored if they match any of the patterns in .hgignore. As
662 New files are ignored if they match any of the patterns in .hgignore. As
663 with add, these changes take effect at the next commit.
663 with add, these changes take effect at the next commit.
664
664
665 This command is now deprecated and will be removed in a future
665 This command is now deprecated and will be removed in a future
666 release. Please use add and remove --after instead.
666 release. Please use add and remove --after instead.
667 """
667 """
668 ui.warn(_('(the addremove command is deprecated; use add and remove '
668 ui.warn(_('(the addremove command is deprecated; use add and remove '
669 '--after instead)\n'))
669 '--after instead)\n'))
670 return addremove_lock(ui, repo, pats, opts)
670 return addremove_lock(ui, repo, pats, opts)
671
671
672 def addremove_lock(ui, repo, pats, opts, wlock=None):
672 def addremove_lock(ui, repo, pats, opts, wlock=None):
673 add, remove = [], []
673 add, remove = [], []
674 for src, abs, rel, exact in walk(repo, pats, opts):
674 for src, abs, rel, exact in walk(repo, pats, opts):
675 if src == 'f' and repo.dirstate.state(abs) == '?':
675 if src == 'f' and repo.dirstate.state(abs) == '?':
676 add.append(abs)
676 add.append(abs)
677 if ui.verbose or not exact:
677 if ui.verbose or not exact:
678 ui.status(_('adding %s\n') % ((pats and rel) or abs))
678 ui.status(_('adding %s\n') % ((pats and rel) or abs))
679 if repo.dirstate.state(abs) != 'r' and not os.path.exists(rel):
679 if repo.dirstate.state(abs) != 'r' and not os.path.exists(rel):
680 remove.append(abs)
680 remove.append(abs)
681 if ui.verbose or not exact:
681 if ui.verbose or not exact:
682 ui.status(_('removing %s\n') % ((pats and rel) or abs))
682 ui.status(_('removing %s\n') % ((pats and rel) or abs))
683 if not opts.get('dry_run'):
683 if not opts.get('dry_run'):
684 repo.add(add, wlock=wlock)
684 repo.add(add, wlock=wlock)
685 repo.remove(remove, wlock=wlock)
685 repo.remove(remove, wlock=wlock)
686
686
687 def annotate(ui, repo, *pats, **opts):
687 def annotate(ui, repo, *pats, **opts):
688 """show changeset information per file line
688 """show changeset information per file line
689
689
690 List changes in files, showing the revision id responsible for each line
690 List changes in files, showing the revision id responsible for each line
691
691
692 This command is useful to discover who did a change or when a change took
692 This command is useful to discover who did a change or when a change took
693 place.
693 place.
694
694
695 Without the -a option, annotate will avoid processing files it
695 Without the -a option, annotate will avoid processing files it
696 detects as binary. With -a, annotate will generate an annotation
696 detects as binary. With -a, annotate will generate an annotation
697 anyway, probably with undesirable results.
697 anyway, probably with undesirable results.
698 """
698 """
699 def getnode(rev):
699 def getnode(rev):
700 return short(repo.changelog.node(rev))
700 return short(repo.changelog.node(rev))
701
701
702 ucache = {}
702 ucache = {}
703 def getname(rev):
703 def getname(rev):
704 cl = repo.changelog.read(repo.changelog.node(rev))
704 cl = repo.changelog.read(repo.changelog.node(rev))
705 return trimuser(ui, cl[1], rev, ucache)
705 return trimuser(ui, cl[1], rev, ucache)
706
706
707 dcache = {}
707 dcache = {}
708 def getdate(rev):
708 def getdate(rev):
709 datestr = dcache.get(rev)
709 datestr = dcache.get(rev)
710 if datestr is None:
710 if datestr is None:
711 cl = repo.changelog.read(repo.changelog.node(rev))
711 cl = repo.changelog.read(repo.changelog.node(rev))
712 datestr = dcache[rev] = util.datestr(cl[2])
712 datestr = dcache[rev] = util.datestr(cl[2])
713 return datestr
713 return datestr
714
714
715 if not pats:
715 if not pats:
716 raise util.Abort(_('at least one file name or pattern required'))
716 raise util.Abort(_('at least one file name or pattern required'))
717
717
718 opmap = [['user', getname], ['number', str], ['changeset', getnode],
718 opmap = [['user', getname], ['number', str], ['changeset', getnode],
719 ['date', getdate]]
719 ['date', getdate]]
720 if not opts['user'] and not opts['changeset'] and not opts['date']:
720 if not opts['user'] and not opts['changeset'] and not opts['date']:
721 opts['number'] = 1
721 opts['number'] = 1
722
722
723 if opts['rev']:
723 if opts['rev']:
724 node = repo.changelog.lookup(opts['rev'])
724 node = repo.changelog.lookup(opts['rev'])
725 else:
725 else:
726 node = repo.dirstate.parents()[0]
726 node = repo.dirstate.parents()[0]
727 change = repo.changelog.read(node)
727 change = repo.changelog.read(node)
728 mmap = repo.manifest.read(change[0])
728 mmap = repo.manifest.read(change[0])
729
729
730 for src, abs, rel, exact in walk(repo, pats, opts, node=node):
730 for src, abs, rel, exact in walk(repo, pats, opts, node=node):
731 f = repo.file(abs)
731 f = repo.file(abs)
732 if not opts['text'] and util.binary(f.read(mmap[abs])):
732 if not opts['text'] and util.binary(f.read(mmap[abs])):
733 ui.write(_("%s: binary file\n") % ((pats and rel) or abs))
733 ui.write(_("%s: binary file\n") % ((pats and rel) or abs))
734 continue
734 continue
735
735
736 lines = f.annotate(mmap[abs])
736 lines = f.annotate(mmap[abs])
737 pieces = []
737 pieces = []
738
738
739 for o, f in opmap:
739 for o, f in opmap:
740 if opts[o]:
740 if opts[o]:
741 l = [f(n) for n, dummy in lines]
741 l = [f(n) for n, dummy in lines]
742 if l:
742 if l:
743 m = max(map(len, l))
743 m = max(map(len, l))
744 pieces.append(["%*s" % (m, x) for x in l])
744 pieces.append(["%*s" % (m, x) for x in l])
745
745
746 if pieces:
746 if pieces:
747 for p, l in zip(zip(*pieces), lines):
747 for p, l in zip(zip(*pieces), lines):
748 ui.write("%s: %s" % (" ".join(p), l[1]))
748 ui.write("%s: %s" % (" ".join(p), l[1]))
749
749
750 def archive(ui, repo, dest, **opts):
750 def archive(ui, repo, dest, **opts):
751 '''create unversioned archive of a repository revision
751 '''create unversioned archive of a repository revision
752
752
753 By default, the revision used is the parent of the working
753 By default, the revision used is the parent of the working
754 directory; use "-r" to specify a different revision.
754 directory; use "-r" to specify a different revision.
755
755
756 To specify the type of archive to create, use "-t". Valid
756 To specify the type of archive to create, use "-t". Valid
757 types are:
757 types are:
758
758
759 "files" (default): a directory full of files
759 "files" (default): a directory full of files
760 "tar": tar archive, uncompressed
760 "tar": tar archive, uncompressed
761 "tbz2": tar archive, compressed using bzip2
761 "tbz2": tar archive, compressed using bzip2
762 "tgz": tar archive, compressed using gzip
762 "tgz": tar archive, compressed using gzip
763 "uzip": zip archive, uncompressed
763 "uzip": zip archive, uncompressed
764 "zip": zip archive, compressed using deflate
764 "zip": zip archive, compressed using deflate
765
765
766 The exact name of the destination archive or directory is given
766 The exact name of the destination archive or directory is given
767 using a format string; see "hg help export" for details.
767 using a format string; see "hg help export" for details.
768
768
769 Each member added to an archive file has a directory prefix
769 Each member added to an archive file has a directory prefix
770 prepended. Use "-p" to specify a format string for the prefix.
770 prepended. Use "-p" to specify a format string for the prefix.
771 The default is the basename of the archive, with suffixes removed.
771 The default is the basename of the archive, with suffixes removed.
772 '''
772 '''
773
773
774 if opts['rev']:
774 if opts['rev']:
775 node = repo.lookup(opts['rev'])
775 node = repo.lookup(opts['rev'])
776 else:
776 else:
777 node, p2 = repo.dirstate.parents()
777 node, p2 = repo.dirstate.parents()
778 if p2 != nullid:
778 if p2 != nullid:
779 raise util.Abort(_('uncommitted merge - please provide a '
779 raise util.Abort(_('uncommitted merge - please provide a '
780 'specific revision'))
780 'specific revision'))
781
781
782 dest = make_filename(repo, repo.changelog, dest, node)
782 dest = make_filename(repo, repo.changelog, dest, node)
783 if os.path.realpath(dest) == repo.root:
783 if os.path.realpath(dest) == repo.root:
784 raise util.Abort(_('repository root cannot be destination'))
784 raise util.Abort(_('repository root cannot be destination'))
785 dummy, matchfn, dummy = matchpats(repo, [], opts)
785 dummy, matchfn, dummy = matchpats(repo, [], opts)
786 kind = opts.get('type') or 'files'
786 kind = opts.get('type') or 'files'
787 prefix = opts['prefix']
787 prefix = opts['prefix']
788 if dest == '-':
788 if dest == '-':
789 if kind == 'files':
789 if kind == 'files':
790 raise util.Abort(_('cannot archive plain files to stdout'))
790 raise util.Abort(_('cannot archive plain files to stdout'))
791 dest = sys.stdout
791 dest = sys.stdout
792 if not prefix: prefix = os.path.basename(repo.root) + '-%h'
792 if not prefix: prefix = os.path.basename(repo.root) + '-%h'
793 prefix = make_filename(repo, repo.changelog, prefix, node)
793 prefix = make_filename(repo, repo.changelog, prefix, node)
794 archival.archive(repo, dest, node, kind, not opts['no_decode'],
794 archival.archive(repo, dest, node, kind, not opts['no_decode'],
795 matchfn, prefix)
795 matchfn, prefix)
796
796
797 def backout(ui, repo, rev, **opts):
797 def backout(ui, repo, rev, **opts):
798 '''reverse effect of earlier changeset
798 '''reverse effect of earlier changeset
799
799
800 Commit the backed out changes as a new changeset. The new
800 Commit the backed out changes as a new changeset. The new
801 changeset is a child of the backed out changeset.
801 changeset is a child of the backed out changeset.
802
802
803 If you back out a changeset other than the tip, a new head is
803 If you back out a changeset other than the tip, a new head is
804 created. This head is the parent of the working directory. If
804 created. This head is the parent of the working directory. If
805 you back out an old changeset, your working directory will appear
805 you back out an old changeset, your working directory will appear
806 old after the backout. You should merge the backout changeset
806 old after the backout. You should merge the backout changeset
807 with another head.
807 with another head.
808
808
809 The --merge option remembers the parent of the working directory
809 The --merge option remembers the parent of the working directory
810 before starting the backout, then merges the new head with that
810 before starting the backout, then merges the new head with that
811 changeset afterwards. This saves you from doing the merge by
811 changeset afterwards. This saves you from doing the merge by
812 hand. The result of this merge is not committed, as for a normal
812 hand. The result of this merge is not committed, as for a normal
813 merge.'''
813 merge.'''
814
814
815 bail_if_changed(repo)
815 bail_if_changed(repo)
816 op1, op2 = repo.dirstate.parents()
816 op1, op2 = repo.dirstate.parents()
817 if op2 != nullid:
817 if op2 != nullid:
818 raise util.Abort(_('outstanding uncommitted merge'))
818 raise util.Abort(_('outstanding uncommitted merge'))
819 node = repo.lookup(rev)
819 node = repo.lookup(rev)
820 parent, p2 = repo.changelog.parents(node)
820 parent, p2 = repo.changelog.parents(node)
821 if parent == nullid:
821 if parent == nullid:
822 raise util.Abort(_('cannot back out a change with no parents'))
822 raise util.Abort(_('cannot back out a change with no parents'))
823 if p2 != nullid:
823 if p2 != nullid:
824 raise util.Abort(_('cannot back out a merge'))
824 raise util.Abort(_('cannot back out a merge'))
825 repo.update(node, force=True, show_stats=False)
825 repo.update(node, force=True, show_stats=False)
826 revert_opts = opts.copy()
826 revert_opts = opts.copy()
827 revert_opts['rev'] = hex(parent)
827 revert_opts['rev'] = hex(parent)
828 revert(ui, repo, **revert_opts)
828 revert(ui, repo, **revert_opts)
829 commit_opts = opts.copy()
829 commit_opts = opts.copy()
830 commit_opts['addremove'] = False
830 commit_opts['addremove'] = False
831 if not commit_opts['message'] and not commit_opts['logfile']:
831 if not commit_opts['message'] and not commit_opts['logfile']:
832 commit_opts['message'] = _("Backed out changeset %s") % (hex(node))
832 commit_opts['message'] = _("Backed out changeset %s") % (hex(node))
833 commit_opts['force_editor'] = True
833 commit_opts['force_editor'] = True
834 commit(ui, repo, **commit_opts)
834 commit(ui, repo, **commit_opts)
835 def nice(node):
835 def nice(node):
836 return '%d:%s' % (repo.changelog.rev(node), short(node))
836 return '%d:%s' % (repo.changelog.rev(node), short(node))
837 ui.status(_('changeset %s backs out changeset %s\n') %
837 ui.status(_('changeset %s backs out changeset %s\n') %
838 (nice(repo.changelog.tip()), nice(node)))
838 (nice(repo.changelog.tip()), nice(node)))
839 if op1 != node:
839 if op1 != node:
840 if opts['merge']:
840 if opts['merge']:
841 ui.status(_('merging with changeset %s\n') % nice(op1))
841 ui.status(_('merging with changeset %s\n') % nice(op1))
842 doupdate(ui, repo, hex(op1), **opts)
842 doupdate(ui, repo, hex(op1), **opts)
843 else:
843 else:
844 ui.status(_('the backout changeset is a new head - '
844 ui.status(_('the backout changeset is a new head - '
845 'do not forget to merge\n'))
845 'do not forget to merge\n'))
846 ui.status(_('(use "backout -m" if you want to auto-merge)\n'))
846 ui.status(_('(use "backout -m" if you want to auto-merge)\n'))
847
847
848 def bundle(ui, repo, fname, dest=None, **opts):
848 def bundle(ui, repo, fname, dest=None, **opts):
849 """create a changegroup file
849 """create a changegroup file
850
850
851 Generate a compressed changegroup file collecting all changesets
851 Generate a compressed changegroup file collecting all changesets
852 not found in the other repository.
852 not found in the other repository.
853
853
854 This file can then be transferred using conventional means and
854 This file can then be transferred using conventional means and
855 applied to another repository with the unbundle command. This is
855 applied to another repository with the unbundle command. This is
856 useful when native push and pull are not available or when
856 useful when native push and pull are not available or when
857 exporting an entire repository is undesirable. The standard file
857 exporting an entire repository is undesirable. The standard file
858 extension is ".hg".
858 extension is ".hg".
859
859
860 Unlike import/export, this exactly preserves all changeset
860 Unlike import/export, this exactly preserves all changeset
861 contents including permissions, rename data, and revision history.
861 contents including permissions, rename data, and revision history.
862 """
862 """
863 dest = ui.expandpath(dest or 'default-push', dest or 'default')
863 dest = ui.expandpath(dest or 'default-push', dest or 'default')
864 other = hg.repository(ui, dest)
864 other = hg.repository(ui, dest)
865 o = repo.findoutgoing(other, force=opts['force'])
865 o = repo.findoutgoing(other, force=opts['force'])
866 cg = repo.changegroup(o, 'bundle')
866 cg = repo.changegroup(o, 'bundle')
867 write_bundle(cg, fname)
867 write_bundle(cg, fname)
868
868
869 def cat(ui, repo, file1, *pats, **opts):
869 def cat(ui, repo, file1, *pats, **opts):
870 """output the latest or given revisions of files
870 """output the latest or given revisions of files
871
871
872 Print the specified files as they were at the given revision.
872 Print the specified files as they were at the given revision.
873 If no revision is given then the tip is used.
873 If no revision is given then the tip is used.
874
874
875 Output may be to a file, in which case the name of the file is
875 Output may be to a file, in which case the name of the file is
876 given using a format string. The formatting rules are the same as
876 given using a format string. The formatting rules are the same as
877 for the export command, with the following additions:
877 for the export command, with the following additions:
878
878
879 %s basename of file being printed
879 %s basename of file being printed
880 %d dirname of file being printed, or '.' if in repo root
880 %d dirname of file being printed, or '.' if in repo root
881 %p root-relative path name of file being printed
881 %p root-relative path name of file being printed
882 """
882 """
883 mf = {}
883 mf = {}
884 rev = opts['rev']
884 rev = opts['rev']
885 if rev:
885 if rev:
886 node = repo.lookup(rev)
886 node = repo.lookup(rev)
887 else:
887 else:
888 node = repo.changelog.tip()
888 node = repo.changelog.tip()
889 change = repo.changelog.read(node)
889 change = repo.changelog.read(node)
890 mf = repo.manifest.read(change[0])
890 mf = repo.manifest.read(change[0])
891 for src, abs, rel, exact in walk(repo, (file1,) + pats, opts, node):
891 for src, abs, rel, exact in walk(repo, (file1,) + pats, opts, node):
892 r = repo.file(abs)
892 r = repo.file(abs)
893 n = mf[abs]
893 n = mf[abs]
894 fp = make_file(repo, r, opts['output'], node=n, pathname=abs)
894 fp = make_file(repo, r, opts['output'], node=n, pathname=abs)
895 fp.write(r.read(n))
895 fp.write(r.read(n))
896
896
897 def clone(ui, source, dest=None, **opts):
897 def clone(ui, source, dest=None, **opts):
898 """make a copy of an existing repository
898 """make a copy of an existing repository
899
899
900 Create a copy of an existing repository in a new directory.
900 Create a copy of an existing repository in a new directory.
901
901
902 If no destination directory name is specified, it defaults to the
902 If no destination directory name is specified, it defaults to the
903 basename of the source.
903 basename of the source.
904
904
905 The location of the source is added to the new repository's
905 The location of the source is added to the new repository's
906 .hg/hgrc file, as the default to be used for future pulls.
906 .hg/hgrc file, as the default to be used for future pulls.
907
907
908 For efficiency, hardlinks are used for cloning whenever the source
908 For efficiency, hardlinks are used for cloning whenever the source
909 and destination are on the same filesystem. Some filesystems,
909 and destination are on the same filesystem. Some filesystems,
910 such as AFS, implement hardlinking incorrectly, but do not report
910 such as AFS, implement hardlinking incorrectly, but do not report
911 errors. In these cases, use the --pull option to avoid
911 errors. In these cases, use the --pull option to avoid
912 hardlinking.
912 hardlinking.
913
913
914 See pull for valid source format details.
914 See pull for valid source format details.
915 """
915 """
916 if dest is None:
916 if dest is None:
917 dest = os.path.basename(os.path.normpath(source))
917 dest = os.path.basename(os.path.normpath(source))
918
918
919 if os.path.exists(dest):
919 if os.path.exists(dest):
920 raise util.Abort(_("destination '%s' already exists"), dest)
920 raise util.Abort(_("destination '%s' already exists"), dest)
921
921
922 dest = os.path.realpath(dest)
922 dest = os.path.realpath(dest)
923
923
924 class Dircleanup(object):
924 class Dircleanup(object):
925 def __init__(self, dir_):
925 def __init__(self, dir_):
926 self.rmtree = shutil.rmtree
926 self.rmtree = shutil.rmtree
927 self.dir_ = dir_
927 self.dir_ = dir_
928 os.mkdir(dir_)
928 os.mkdir(dir_)
929 def close(self):
929 def close(self):
930 self.dir_ = None
930 self.dir_ = None
931 def __del__(self):
931 def __del__(self):
932 if self.dir_:
932 if self.dir_:
933 self.rmtree(self.dir_, True)
933 self.rmtree(self.dir_, True)
934
934
935 if opts['ssh']:
935 if opts['ssh']:
936 ui.setconfig("ui", "ssh", opts['ssh'])
936 ui.setconfig("ui", "ssh", opts['ssh'])
937 if opts['remotecmd']:
937 if opts['remotecmd']:
938 ui.setconfig("ui", "remotecmd", opts['remotecmd'])
938 ui.setconfig("ui", "remotecmd", opts['remotecmd'])
939
939
940 source = ui.expandpath(source)
940 source = ui.expandpath(source)
941
941
942 d = Dircleanup(dest)
942 d = Dircleanup(dest)
943 abspath = source
943 abspath = source
944 other = hg.repository(ui, source)
944 other = hg.repository(ui, source)
945
945
946 copy = False
946 copy = False
947 if other.dev() != -1:
947 if other.dev() != -1:
948 abspath = os.path.abspath(source)
948 abspath = os.path.abspath(source)
949 if not opts['pull'] and not opts['rev']:
949 if not opts['pull'] and not opts['rev']:
950 copy = True
950 copy = True
951
951
952 if copy:
952 if copy:
953 try:
953 try:
954 # we use a lock here because if we race with commit, we
954 # we use a lock here because if we race with commit, we
955 # can end up with extra data in the cloned revlogs that's
955 # can end up with extra data in the cloned revlogs that's
956 # not pointed to by changesets, thus causing verify to
956 # not pointed to by changesets, thus causing verify to
957 # fail
957 # fail
958 l1 = other.lock()
958 l1 = other.lock()
959 except lock.LockException:
959 except lock.LockException:
960 copy = False
960 copy = False
961
961
962 if copy:
962 if copy:
963 # we lock here to avoid premature writing to the target
963 # we lock here to avoid premature writing to the target
964 os.mkdir(os.path.join(dest, ".hg"))
964 os.mkdir(os.path.join(dest, ".hg"))
965 l2 = lock.lock(os.path.join(dest, ".hg", "lock"))
965 l2 = lock.lock(os.path.join(dest, ".hg", "lock"))
966
966
967 files = "data 00manifest.d 00manifest.i 00changelog.d 00changelog.i"
967 files = "data 00manifest.d 00manifest.i 00changelog.d 00changelog.i"
968 for f in files.split():
968 for f in files.split():
969 src = os.path.join(source, ".hg", f)
969 src = os.path.join(source, ".hg", f)
970 dst = os.path.join(dest, ".hg", f)
970 dst = os.path.join(dest, ".hg", f)
971 try:
971 try:
972 util.copyfiles(src, dst)
972 util.copyfiles(src, dst)
973 except OSError, inst:
973 except OSError, inst:
974 if inst.errno != errno.ENOENT:
974 if inst.errno != errno.ENOENT:
975 raise
975 raise
976
976
977 repo = hg.repository(ui, dest)
977 repo = hg.repository(ui, dest)
978
978
979 else:
979 else:
980 revs = None
980 revs = None
981 if opts['rev']:
981 if opts['rev']:
982 if not other.local():
982 if not other.local():
983 error = _("clone -r not supported yet for remote repositories.")
983 error = _("clone -r not supported yet for remote repositories.")
984 raise util.Abort(error)
984 raise util.Abort(error)
985 else:
985 else:
986 revs = [other.lookup(rev) for rev in opts['rev']]
986 revs = [other.lookup(rev) for rev in opts['rev']]
987 repo = hg.repository(ui, dest, create=1)
987 repo = hg.repository(ui, dest, create=1)
988 repo.pull(other, heads = revs)
988 repo.pull(other, heads = revs)
989
989
990 f = repo.opener("hgrc", "w", text=True)
990 f = repo.opener("hgrc", "w", text=True)
991 f.write("[paths]\n")
991 f.write("[paths]\n")
992 f.write("default = %s\n" % abspath)
992 f.write("default = %s\n" % abspath)
993 f.close()
993 f.close()
994
994
995 if not opts['noupdate']:
995 if not opts['noupdate']:
996 doupdate(repo.ui, repo)
996 doupdate(repo.ui, repo)
997
997
998 d.close()
998 d.close()
999
999
1000 def commit(ui, repo, *pats, **opts):
1000 def commit(ui, repo, *pats, **opts):
1001 """commit the specified files or all outstanding changes
1001 """commit the specified files or all outstanding changes
1002
1002
1003 Commit changes to the given files into the repository.
1003 Commit changes to the given files into the repository.
1004
1004
1005 If a list of files is omitted, all changes reported by "hg status"
1005 If a list of files is omitted, all changes reported by "hg status"
1006 will be committed.
1006 will be committed.
1007
1007
1008 If no commit message is specified, the editor configured in your hgrc
1008 If no commit message is specified, the editor configured in your hgrc
1009 or in the EDITOR environment variable is started to enter a message.
1009 or in the EDITOR environment variable is started to enter a message.
1010 """
1010 """
1011 message = opts['message']
1011 message = opts['message']
1012 logfile = opts['logfile']
1012 logfile = opts['logfile']
1013
1013
1014 if message and logfile:
1014 if message and logfile:
1015 raise util.Abort(_('options --message and --logfile are mutually '
1015 raise util.Abort(_('options --message and --logfile are mutually '
1016 'exclusive'))
1016 'exclusive'))
1017 if not message and logfile:
1017 if not message and logfile:
1018 try:
1018 try:
1019 if logfile == '-':
1019 if logfile == '-':
1020 message = sys.stdin.read()
1020 message = sys.stdin.read()
1021 else:
1021 else:
1022 message = open(logfile).read()
1022 message = open(logfile).read()
1023 except IOError, inst:
1023 except IOError, inst:
1024 raise util.Abort(_("can't read commit message '%s': %s") %
1024 raise util.Abort(_("can't read commit message '%s': %s") %
1025 (logfile, inst.strerror))
1025 (logfile, inst.strerror))
1026
1026
1027 if opts['addremove']:
1027 if opts['addremove']:
1028 addremove_lock(ui, repo, pats, opts)
1028 addremove_lock(ui, repo, pats, opts)
1029 fns, match, anypats = matchpats(repo, pats, opts)
1029 fns, match, anypats = matchpats(repo, pats, opts)
1030 if pats:
1030 if pats:
1031 modified, added, removed, deleted, unknown = (
1031 modified, added, removed, deleted, unknown = (
1032 repo.changes(files=fns, match=match))
1032 repo.changes(files=fns, match=match))
1033 files = modified + added + removed
1033 files = modified + added + removed
1034 else:
1034 else:
1035 files = []
1035 files = []
1036 try:
1036 try:
1037 repo.commit(files, message, opts['user'], opts['date'], match,
1037 repo.commit(files, message, opts['user'], opts['date'], match,
1038 force_editor=opts.get('force_editor'))
1038 force_editor=opts.get('force_editor'))
1039 except ValueError, inst:
1039 except ValueError, inst:
1040 raise util.Abort(str(inst))
1040 raise util.Abort(str(inst))
1041
1041
1042 def docopy(ui, repo, pats, opts, wlock):
1042 def docopy(ui, repo, pats, opts, wlock):
1043 # called with the repo lock held
1043 # called with the repo lock held
1044 cwd = repo.getcwd()
1044 cwd = repo.getcwd()
1045 errors = 0
1045 errors = 0
1046 copied = []
1046 copied = []
1047 targets = {}
1047 targets = {}
1048
1048
1049 def okaytocopy(abs, rel, exact):
1049 def okaytocopy(abs, rel, exact):
1050 reasons = {'?': _('is not managed'),
1050 reasons = {'?': _('is not managed'),
1051 'a': _('has been marked for add'),
1051 'a': _('has been marked for add'),
1052 'r': _('has been marked for remove')}
1052 'r': _('has been marked for remove')}
1053 state = repo.dirstate.state(abs)
1053 state = repo.dirstate.state(abs)
1054 reason = reasons.get(state)
1054 reason = reasons.get(state)
1055 if reason:
1055 if reason:
1056 if state == 'a':
1056 if state == 'a':
1057 origsrc = repo.dirstate.copied(abs)
1057 origsrc = repo.dirstate.copied(abs)
1058 if origsrc is not None:
1058 if origsrc is not None:
1059 return origsrc
1059 return origsrc
1060 if exact:
1060 if exact:
1061 ui.warn(_('%s: not copying - file %s\n') % (rel, reason))
1061 ui.warn(_('%s: not copying - file %s\n') % (rel, reason))
1062 else:
1062 else:
1063 return abs
1063 return abs
1064
1064
1065 def copy(origsrc, abssrc, relsrc, target, exact):
1065 def copy(origsrc, abssrc, relsrc, target, exact):
1066 abstarget = util.canonpath(repo.root, cwd, target)
1066 abstarget = util.canonpath(repo.root, cwd, target)
1067 reltarget = util.pathto(cwd, abstarget)
1067 reltarget = util.pathto(cwd, abstarget)
1068 prevsrc = targets.get(abstarget)
1068 prevsrc = targets.get(abstarget)
1069 if prevsrc is not None:
1069 if prevsrc is not None:
1070 ui.warn(_('%s: not overwriting - %s collides with %s\n') %
1070 ui.warn(_('%s: not overwriting - %s collides with %s\n') %
1071 (reltarget, abssrc, prevsrc))
1071 (reltarget, abssrc, prevsrc))
1072 return
1072 return
1073 if (not opts['after'] and os.path.exists(reltarget) or
1073 if (not opts['after'] and os.path.exists(reltarget) or
1074 opts['after'] and repo.dirstate.state(abstarget) not in '?r'):
1074 opts['after'] and repo.dirstate.state(abstarget) not in '?r'):
1075 if not opts['force']:
1075 if not opts['force']:
1076 ui.warn(_('%s: not overwriting - file exists\n') %
1076 ui.warn(_('%s: not overwriting - file exists\n') %
1077 reltarget)
1077 reltarget)
1078 return
1078 return
1079 if not opts['after'] and not opts.get('dry_run'):
1079 if not opts['after'] and not opts.get('dry_run'):
1080 os.unlink(reltarget)
1080 os.unlink(reltarget)
1081 if opts['after']:
1081 if opts['after']:
1082 if not os.path.exists(reltarget):
1082 if not os.path.exists(reltarget):
1083 return
1083 return
1084 else:
1084 else:
1085 targetdir = os.path.dirname(reltarget) or '.'
1085 targetdir = os.path.dirname(reltarget) or '.'
1086 if not os.path.isdir(targetdir) and not opts.get('dry_run'):
1086 if not os.path.isdir(targetdir) and not opts.get('dry_run'):
1087 os.makedirs(targetdir)
1087 os.makedirs(targetdir)
1088 try:
1088 try:
1089 restore = repo.dirstate.state(abstarget) == 'r'
1089 restore = repo.dirstate.state(abstarget) == 'r'
1090 if restore and not opts.get('dry_run'):
1090 if restore and not opts.get('dry_run'):
1091 repo.undelete([abstarget], wlock)
1091 repo.undelete([abstarget], wlock)
1092 try:
1092 try:
1093 if not opts.get('dry_run'):
1093 if not opts.get('dry_run'):
1094 shutil.copyfile(relsrc, reltarget)
1094 shutil.copyfile(relsrc, reltarget)
1095 shutil.copymode(relsrc, reltarget)
1095 shutil.copymode(relsrc, reltarget)
1096 restore = False
1096 restore = False
1097 finally:
1097 finally:
1098 if restore:
1098 if restore:
1099 repo.remove([abstarget], wlock)
1099 repo.remove([abstarget], wlock)
1100 except shutil.Error, inst:
1100 except shutil.Error, inst:
1101 raise util.Abort(str(inst))
1101 raise util.Abort(str(inst))
1102 except IOError, inst:
1102 except IOError, inst:
1103 if inst.errno == errno.ENOENT:
1103 if inst.errno == errno.ENOENT:
1104 ui.warn(_('%s: deleted in working copy\n') % relsrc)
1104 ui.warn(_('%s: deleted in working copy\n') % relsrc)
1105 else:
1105 else:
1106 ui.warn(_('%s: cannot copy - %s\n') %
1106 ui.warn(_('%s: cannot copy - %s\n') %
1107 (relsrc, inst.strerror))
1107 (relsrc, inst.strerror))
1108 errors += 1
1108 errors += 1
1109 return
1109 return
1110 if ui.verbose or not exact:
1110 if ui.verbose or not exact:
1111 ui.status(_('copying %s to %s\n') % (relsrc, reltarget))
1111 ui.status(_('copying %s to %s\n') % (relsrc, reltarget))
1112 targets[abstarget] = abssrc
1112 targets[abstarget] = abssrc
1113 if abstarget != origsrc and not opts.get('dry_run'):
1113 if abstarget != origsrc and not opts.get('dry_run'):
1114 repo.copy(origsrc, abstarget, wlock)
1114 repo.copy(origsrc, abstarget, wlock)
1115 copied.append((abssrc, relsrc, exact))
1115 copied.append((abssrc, relsrc, exact))
1116
1116
1117 def targetpathfn(pat, dest, srcs):
1117 def targetpathfn(pat, dest, srcs):
1118 if os.path.isdir(pat):
1118 if os.path.isdir(pat):
1119 abspfx = util.canonpath(repo.root, cwd, pat)
1119 abspfx = util.canonpath(repo.root, cwd, pat)
1120 if destdirexists:
1120 if destdirexists:
1121 striplen = len(os.path.split(abspfx)[0])
1121 striplen = len(os.path.split(abspfx)[0])
1122 else:
1122 else:
1123 striplen = len(abspfx)
1123 striplen = len(abspfx)
1124 if striplen:
1124 if striplen:
1125 striplen += len(os.sep)
1125 striplen += len(os.sep)
1126 res = lambda p: os.path.join(dest, p[striplen:])
1126 res = lambda p: os.path.join(dest, p[striplen:])
1127 elif destdirexists:
1127 elif destdirexists:
1128 res = lambda p: os.path.join(dest, os.path.basename(p))
1128 res = lambda p: os.path.join(dest, os.path.basename(p))
1129 else:
1129 else:
1130 res = lambda p: dest
1130 res = lambda p: dest
1131 return res
1131 return res
1132
1132
1133 def targetpathafterfn(pat, dest, srcs):
1133 def targetpathafterfn(pat, dest, srcs):
1134 if util.patkind(pat, None)[0]:
1134 if util.patkind(pat, None)[0]:
1135 # a mercurial pattern
1135 # a mercurial pattern
1136 res = lambda p: os.path.join(dest, os.path.basename(p))
1136 res = lambda p: os.path.join(dest, os.path.basename(p))
1137 else:
1137 else:
1138 abspfx = util.canonpath(repo.root, cwd, pat)
1138 abspfx = util.canonpath(repo.root, cwd, pat)
1139 if len(abspfx) < len(srcs[0][0]):
1139 if len(abspfx) < len(srcs[0][0]):
1140 # A directory. Either the target path contains the last
1140 # A directory. Either the target path contains the last
1141 # component of the source path or it does not.
1141 # component of the source path or it does not.
1142 def evalpath(striplen):
1142 def evalpath(striplen):
1143 score = 0
1143 score = 0
1144 for s in srcs:
1144 for s in srcs:
1145 t = os.path.join(dest, s[0][striplen:])
1145 t = os.path.join(dest, s[0][striplen:])
1146 if os.path.exists(t):
1146 if os.path.exists(t):
1147 score += 1
1147 score += 1
1148 return score
1148 return score
1149
1149
1150 striplen = len(abspfx)
1150 striplen = len(abspfx)
1151 if striplen:
1151 if striplen:
1152 striplen += len(os.sep)
1152 striplen += len(os.sep)
1153 if os.path.isdir(os.path.join(dest, os.path.split(abspfx)[1])):
1153 if os.path.isdir(os.path.join(dest, os.path.split(abspfx)[1])):
1154 score = evalpath(striplen)
1154 score = evalpath(striplen)
1155 striplen1 = len(os.path.split(abspfx)[0])
1155 striplen1 = len(os.path.split(abspfx)[0])
1156 if striplen1:
1156 if striplen1:
1157 striplen1 += len(os.sep)
1157 striplen1 += len(os.sep)
1158 if evalpath(striplen1) > score:
1158 if evalpath(striplen1) > score:
1159 striplen = striplen1
1159 striplen = striplen1
1160 res = lambda p: os.path.join(dest, p[striplen:])
1160 res = lambda p: os.path.join(dest, p[striplen:])
1161 else:
1161 else:
1162 # a file
1162 # a file
1163 if destdirexists:
1163 if destdirexists:
1164 res = lambda p: os.path.join(dest, os.path.basename(p))
1164 res = lambda p: os.path.join(dest, os.path.basename(p))
1165 else:
1165 else:
1166 res = lambda p: dest
1166 res = lambda p: dest
1167 return res
1167 return res
1168
1168
1169
1169
1170 pats = list(pats)
1170 pats = list(pats)
1171 if not pats:
1171 if not pats:
1172 raise util.Abort(_('no source or destination specified'))
1172 raise util.Abort(_('no source or destination specified'))
1173 if len(pats) == 1:
1173 if len(pats) == 1:
1174 raise util.Abort(_('no destination specified'))
1174 raise util.Abort(_('no destination specified'))
1175 dest = pats.pop()
1175 dest = pats.pop()
1176 destdirexists = os.path.isdir(dest)
1176 destdirexists = os.path.isdir(dest)
1177 if (len(pats) > 1 or util.patkind(pats[0], None)[0]) and not destdirexists:
1177 if (len(pats) > 1 or util.patkind(pats[0], None)[0]) and not destdirexists:
1178 raise util.Abort(_('with multiple sources, destination must be an '
1178 raise util.Abort(_('with multiple sources, destination must be an '
1179 'existing directory'))
1179 'existing directory'))
1180 if opts['after']:
1180 if opts['after']:
1181 tfn = targetpathafterfn
1181 tfn = targetpathafterfn
1182 else:
1182 else:
1183 tfn = targetpathfn
1183 tfn = targetpathfn
1184 copylist = []
1184 copylist = []
1185 for pat in pats:
1185 for pat in pats:
1186 srcs = []
1186 srcs = []
1187 for tag, abssrc, relsrc, exact in walk(repo, [pat], opts):
1187 for tag, abssrc, relsrc, exact in walk(repo, [pat], opts):
1188 origsrc = okaytocopy(abssrc, relsrc, exact)
1188 origsrc = okaytocopy(abssrc, relsrc, exact)
1189 if origsrc:
1189 if origsrc:
1190 srcs.append((origsrc, abssrc, relsrc, exact))
1190 srcs.append((origsrc, abssrc, relsrc, exact))
1191 if not srcs:
1191 if not srcs:
1192 continue
1192 continue
1193 copylist.append((tfn(pat, dest, srcs), srcs))
1193 copylist.append((tfn(pat, dest, srcs), srcs))
1194 if not copylist:
1194 if not copylist:
1195 raise util.Abort(_('no files to copy'))
1195 raise util.Abort(_('no files to copy'))
1196
1196
1197 for targetpath, srcs in copylist:
1197 for targetpath, srcs in copylist:
1198 for origsrc, abssrc, relsrc, exact in srcs:
1198 for origsrc, abssrc, relsrc, exact in srcs:
1199 copy(origsrc, abssrc, relsrc, targetpath(abssrc), exact)
1199 copy(origsrc, abssrc, relsrc, targetpath(abssrc), exact)
1200
1200
1201 if errors:
1201 if errors:
1202 ui.warn(_('(consider using --after)\n'))
1202 ui.warn(_('(consider using --after)\n'))
1203 return errors, copied
1203 return errors, copied
1204
1204
1205 def copy(ui, repo, *pats, **opts):
1205 def copy(ui, repo, *pats, **opts):
1206 """mark files as copied for the next commit
1206 """mark files as copied for the next commit
1207
1207
1208 Mark dest as having copies of source files. If dest is a
1208 Mark dest as having copies of source files. If dest is a
1209 directory, copies are put in that directory. If dest is a file,
1209 directory, copies are put in that directory. If dest is a file,
1210 there can only be one source.
1210 there can only be one source.
1211
1211
1212 By default, this command copies the contents of files as they
1212 By default, this command copies the contents of files as they
1213 stand in the working directory. If invoked with --after, the
1213 stand in the working directory. If invoked with --after, the
1214 operation is recorded, but no copying is performed.
1214 operation is recorded, but no copying is performed.
1215
1215
1216 This command takes effect in the next commit.
1216 This command takes effect in the next commit.
1217
1217
1218 NOTE: This command should be treated as experimental. While it
1218 NOTE: This command should be treated as experimental. While it
1219 should properly record copied files, this information is not yet
1219 should properly record copied files, this information is not yet
1220 fully used by merge, nor fully reported by log.
1220 fully used by merge, nor fully reported by log.
1221 """
1221 """
1222 wlock = repo.wlock(0)
1222 wlock = repo.wlock(0)
1223 errs, copied = docopy(ui, repo, pats, opts, wlock)
1223 errs, copied = docopy(ui, repo, pats, opts, wlock)
1224 return errs
1224 return errs
1225
1225
1226 def debugancestor(ui, index, rev1, rev2):
1226 def debugancestor(ui, index, rev1, rev2):
1227 """find the ancestor revision of two revisions in a given index"""
1227 """find the ancestor revision of two revisions in a given index"""
1228 r = revlog.revlog(util.opener(os.getcwd(), audit=False), index, "", 0)
1228 r = revlog.revlog(util.opener(os.getcwd(), audit=False), index, "", 0)
1229 a = r.ancestor(r.lookup(rev1), r.lookup(rev2))
1229 a = r.ancestor(r.lookup(rev1), r.lookup(rev2))
1230 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1230 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
1231
1231
1232 def debugcomplete(ui, cmd='', **opts):
1232 def debugcomplete(ui, cmd='', **opts):
1233 """returns the completion list associated with the given command"""
1233 """returns the completion list associated with the given command"""
1234
1234
1235 if opts['options']:
1235 if opts['options']:
1236 options = []
1236 options = []
1237 otables = [globalopts]
1237 otables = [globalopts]
1238 if cmd:
1238 if cmd:
1239 aliases, entry = find(cmd)
1239 aliases, entry = find(cmd)
1240 otables.append(entry[1])
1240 otables.append(entry[1])
1241 for t in otables:
1241 for t in otables:
1242 for o in t:
1242 for o in t:
1243 if o[0]:
1243 if o[0]:
1244 options.append('-%s' % o[0])
1244 options.append('-%s' % o[0])
1245 options.append('--%s' % o[1])
1245 options.append('--%s' % o[1])
1246 ui.write("%s\n" % "\n".join(options))
1246 ui.write("%s\n" % "\n".join(options))
1247 return
1247 return
1248
1248
1249 clist = findpossible(cmd).keys()
1249 clist = findpossible(cmd).keys()
1250 clist.sort()
1250 clist.sort()
1251 ui.write("%s\n" % "\n".join(clist))
1251 ui.write("%s\n" % "\n".join(clist))
1252
1252
1253 def debugrebuildstate(ui, repo, rev=None):
1253 def debugrebuildstate(ui, repo, rev=None):
1254 """rebuild the dirstate as it would look like for the given revision"""
1254 """rebuild the dirstate as it would look like for the given revision"""
1255 if not rev:
1255 if not rev:
1256 rev = repo.changelog.tip()
1256 rev = repo.changelog.tip()
1257 else:
1257 else:
1258 rev = repo.lookup(rev)
1258 rev = repo.lookup(rev)
1259 change = repo.changelog.read(rev)
1259 change = repo.changelog.read(rev)
1260 n = change[0]
1260 n = change[0]
1261 files = repo.manifest.readflags(n)
1261 files = repo.manifest.readflags(n)
1262 wlock = repo.wlock()
1262 wlock = repo.wlock()
1263 repo.dirstate.rebuild(rev, files.iteritems())
1263 repo.dirstate.rebuild(rev, files.iteritems())
1264
1264
1265 def debugcheckstate(ui, repo):
1265 def debugcheckstate(ui, repo):
1266 """validate the correctness of the current dirstate"""
1266 """validate the correctness of the current dirstate"""
1267 parent1, parent2 = repo.dirstate.parents()
1267 parent1, parent2 = repo.dirstate.parents()
1268 repo.dirstate.read()
1268 repo.dirstate.read()
1269 dc = repo.dirstate.map
1269 dc = repo.dirstate.map
1270 keys = dc.keys()
1270 keys = dc.keys()
1271 keys.sort()
1271 keys.sort()
1272 m1n = repo.changelog.read(parent1)[0]
1272 m1n = repo.changelog.read(parent1)[0]
1273 m2n = repo.changelog.read(parent2)[0]
1273 m2n = repo.changelog.read(parent2)[0]
1274 m1 = repo.manifest.read(m1n)
1274 m1 = repo.manifest.read(m1n)
1275 m2 = repo.manifest.read(m2n)
1275 m2 = repo.manifest.read(m2n)
1276 errors = 0
1276 errors = 0
1277 for f in dc:
1277 for f in dc:
1278 state = repo.dirstate.state(f)
1278 state = repo.dirstate.state(f)
1279 if state in "nr" and f not in m1:
1279 if state in "nr" and f not in m1:
1280 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1280 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1281 errors += 1
1281 errors += 1
1282 if state in "a" and f in m1:
1282 if state in "a" and f in m1:
1283 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1283 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1284 errors += 1
1284 errors += 1
1285 if state in "m" and f not in m1 and f not in m2:
1285 if state in "m" and f not in m1 and f not in m2:
1286 ui.warn(_("%s in state %s, but not in either manifest\n") %
1286 ui.warn(_("%s in state %s, but not in either manifest\n") %
1287 (f, state))
1287 (f, state))
1288 errors += 1
1288 errors += 1
1289 for f in m1:
1289 for f in m1:
1290 state = repo.dirstate.state(f)
1290 state = repo.dirstate.state(f)
1291 if state not in "nrm":
1291 if state not in "nrm":
1292 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1292 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1293 errors += 1
1293 errors += 1
1294 if errors:
1294 if errors:
1295 error = _(".hg/dirstate inconsistent with current parent's manifest")
1295 error = _(".hg/dirstate inconsistent with current parent's manifest")
1296 raise util.Abort(error)
1296 raise util.Abort(error)
1297
1297
1298 def debugconfig(ui, repo, *values):
1298 def debugconfig(ui, repo, *values):
1299 """show combined config settings from all hgrc files
1299 """show combined config settings from all hgrc files
1300
1300
1301 With no args, print names and values of all config items.
1301 With no args, print names and values of all config items.
1302
1302
1303 With one arg of the form section.name, print just the value of
1303 With one arg of the form section.name, print just the value of
1304 that config item.
1304 that config item.
1305
1305
1306 With multiple args, print names and values of all config items
1306 With multiple args, print names and values of all config items
1307 with matching section names."""
1307 with matching section names."""
1308
1308
1309 if values:
1309 if values:
1310 if len([v for v in values if '.' in v]) > 1:
1310 if len([v for v in values if '.' in v]) > 1:
1311 raise util.Abort(_('only one config item permitted'))
1311 raise util.Abort(_('only one config item permitted'))
1312 for section, name, value in ui.walkconfig():
1312 for section, name, value in ui.walkconfig():
1313 sectname = section + '.' + name
1313 sectname = section + '.' + name
1314 if values:
1314 if values:
1315 for v in values:
1315 for v in values:
1316 if v == section:
1316 if v == section:
1317 ui.write('%s=%s\n' % (sectname, value))
1317 ui.write('%s=%s\n' % (sectname, value))
1318 elif v == sectname:
1318 elif v == sectname:
1319 ui.write(value, '\n')
1319 ui.write(value, '\n')
1320 else:
1320 else:
1321 ui.write('%s=%s\n' % (sectname, value))
1321 ui.write('%s=%s\n' % (sectname, value))
1322
1322
1323 def debugsetparents(ui, repo, rev1, rev2=None):
1323 def debugsetparents(ui, repo, rev1, rev2=None):
1324 """manually set the parents of the current working directory
1324 """manually set the parents of the current working directory
1325
1325
1326 This is useful for writing repository conversion tools, but should
1326 This is useful for writing repository conversion tools, but should
1327 be used with care.
1327 be used with care.
1328 """
1328 """
1329
1329
1330 if not rev2:
1330 if not rev2:
1331 rev2 = hex(nullid)
1331 rev2 = hex(nullid)
1332
1332
1333 repo.dirstate.setparents(repo.lookup(rev1), repo.lookup(rev2))
1333 repo.dirstate.setparents(repo.lookup(rev1), repo.lookup(rev2))
1334
1334
1335 def debugstate(ui, repo):
1335 def debugstate(ui, repo):
1336 """show the contents of the current dirstate"""
1336 """show the contents of the current dirstate"""
1337 repo.dirstate.read()
1337 repo.dirstate.read()
1338 dc = repo.dirstate.map
1338 dc = repo.dirstate.map
1339 keys = dc.keys()
1339 keys = dc.keys()
1340 keys.sort()
1340 keys.sort()
1341 for file_ in keys:
1341 for file_ in keys:
1342 ui.write("%c %3o %10d %s %s\n"
1342 ui.write("%c %3o %10d %s %s\n"
1343 % (dc[file_][0], dc[file_][1] & 0777, dc[file_][2],
1343 % (dc[file_][0], dc[file_][1] & 0777, dc[file_][2],
1344 time.strftime("%x %X",
1344 time.strftime("%x %X",
1345 time.localtime(dc[file_][3])), file_))
1345 time.localtime(dc[file_][3])), file_))
1346 for f in repo.dirstate.copies:
1346 for f in repo.dirstate.copies:
1347 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copies[f], f))
1347 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copies[f], f))
1348
1348
1349 def debugdata(ui, file_, rev):
1349 def debugdata(ui, file_, rev):
1350 """dump the contents of an data file revision"""
1350 """dump the contents of an data file revision"""
1351 r = revlog.revlog(util.opener(os.getcwd(), audit=False),
1351 r = revlog.revlog(util.opener(os.getcwd(), audit=False),
1352 file_[:-2] + ".i", file_, 0)
1352 file_[:-2] + ".i", file_, 0)
1353 try:
1353 try:
1354 ui.write(r.revision(r.lookup(rev)))
1354 ui.write(r.revision(r.lookup(rev)))
1355 except KeyError:
1355 except KeyError:
1356 raise util.Abort(_('invalid revision identifier %s'), rev)
1356 raise util.Abort(_('invalid revision identifier %s'), rev)
1357
1357
1358 def debugindex(ui, file_):
1358 def debugindex(ui, file_):
1359 """dump the contents of an index file"""
1359 """dump the contents of an index file"""
1360 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_, "", 0)
1360 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_, "", 0)
1361 ui.write(" rev offset length base linkrev" +
1361 ui.write(" rev offset length base linkrev" +
1362 " nodeid p1 p2\n")
1362 " nodeid p1 p2\n")
1363 for i in range(r.count()):
1363 for i in range(r.count()):
1364 node = r.node(i)
1364 node = r.node(i)
1365 pp = r.parents(node)
1365 pp = r.parents(node)
1366 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1366 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1367 i, r.start(i), r.length(i), r.base(i), r.linkrev(node),
1367 i, r.start(i), r.length(i), r.base(i), r.linkrev(node),
1368 short(node), short(pp[0]), short(pp[1])))
1368 short(node), short(pp[0]), short(pp[1])))
1369
1369
1370 def debugindexdot(ui, file_):
1370 def debugindexdot(ui, file_):
1371 """dump an index DAG as a .dot file"""
1371 """dump an index DAG as a .dot file"""
1372 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_, "", 0)
1372 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_, "", 0)
1373 ui.write("digraph G {\n")
1373 ui.write("digraph G {\n")
1374 for i in range(r.count()):
1374 for i in range(r.count()):
1375 node = r.node(i)
1375 node = r.node(i)
1376 pp = r.parents(node)
1376 pp = r.parents(node)
1377 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1377 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1378 if pp[1] != nullid:
1378 if pp[1] != nullid:
1379 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1379 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1380 ui.write("}\n")
1380 ui.write("}\n")
1381
1381
1382 def debugrename(ui, repo, file, rev=None):
1382 def debugrename(ui, repo, file, rev=None):
1383 """dump rename information"""
1383 """dump rename information"""
1384 r = repo.file(relpath(repo, [file])[0])
1384 r = repo.file(relpath(repo, [file])[0])
1385 if rev:
1385 if rev:
1386 try:
1386 try:
1387 # assume all revision numbers are for changesets
1387 # assume all revision numbers are for changesets
1388 n = repo.lookup(rev)
1388 n = repo.lookup(rev)
1389 change = repo.changelog.read(n)
1389 change = repo.changelog.read(n)
1390 m = repo.manifest.read(change[0])
1390 m = repo.manifest.read(change[0])
1391 n = m[relpath(repo, [file])[0]]
1391 n = m[relpath(repo, [file])[0]]
1392 except (hg.RepoError, KeyError):
1392 except (hg.RepoError, KeyError):
1393 n = r.lookup(rev)
1393 n = r.lookup(rev)
1394 else:
1394 else:
1395 n = r.tip()
1395 n = r.tip()
1396 m = r.renamed(n)
1396 m = r.renamed(n)
1397 if m:
1397 if m:
1398 ui.write(_("renamed from %s:%s\n") % (m[0], hex(m[1])))
1398 ui.write(_("renamed from %s:%s\n") % (m[0], hex(m[1])))
1399 else:
1399 else:
1400 ui.write(_("not renamed\n"))
1400 ui.write(_("not renamed\n"))
1401
1401
1402 def debugwalk(ui, repo, *pats, **opts):
1402 def debugwalk(ui, repo, *pats, **opts):
1403 """show how files match on given patterns"""
1403 """show how files match on given patterns"""
1404 items = list(walk(repo, pats, opts))
1404 items = list(walk(repo, pats, opts))
1405 if not items:
1405 if not items:
1406 return
1406 return
1407 fmt = '%%s %%-%ds %%-%ds %%s' % (
1407 fmt = '%%s %%-%ds %%-%ds %%s' % (
1408 max([len(abs) for (src, abs, rel, exact) in items]),
1408 max([len(abs) for (src, abs, rel, exact) in items]),
1409 max([len(rel) for (src, abs, rel, exact) in items]))
1409 max([len(rel) for (src, abs, rel, exact) in items]))
1410 for src, abs, rel, exact in items:
1410 for src, abs, rel, exact in items:
1411 line = fmt % (src, abs, rel, exact and 'exact' or '')
1411 line = fmt % (src, abs, rel, exact and 'exact' or '')
1412 ui.write("%s\n" % line.rstrip())
1412 ui.write("%s\n" % line.rstrip())
1413
1413
1414 def diff(ui, repo, *pats, **opts):
1414 def diff(ui, repo, *pats, **opts):
1415 """diff repository (or selected files)
1415 """diff repository (or selected files)
1416
1416
1417 Show differences between revisions for the specified files.
1417 Show differences between revisions for the specified files.
1418
1418
1419 Differences between files are shown using the unified diff format.
1419 Differences between files are shown using the unified diff format.
1420
1420
1421 When two revision arguments are given, then changes are shown
1421 When two revision arguments are given, then changes are shown
1422 between those revisions. If only one revision is specified then
1422 between those revisions. If only one revision is specified then
1423 that revision is compared to the working directory, and, when no
1423 that revision is compared to the working directory, and, when no
1424 revisions are specified, the working directory files are compared
1424 revisions are specified, the working directory files are compared
1425 to its parent.
1425 to its parent.
1426
1426
1427 Without the -a option, diff will avoid generating diffs of files
1427 Without the -a option, diff will avoid generating diffs of files
1428 it detects as binary. With -a, diff will generate a diff anyway,
1428 it detects as binary. With -a, diff will generate a diff anyway,
1429 probably with undesirable results.
1429 probably with undesirable results.
1430 """
1430 """
1431 node1, node2 = revpair(ui, repo, opts['rev'])
1431 node1, node2 = revpair(ui, repo, opts['rev'])
1432
1432
1433 fns, matchfn, anypats = matchpats(repo, pats, opts)
1433 fns, matchfn, anypats = matchpats(repo, pats, opts)
1434
1434
1435 dodiff(sys.stdout, ui, repo, node1, node2, fns, match=matchfn,
1435 dodiff(sys.stdout, ui, repo, node1, node2, fns, match=matchfn,
1436 text=opts['text'], opts=opts)
1436 text=opts['text'], opts=opts)
1437
1437
1438 def doexport(ui, repo, changeset, seqno, total, revwidth, opts):
1438 def doexport(ui, repo, changeset, seqno, total, revwidth, opts):
1439 node = repo.lookup(changeset)
1439 node = repo.lookup(changeset)
1440 parents = [p for p in repo.changelog.parents(node) if p != nullid]
1440 parents = [p for p in repo.changelog.parents(node) if p != nullid]
1441 if opts['switch_parent']:
1441 if opts['switch_parent']:
1442 parents.reverse()
1442 parents.reverse()
1443 prev = (parents and parents[0]) or nullid
1443 prev = (parents and parents[0]) or nullid
1444 change = repo.changelog.read(node)
1444 change = repo.changelog.read(node)
1445
1445
1446 fp = make_file(repo, repo.changelog, opts['output'],
1446 fp = make_file(repo, repo.changelog, opts['output'],
1447 node=node, total=total, seqno=seqno,
1447 node=node, total=total, seqno=seqno,
1448 revwidth=revwidth)
1448 revwidth=revwidth)
1449 if fp != sys.stdout:
1449 if fp != sys.stdout:
1450 ui.note("%s\n" % fp.name)
1450 ui.note("%s\n" % fp.name)
1451
1451
1452 fp.write("# HG changeset patch\n")
1452 fp.write("# HG changeset patch\n")
1453 fp.write("# User %s\n" % change[1])
1453 fp.write("# User %s\n" % change[1])
1454 fp.write("# Date %d %d\n" % change[2])
1454 fp.write("# Date %d %d\n" % change[2])
1455 fp.write("# Node ID %s\n" % hex(node))
1455 fp.write("# Node ID %s\n" % hex(node))
1456 fp.write("# Parent %s\n" % hex(prev))
1456 fp.write("# Parent %s\n" % hex(prev))
1457 if len(parents) > 1:
1457 if len(parents) > 1:
1458 fp.write("# Parent %s\n" % hex(parents[1]))
1458 fp.write("# Parent %s\n" % hex(parents[1]))
1459 fp.write(change[4].rstrip())
1459 fp.write(change[4].rstrip())
1460 fp.write("\n\n")
1460 fp.write("\n\n")
1461
1461
1462 dodiff(fp, ui, repo, prev, node, text=opts['text'])
1462 dodiff(fp, ui, repo, prev, node, text=opts['text'])
1463 if fp != sys.stdout:
1463 if fp != sys.stdout:
1464 fp.close()
1464 fp.close()
1465
1465
1466 def export(ui, repo, *changesets, **opts):
1466 def export(ui, repo, *changesets, **opts):
1467 """dump the header and diffs for one or more changesets
1467 """dump the header and diffs for one or more changesets
1468
1468
1469 Print the changeset header and diffs for one or more revisions.
1469 Print the changeset header and diffs for one or more revisions.
1470
1470
1471 The information shown in the changeset header is: author,
1471 The information shown in the changeset header is: author,
1472 changeset hash, parent and commit comment.
1472 changeset hash, parent and commit comment.
1473
1473
1474 Output may be to a file, in which case the name of the file is
1474 Output may be to a file, in which case the name of the file is
1475 given using a format string. The formatting rules are as follows:
1475 given using a format string. The formatting rules are as follows:
1476
1476
1477 %% literal "%" character
1477 %% literal "%" character
1478 %H changeset hash (40 bytes of hexadecimal)
1478 %H changeset hash (40 bytes of hexadecimal)
1479 %N number of patches being generated
1479 %N number of patches being generated
1480 %R changeset revision number
1480 %R changeset revision number
1481 %b basename of the exporting repository
1481 %b basename of the exporting repository
1482 %h short-form changeset hash (12 bytes of hexadecimal)
1482 %h short-form changeset hash (12 bytes of hexadecimal)
1483 %n zero-padded sequence number, starting at 1
1483 %n zero-padded sequence number, starting at 1
1484 %r zero-padded changeset revision number
1484 %r zero-padded changeset revision number
1485
1485
1486 Without the -a option, export will avoid generating diffs of files
1486 Without the -a option, export will avoid generating diffs of files
1487 it detects as binary. With -a, export will generate a diff anyway,
1487 it detects as binary. With -a, export will generate a diff anyway,
1488 probably with undesirable results.
1488 probably with undesirable results.
1489
1489
1490 With the --switch-parent option, the diff will be against the second
1490 With the --switch-parent option, the diff will be against the second
1491 parent. It can be useful to review a merge.
1491 parent. It can be useful to review a merge.
1492 """
1492 """
1493 if not changesets:
1493 if not changesets:
1494 raise util.Abort(_("export requires at least one changeset"))
1494 raise util.Abort(_("export requires at least one changeset"))
1495 seqno = 0
1495 seqno = 0
1496 revs = list(revrange(ui, repo, changesets))
1496 revs = list(revrange(ui, repo, changesets))
1497 total = len(revs)
1497 total = len(revs)
1498 revwidth = max(map(len, revs))
1498 revwidth = max(map(len, revs))
1499 msg = len(revs) > 1 and _("Exporting patches:\n") or _("Exporting patch:\n")
1499 msg = len(revs) > 1 and _("Exporting patches:\n") or _("Exporting patch:\n")
1500 ui.note(msg)
1500 ui.note(msg)
1501 for cset in revs:
1501 for cset in revs:
1502 seqno += 1
1502 seqno += 1
1503 doexport(ui, repo, cset, seqno, total, revwidth, opts)
1503 doexport(ui, repo, cset, seqno, total, revwidth, opts)
1504
1504
1505 def forget(ui, repo, *pats, **opts):
1505 def forget(ui, repo, *pats, **opts):
1506 """don't add the specified files on the next commit (DEPRECATED)
1506 """don't add the specified files on the next commit (DEPRECATED)
1507
1507
1508 (DEPRECATED)
1508 (DEPRECATED)
1509 Undo an 'hg add' scheduled for the next commit.
1509 Undo an 'hg add' scheduled for the next commit.
1510
1510
1511 This command is now deprecated and will be removed in a future
1511 This command is now deprecated and will be removed in a future
1512 release. Please use revert instead.
1512 release. Please use revert instead.
1513 """
1513 """
1514 ui.warn(_("(the forget command is deprecated; use revert instead)\n"))
1514 ui.warn(_("(the forget command is deprecated; use revert instead)\n"))
1515 forget = []
1515 forget = []
1516 for src, abs, rel, exact in walk(repo, pats, opts):
1516 for src, abs, rel, exact in walk(repo, pats, opts):
1517 if repo.dirstate.state(abs) == 'a':
1517 if repo.dirstate.state(abs) == 'a':
1518 forget.append(abs)
1518 forget.append(abs)
1519 if ui.verbose or not exact:
1519 if ui.verbose or not exact:
1520 ui.status(_('forgetting %s\n') % ((pats and rel) or abs))
1520 ui.status(_('forgetting %s\n') % ((pats and rel) or abs))
1521 repo.forget(forget)
1521 repo.forget(forget)
1522
1522
1523 def grep(ui, repo, pattern, *pats, **opts):
1523 def grep(ui, repo, pattern, *pats, **opts):
1524 """search for a pattern in specified files and revisions
1524 """search for a pattern in specified files and revisions
1525
1525
1526 Search revisions of files for a regular expression.
1526 Search revisions of files for a regular expression.
1527
1527
1528 This command behaves differently than Unix grep. It only accepts
1528 This command behaves differently than Unix grep. It only accepts
1529 Python/Perl regexps. It searches repository history, not the
1529 Python/Perl regexps. It searches repository history, not the
1530 working directory. It always prints the revision number in which
1530 working directory. It always prints the revision number in which
1531 a match appears.
1531 a match appears.
1532
1532
1533 By default, grep only prints output for the first revision of a
1533 By default, grep only prints output for the first revision of a
1534 file in which it finds a match. To get it to print every revision
1534 file in which it finds a match. To get it to print every revision
1535 that contains a change in match status ("-" for a match that
1535 that contains a change in match status ("-" for a match that
1536 becomes a non-match, or "+" for a non-match that becomes a match),
1536 becomes a non-match, or "+" for a non-match that becomes a match),
1537 use the --all flag.
1537 use the --all flag.
1538 """
1538 """
1539 reflags = 0
1539 reflags = 0
1540 if opts['ignore_case']:
1540 if opts['ignore_case']:
1541 reflags |= re.I
1541 reflags |= re.I
1542 regexp = re.compile(pattern, reflags)
1542 regexp = re.compile(pattern, reflags)
1543 sep, eol = ':', '\n'
1543 sep, eol = ':', '\n'
1544 if opts['print0']:
1544 if opts['print0']:
1545 sep = eol = '\0'
1545 sep = eol = '\0'
1546
1546
1547 fcache = {}
1547 fcache = {}
1548 def getfile(fn):
1548 def getfile(fn):
1549 if fn not in fcache:
1549 if fn not in fcache:
1550 fcache[fn] = repo.file(fn)
1550 fcache[fn] = repo.file(fn)
1551 return fcache[fn]
1551 return fcache[fn]
1552
1552
1553 def matchlines(body):
1553 def matchlines(body):
1554 begin = 0
1554 begin = 0
1555 linenum = 0
1555 linenum = 0
1556 while True:
1556 while True:
1557 match = regexp.search(body, begin)
1557 match = regexp.search(body, begin)
1558 if not match:
1558 if not match:
1559 break
1559 break
1560 mstart, mend = match.span()
1560 mstart, mend = match.span()
1561 linenum += body.count('\n', begin, mstart) + 1
1561 linenum += body.count('\n', begin, mstart) + 1
1562 lstart = body.rfind('\n', begin, mstart) + 1 or begin
1562 lstart = body.rfind('\n', begin, mstart) + 1 or begin
1563 lend = body.find('\n', mend)
1563 lend = body.find('\n', mend)
1564 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
1564 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
1565 begin = lend + 1
1565 begin = lend + 1
1566
1566
1567 class linestate(object):
1567 class linestate(object):
1568 def __init__(self, line, linenum, colstart, colend):
1568 def __init__(self, line, linenum, colstart, colend):
1569 self.line = line
1569 self.line = line
1570 self.linenum = linenum
1570 self.linenum = linenum
1571 self.colstart = colstart
1571 self.colstart = colstart
1572 self.colend = colend
1572 self.colend = colend
1573 def __eq__(self, other):
1573 def __eq__(self, other):
1574 return self.line == other.line
1574 return self.line == other.line
1575 def __hash__(self):
1575 def __hash__(self):
1576 return hash(self.line)
1576 return hash(self.line)
1577
1577
1578 matches = {}
1578 matches = {}
1579 def grepbody(fn, rev, body):
1579 def grepbody(fn, rev, body):
1580 matches[rev].setdefault(fn, {})
1580 matches[rev].setdefault(fn, {})
1581 m = matches[rev][fn]
1581 m = matches[rev][fn]
1582 for lnum, cstart, cend, line in matchlines(body):
1582 for lnum, cstart, cend, line in matchlines(body):
1583 s = linestate(line, lnum, cstart, cend)
1583 s = linestate(line, lnum, cstart, cend)
1584 m[s] = s
1584 m[s] = s
1585
1585
1586 # FIXME: prev isn't used, why ?
1586 # FIXME: prev isn't used, why ?
1587 prev = {}
1587 prev = {}
1588 ucache = {}
1588 ucache = {}
1589 def display(fn, rev, states, prevstates):
1589 def display(fn, rev, states, prevstates):
1590 diff = list(sets.Set(states).symmetric_difference(sets.Set(prevstates)))
1590 diff = list(sets.Set(states).symmetric_difference(sets.Set(prevstates)))
1591 diff.sort(lambda x, y: cmp(x.linenum, y.linenum))
1591 diff.sort(lambda x, y: cmp(x.linenum, y.linenum))
1592 counts = {'-': 0, '+': 0}
1592 counts = {'-': 0, '+': 0}
1593 filerevmatches = {}
1593 filerevmatches = {}
1594 for l in diff:
1594 for l in diff:
1595 if incrementing or not opts['all']:
1595 if incrementing or not opts['all']:
1596 change = ((l in prevstates) and '-') or '+'
1596 change = ((l in prevstates) and '-') or '+'
1597 r = rev
1597 r = rev
1598 else:
1598 else:
1599 change = ((l in states) and '-') or '+'
1599 change = ((l in states) and '-') or '+'
1600 r = prev[fn]
1600 r = prev[fn]
1601 cols = [fn, str(rev)]
1601 cols = [fn, str(rev)]
1602 if opts['line_number']:
1602 if opts['line_number']:
1603 cols.append(str(l.linenum))
1603 cols.append(str(l.linenum))
1604 if opts['all']:
1604 if opts['all']:
1605 cols.append(change)
1605 cols.append(change)
1606 if opts['user']:
1606 if opts['user']:
1607 cols.append(trimuser(ui, getchange(rev)[1], rev,
1607 cols.append(trimuser(ui, getchange(rev)[1], rev,
1608 ucache))
1608 ucache))
1609 if opts['files_with_matches']:
1609 if opts['files_with_matches']:
1610 c = (fn, rev)
1610 c = (fn, rev)
1611 if c in filerevmatches:
1611 if c in filerevmatches:
1612 continue
1612 continue
1613 filerevmatches[c] = 1
1613 filerevmatches[c] = 1
1614 else:
1614 else:
1615 cols.append(l.line)
1615 cols.append(l.line)
1616 ui.write(sep.join(cols), eol)
1616 ui.write(sep.join(cols), eol)
1617 counts[change] += 1
1617 counts[change] += 1
1618 return counts['+'], counts['-']
1618 return counts['+'], counts['-']
1619
1619
1620 fstate = {}
1620 fstate = {}
1621 skip = {}
1621 skip = {}
1622 changeiter, getchange, matchfn = walkchangerevs(ui, repo, pats, opts)
1622 changeiter, getchange, matchfn = walkchangerevs(ui, repo, pats, opts)
1623 count = 0
1623 count = 0
1624 incrementing = False
1624 incrementing = False
1625 for st, rev, fns in changeiter:
1625 for st, rev, fns in changeiter:
1626 if st == 'window':
1626 if st == 'window':
1627 incrementing = rev
1627 incrementing = rev
1628 matches.clear()
1628 matches.clear()
1629 elif st == 'add':
1629 elif st == 'add':
1630 change = repo.changelog.read(repo.lookup(str(rev)))
1630 change = repo.changelog.read(repo.lookup(str(rev)))
1631 mf = repo.manifest.read(change[0])
1631 mf = repo.manifest.read(change[0])
1632 matches[rev] = {}
1632 matches[rev] = {}
1633 for fn in fns:
1633 for fn in fns:
1634 if fn in skip:
1634 if fn in skip:
1635 continue
1635 continue
1636 fstate.setdefault(fn, {})
1636 fstate.setdefault(fn, {})
1637 try:
1637 try:
1638 grepbody(fn, rev, getfile(fn).read(mf[fn]))
1638 grepbody(fn, rev, getfile(fn).read(mf[fn]))
1639 except KeyError:
1639 except KeyError:
1640 pass
1640 pass
1641 elif st == 'iter':
1641 elif st == 'iter':
1642 states = matches[rev].items()
1642 states = matches[rev].items()
1643 states.sort()
1643 states.sort()
1644 for fn, m in states:
1644 for fn, m in states:
1645 if fn in skip:
1645 if fn in skip:
1646 continue
1646 continue
1647 if incrementing or not opts['all'] or fstate[fn]:
1647 if incrementing or not opts['all'] or fstate[fn]:
1648 pos, neg = display(fn, rev, m, fstate[fn])
1648 pos, neg = display(fn, rev, m, fstate[fn])
1649 count += pos + neg
1649 count += pos + neg
1650 if pos and not opts['all']:
1650 if pos and not opts['all']:
1651 skip[fn] = True
1651 skip[fn] = True
1652 fstate[fn] = m
1652 fstate[fn] = m
1653 prev[fn] = rev
1653 prev[fn] = rev
1654
1654
1655 if not incrementing:
1655 if not incrementing:
1656 fstate = fstate.items()
1656 fstate = fstate.items()
1657 fstate.sort()
1657 fstate.sort()
1658 for fn, state in fstate:
1658 for fn, state in fstate:
1659 if fn in skip:
1659 if fn in skip:
1660 continue
1660 continue
1661 display(fn, rev, {}, state)
1661 display(fn, rev, {}, state)
1662 return (count == 0 and 1) or 0
1662 return (count == 0 and 1) or 0
1663
1663
1664 def heads(ui, repo, **opts):
1664 def heads(ui, repo, **opts):
1665 """show current repository heads
1665 """show current repository heads
1666
1666
1667 Show all repository head changesets.
1667 Show all repository head changesets.
1668
1668
1669 Repository "heads" are changesets that don't have children
1669 Repository "heads" are changesets that don't have children
1670 changesets. They are where development generally takes place and
1670 changesets. They are where development generally takes place and
1671 are the usual targets for update and merge operations.
1671 are the usual targets for update and merge operations.
1672 """
1672 """
1673 if opts['rev']:
1673 if opts['rev']:
1674 heads = repo.heads(repo.lookup(opts['rev']))
1674 heads = repo.heads(repo.lookup(opts['rev']))
1675 else:
1675 else:
1676 heads = repo.heads()
1676 heads = repo.heads()
1677 br = None
1677 br = None
1678 if opts['branches']:
1678 if opts['branches']:
1679 br = repo.branchlookup(heads)
1679 br = repo.branchlookup(heads)
1680 displayer = show_changeset(ui, repo, opts)
1680 displayer = show_changeset(ui, repo, opts)
1681 for n in heads:
1681 for n in heads:
1682 displayer.show(changenode=n, brinfo=br)
1682 displayer.show(changenode=n, brinfo=br)
1683
1683
1684 def identify(ui, repo):
1684 def identify(ui, repo):
1685 """print information about the working copy
1685 """print information about the working copy
1686
1686
1687 Print a short summary of the current state of the repo.
1687 Print a short summary of the current state of the repo.
1688
1688
1689 This summary identifies the repository state using one or two parent
1689 This summary identifies the repository state using one or two parent
1690 hash identifiers, followed by a "+" if there are uncommitted changes
1690 hash identifiers, followed by a "+" if there are uncommitted changes
1691 in the working directory, followed by a list of tags for this revision.
1691 in the working directory, followed by a list of tags for this revision.
1692 """
1692 """
1693 parents = [p for p in repo.dirstate.parents() if p != nullid]
1693 parents = [p for p in repo.dirstate.parents() if p != nullid]
1694 if not parents:
1694 if not parents:
1695 ui.write(_("unknown\n"))
1695 ui.write(_("unknown\n"))
1696 return
1696 return
1697
1697
1698 hexfunc = ui.verbose and hex or short
1698 hexfunc = ui.verbose and hex or short
1699 modified, added, removed, deleted, unknown = repo.changes()
1699 modified, added, removed, deleted, unknown = repo.changes()
1700 output = ["%s%s" %
1700 output = ["%s%s" %
1701 ('+'.join([hexfunc(parent) for parent in parents]),
1701 ('+'.join([hexfunc(parent) for parent in parents]),
1702 (modified or added or removed or deleted) and "+" or "")]
1702 (modified or added or removed or deleted) and "+" or "")]
1703
1703
1704 if not ui.quiet:
1704 if not ui.quiet:
1705 # multiple tags for a single parent separated by '/'
1705 # multiple tags for a single parent separated by '/'
1706 parenttags = ['/'.join(tags)
1706 parenttags = ['/'.join(tags)
1707 for tags in map(repo.nodetags, parents) if tags]
1707 for tags in map(repo.nodetags, parents) if tags]
1708 # tags for multiple parents separated by ' + '
1708 # tags for multiple parents separated by ' + '
1709 if parenttags:
1709 if parenttags:
1710 output.append(' + '.join(parenttags))
1710 output.append(' + '.join(parenttags))
1711
1711
1712 ui.write("%s\n" % ' '.join(output))
1712 ui.write("%s\n" % ' '.join(output))
1713
1713
1714 def import_(ui, repo, patch1, *patches, **opts):
1714 def import_(ui, repo, patch1, *patches, **opts):
1715 """import an ordered set of patches
1715 """import an ordered set of patches
1716
1716
1717 Import a list of patches and commit them individually.
1717 Import a list of patches and commit them individually.
1718
1718
1719 If there are outstanding changes in the working directory, import
1719 If there are outstanding changes in the working directory, import
1720 will abort unless given the -f flag.
1720 will abort unless given the -f flag.
1721
1721
1722 You can import a patch straight from a mail message. Even patches
1722 You can import a patch straight from a mail message. Even patches
1723 as attachments work (body part must be type text/plain or
1723 as attachments work (body part must be type text/plain or
1724 text/x-patch to be used). From and Subject headers of email
1724 text/x-patch to be used). From and Subject headers of email
1725 message are used as default committer and commit message. All
1725 message are used as default committer and commit message. All
1726 text/plain body parts before first diff are added to commit
1726 text/plain body parts before first diff are added to commit
1727 message.
1727 message.
1728
1728
1729 If imported patch was generated by hg export, user and description
1729 If imported patch was generated by hg export, user and description
1730 from patch override values from message headers and body. Values
1730 from patch override values from message headers and body. Values
1731 given on command line with -m and -u override these.
1731 given on command line with -m and -u override these.
1732
1732
1733 To read a patch from standard input, use patch name "-".
1733 To read a patch from standard input, use patch name "-".
1734 """
1734 """
1735 patches = (patch1,) + patches
1735 patches = (patch1,) + patches
1736
1736
1737 if not opts['force']:
1737 if not opts['force']:
1738 bail_if_changed(repo)
1738 bail_if_changed(repo)
1739
1739
1740 d = opts["base"]
1740 d = opts["base"]
1741 strip = opts["strip"]
1741 strip = opts["strip"]
1742
1742
1743 mailre = re.compile(r'(?:From |[\w-]+:)')
1743 mailre = re.compile(r'(?:From |[\w-]+:)')
1744
1744
1745 # attempt to detect the start of a patch
1745 # attempt to detect the start of a patch
1746 # (this heuristic is borrowed from quilt)
1746 # (this heuristic is borrowed from quilt)
1747 diffre = re.compile(r'^(?:Index:[ \t]|diff[ \t]|RCS file: |' +
1747 diffre = re.compile(r'^(?:Index:[ \t]|diff[ \t]|RCS file: |' +
1748 'retrieving revision [0-9]+(\.[0-9]+)*$|' +
1748 'retrieving revision [0-9]+(\.[0-9]+)*$|' +
1749 '(---|\*\*\*)[ \t])', re.MULTILINE)
1749 '(---|\*\*\*)[ \t])', re.MULTILINE)
1750
1750
1751 for patch in patches:
1751 for patch in patches:
1752 pf = os.path.join(d, patch)
1752 pf = os.path.join(d, patch)
1753
1753
1754 message = None
1754 message = None
1755 user = None
1755 user = None
1756 date = None
1756 date = None
1757 hgpatch = False
1757 hgpatch = False
1758
1758
1759 p = email.Parser.Parser()
1759 p = email.Parser.Parser()
1760 if pf == '-':
1760 if pf == '-':
1761 msg = p.parse(sys.stdin)
1761 msg = p.parse(sys.stdin)
1762 ui.status(_("applying patch from stdin\n"))
1762 ui.status(_("applying patch from stdin\n"))
1763 else:
1763 else:
1764 msg = p.parse(file(pf))
1764 msg = p.parse(file(pf))
1765 ui.status(_("applying %s\n") % patch)
1765 ui.status(_("applying %s\n") % patch)
1766
1766
1767 fd, tmpname = tempfile.mkstemp(prefix='hg-patch-')
1767 fd, tmpname = tempfile.mkstemp(prefix='hg-patch-')
1768 tmpfp = os.fdopen(fd, 'w')
1768 tmpfp = os.fdopen(fd, 'w')
1769 try:
1769 try:
1770 message = msg['Subject']
1770 message = msg['Subject']
1771 if message:
1771 if message:
1772 message = message.replace('\n\t', ' ')
1772 message = message.replace('\n\t', ' ')
1773 ui.debug('Subject: %s\n' % message)
1773 ui.debug('Subject: %s\n' % message)
1774 user = msg['From']
1774 user = msg['From']
1775 if user:
1775 if user:
1776 ui.debug('From: %s\n' % user)
1776 ui.debug('From: %s\n' % user)
1777 diffs_seen = 0
1777 diffs_seen = 0
1778 ok_types = ('text/plain', 'text/x-patch')
1778 ok_types = ('text/plain', 'text/x-patch')
1779 for part in msg.walk():
1779 for part in msg.walk():
1780 content_type = part.get_content_type()
1780 content_type = part.get_content_type()
1781 ui.debug('Content-Type: %s\n' % content_type)
1781 ui.debug('Content-Type: %s\n' % content_type)
1782 if content_type not in ok_types:
1782 if content_type not in ok_types:
1783 continue
1783 continue
1784 payload = part.get_payload(decode=True)
1784 payload = part.get_payload(decode=True)
1785 m = diffre.search(payload)
1785 m = diffre.search(payload)
1786 if m:
1786 if m:
1787 ui.debug(_('found patch at byte %d\n') % m.start(0))
1787 ui.debug(_('found patch at byte %d\n') % m.start(0))
1788 diffs_seen += 1
1788 diffs_seen += 1
1789 hgpatch = False
1789 hgpatch = False
1790 fp = cStringIO.StringIO()
1790 fp = cStringIO.StringIO()
1791 if message:
1791 if message:
1792 fp.write(message)
1792 fp.write(message)
1793 fp.write('\n')
1793 fp.write('\n')
1794 for line in payload[:m.start(0)].splitlines():
1794 for line in payload[:m.start(0)].splitlines():
1795 if line.startswith('# HG changeset patch'):
1795 if line.startswith('# HG changeset patch'):
1796 ui.debug(_('patch generated by hg export\n'))
1796 ui.debug(_('patch generated by hg export\n'))
1797 hgpatch = True
1797 hgpatch = True
1798 # drop earlier commit message content
1798 # drop earlier commit message content
1799 fp.seek(0)
1799 fp.seek(0)
1800 fp.truncate()
1800 fp.truncate()
1801 elif hgpatch:
1801 elif hgpatch:
1802 if line.startswith('# User '):
1802 if line.startswith('# User '):
1803 user = line[7:]
1803 user = line[7:]
1804 ui.debug('From: %s\n' % user)
1804 ui.debug('From: %s\n' % user)
1805 elif line.startswith("# Date "):
1805 elif line.startswith("# Date "):
1806 date = line[7:]
1806 date = line[7:]
1807 if not line.startswith('# '):
1807 if not line.startswith('# '):
1808 fp.write(line)
1808 fp.write(line)
1809 fp.write('\n')
1809 fp.write('\n')
1810 message = fp.getvalue()
1810 message = fp.getvalue()
1811 if tmpfp:
1811 if tmpfp:
1812 tmpfp.write(payload)
1812 tmpfp.write(payload)
1813 if not payload.endswith('\n'):
1813 if not payload.endswith('\n'):
1814 tmpfp.write('\n')
1814 tmpfp.write('\n')
1815 elif not diffs_seen and message and content_type == 'text/plain':
1815 elif not diffs_seen and message and content_type == 'text/plain':
1816 message += '\n' + payload
1816 message += '\n' + payload
1817
1817
1818 if opts['message']:
1818 if opts['message']:
1819 # pickup the cmdline msg
1819 # pickup the cmdline msg
1820 message = opts['message']
1820 message = opts['message']
1821 elif message:
1821 elif message:
1822 # pickup the patch msg
1822 # pickup the patch msg
1823 message = message.strip()
1823 message = message.strip()
1824 else:
1824 else:
1825 # launch the editor
1825 # launch the editor
1826 message = None
1826 message = None
1827 ui.debug(_('message:\n%s\n') % message)
1827 ui.debug(_('message:\n%s\n') % message)
1828
1828
1829 tmpfp.close()
1829 tmpfp.close()
1830 if not diffs_seen:
1830 if not diffs_seen:
1831 raise util.Abort(_('no diffs found'))
1831 raise util.Abort(_('no diffs found'))
1832
1832
1833 files = util.patch(strip, tmpname, ui)
1833 files = util.patch(strip, tmpname, ui)
1834 if len(files) > 0:
1834 if len(files) > 0:
1835 addremove_lock(ui, repo, files, {})
1835 addremove_lock(ui, repo, files, {})
1836 repo.commit(files, message, user, date)
1836 repo.commit(files, message, user, date)
1837 finally:
1837 finally:
1838 os.unlink(tmpname)
1838 os.unlink(tmpname)
1839
1839
1840 def incoming(ui, repo, source="default", **opts):
1840 def incoming(ui, repo, source="default", **opts):
1841 """show new changesets found in source
1841 """show new changesets found in source
1842
1842
1843 Show new changesets found in the specified path/URL or the default
1843 Show new changesets found in the specified path/URL or the default
1844 pull location. These are the changesets that would be pulled if a pull
1844 pull location. These are the changesets that would be pulled if a pull
1845 was requested.
1845 was requested.
1846
1846
1847 For remote repository, using --bundle avoids downloading the changesets
1847 For remote repository, using --bundle avoids downloading the changesets
1848 twice if the incoming is followed by a pull.
1848 twice if the incoming is followed by a pull.
1849
1849
1850 See pull for valid source format details.
1850 See pull for valid source format details.
1851 """
1851 """
1852 source = ui.expandpath(source)
1852 source = ui.expandpath(source)
1853 if opts['ssh']:
1853 if opts['ssh']:
1854 ui.setconfig("ui", "ssh", opts['ssh'])
1854 ui.setconfig("ui", "ssh", opts['ssh'])
1855 if opts['remotecmd']:
1855 if opts['remotecmd']:
1856 ui.setconfig("ui", "remotecmd", opts['remotecmd'])
1856 ui.setconfig("ui", "remotecmd", opts['remotecmd'])
1857
1857
1858 other = hg.repository(ui, source)
1858 other = hg.repository(ui, source)
1859 incoming = repo.findincoming(other, force=opts["force"])
1859 incoming = repo.findincoming(other, force=opts["force"])
1860 if not incoming:
1860 if not incoming:
1861 ui.status(_("no changes found\n"))
1861 ui.status(_("no changes found\n"))
1862 return
1862 return
1863
1863
1864 cleanup = None
1864 cleanup = None
1865 try:
1865 try:
1866 fname = opts["bundle"]
1866 fname = opts["bundle"]
1867 if fname or not other.local():
1867 if fname or not other.local():
1868 # create a bundle (uncompressed if other repo is not local)
1868 # create a bundle (uncompressed if other repo is not local)
1869 cg = other.changegroup(incoming, "incoming")
1869 cg = other.changegroup(incoming, "incoming")
1870 fname = cleanup = write_bundle(cg, fname, compress=other.local())
1870 fname = cleanup = write_bundle(cg, fname, compress=other.local())
1871 # keep written bundle?
1871 # keep written bundle?
1872 if opts["bundle"]:
1872 if opts["bundle"]:
1873 cleanup = None
1873 cleanup = None
1874 if not other.local():
1874 if not other.local():
1875 # use the created uncompressed bundlerepo
1875 # use the created uncompressed bundlerepo
1876 other = bundlerepo.bundlerepository(ui, repo.root, fname)
1876 other = bundlerepo.bundlerepository(ui, repo.root, fname)
1877
1877
1878 o = other.changelog.nodesbetween(incoming)[0]
1878 revs = None
1879 if opts['rev']:
1880 revs = [other.lookup(rev) for rev in opts['rev']]
1881 o = other.changelog.nodesbetween(incoming, revs)[0]
1879 if opts['newest_first']:
1882 if opts['newest_first']:
1880 o.reverse()
1883 o.reverse()
1881 displayer = show_changeset(ui, other, opts)
1884 displayer = show_changeset(ui, other, opts)
1882 for n in o:
1885 for n in o:
1883 parents = [p for p in other.changelog.parents(n) if p != nullid]
1886 parents = [p for p in other.changelog.parents(n) if p != nullid]
1884 if opts['no_merges'] and len(parents) == 2:
1887 if opts['no_merges'] and len(parents) == 2:
1885 continue
1888 continue
1886 displayer.show(changenode=n)
1889 displayer.show(changenode=n)
1887 if opts['patch']:
1890 if opts['patch']:
1888 prev = (parents and parents[0]) or nullid
1891 prev = (parents and parents[0]) or nullid
1889 dodiff(ui, ui, other, prev, n)
1892 dodiff(ui, ui, other, prev, n)
1890 ui.write("\n")
1893 ui.write("\n")
1891 finally:
1894 finally:
1892 if hasattr(other, 'close'):
1895 if hasattr(other, 'close'):
1893 other.close()
1896 other.close()
1894 if cleanup:
1897 if cleanup:
1895 os.unlink(cleanup)
1898 os.unlink(cleanup)
1896
1899
1897 def init(ui, dest="."):
1900 def init(ui, dest="."):
1898 """create a new repository in the given directory
1901 """create a new repository in the given directory
1899
1902
1900 Initialize a new repository in the given directory. If the given
1903 Initialize a new repository in the given directory. If the given
1901 directory does not exist, it is created.
1904 directory does not exist, it is created.
1902
1905
1903 If no directory is given, the current directory is used.
1906 If no directory is given, the current directory is used.
1904 """
1907 """
1905 if not os.path.exists(dest):
1908 if not os.path.exists(dest):
1906 os.mkdir(dest)
1909 os.mkdir(dest)
1907 hg.repository(ui, dest, create=1)
1910 hg.repository(ui, dest, create=1)
1908
1911
1909 def locate(ui, repo, *pats, **opts):
1912 def locate(ui, repo, *pats, **opts):
1910 """locate files matching specific patterns
1913 """locate files matching specific patterns
1911
1914
1912 Print all files under Mercurial control whose names match the
1915 Print all files under Mercurial control whose names match the
1913 given patterns.
1916 given patterns.
1914
1917
1915 This command searches the current directory and its
1918 This command searches the current directory and its
1916 subdirectories. To search an entire repository, move to the root
1919 subdirectories. To search an entire repository, move to the root
1917 of the repository.
1920 of the repository.
1918
1921
1919 If no patterns are given to match, this command prints all file
1922 If no patterns are given to match, this command prints all file
1920 names.
1923 names.
1921
1924
1922 If you want to feed the output of this command into the "xargs"
1925 If you want to feed the output of this command into the "xargs"
1923 command, use the "-0" option to both this command and "xargs".
1926 command, use the "-0" option to both this command and "xargs".
1924 This will avoid the problem of "xargs" treating single filenames
1927 This will avoid the problem of "xargs" treating single filenames
1925 that contain white space as multiple filenames.
1928 that contain white space as multiple filenames.
1926 """
1929 """
1927 end = opts['print0'] and '\0' or '\n'
1930 end = opts['print0'] and '\0' or '\n'
1928 rev = opts['rev']
1931 rev = opts['rev']
1929 if rev:
1932 if rev:
1930 node = repo.lookup(rev)
1933 node = repo.lookup(rev)
1931 else:
1934 else:
1932 node = None
1935 node = None
1933
1936
1934 for src, abs, rel, exact in walk(repo, pats, opts, node=node,
1937 for src, abs, rel, exact in walk(repo, pats, opts, node=node,
1935 head='(?:.*/|)'):
1938 head='(?:.*/|)'):
1936 if not node and repo.dirstate.state(abs) == '?':
1939 if not node and repo.dirstate.state(abs) == '?':
1937 continue
1940 continue
1938 if opts['fullpath']:
1941 if opts['fullpath']:
1939 ui.write(os.path.join(repo.root, abs), end)
1942 ui.write(os.path.join(repo.root, abs), end)
1940 else:
1943 else:
1941 ui.write(((pats and rel) or abs), end)
1944 ui.write(((pats and rel) or abs), end)
1942
1945
1943 def log(ui, repo, *pats, **opts):
1946 def log(ui, repo, *pats, **opts):
1944 """show revision history of entire repository or files
1947 """show revision history of entire repository or files
1945
1948
1946 Print the revision history of the specified files or the entire project.
1949 Print the revision history of the specified files or the entire project.
1947
1950
1948 By default this command outputs: changeset id and hash, tags,
1951 By default this command outputs: changeset id and hash, tags,
1949 non-trivial parents, user, date and time, and a summary for each
1952 non-trivial parents, user, date and time, and a summary for each
1950 commit. When the -v/--verbose switch is used, the list of changed
1953 commit. When the -v/--verbose switch is used, the list of changed
1951 files and full commit message is shown.
1954 files and full commit message is shown.
1952 """
1955 """
1953 class dui(object):
1956 class dui(object):
1954 # Implement and delegate some ui protocol. Save hunks of
1957 # Implement and delegate some ui protocol. Save hunks of
1955 # output for later display in the desired order.
1958 # output for later display in the desired order.
1956 def __init__(self, ui):
1959 def __init__(self, ui):
1957 self.ui = ui
1960 self.ui = ui
1958 self.hunk = {}
1961 self.hunk = {}
1959 self.header = {}
1962 self.header = {}
1960 def bump(self, rev):
1963 def bump(self, rev):
1961 self.rev = rev
1964 self.rev = rev
1962 self.hunk[rev] = []
1965 self.hunk[rev] = []
1963 self.header[rev] = []
1966 self.header[rev] = []
1964 def note(self, *args):
1967 def note(self, *args):
1965 if self.verbose:
1968 if self.verbose:
1966 self.write(*args)
1969 self.write(*args)
1967 def status(self, *args):
1970 def status(self, *args):
1968 if not self.quiet:
1971 if not self.quiet:
1969 self.write(*args)
1972 self.write(*args)
1970 def write(self, *args):
1973 def write(self, *args):
1971 self.hunk[self.rev].append(args)
1974 self.hunk[self.rev].append(args)
1972 def write_header(self, *args):
1975 def write_header(self, *args):
1973 self.header[self.rev].append(args)
1976 self.header[self.rev].append(args)
1974 def debug(self, *args):
1977 def debug(self, *args):
1975 if self.debugflag:
1978 if self.debugflag:
1976 self.write(*args)
1979 self.write(*args)
1977 def __getattr__(self, key):
1980 def __getattr__(self, key):
1978 return getattr(self.ui, key)
1981 return getattr(self.ui, key)
1979
1982
1980 changeiter, getchange, matchfn = walkchangerevs(ui, repo, pats, opts)
1983 changeiter, getchange, matchfn = walkchangerevs(ui, repo, pats, opts)
1981
1984
1982 if opts['limit']:
1985 if opts['limit']:
1983 try:
1986 try:
1984 limit = int(opts['limit'])
1987 limit = int(opts['limit'])
1985 except ValueError:
1988 except ValueError:
1986 raise util.Abort(_('limit must be a positive integer'))
1989 raise util.Abort(_('limit must be a positive integer'))
1987 if limit <= 0: raise util.Abort(_('limit must be positive'))
1990 if limit <= 0: raise util.Abort(_('limit must be positive'))
1988 else:
1991 else:
1989 limit = sys.maxint
1992 limit = sys.maxint
1990 count = 0
1993 count = 0
1991
1994
1992 displayer = show_changeset(ui, repo, opts)
1995 displayer = show_changeset(ui, repo, opts)
1993 for st, rev, fns in changeiter:
1996 for st, rev, fns in changeiter:
1994 if st == 'window':
1997 if st == 'window':
1995 du = dui(ui)
1998 du = dui(ui)
1996 displayer.ui = du
1999 displayer.ui = du
1997 elif st == 'add':
2000 elif st == 'add':
1998 du.bump(rev)
2001 du.bump(rev)
1999 changenode = repo.changelog.node(rev)
2002 changenode = repo.changelog.node(rev)
2000 parents = [p for p in repo.changelog.parents(changenode)
2003 parents = [p for p in repo.changelog.parents(changenode)
2001 if p != nullid]
2004 if p != nullid]
2002 if opts['no_merges'] and len(parents) == 2:
2005 if opts['no_merges'] and len(parents) == 2:
2003 continue
2006 continue
2004 if opts['only_merges'] and len(parents) != 2:
2007 if opts['only_merges'] and len(parents) != 2:
2005 continue
2008 continue
2006
2009
2007 if opts['keyword']:
2010 if opts['keyword']:
2008 changes = getchange(rev)
2011 changes = getchange(rev)
2009 miss = 0
2012 miss = 0
2010 for k in [kw.lower() for kw in opts['keyword']]:
2013 for k in [kw.lower() for kw in opts['keyword']]:
2011 if not (k in changes[1].lower() or
2014 if not (k in changes[1].lower() or
2012 k in changes[4].lower() or
2015 k in changes[4].lower() or
2013 k in " ".join(changes[3][:20]).lower()):
2016 k in " ".join(changes[3][:20]).lower()):
2014 miss = 1
2017 miss = 1
2015 break
2018 break
2016 if miss:
2019 if miss:
2017 continue
2020 continue
2018
2021
2019 br = None
2022 br = None
2020 if opts['branches']:
2023 if opts['branches']:
2021 br = repo.branchlookup([repo.changelog.node(rev)])
2024 br = repo.branchlookup([repo.changelog.node(rev)])
2022
2025
2023 displayer.show(rev, brinfo=br)
2026 displayer.show(rev, brinfo=br)
2024 if opts['patch']:
2027 if opts['patch']:
2025 prev = (parents and parents[0]) or nullid
2028 prev = (parents and parents[0]) or nullid
2026 dodiff(du, du, repo, prev, changenode, match=matchfn)
2029 dodiff(du, du, repo, prev, changenode, match=matchfn)
2027 du.write("\n\n")
2030 du.write("\n\n")
2028 elif st == 'iter':
2031 elif st == 'iter':
2029 if count == limit: break
2032 if count == limit: break
2030 if du.header[rev]:
2033 if du.header[rev]:
2031 for args in du.header[rev]:
2034 for args in du.header[rev]:
2032 ui.write_header(*args)
2035 ui.write_header(*args)
2033 if du.hunk[rev]:
2036 if du.hunk[rev]:
2034 count += 1
2037 count += 1
2035 for args in du.hunk[rev]:
2038 for args in du.hunk[rev]:
2036 ui.write(*args)
2039 ui.write(*args)
2037
2040
2038 def manifest(ui, repo, rev=None):
2041 def manifest(ui, repo, rev=None):
2039 """output the latest or given revision of the project manifest
2042 """output the latest or given revision of the project manifest
2040
2043
2041 Print a list of version controlled files for the given revision.
2044 Print a list of version controlled files for the given revision.
2042
2045
2043 The manifest is the list of files being version controlled. If no revision
2046 The manifest is the list of files being version controlled. If no revision
2044 is given then the tip is used.
2047 is given then the tip is used.
2045 """
2048 """
2046 if rev:
2049 if rev:
2047 try:
2050 try:
2048 # assume all revision numbers are for changesets
2051 # assume all revision numbers are for changesets
2049 n = repo.lookup(rev)
2052 n = repo.lookup(rev)
2050 change = repo.changelog.read(n)
2053 change = repo.changelog.read(n)
2051 n = change[0]
2054 n = change[0]
2052 except hg.RepoError:
2055 except hg.RepoError:
2053 n = repo.manifest.lookup(rev)
2056 n = repo.manifest.lookup(rev)
2054 else:
2057 else:
2055 n = repo.manifest.tip()
2058 n = repo.manifest.tip()
2056 m = repo.manifest.read(n)
2059 m = repo.manifest.read(n)
2057 mf = repo.manifest.readflags(n)
2060 mf = repo.manifest.readflags(n)
2058 files = m.keys()
2061 files = m.keys()
2059 files.sort()
2062 files.sort()
2060
2063
2061 for f in files:
2064 for f in files:
2062 ui.write("%40s %3s %s\n" % (hex(m[f]), mf[f] and "755" or "644", f))
2065 ui.write("%40s %3s %s\n" % (hex(m[f]), mf[f] and "755" or "644", f))
2063
2066
2064 def merge(ui, repo, node=None, **opts):
2067 def merge(ui, repo, node=None, **opts):
2065 """Merge working directory with another revision
2068 """Merge working directory with another revision
2066
2069
2067 Merge the contents of the current working directory and the
2070 Merge the contents of the current working directory and the
2068 requested revision. Files that changed between either parent are
2071 requested revision. Files that changed between either parent are
2069 marked as changed for the next commit and a commit must be
2072 marked as changed for the next commit and a commit must be
2070 performed before any further updates are allowed.
2073 performed before any further updates are allowed.
2071 """
2074 """
2072 return doupdate(ui, repo, node=node, merge=True, **opts)
2075 return doupdate(ui, repo, node=node, merge=True, **opts)
2073
2076
2074 def outgoing(ui, repo, dest=None, **opts):
2077 def outgoing(ui, repo, dest=None, **opts):
2075 """show changesets not found in destination
2078 """show changesets not found in destination
2076
2079
2077 Show changesets not found in the specified destination repository or
2080 Show changesets not found in the specified destination repository or
2078 the default push location. These are the changesets that would be pushed
2081 the default push location. These are the changesets that would be pushed
2079 if a push was requested.
2082 if a push was requested.
2080
2083
2081 See pull for valid destination format details.
2084 See pull for valid destination format details.
2082 """
2085 """
2083 dest = ui.expandpath(dest or 'default-push', dest or 'default')
2086 dest = ui.expandpath(dest or 'default-push', dest or 'default')
2084 if opts['ssh']:
2087 if opts['ssh']:
2085 ui.setconfig("ui", "ssh", opts['ssh'])
2088 ui.setconfig("ui", "ssh", opts['ssh'])
2086 if opts['remotecmd']:
2089 if opts['remotecmd']:
2087 ui.setconfig("ui", "remotecmd", opts['remotecmd'])
2090 ui.setconfig("ui", "remotecmd", opts['remotecmd'])
2091 revs = None
2092 if opts['rev']:
2093 revs = [repo.lookup(rev) for rev in opts['rev']]
2088
2094
2089 other = hg.repository(ui, dest)
2095 other = hg.repository(ui, dest)
2090 o = repo.findoutgoing(other, force=opts['force'])
2096 o = repo.findoutgoing(other, force=opts['force'])
2091 if not o:
2097 if not o:
2092 ui.status(_("no changes found\n"))
2098 ui.status(_("no changes found\n"))
2093 return
2099 return
2094 o = repo.changelog.nodesbetween(o)[0]
2100 o = repo.changelog.nodesbetween(o, revs)[0]
2095 if opts['newest_first']:
2101 if opts['newest_first']:
2096 o.reverse()
2102 o.reverse()
2097 displayer = show_changeset(ui, repo, opts)
2103 displayer = show_changeset(ui, repo, opts)
2098 for n in o:
2104 for n in o:
2099 parents = [p for p in repo.changelog.parents(n) if p != nullid]
2105 parents = [p for p in repo.changelog.parents(n) if p != nullid]
2100 if opts['no_merges'] and len(parents) == 2:
2106 if opts['no_merges'] and len(parents) == 2:
2101 continue
2107 continue
2102 displayer.show(changenode=n)
2108 displayer.show(changenode=n)
2103 if opts['patch']:
2109 if opts['patch']:
2104 prev = (parents and parents[0]) or nullid
2110 prev = (parents and parents[0]) or nullid
2105 dodiff(ui, ui, repo, prev, n)
2111 dodiff(ui, ui, repo, prev, n)
2106 ui.write("\n")
2112 ui.write("\n")
2107
2113
2108 def parents(ui, repo, rev=None, branches=None, **opts):
2114 def parents(ui, repo, rev=None, branches=None, **opts):
2109 """show the parents of the working dir or revision
2115 """show the parents of the working dir or revision
2110
2116
2111 Print the working directory's parent revisions.
2117 Print the working directory's parent revisions.
2112 """
2118 """
2113 if rev:
2119 if rev:
2114 p = repo.changelog.parents(repo.lookup(rev))
2120 p = repo.changelog.parents(repo.lookup(rev))
2115 else:
2121 else:
2116 p = repo.dirstate.parents()
2122 p = repo.dirstate.parents()
2117
2123
2118 br = None
2124 br = None
2119 if branches is not None:
2125 if branches is not None:
2120 br = repo.branchlookup(p)
2126 br = repo.branchlookup(p)
2121 displayer = show_changeset(ui, repo, opts)
2127 displayer = show_changeset(ui, repo, opts)
2122 for n in p:
2128 for n in p:
2123 if n != nullid:
2129 if n != nullid:
2124 displayer.show(changenode=n, brinfo=br)
2130 displayer.show(changenode=n, brinfo=br)
2125
2131
2126 def paths(ui, repo, search=None):
2132 def paths(ui, repo, search=None):
2127 """show definition of symbolic path names
2133 """show definition of symbolic path names
2128
2134
2129 Show definition of symbolic path name NAME. If no name is given, show
2135 Show definition of symbolic path name NAME. If no name is given, show
2130 definition of available names.
2136 definition of available names.
2131
2137
2132 Path names are defined in the [paths] section of /etc/mercurial/hgrc
2138 Path names are defined in the [paths] section of /etc/mercurial/hgrc
2133 and $HOME/.hgrc. If run inside a repository, .hg/hgrc is used, too.
2139 and $HOME/.hgrc. If run inside a repository, .hg/hgrc is used, too.
2134 """
2140 """
2135 if search:
2141 if search:
2136 for name, path in ui.configitems("paths"):
2142 for name, path in ui.configitems("paths"):
2137 if name == search:
2143 if name == search:
2138 ui.write("%s\n" % path)
2144 ui.write("%s\n" % path)
2139 return
2145 return
2140 ui.warn(_("not found!\n"))
2146 ui.warn(_("not found!\n"))
2141 return 1
2147 return 1
2142 else:
2148 else:
2143 for name, path in ui.configitems("paths"):
2149 for name, path in ui.configitems("paths"):
2144 ui.write("%s = %s\n" % (name, path))
2150 ui.write("%s = %s\n" % (name, path))
2145
2151
2146 def postincoming(ui, repo, modheads, optupdate):
2152 def postincoming(ui, repo, modheads, optupdate):
2147 if modheads == 0:
2153 if modheads == 0:
2148 return
2154 return
2149 if optupdate:
2155 if optupdate:
2150 if modheads == 1:
2156 if modheads == 1:
2151 return doupdate(ui, repo)
2157 return doupdate(ui, repo)
2152 else:
2158 else:
2153 ui.status(_("not updating, since new heads added\n"))
2159 ui.status(_("not updating, since new heads added\n"))
2154 if modheads > 1:
2160 if modheads > 1:
2155 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
2161 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
2156 else:
2162 else:
2157 ui.status(_("(run 'hg update' to get a working copy)\n"))
2163 ui.status(_("(run 'hg update' to get a working copy)\n"))
2158
2164
2159 def pull(ui, repo, source="default", **opts):
2165 def pull(ui, repo, source="default", **opts):
2160 """pull changes from the specified source
2166 """pull changes from the specified source
2161
2167
2162 Pull changes from a remote repository to a local one.
2168 Pull changes from a remote repository to a local one.
2163
2169
2164 This finds all changes from the repository at the specified path
2170 This finds all changes from the repository at the specified path
2165 or URL and adds them to the local repository. By default, this
2171 or URL and adds them to the local repository. By default, this
2166 does not update the copy of the project in the working directory.
2172 does not update the copy of the project in the working directory.
2167
2173
2168 Valid URLs are of the form:
2174 Valid URLs are of the form:
2169
2175
2170 local/filesystem/path
2176 local/filesystem/path
2171 http://[user@]host[:port][/path]
2177 http://[user@]host[:port][/path]
2172 https://[user@]host[:port][/path]
2178 https://[user@]host[:port][/path]
2173 ssh://[user@]host[:port][/path]
2179 ssh://[user@]host[:port][/path]
2174
2180
2175 Some notes about using SSH with Mercurial:
2181 Some notes about using SSH with Mercurial:
2176 - SSH requires an accessible shell account on the destination machine
2182 - SSH requires an accessible shell account on the destination machine
2177 and a copy of hg in the remote path or specified with as remotecmd.
2183 and a copy of hg in the remote path or specified with as remotecmd.
2178 - /path is relative to the remote user's home directory by default.
2184 - /path is relative to the remote user's home directory by default.
2179 Use two slashes at the start of a path to specify an absolute path.
2185 Use two slashes at the start of a path to specify an absolute path.
2180 - Mercurial doesn't use its own compression via SSH; the right thing
2186 - Mercurial doesn't use its own compression via SSH; the right thing
2181 to do is to configure it in your ~/.ssh/ssh_config, e.g.:
2187 to do is to configure it in your ~/.ssh/ssh_config, e.g.:
2182 Host *.mylocalnetwork.example.com
2188 Host *.mylocalnetwork.example.com
2183 Compression off
2189 Compression off
2184 Host *
2190 Host *
2185 Compression on
2191 Compression on
2186 Alternatively specify "ssh -C" as your ssh command in your hgrc or
2192 Alternatively specify "ssh -C" as your ssh command in your hgrc or
2187 with the --ssh command line option.
2193 with the --ssh command line option.
2188 """
2194 """
2189 source = ui.expandpath(source)
2195 source = ui.expandpath(source)
2190
2196
2191 if opts['ssh']:
2197 if opts['ssh']:
2192 ui.setconfig("ui", "ssh", opts['ssh'])
2198 ui.setconfig("ui", "ssh", opts['ssh'])
2193 if opts['remotecmd']:
2199 if opts['remotecmd']:
2194 ui.setconfig("ui", "remotecmd", opts['remotecmd'])
2200 ui.setconfig("ui", "remotecmd", opts['remotecmd'])
2195
2201
2196 other = hg.repository(ui, source)
2202 other = hg.repository(ui, source)
2197 ui.status(_('pulling from %s\n') % (source))
2203 ui.status(_('pulling from %s\n') % (source))
2198 revs = None
2204 revs = None
2199 if opts['rev'] and not other.local():
2205 if opts['rev'] and not other.local():
2200 raise util.Abort(_("pull -r doesn't work for remote repositories yet"))
2206 raise util.Abort(_("pull -r doesn't work for remote repositories yet"))
2201 elif opts['rev']:
2207 elif opts['rev']:
2202 revs = [other.lookup(rev) for rev in opts['rev']]
2208 revs = [other.lookup(rev) for rev in opts['rev']]
2203 modheads = repo.pull(other, heads=revs, force=opts['force'])
2209 modheads = repo.pull(other, heads=revs, force=opts['force'])
2204 return postincoming(ui, repo, modheads, opts['update'])
2210 return postincoming(ui, repo, modheads, opts['update'])
2205
2211
2206 def push(ui, repo, dest=None, **opts):
2212 def push(ui, repo, dest=None, **opts):
2207 """push changes to the specified destination
2213 """push changes to the specified destination
2208
2214
2209 Push changes from the local repository to the given destination.
2215 Push changes from the local repository to the given destination.
2210
2216
2211 This is the symmetrical operation for pull. It helps to move
2217 This is the symmetrical operation for pull. It helps to move
2212 changes from the current repository to a different one. If the
2218 changes from the current repository to a different one. If the
2213 destination is local this is identical to a pull in that directory
2219 destination is local this is identical to a pull in that directory
2214 from the current one.
2220 from the current one.
2215
2221
2216 By default, push will refuse to run if it detects the result would
2222 By default, push will refuse to run if it detects the result would
2217 increase the number of remote heads. This generally indicates the
2223 increase the number of remote heads. This generally indicates the
2218 the client has forgotten to sync and merge before pushing.
2224 the client has forgotten to sync and merge before pushing.
2219
2225
2220 Valid URLs are of the form:
2226 Valid URLs are of the form:
2221
2227
2222 local/filesystem/path
2228 local/filesystem/path
2223 ssh://[user@]host[:port][/path]
2229 ssh://[user@]host[:port][/path]
2224
2230
2225 Look at the help text for the pull command for important details
2231 Look at the help text for the pull command for important details
2226 about ssh:// URLs.
2232 about ssh:// URLs.
2227 """
2233 """
2228 dest = ui.expandpath(dest or 'default-push', dest or 'default')
2234 dest = ui.expandpath(dest or 'default-push', dest or 'default')
2229
2235
2230 if opts['ssh']:
2236 if opts['ssh']:
2231 ui.setconfig("ui", "ssh", opts['ssh'])
2237 ui.setconfig("ui", "ssh", opts['ssh'])
2232 if opts['remotecmd']:
2238 if opts['remotecmd']:
2233 ui.setconfig("ui", "remotecmd", opts['remotecmd'])
2239 ui.setconfig("ui", "remotecmd", opts['remotecmd'])
2234
2240
2235 other = hg.repository(ui, dest)
2241 other = hg.repository(ui, dest)
2236 ui.status('pushing to %s\n' % (dest))
2242 ui.status('pushing to %s\n' % (dest))
2237 revs = None
2243 revs = None
2238 if opts['rev']:
2244 if opts['rev']:
2239 revs = [repo.lookup(rev) for rev in opts['rev']]
2245 revs = [repo.lookup(rev) for rev in opts['rev']]
2240 r = repo.push(other, opts['force'], revs=revs)
2246 r = repo.push(other, opts['force'], revs=revs)
2241 return r == 0
2247 return r == 0
2242
2248
2243 def rawcommit(ui, repo, *flist, **rc):
2249 def rawcommit(ui, repo, *flist, **rc):
2244 """raw commit interface (DEPRECATED)
2250 """raw commit interface (DEPRECATED)
2245
2251
2246 (DEPRECATED)
2252 (DEPRECATED)
2247 Lowlevel commit, for use in helper scripts.
2253 Lowlevel commit, for use in helper scripts.
2248
2254
2249 This command is not intended to be used by normal users, as it is
2255 This command is not intended to be used by normal users, as it is
2250 primarily useful for importing from other SCMs.
2256 primarily useful for importing from other SCMs.
2251
2257
2252 This command is now deprecated and will be removed in a future
2258 This command is now deprecated and will be removed in a future
2253 release, please use debugsetparents and commit instead.
2259 release, please use debugsetparents and commit instead.
2254 """
2260 """
2255
2261
2256 ui.warn(_("(the rawcommit command is deprecated)\n"))
2262 ui.warn(_("(the rawcommit command is deprecated)\n"))
2257
2263
2258 message = rc['message']
2264 message = rc['message']
2259 if not message and rc['logfile']:
2265 if not message and rc['logfile']:
2260 try:
2266 try:
2261 message = open(rc['logfile']).read()
2267 message = open(rc['logfile']).read()
2262 except IOError:
2268 except IOError:
2263 pass
2269 pass
2264 if not message and not rc['logfile']:
2270 if not message and not rc['logfile']:
2265 raise util.Abort(_("missing commit message"))
2271 raise util.Abort(_("missing commit message"))
2266
2272
2267 files = relpath(repo, list(flist))
2273 files = relpath(repo, list(flist))
2268 if rc['files']:
2274 if rc['files']:
2269 files += open(rc['files']).read().splitlines()
2275 files += open(rc['files']).read().splitlines()
2270
2276
2271 rc['parent'] = map(repo.lookup, rc['parent'])
2277 rc['parent'] = map(repo.lookup, rc['parent'])
2272
2278
2273 try:
2279 try:
2274 repo.rawcommit(files, message, rc['user'], rc['date'], *rc['parent'])
2280 repo.rawcommit(files, message, rc['user'], rc['date'], *rc['parent'])
2275 except ValueError, inst:
2281 except ValueError, inst:
2276 raise util.Abort(str(inst))
2282 raise util.Abort(str(inst))
2277
2283
2278 def recover(ui, repo):
2284 def recover(ui, repo):
2279 """roll back an interrupted transaction
2285 """roll back an interrupted transaction
2280
2286
2281 Recover from an interrupted commit or pull.
2287 Recover from an interrupted commit or pull.
2282
2288
2283 This command tries to fix the repository status after an interrupted
2289 This command tries to fix the repository status after an interrupted
2284 operation. It should only be necessary when Mercurial suggests it.
2290 operation. It should only be necessary when Mercurial suggests it.
2285 """
2291 """
2286 if repo.recover():
2292 if repo.recover():
2287 return repo.verify()
2293 return repo.verify()
2288 return 1
2294 return 1
2289
2295
2290 def remove(ui, repo, *pats, **opts):
2296 def remove(ui, repo, *pats, **opts):
2291 """remove the specified files on the next commit
2297 """remove the specified files on the next commit
2292
2298
2293 Schedule the indicated files for removal from the repository.
2299 Schedule the indicated files for removal from the repository.
2294
2300
2295 This command schedules the files to be removed at the next commit.
2301 This command schedules the files to be removed at the next commit.
2296 This only removes files from the current branch, not from the
2302 This only removes files from the current branch, not from the
2297 entire project history. If the files still exist in the working
2303 entire project history. If the files still exist in the working
2298 directory, they will be deleted from it. If invoked with --after,
2304 directory, they will be deleted from it. If invoked with --after,
2299 files that have been manually deleted are marked as removed.
2305 files that have been manually deleted are marked as removed.
2300
2306
2301 Modified files and added files are not removed by default. To
2307 Modified files and added files are not removed by default. To
2302 remove them, use the -f/--force option.
2308 remove them, use the -f/--force option.
2303 """
2309 """
2304 names = []
2310 names = []
2305 if not opts['after'] and not pats:
2311 if not opts['after'] and not pats:
2306 raise util.Abort(_('no files specified'))
2312 raise util.Abort(_('no files specified'))
2307 files, matchfn, anypats = matchpats(repo, pats, opts)
2313 files, matchfn, anypats = matchpats(repo, pats, opts)
2308 exact = dict.fromkeys(files)
2314 exact = dict.fromkeys(files)
2309 mardu = map(dict.fromkeys, repo.changes(files=files, match=matchfn))
2315 mardu = map(dict.fromkeys, repo.changes(files=files, match=matchfn))
2310 modified, added, removed, deleted, unknown = mardu
2316 modified, added, removed, deleted, unknown = mardu
2311 remove, forget = [], []
2317 remove, forget = [], []
2312 for src, abs, rel, exact in walk(repo, pats, opts):
2318 for src, abs, rel, exact in walk(repo, pats, opts):
2313 reason = None
2319 reason = None
2314 if abs not in deleted and opts['after']:
2320 if abs not in deleted and opts['after']:
2315 reason = _('is still present')
2321 reason = _('is still present')
2316 elif abs in modified and not opts['force']:
2322 elif abs in modified and not opts['force']:
2317 reason = _('is modified (use -f to force removal)')
2323 reason = _('is modified (use -f to force removal)')
2318 elif abs in added:
2324 elif abs in added:
2319 if opts['force']:
2325 if opts['force']:
2320 forget.append(abs)
2326 forget.append(abs)
2321 continue
2327 continue
2322 reason = _('has been marked for add (use -f to force removal)')
2328 reason = _('has been marked for add (use -f to force removal)')
2323 elif abs in unknown:
2329 elif abs in unknown:
2324 reason = _('is not managed')
2330 reason = _('is not managed')
2325 elif abs in removed:
2331 elif abs in removed:
2326 continue
2332 continue
2327 if reason:
2333 if reason:
2328 if exact:
2334 if exact:
2329 ui.warn(_('not removing %s: file %s\n') % (rel, reason))
2335 ui.warn(_('not removing %s: file %s\n') % (rel, reason))
2330 else:
2336 else:
2331 if ui.verbose or not exact:
2337 if ui.verbose or not exact:
2332 ui.status(_('removing %s\n') % rel)
2338 ui.status(_('removing %s\n') % rel)
2333 remove.append(abs)
2339 remove.append(abs)
2334 repo.forget(forget)
2340 repo.forget(forget)
2335 repo.remove(remove, unlink=not opts['after'])
2341 repo.remove(remove, unlink=not opts['after'])
2336
2342
2337 def rename(ui, repo, *pats, **opts):
2343 def rename(ui, repo, *pats, **opts):
2338 """rename files; equivalent of copy + remove
2344 """rename files; equivalent of copy + remove
2339
2345
2340 Mark dest as copies of sources; mark sources for deletion. If
2346 Mark dest as copies of sources; mark sources for deletion. If
2341 dest is a directory, copies are put in that directory. If dest is
2347 dest is a directory, copies are put in that directory. If dest is
2342 a file, there can only be one source.
2348 a file, there can only be one source.
2343
2349
2344 By default, this command copies the contents of files as they
2350 By default, this command copies the contents of files as they
2345 stand in the working directory. If invoked with --after, the
2351 stand in the working directory. If invoked with --after, the
2346 operation is recorded, but no copying is performed.
2352 operation is recorded, but no copying is performed.
2347
2353
2348 This command takes effect in the next commit.
2354 This command takes effect in the next commit.
2349
2355
2350 NOTE: This command should be treated as experimental. While it
2356 NOTE: This command should be treated as experimental. While it
2351 should properly record rename files, this information is not yet
2357 should properly record rename files, this information is not yet
2352 fully used by merge, nor fully reported by log.
2358 fully used by merge, nor fully reported by log.
2353 """
2359 """
2354 wlock = repo.wlock(0)
2360 wlock = repo.wlock(0)
2355 errs, copied = docopy(ui, repo, pats, opts, wlock)
2361 errs, copied = docopy(ui, repo, pats, opts, wlock)
2356 names = []
2362 names = []
2357 for abs, rel, exact in copied:
2363 for abs, rel, exact in copied:
2358 if ui.verbose or not exact:
2364 if ui.verbose or not exact:
2359 ui.status(_('removing %s\n') % rel)
2365 ui.status(_('removing %s\n') % rel)
2360 names.append(abs)
2366 names.append(abs)
2361 if not opts.get('dry_run'):
2367 if not opts.get('dry_run'):
2362 repo.remove(names, True, wlock)
2368 repo.remove(names, True, wlock)
2363 return errs
2369 return errs
2364
2370
2365 def revert(ui, repo, *pats, **opts):
2371 def revert(ui, repo, *pats, **opts):
2366 """revert files or dirs to their states as of some revision
2372 """revert files or dirs to their states as of some revision
2367
2373
2368 With no revision specified, revert the named files or directories
2374 With no revision specified, revert the named files or directories
2369 to the contents they had in the parent of the working directory.
2375 to the contents they had in the parent of the working directory.
2370 This restores the contents of the affected files to an unmodified
2376 This restores the contents of the affected files to an unmodified
2371 state. If the working directory has two parents, you must
2377 state. If the working directory has two parents, you must
2372 explicitly specify the revision to revert to.
2378 explicitly specify the revision to revert to.
2373
2379
2374 Modified files are saved with a .orig suffix before reverting.
2380 Modified files are saved with a .orig suffix before reverting.
2375 To disable these backups, use --no-backup.
2381 To disable these backups, use --no-backup.
2376
2382
2377 Using the -r option, revert the given files or directories to
2383 Using the -r option, revert the given files or directories to
2378 their contents as of a specific revision. This can be helpful to"roll
2384 their contents as of a specific revision. This can be helpful to"roll
2379 back" some or all of a change that should not have been committed.
2385 back" some or all of a change that should not have been committed.
2380
2386
2381 Revert modifies the working directory. It does not commit any
2387 Revert modifies the working directory. It does not commit any
2382 changes, or change the parent of the working directory. If you
2388 changes, or change the parent of the working directory. If you
2383 revert to a revision other than the parent of the working
2389 revert to a revision other than the parent of the working
2384 directory, the reverted files will thus appear modified
2390 directory, the reverted files will thus appear modified
2385 afterwards.
2391 afterwards.
2386
2392
2387 If a file has been deleted, it is recreated. If the executable
2393 If a file has been deleted, it is recreated. If the executable
2388 mode of a file was changed, it is reset.
2394 mode of a file was changed, it is reset.
2389
2395
2390 If names are given, all files matching the names are reverted.
2396 If names are given, all files matching the names are reverted.
2391
2397
2392 If no arguments are given, all files in the repository are reverted.
2398 If no arguments are given, all files in the repository are reverted.
2393 """
2399 """
2394 parent, p2 = repo.dirstate.parents()
2400 parent, p2 = repo.dirstate.parents()
2395 if opts['rev']:
2401 if opts['rev']:
2396 node = repo.lookup(opts['rev'])
2402 node = repo.lookup(opts['rev'])
2397 elif p2 != nullid:
2403 elif p2 != nullid:
2398 raise util.Abort(_('working dir has two parents; '
2404 raise util.Abort(_('working dir has two parents; '
2399 'you must specify the revision to revert to'))
2405 'you must specify the revision to revert to'))
2400 else:
2406 else:
2401 node = parent
2407 node = parent
2402 mf = repo.manifest.read(repo.changelog.read(node)[0])
2408 mf = repo.manifest.read(repo.changelog.read(node)[0])
2403 if node == parent:
2409 if node == parent:
2404 pmf = mf
2410 pmf = mf
2405 else:
2411 else:
2406 pmf = None
2412 pmf = None
2407
2413
2408 wlock = repo.wlock()
2414 wlock = repo.wlock()
2409
2415
2410 # need all matching names in dirstate and manifest of target rev,
2416 # need all matching names in dirstate and manifest of target rev,
2411 # so have to walk both. do not print errors if files exist in one
2417 # so have to walk both. do not print errors if files exist in one
2412 # but not other.
2418 # but not other.
2413
2419
2414 names = {}
2420 names = {}
2415 target_only = {}
2421 target_only = {}
2416
2422
2417 # walk dirstate.
2423 # walk dirstate.
2418
2424
2419 for src, abs, rel, exact in walk(repo, pats, opts, badmatch=mf.has_key):
2425 for src, abs, rel, exact in walk(repo, pats, opts, badmatch=mf.has_key):
2420 names[abs] = (rel, exact)
2426 names[abs] = (rel, exact)
2421 if src == 'b':
2427 if src == 'b':
2422 target_only[abs] = True
2428 target_only[abs] = True
2423
2429
2424 # walk target manifest.
2430 # walk target manifest.
2425
2431
2426 for src, abs, rel, exact in walk(repo, pats, opts, node=node,
2432 for src, abs, rel, exact in walk(repo, pats, opts, node=node,
2427 badmatch=names.has_key):
2433 badmatch=names.has_key):
2428 if abs in names: continue
2434 if abs in names: continue
2429 names[abs] = (rel, exact)
2435 names[abs] = (rel, exact)
2430 target_only[abs] = True
2436 target_only[abs] = True
2431
2437
2432 changes = repo.changes(match=names.has_key, wlock=wlock)
2438 changes = repo.changes(match=names.has_key, wlock=wlock)
2433 modified, added, removed, deleted, unknown = map(dict.fromkeys, changes)
2439 modified, added, removed, deleted, unknown = map(dict.fromkeys, changes)
2434
2440
2435 revert = ([], _('reverting %s\n'))
2441 revert = ([], _('reverting %s\n'))
2436 add = ([], _('adding %s\n'))
2442 add = ([], _('adding %s\n'))
2437 remove = ([], _('removing %s\n'))
2443 remove = ([], _('removing %s\n'))
2438 forget = ([], _('forgetting %s\n'))
2444 forget = ([], _('forgetting %s\n'))
2439 undelete = ([], _('undeleting %s\n'))
2445 undelete = ([], _('undeleting %s\n'))
2440 update = {}
2446 update = {}
2441
2447
2442 disptable = (
2448 disptable = (
2443 # dispatch table:
2449 # dispatch table:
2444 # file state
2450 # file state
2445 # action if in target manifest
2451 # action if in target manifest
2446 # action if not in target manifest
2452 # action if not in target manifest
2447 # make backup if in target manifest
2453 # make backup if in target manifest
2448 # make backup if not in target manifest
2454 # make backup if not in target manifest
2449 (modified, revert, remove, True, True),
2455 (modified, revert, remove, True, True),
2450 (added, revert, forget, True, False),
2456 (added, revert, forget, True, False),
2451 (removed, undelete, None, False, False),
2457 (removed, undelete, None, False, False),
2452 (deleted, revert, remove, False, False),
2458 (deleted, revert, remove, False, False),
2453 (unknown, add, None, True, False),
2459 (unknown, add, None, True, False),
2454 (target_only, add, None, False, False),
2460 (target_only, add, None, False, False),
2455 )
2461 )
2456
2462
2457 entries = names.items()
2463 entries = names.items()
2458 entries.sort()
2464 entries.sort()
2459
2465
2460 for abs, (rel, exact) in entries:
2466 for abs, (rel, exact) in entries:
2461 mfentry = mf.get(abs)
2467 mfentry = mf.get(abs)
2462 def handle(xlist, dobackup):
2468 def handle(xlist, dobackup):
2463 xlist[0].append(abs)
2469 xlist[0].append(abs)
2464 update[abs] = 1
2470 update[abs] = 1
2465 if dobackup and not opts['no_backup'] and os.path.exists(rel):
2471 if dobackup and not opts['no_backup'] and os.path.exists(rel):
2466 bakname = "%s.orig" % rel
2472 bakname = "%s.orig" % rel
2467 ui.note(_('saving current version of %s as %s\n') %
2473 ui.note(_('saving current version of %s as %s\n') %
2468 (rel, bakname))
2474 (rel, bakname))
2469 if not opts.get('dry_run'):
2475 if not opts.get('dry_run'):
2470 shutil.copyfile(rel, bakname)
2476 shutil.copyfile(rel, bakname)
2471 shutil.copymode(rel, bakname)
2477 shutil.copymode(rel, bakname)
2472 if ui.verbose or not exact:
2478 if ui.verbose or not exact:
2473 ui.status(xlist[1] % rel)
2479 ui.status(xlist[1] % rel)
2474 for table, hitlist, misslist, backuphit, backupmiss in disptable:
2480 for table, hitlist, misslist, backuphit, backupmiss in disptable:
2475 if abs not in table: continue
2481 if abs not in table: continue
2476 # file has changed in dirstate
2482 # file has changed in dirstate
2477 if mfentry:
2483 if mfentry:
2478 handle(hitlist, backuphit)
2484 handle(hitlist, backuphit)
2479 elif misslist is not None:
2485 elif misslist is not None:
2480 handle(misslist, backupmiss)
2486 handle(misslist, backupmiss)
2481 else:
2487 else:
2482 if exact: ui.warn(_('file not managed: %s\n' % rel))
2488 if exact: ui.warn(_('file not managed: %s\n' % rel))
2483 break
2489 break
2484 else:
2490 else:
2485 # file has not changed in dirstate
2491 # file has not changed in dirstate
2486 if node == parent:
2492 if node == parent:
2487 if exact: ui.warn(_('no changes needed to %s\n' % rel))
2493 if exact: ui.warn(_('no changes needed to %s\n' % rel))
2488 continue
2494 continue
2489 if pmf is None:
2495 if pmf is None:
2490 # only need parent manifest in this unlikely case,
2496 # only need parent manifest in this unlikely case,
2491 # so do not read by default
2497 # so do not read by default
2492 pmf = repo.manifest.read(repo.changelog.read(parent)[0])
2498 pmf = repo.manifest.read(repo.changelog.read(parent)[0])
2493 if abs in pmf:
2499 if abs in pmf:
2494 if mfentry:
2500 if mfentry:
2495 # if version of file is same in parent and target
2501 # if version of file is same in parent and target
2496 # manifests, do nothing
2502 # manifests, do nothing
2497 if pmf[abs] != mfentry:
2503 if pmf[abs] != mfentry:
2498 handle(revert, False)
2504 handle(revert, False)
2499 else:
2505 else:
2500 handle(remove, False)
2506 handle(remove, False)
2501
2507
2502 if not opts.get('dry_run'):
2508 if not opts.get('dry_run'):
2503 repo.dirstate.forget(forget[0])
2509 repo.dirstate.forget(forget[0])
2504 r = repo.update(node, False, True, update.has_key, False, wlock=wlock,
2510 r = repo.update(node, False, True, update.has_key, False, wlock=wlock,
2505 show_stats=False)
2511 show_stats=False)
2506 repo.dirstate.update(add[0], 'a')
2512 repo.dirstate.update(add[0], 'a')
2507 repo.dirstate.update(undelete[0], 'n')
2513 repo.dirstate.update(undelete[0], 'n')
2508 repo.dirstate.update(remove[0], 'r')
2514 repo.dirstate.update(remove[0], 'r')
2509 return r
2515 return r
2510
2516
2511 def rollback(ui, repo):
2517 def rollback(ui, repo):
2512 """roll back the last transaction in this repository
2518 """roll back the last transaction in this repository
2513
2519
2514 Roll back the last transaction in this repository, restoring the
2520 Roll back the last transaction in this repository, restoring the
2515 project to its state prior to the transaction.
2521 project to its state prior to the transaction.
2516
2522
2517 Transactions are used to encapsulate the effects of all commands
2523 Transactions are used to encapsulate the effects of all commands
2518 that create new changesets or propagate existing changesets into a
2524 that create new changesets or propagate existing changesets into a
2519 repository. For example, the following commands are transactional,
2525 repository. For example, the following commands are transactional,
2520 and their effects can be rolled back:
2526 and their effects can be rolled back:
2521
2527
2522 commit
2528 commit
2523 import
2529 import
2524 pull
2530 pull
2525 push (with this repository as destination)
2531 push (with this repository as destination)
2526 unbundle
2532 unbundle
2527
2533
2528 This command should be used with care. There is only one level of
2534 This command should be used with care. There is only one level of
2529 rollback, and there is no way to undo a rollback.
2535 rollback, and there is no way to undo a rollback.
2530
2536
2531 This command is not intended for use on public repositories. Once
2537 This command is not intended for use on public repositories. Once
2532 changes are visible for pull by other users, rolling a transaction
2538 changes are visible for pull by other users, rolling a transaction
2533 back locally is ineffective (someone else may already have pulled
2539 back locally is ineffective (someone else may already have pulled
2534 the changes). Furthermore, a race is possible with readers of the
2540 the changes). Furthermore, a race is possible with readers of the
2535 repository; for example an in-progress pull from the repository
2541 repository; for example an in-progress pull from the repository
2536 may fail if a rollback is performed.
2542 may fail if a rollback is performed.
2537 """
2543 """
2538 repo.rollback()
2544 repo.rollback()
2539
2545
2540 def root(ui, repo):
2546 def root(ui, repo):
2541 """print the root (top) of the current working dir
2547 """print the root (top) of the current working dir
2542
2548
2543 Print the root directory of the current repository.
2549 Print the root directory of the current repository.
2544 """
2550 """
2545 ui.write(repo.root + "\n")
2551 ui.write(repo.root + "\n")
2546
2552
2547 def serve(ui, repo, **opts):
2553 def serve(ui, repo, **opts):
2548 """export the repository via HTTP
2554 """export the repository via HTTP
2549
2555
2550 Start a local HTTP repository browser and pull server.
2556 Start a local HTTP repository browser and pull server.
2551
2557
2552 By default, the server logs accesses to stdout and errors to
2558 By default, the server logs accesses to stdout and errors to
2553 stderr. Use the "-A" and "-E" options to log to files.
2559 stderr. Use the "-A" and "-E" options to log to files.
2554 """
2560 """
2555
2561
2556 if opts["stdio"]:
2562 if opts["stdio"]:
2557 if repo is None:
2563 if repo is None:
2558 raise hg.RepoError(_('no repo found'))
2564 raise hg.RepoError(_('no repo found'))
2559 s = sshserver.sshserver(ui, repo)
2565 s = sshserver.sshserver(ui, repo)
2560 s.serve_forever()
2566 s.serve_forever()
2561
2567
2562 optlist = ("name templates style address port ipv6"
2568 optlist = ("name templates style address port ipv6"
2563 " accesslog errorlog webdir_conf")
2569 " accesslog errorlog webdir_conf")
2564 for o in optlist.split():
2570 for o in optlist.split():
2565 if opts[o]:
2571 if opts[o]:
2566 ui.setconfig("web", o, opts[o])
2572 ui.setconfig("web", o, opts[o])
2567
2573
2568 if repo is None and not ui.config("web", "webdir_conf"):
2574 if repo is None and not ui.config("web", "webdir_conf"):
2569 raise hg.RepoError(_('no repo found'))
2575 raise hg.RepoError(_('no repo found'))
2570
2576
2571 if opts['daemon'] and not opts['daemon_pipefds']:
2577 if opts['daemon'] and not opts['daemon_pipefds']:
2572 rfd, wfd = os.pipe()
2578 rfd, wfd = os.pipe()
2573 args = sys.argv[:]
2579 args = sys.argv[:]
2574 args.append('--daemon-pipefds=%d,%d' % (rfd, wfd))
2580 args.append('--daemon-pipefds=%d,%d' % (rfd, wfd))
2575 pid = os.spawnvp(os.P_NOWAIT | getattr(os, 'P_DETACH', 0),
2581 pid = os.spawnvp(os.P_NOWAIT | getattr(os, 'P_DETACH', 0),
2576 args[0], args)
2582 args[0], args)
2577 os.close(wfd)
2583 os.close(wfd)
2578 os.read(rfd, 1)
2584 os.read(rfd, 1)
2579 os._exit(0)
2585 os._exit(0)
2580
2586
2581 try:
2587 try:
2582 httpd = hgweb.server.create_server(ui, repo)
2588 httpd = hgweb.server.create_server(ui, repo)
2583 except socket.error, inst:
2589 except socket.error, inst:
2584 raise util.Abort(_('cannot start server: ') + inst.args[1])
2590 raise util.Abort(_('cannot start server: ') + inst.args[1])
2585
2591
2586 if ui.verbose:
2592 if ui.verbose:
2587 addr, port = httpd.socket.getsockname()
2593 addr, port = httpd.socket.getsockname()
2588 if addr == '0.0.0.0':
2594 if addr == '0.0.0.0':
2589 addr = socket.gethostname()
2595 addr = socket.gethostname()
2590 else:
2596 else:
2591 try:
2597 try:
2592 addr = socket.gethostbyaddr(addr)[0]
2598 addr = socket.gethostbyaddr(addr)[0]
2593 except socket.error:
2599 except socket.error:
2594 pass
2600 pass
2595 if port != 80:
2601 if port != 80:
2596 ui.status(_('listening at http://%s:%d/\n') % (addr, port))
2602 ui.status(_('listening at http://%s:%d/\n') % (addr, port))
2597 else:
2603 else:
2598 ui.status(_('listening at http://%s/\n') % addr)
2604 ui.status(_('listening at http://%s/\n') % addr)
2599
2605
2600 if opts['pid_file']:
2606 if opts['pid_file']:
2601 fp = open(opts['pid_file'], 'w')
2607 fp = open(opts['pid_file'], 'w')
2602 fp.write(str(os.getpid()))
2608 fp.write(str(os.getpid()))
2603 fp.close()
2609 fp.close()
2604
2610
2605 if opts['daemon_pipefds']:
2611 if opts['daemon_pipefds']:
2606 rfd, wfd = [int(x) for x in opts['daemon_pipefds'].split(',')]
2612 rfd, wfd = [int(x) for x in opts['daemon_pipefds'].split(',')]
2607 os.close(rfd)
2613 os.close(rfd)
2608 os.write(wfd, 'y')
2614 os.write(wfd, 'y')
2609 os.close(wfd)
2615 os.close(wfd)
2610 sys.stdout.flush()
2616 sys.stdout.flush()
2611 sys.stderr.flush()
2617 sys.stderr.flush()
2612 fd = os.open(util.nulldev, os.O_RDWR)
2618 fd = os.open(util.nulldev, os.O_RDWR)
2613 if fd != 0: os.dup2(fd, 0)
2619 if fd != 0: os.dup2(fd, 0)
2614 if fd != 1: os.dup2(fd, 1)
2620 if fd != 1: os.dup2(fd, 1)
2615 if fd != 2: os.dup2(fd, 2)
2621 if fd != 2: os.dup2(fd, 2)
2616 if fd not in (0, 1, 2): os.close(fd)
2622 if fd not in (0, 1, 2): os.close(fd)
2617
2623
2618 httpd.serve_forever()
2624 httpd.serve_forever()
2619
2625
2620 def status(ui, repo, *pats, **opts):
2626 def status(ui, repo, *pats, **opts):
2621 """show changed files in the working directory
2627 """show changed files in the working directory
2622
2628
2623 Show changed files in the repository. If names are
2629 Show changed files in the repository. If names are
2624 given, only files that match are shown.
2630 given, only files that match are shown.
2625
2631
2626 The codes used to show the status of files are:
2632 The codes used to show the status of files are:
2627 M = modified
2633 M = modified
2628 A = added
2634 A = added
2629 R = removed
2635 R = removed
2630 ! = deleted, but still tracked
2636 ! = deleted, but still tracked
2631 ? = not tracked
2637 ? = not tracked
2632 I = ignored (not shown by default)
2638 I = ignored (not shown by default)
2633 """
2639 """
2634
2640
2635 show_ignored = opts['ignored'] and True or False
2641 show_ignored = opts['ignored'] and True or False
2636 files, matchfn, anypats = matchpats(repo, pats, opts)
2642 files, matchfn, anypats = matchpats(repo, pats, opts)
2637 cwd = (pats and repo.getcwd()) or ''
2643 cwd = (pats and repo.getcwd()) or ''
2638 modified, added, removed, deleted, unknown, ignored = [
2644 modified, added, removed, deleted, unknown, ignored = [
2639 [util.pathto(cwd, x) for x in n]
2645 [util.pathto(cwd, x) for x in n]
2640 for n in repo.changes(files=files, match=matchfn,
2646 for n in repo.changes(files=files, match=matchfn,
2641 show_ignored=show_ignored)]
2647 show_ignored=show_ignored)]
2642
2648
2643 changetypes = [('modified', 'M', modified),
2649 changetypes = [('modified', 'M', modified),
2644 ('added', 'A', added),
2650 ('added', 'A', added),
2645 ('removed', 'R', removed),
2651 ('removed', 'R', removed),
2646 ('deleted', '!', deleted),
2652 ('deleted', '!', deleted),
2647 ('unknown', '?', unknown),
2653 ('unknown', '?', unknown),
2648 ('ignored', 'I', ignored)]
2654 ('ignored', 'I', ignored)]
2649
2655
2650 end = opts['print0'] and '\0' or '\n'
2656 end = opts['print0'] and '\0' or '\n'
2651
2657
2652 for opt, char, changes in ([ct for ct in changetypes if opts[ct[0]]]
2658 for opt, char, changes in ([ct for ct in changetypes if opts[ct[0]]]
2653 or changetypes):
2659 or changetypes):
2654 if opts['no_status']:
2660 if opts['no_status']:
2655 format = "%%s%s" % end
2661 format = "%%s%s" % end
2656 else:
2662 else:
2657 format = "%s %%s%s" % (char, end)
2663 format = "%s %%s%s" % (char, end)
2658
2664
2659 for f in changes:
2665 for f in changes:
2660 ui.write(format % f)
2666 ui.write(format % f)
2661
2667
2662 def tag(ui, repo, name, rev_=None, **opts):
2668 def tag(ui, repo, name, rev_=None, **opts):
2663 """add a tag for the current tip or a given revision
2669 """add a tag for the current tip or a given revision
2664
2670
2665 Name a particular revision using <name>.
2671 Name a particular revision using <name>.
2666
2672
2667 Tags are used to name particular revisions of the repository and are
2673 Tags are used to name particular revisions of the repository and are
2668 very useful to compare different revision, to go back to significant
2674 very useful to compare different revision, to go back to significant
2669 earlier versions or to mark branch points as releases, etc.
2675 earlier versions or to mark branch points as releases, etc.
2670
2676
2671 If no revision is given, the tip is used.
2677 If no revision is given, the tip is used.
2672
2678
2673 To facilitate version control, distribution, and merging of tags,
2679 To facilitate version control, distribution, and merging of tags,
2674 they are stored as a file named ".hgtags" which is managed
2680 they are stored as a file named ".hgtags" which is managed
2675 similarly to other project files and can be hand-edited if
2681 similarly to other project files and can be hand-edited if
2676 necessary. The file '.hg/localtags' is used for local tags (not
2682 necessary. The file '.hg/localtags' is used for local tags (not
2677 shared among repositories).
2683 shared among repositories).
2678 """
2684 """
2679 if name == "tip":
2685 if name == "tip":
2680 raise util.Abort(_("the name 'tip' is reserved"))
2686 raise util.Abort(_("the name 'tip' is reserved"))
2681 if rev_ is not None:
2687 if rev_ is not None:
2682 ui.warn(_("use of 'hg tag NAME [REV]' is deprecated, "
2688 ui.warn(_("use of 'hg tag NAME [REV]' is deprecated, "
2683 "please use 'hg tag [-r REV] NAME' instead\n"))
2689 "please use 'hg tag [-r REV] NAME' instead\n"))
2684 if opts['rev']:
2690 if opts['rev']:
2685 raise util.Abort(_("use only one form to specify the revision"))
2691 raise util.Abort(_("use only one form to specify the revision"))
2686 if opts['rev']:
2692 if opts['rev']:
2687 rev_ = opts['rev']
2693 rev_ = opts['rev']
2688 if rev_:
2694 if rev_:
2689 r = hex(repo.lookup(rev_))
2695 r = hex(repo.lookup(rev_))
2690 else:
2696 else:
2691 r = hex(repo.changelog.tip())
2697 r = hex(repo.changelog.tip())
2692
2698
2693 disallowed = (revrangesep, '\r', '\n')
2699 disallowed = (revrangesep, '\r', '\n')
2694 for c in disallowed:
2700 for c in disallowed:
2695 if name.find(c) >= 0:
2701 if name.find(c) >= 0:
2696 raise util.Abort(_("%s cannot be used in a tag name") % repr(c))
2702 raise util.Abort(_("%s cannot be used in a tag name") % repr(c))
2697
2703
2698 repo.hook('pretag', throw=True, node=r, tag=name,
2704 repo.hook('pretag', throw=True, node=r, tag=name,
2699 local=int(not not opts['local']))
2705 local=int(not not opts['local']))
2700
2706
2701 if opts['local']:
2707 if opts['local']:
2702 repo.opener("localtags", "a").write("%s %s\n" % (r, name))
2708 repo.opener("localtags", "a").write("%s %s\n" % (r, name))
2703 repo.hook('tag', node=r, tag=name, local=1)
2709 repo.hook('tag', node=r, tag=name, local=1)
2704 return
2710 return
2705
2711
2706 for x in repo.changes():
2712 for x in repo.changes():
2707 if ".hgtags" in x:
2713 if ".hgtags" in x:
2708 raise util.Abort(_("working copy of .hgtags is changed "
2714 raise util.Abort(_("working copy of .hgtags is changed "
2709 "(please commit .hgtags manually)"))
2715 "(please commit .hgtags manually)"))
2710
2716
2711 repo.wfile(".hgtags", "ab").write("%s %s\n" % (r, name))
2717 repo.wfile(".hgtags", "ab").write("%s %s\n" % (r, name))
2712 if repo.dirstate.state(".hgtags") == '?':
2718 if repo.dirstate.state(".hgtags") == '?':
2713 repo.add([".hgtags"])
2719 repo.add([".hgtags"])
2714
2720
2715 message = (opts['message'] or
2721 message = (opts['message'] or
2716 _("Added tag %s for changeset %s") % (name, r))
2722 _("Added tag %s for changeset %s") % (name, r))
2717 try:
2723 try:
2718 repo.commit([".hgtags"], message, opts['user'], opts['date'])
2724 repo.commit([".hgtags"], message, opts['user'], opts['date'])
2719 repo.hook('tag', node=r, tag=name, local=0)
2725 repo.hook('tag', node=r, tag=name, local=0)
2720 except ValueError, inst:
2726 except ValueError, inst:
2721 raise util.Abort(str(inst))
2727 raise util.Abort(str(inst))
2722
2728
2723 def tags(ui, repo):
2729 def tags(ui, repo):
2724 """list repository tags
2730 """list repository tags
2725
2731
2726 List the repository tags.
2732 List the repository tags.
2727
2733
2728 This lists both regular and local tags.
2734 This lists both regular and local tags.
2729 """
2735 """
2730
2736
2731 l = repo.tagslist()
2737 l = repo.tagslist()
2732 l.reverse()
2738 l.reverse()
2733 for t, n in l:
2739 for t, n in l:
2734 try:
2740 try:
2735 r = "%5d:%s" % (repo.changelog.rev(n), hex(n))
2741 r = "%5d:%s" % (repo.changelog.rev(n), hex(n))
2736 except KeyError:
2742 except KeyError:
2737 r = " ?:?"
2743 r = " ?:?"
2738 if ui.quiet:
2744 if ui.quiet:
2739 ui.write("%s\n" % t)
2745 ui.write("%s\n" % t)
2740 else:
2746 else:
2741 ui.write("%-30s %s\n" % (t, r))
2747 ui.write("%-30s %s\n" % (t, r))
2742
2748
2743 def tip(ui, repo, **opts):
2749 def tip(ui, repo, **opts):
2744 """show the tip revision
2750 """show the tip revision
2745
2751
2746 Show the tip revision.
2752 Show the tip revision.
2747 """
2753 """
2748 n = repo.changelog.tip()
2754 n = repo.changelog.tip()
2749 br = None
2755 br = None
2750 if opts['branches']:
2756 if opts['branches']:
2751 br = repo.branchlookup([n])
2757 br = repo.branchlookup([n])
2752 show_changeset(ui, repo, opts).show(changenode=n, brinfo=br)
2758 show_changeset(ui, repo, opts).show(changenode=n, brinfo=br)
2753 if opts['patch']:
2759 if opts['patch']:
2754 dodiff(ui, ui, repo, repo.changelog.parents(n)[0], n)
2760 dodiff(ui, ui, repo, repo.changelog.parents(n)[0], n)
2755
2761
2756 def unbundle(ui, repo, fname, **opts):
2762 def unbundle(ui, repo, fname, **opts):
2757 """apply a changegroup file
2763 """apply a changegroup file
2758
2764
2759 Apply a compressed changegroup file generated by the bundle
2765 Apply a compressed changegroup file generated by the bundle
2760 command.
2766 command.
2761 """
2767 """
2762 f = urllib.urlopen(fname)
2768 f = urllib.urlopen(fname)
2763
2769
2764 header = f.read(6)
2770 header = f.read(6)
2765 if not header.startswith("HG"):
2771 if not header.startswith("HG"):
2766 raise util.Abort(_("%s: not a Mercurial bundle file") % fname)
2772 raise util.Abort(_("%s: not a Mercurial bundle file") % fname)
2767 elif not header.startswith("HG10"):
2773 elif not header.startswith("HG10"):
2768 raise util.Abort(_("%s: unknown bundle version") % fname)
2774 raise util.Abort(_("%s: unknown bundle version") % fname)
2769 elif header == "HG10BZ":
2775 elif header == "HG10BZ":
2770 def generator(f):
2776 def generator(f):
2771 zd = bz2.BZ2Decompressor()
2777 zd = bz2.BZ2Decompressor()
2772 zd.decompress("BZ")
2778 zd.decompress("BZ")
2773 for chunk in f:
2779 for chunk in f:
2774 yield zd.decompress(chunk)
2780 yield zd.decompress(chunk)
2775 elif header == "HG10UN":
2781 elif header == "HG10UN":
2776 def generator(f):
2782 def generator(f):
2777 for chunk in f:
2783 for chunk in f:
2778 yield chunk
2784 yield chunk
2779 else:
2785 else:
2780 raise util.Abort(_("%s: unknown bundle compression type")
2786 raise util.Abort(_("%s: unknown bundle compression type")
2781 % fname)
2787 % fname)
2782 gen = generator(util.filechunkiter(f, 4096))
2788 gen = generator(util.filechunkiter(f, 4096))
2783 modheads = repo.addchangegroup(util.chunkbuffer(gen), 'unbundle')
2789 modheads = repo.addchangegroup(util.chunkbuffer(gen), 'unbundle')
2784 return postincoming(ui, repo, modheads, opts['update'])
2790 return postincoming(ui, repo, modheads, opts['update'])
2785
2791
2786 def undo(ui, repo):
2792 def undo(ui, repo):
2787 """undo the last commit or pull (DEPRECATED)
2793 """undo the last commit or pull (DEPRECATED)
2788
2794
2789 (DEPRECATED)
2795 (DEPRECATED)
2790 This command is now deprecated and will be removed in a future
2796 This command is now deprecated and will be removed in a future
2791 release. Please use the rollback command instead. For usage
2797 release. Please use the rollback command instead. For usage
2792 instructions, see the rollback command.
2798 instructions, see the rollback command.
2793 """
2799 """
2794 ui.warn(_('(the undo command is deprecated; use rollback instead)\n'))
2800 ui.warn(_('(the undo command is deprecated; use rollback instead)\n'))
2795 repo.rollback()
2801 repo.rollback()
2796
2802
2797 def update(ui, repo, node=None, merge=False, clean=False, force=None,
2803 def update(ui, repo, node=None, merge=False, clean=False, force=None,
2798 branch=None, **opts):
2804 branch=None, **opts):
2799 """update or merge working directory
2805 """update or merge working directory
2800
2806
2801 Update the working directory to the specified revision.
2807 Update the working directory to the specified revision.
2802
2808
2803 If there are no outstanding changes in the working directory and
2809 If there are no outstanding changes in the working directory and
2804 there is a linear relationship between the current version and the
2810 there is a linear relationship between the current version and the
2805 requested version, the result is the requested version.
2811 requested version, the result is the requested version.
2806
2812
2807 To merge the working directory with another revision, use the
2813 To merge the working directory with another revision, use the
2808 merge command.
2814 merge command.
2809
2815
2810 By default, update will refuse to run if doing so would require
2816 By default, update will refuse to run if doing so would require
2811 merging or discarding local changes.
2817 merging or discarding local changes.
2812 """
2818 """
2813 if merge:
2819 if merge:
2814 ui.warn(_('(the -m/--merge option is deprecated; '
2820 ui.warn(_('(the -m/--merge option is deprecated; '
2815 'use the merge command instead)\n'))
2821 'use the merge command instead)\n'))
2816 return doupdate(ui, repo, node, merge, clean, force, branch, **opts)
2822 return doupdate(ui, repo, node, merge, clean, force, branch, **opts)
2817
2823
2818 def doupdate(ui, repo, node=None, merge=False, clean=False, force=None,
2824 def doupdate(ui, repo, node=None, merge=False, clean=False, force=None,
2819 branch=None, **opts):
2825 branch=None, **opts):
2820 if branch:
2826 if branch:
2821 br = repo.branchlookup(branch=branch)
2827 br = repo.branchlookup(branch=branch)
2822 found = []
2828 found = []
2823 for x in br:
2829 for x in br:
2824 if branch in br[x]:
2830 if branch in br[x]:
2825 found.append(x)
2831 found.append(x)
2826 if len(found) > 1:
2832 if len(found) > 1:
2827 ui.warn(_("Found multiple heads for %s\n") % branch)
2833 ui.warn(_("Found multiple heads for %s\n") % branch)
2828 for x in found:
2834 for x in found:
2829 show_changeset(ui, repo, opts).show(changenode=x, brinfo=br)
2835 show_changeset(ui, repo, opts).show(changenode=x, brinfo=br)
2830 return 1
2836 return 1
2831 if len(found) == 1:
2837 if len(found) == 1:
2832 node = found[0]
2838 node = found[0]
2833 ui.warn(_("Using head %s for branch %s\n") % (short(node), branch))
2839 ui.warn(_("Using head %s for branch %s\n") % (short(node), branch))
2834 else:
2840 else:
2835 ui.warn(_("branch %s not found\n") % (branch))
2841 ui.warn(_("branch %s not found\n") % (branch))
2836 return 1
2842 return 1
2837 else:
2843 else:
2838 node = node and repo.lookup(node) or repo.changelog.tip()
2844 node = node and repo.lookup(node) or repo.changelog.tip()
2839 return repo.update(node, allow=merge, force=clean, forcemerge=force)
2845 return repo.update(node, allow=merge, force=clean, forcemerge=force)
2840
2846
2841 def verify(ui, repo):
2847 def verify(ui, repo):
2842 """verify the integrity of the repository
2848 """verify the integrity of the repository
2843
2849
2844 Verify the integrity of the current repository.
2850 Verify the integrity of the current repository.
2845
2851
2846 This will perform an extensive check of the repository's
2852 This will perform an extensive check of the repository's
2847 integrity, validating the hashes and checksums of each entry in
2853 integrity, validating the hashes and checksums of each entry in
2848 the changelog, manifest, and tracked files, as well as the
2854 the changelog, manifest, and tracked files, as well as the
2849 integrity of their crosslinks and indices.
2855 integrity of their crosslinks and indices.
2850 """
2856 """
2851 return repo.verify()
2857 return repo.verify()
2852
2858
2853 # Command options and aliases are listed here, alphabetically
2859 # Command options and aliases are listed here, alphabetically
2854
2860
2855 table = {
2861 table = {
2856 "^add":
2862 "^add":
2857 (add,
2863 (add,
2858 [('I', 'include', [], _('include names matching the given patterns')),
2864 [('I', 'include', [], _('include names matching the given patterns')),
2859 ('X', 'exclude', [], _('exclude names matching the given patterns')),
2865 ('X', 'exclude', [], _('exclude names matching the given patterns')),
2860 ('n', 'dry-run', None, _('do not perform actions, just print output'))],
2866 ('n', 'dry-run', None, _('do not perform actions, just print output'))],
2861 _('hg add [OPTION]... [FILE]...')),
2867 _('hg add [OPTION]... [FILE]...')),
2862 "debugaddremove|addremove":
2868 "debugaddremove|addremove":
2863 (addremove,
2869 (addremove,
2864 [('I', 'include', [], _('include names matching the given patterns')),
2870 [('I', 'include', [], _('include names matching the given patterns')),
2865 ('X', 'exclude', [], _('exclude names matching the given patterns')),
2871 ('X', 'exclude', [], _('exclude names matching the given patterns')),
2866 ('n', 'dry-run', None, _('do not perform actions, just print output'))],
2872 ('n', 'dry-run', None, _('do not perform actions, just print output'))],
2867 _('hg addremove [OPTION]... [FILE]...')),
2873 _('hg addremove [OPTION]... [FILE]...')),
2868 "^annotate":
2874 "^annotate":
2869 (annotate,
2875 (annotate,
2870 [('r', 'rev', '', _('annotate the specified revision')),
2876 [('r', 'rev', '', _('annotate the specified revision')),
2871 ('a', 'text', None, _('treat all files as text')),
2877 ('a', 'text', None, _('treat all files as text')),
2872 ('u', 'user', None, _('list the author')),
2878 ('u', 'user', None, _('list the author')),
2873 ('d', 'date', None, _('list the date')),
2879 ('d', 'date', None, _('list the date')),
2874 ('n', 'number', None, _('list the revision number (default)')),
2880 ('n', 'number', None, _('list the revision number (default)')),
2875 ('c', 'changeset', None, _('list the changeset')),
2881 ('c', 'changeset', None, _('list the changeset')),
2876 ('I', 'include', [], _('include names matching the given patterns')),
2882 ('I', 'include', [], _('include names matching the given patterns')),
2877 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2883 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2878 _('hg annotate [-r REV] [-a] [-u] [-d] [-n] [-c] FILE...')),
2884 _('hg annotate [-r REV] [-a] [-u] [-d] [-n] [-c] FILE...')),
2879 "archive":
2885 "archive":
2880 (archive,
2886 (archive,
2881 [('', 'no-decode', None, _('do not pass files through decoders')),
2887 [('', 'no-decode', None, _('do not pass files through decoders')),
2882 ('p', 'prefix', '', _('directory prefix for files in archive')),
2888 ('p', 'prefix', '', _('directory prefix for files in archive')),
2883 ('r', 'rev', '', _('revision to distribute')),
2889 ('r', 'rev', '', _('revision to distribute')),
2884 ('t', 'type', '', _('type of distribution to create')),
2890 ('t', 'type', '', _('type of distribution to create')),
2885 ('I', 'include', [], _('include names matching the given patterns')),
2891 ('I', 'include', [], _('include names matching the given patterns')),
2886 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2892 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2887 _('hg archive [OPTION]... DEST')),
2893 _('hg archive [OPTION]... DEST')),
2888 "backout":
2894 "backout":
2889 (backout,
2895 (backout,
2890 [('', 'merge', None,
2896 [('', 'merge', None,
2891 _('merge with old dirstate parent after backout')),
2897 _('merge with old dirstate parent after backout')),
2892 ('m', 'message', '', _('use <text> as commit message')),
2898 ('m', 'message', '', _('use <text> as commit message')),
2893 ('l', 'logfile', '', _('read commit message from <file>')),
2899 ('l', 'logfile', '', _('read commit message from <file>')),
2894 ('d', 'date', '', _('record datecode as commit date')),
2900 ('d', 'date', '', _('record datecode as commit date')),
2895 ('u', 'user', '', _('record user as committer')),
2901 ('u', 'user', '', _('record user as committer')),
2896 ('I', 'include', [], _('include names matching the given patterns')),
2902 ('I', 'include', [], _('include names matching the given patterns')),
2897 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2903 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2898 _('hg backout [OPTION]... REV')),
2904 _('hg backout [OPTION]... REV')),
2899 "bundle":
2905 "bundle":
2900 (bundle,
2906 (bundle,
2901 [('f', 'force', None,
2907 [('f', 'force', None,
2902 _('run even when remote repository is unrelated'))],
2908 _('run even when remote repository is unrelated'))],
2903 _('hg bundle FILE DEST')),
2909 _('hg bundle FILE DEST')),
2904 "cat":
2910 "cat":
2905 (cat,
2911 (cat,
2906 [('o', 'output', '', _('print output to file with formatted name')),
2912 [('o', 'output', '', _('print output to file with formatted name')),
2907 ('r', 'rev', '', _('print the given revision')),
2913 ('r', 'rev', '', _('print the given revision')),
2908 ('I', 'include', [], _('include names matching the given patterns')),
2914 ('I', 'include', [], _('include names matching the given patterns')),
2909 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2915 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2910 _('hg cat [OPTION]... FILE...')),
2916 _('hg cat [OPTION]... FILE...')),
2911 "^clone":
2917 "^clone":
2912 (clone,
2918 (clone,
2913 [('U', 'noupdate', None, _('do not update the new working directory')),
2919 [('U', 'noupdate', None, _('do not update the new working directory')),
2914 ('r', 'rev', [],
2920 ('r', 'rev', [],
2915 _('a changeset you would like to have after cloning')),
2921 _('a changeset you would like to have after cloning')),
2916 ('', 'pull', None, _('use pull protocol to copy metadata')),
2922 ('', 'pull', None, _('use pull protocol to copy metadata')),
2917 ('e', 'ssh', '', _('specify ssh command to use')),
2923 ('e', 'ssh', '', _('specify ssh command to use')),
2918 ('', 'remotecmd', '',
2924 ('', 'remotecmd', '',
2919 _('specify hg command to run on the remote side'))],
2925 _('specify hg command to run on the remote side'))],
2920 _('hg clone [OPTION]... SOURCE [DEST]')),
2926 _('hg clone [OPTION]... SOURCE [DEST]')),
2921 "^commit|ci":
2927 "^commit|ci":
2922 (commit,
2928 (commit,
2923 [('A', 'addremove', None,
2929 [('A', 'addremove', None,
2924 _('mark new/missing files as added/removed before committing')),
2930 _('mark new/missing files as added/removed before committing')),
2925 ('m', 'message', '', _('use <text> as commit message')),
2931 ('m', 'message', '', _('use <text> as commit message')),
2926 ('l', 'logfile', '', _('read the commit message from <file>')),
2932 ('l', 'logfile', '', _('read the commit message from <file>')),
2927 ('d', 'date', '', _('record datecode as commit date')),
2933 ('d', 'date', '', _('record datecode as commit date')),
2928 ('u', 'user', '', _('record user as commiter')),
2934 ('u', 'user', '', _('record user as commiter')),
2929 ('I', 'include', [], _('include names matching the given patterns')),
2935 ('I', 'include', [], _('include names matching the given patterns')),
2930 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2936 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2931 _('hg commit [OPTION]... [FILE]...')),
2937 _('hg commit [OPTION]... [FILE]...')),
2932 "copy|cp":
2938 "copy|cp":
2933 (copy,
2939 (copy,
2934 [('A', 'after', None, _('record a copy that has already occurred')),
2940 [('A', 'after', None, _('record a copy that has already occurred')),
2935 ('f', 'force', None,
2941 ('f', 'force', None,
2936 _('forcibly copy over an existing managed file')),
2942 _('forcibly copy over an existing managed file')),
2937 ('I', 'include', [], _('include names matching the given patterns')),
2943 ('I', 'include', [], _('include names matching the given patterns')),
2938 ('X', 'exclude', [], _('exclude names matching the given patterns')),
2944 ('X', 'exclude', [], _('exclude names matching the given patterns')),
2939 ('n', 'dry-run', None, _('do not perform actions, just print output'))],
2945 ('n', 'dry-run', None, _('do not perform actions, just print output'))],
2940 _('hg copy [OPTION]... [SOURCE]... DEST')),
2946 _('hg copy [OPTION]... [SOURCE]... DEST')),
2941 "debugancestor": (debugancestor, [], _('debugancestor INDEX REV1 REV2')),
2947 "debugancestor": (debugancestor, [], _('debugancestor INDEX REV1 REV2')),
2942 "debugcomplete":
2948 "debugcomplete":
2943 (debugcomplete,
2949 (debugcomplete,
2944 [('o', 'options', None, _('show the command options'))],
2950 [('o', 'options', None, _('show the command options'))],
2945 _('debugcomplete [-o] CMD')),
2951 _('debugcomplete [-o] CMD')),
2946 "debugrebuildstate":
2952 "debugrebuildstate":
2947 (debugrebuildstate,
2953 (debugrebuildstate,
2948 [('r', 'rev', '', _('revision to rebuild to'))],
2954 [('r', 'rev', '', _('revision to rebuild to'))],
2949 _('debugrebuildstate [-r REV] [REV]')),
2955 _('debugrebuildstate [-r REV] [REV]')),
2950 "debugcheckstate": (debugcheckstate, [], _('debugcheckstate')),
2956 "debugcheckstate": (debugcheckstate, [], _('debugcheckstate')),
2951 "debugconfig": (debugconfig, [], _('debugconfig [NAME]...')),
2957 "debugconfig": (debugconfig, [], _('debugconfig [NAME]...')),
2952 "debugsetparents": (debugsetparents, [], _('debugsetparents REV1 [REV2]')),
2958 "debugsetparents": (debugsetparents, [], _('debugsetparents REV1 [REV2]')),
2953 "debugstate": (debugstate, [], _('debugstate')),
2959 "debugstate": (debugstate, [], _('debugstate')),
2954 "debugdata": (debugdata, [], _('debugdata FILE REV')),
2960 "debugdata": (debugdata, [], _('debugdata FILE REV')),
2955 "debugindex": (debugindex, [], _('debugindex FILE')),
2961 "debugindex": (debugindex, [], _('debugindex FILE')),
2956 "debugindexdot": (debugindexdot, [], _('debugindexdot FILE')),
2962 "debugindexdot": (debugindexdot, [], _('debugindexdot FILE')),
2957 "debugrename": (debugrename, [], _('debugrename FILE [REV]')),
2963 "debugrename": (debugrename, [], _('debugrename FILE [REV]')),
2958 "debugwalk":
2964 "debugwalk":
2959 (debugwalk,
2965 (debugwalk,
2960 [('I', 'include', [], _('include names matching the given patterns')),
2966 [('I', 'include', [], _('include names matching the given patterns')),
2961 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2967 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2962 _('debugwalk [OPTION]... [FILE]...')),
2968 _('debugwalk [OPTION]... [FILE]...')),
2963 "^diff":
2969 "^diff":
2964 (diff,
2970 (diff,
2965 [('r', 'rev', [], _('revision')),
2971 [('r', 'rev', [], _('revision')),
2966 ('a', 'text', None, _('treat all files as text')),
2972 ('a', 'text', None, _('treat all files as text')),
2967 ('p', 'show-function', None,
2973 ('p', 'show-function', None,
2968 _('show which function each change is in')),
2974 _('show which function each change is in')),
2969 ('w', 'ignore-all-space', None,
2975 ('w', 'ignore-all-space', None,
2970 _('ignore white space when comparing lines')),
2976 _('ignore white space when comparing lines')),
2971 ('I', 'include', [], _('include names matching the given patterns')),
2977 ('I', 'include', [], _('include names matching the given patterns')),
2972 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2978 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2973 _('hg diff [-a] [-I] [-X] [-r REV1 [-r REV2]] [FILE]...')),
2979 _('hg diff [-a] [-I] [-X] [-r REV1 [-r REV2]] [FILE]...')),
2974 "^export":
2980 "^export":
2975 (export,
2981 (export,
2976 [('o', 'output', '', _('print output to file with formatted name')),
2982 [('o', 'output', '', _('print output to file with formatted name')),
2977 ('a', 'text', None, _('treat all files as text')),
2983 ('a', 'text', None, _('treat all files as text')),
2978 ('', 'switch-parent', None, _('diff against the second parent'))],
2984 ('', 'switch-parent', None, _('diff against the second parent'))],
2979 _('hg export [-a] [-o OUTFILESPEC] REV...')),
2985 _('hg export [-a] [-o OUTFILESPEC] REV...')),
2980 "debugforget|forget":
2986 "debugforget|forget":
2981 (forget,
2987 (forget,
2982 [('I', 'include', [], _('include names matching the given patterns')),
2988 [('I', 'include', [], _('include names matching the given patterns')),
2983 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2989 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2984 _('hg forget [OPTION]... FILE...')),
2990 _('hg forget [OPTION]... FILE...')),
2985 "grep":
2991 "grep":
2986 (grep,
2992 (grep,
2987 [('0', 'print0', None, _('end fields with NUL')),
2993 [('0', 'print0', None, _('end fields with NUL')),
2988 ('', 'all', None, _('print all revisions that match')),
2994 ('', 'all', None, _('print all revisions that match')),
2989 ('i', 'ignore-case', None, _('ignore case when matching')),
2995 ('i', 'ignore-case', None, _('ignore case when matching')),
2990 ('l', 'files-with-matches', None,
2996 ('l', 'files-with-matches', None,
2991 _('print only filenames and revs that match')),
2997 _('print only filenames and revs that match')),
2992 ('n', 'line-number', None, _('print matching line numbers')),
2998 ('n', 'line-number', None, _('print matching line numbers')),
2993 ('r', 'rev', [], _('search in given revision range')),
2999 ('r', 'rev', [], _('search in given revision range')),
2994 ('u', 'user', None, _('print user who committed change')),
3000 ('u', 'user', None, _('print user who committed change')),
2995 ('I', 'include', [], _('include names matching the given patterns')),
3001 ('I', 'include', [], _('include names matching the given patterns')),
2996 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
3002 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
2997 _('hg grep [OPTION]... PATTERN [FILE]...')),
3003 _('hg grep [OPTION]... PATTERN [FILE]...')),
2998 "heads":
3004 "heads":
2999 (heads,
3005 (heads,
3000 [('b', 'branches', None, _('show branches')),
3006 [('b', 'branches', None, _('show branches')),
3001 ('', 'style', '', _('display using template map file')),
3007 ('', 'style', '', _('display using template map file')),
3002 ('r', 'rev', '', _('show only heads which are descendants of rev')),
3008 ('r', 'rev', '', _('show only heads which are descendants of rev')),
3003 ('', 'template', '', _('display with template'))],
3009 ('', 'template', '', _('display with template'))],
3004 _('hg heads [-b] [-r <rev>]')),
3010 _('hg heads [-b] [-r <rev>]')),
3005 "help": (help_, [], _('hg help [COMMAND]')),
3011 "help": (help_, [], _('hg help [COMMAND]')),
3006 "identify|id": (identify, [], _('hg identify')),
3012 "identify|id": (identify, [], _('hg identify')),
3007 "import|patch":
3013 "import|patch":
3008 (import_,
3014 (import_,
3009 [('p', 'strip', 1,
3015 [('p', 'strip', 1,
3010 _('directory strip option for patch. This has the same\n'
3016 _('directory strip option for patch. This has the same\n'
3011 'meaning as the corresponding patch option')),
3017 'meaning as the corresponding patch option')),
3012 ('m', 'message', '', _('use <text> as commit message')),
3018 ('m', 'message', '', _('use <text> as commit message')),
3013 ('b', 'base', '', _('base path')),
3019 ('b', 'base', '', _('base path')),
3014 ('f', 'force', None,
3020 ('f', 'force', None,
3015 _('skip check for outstanding uncommitted changes'))],
3021 _('skip check for outstanding uncommitted changes'))],
3016 _('hg import [-p NUM] [-b BASE] [-m MESSAGE] [-f] PATCH...')),
3022 _('hg import [-p NUM] [-b BASE] [-m MESSAGE] [-f] PATCH...')),
3017 "incoming|in": (incoming,
3023 "incoming|in": (incoming,
3018 [('M', 'no-merges', None, _('do not show merges')),
3024 [('M', 'no-merges', None, _('do not show merges')),
3019 ('f', 'force', None,
3025 ('f', 'force', None,
3020 _('run even when remote repository is unrelated')),
3026 _('run even when remote repository is unrelated')),
3021 ('', 'style', '', _('display using template map file')),
3027 ('', 'style', '', _('display using template map file')),
3022 ('n', 'newest-first', None, _('show newest record first')),
3028 ('n', 'newest-first', None, _('show newest record first')),
3023 ('', 'bundle', '', _('file to store the bundles into')),
3029 ('', 'bundle', '', _('file to store the bundles into')),
3024 ('p', 'patch', None, _('show patch')),
3030 ('p', 'patch', None, _('show patch')),
3031 ('r', 'rev', [], _('a specific revision you would like to pull')),
3025 ('', 'template', '', _('display with template')),
3032 ('', 'template', '', _('display with template')),
3026 ('e', 'ssh', '', _('specify ssh command to use')),
3033 ('e', 'ssh', '', _('specify ssh command to use')),
3027 ('', 'remotecmd', '',
3034 ('', 'remotecmd', '',
3028 _('specify hg command to run on the remote side'))],
3035 _('specify hg command to run on the remote side'))],
3029 _('hg incoming [-p] [-n] [-M] [--bundle FILENAME] [SOURCE]')),
3036 _('hg incoming [-p] [-n] [-M] [-r REV]...'
3037 '[--bundle FILENAME] [SOURCE]')),
3030 "^init": (init, [], _('hg init [DEST]')),
3038 "^init": (init, [], _('hg init [DEST]')),
3031 "locate":
3039 "locate":
3032 (locate,
3040 (locate,
3033 [('r', 'rev', '', _('search the repository as it stood at rev')),
3041 [('r', 'rev', '', _('search the repository as it stood at rev')),
3034 ('0', 'print0', None,
3042 ('0', 'print0', None,
3035 _('end filenames with NUL, for use with xargs')),
3043 _('end filenames with NUL, for use with xargs')),
3036 ('f', 'fullpath', None,
3044 ('f', 'fullpath', None,
3037 _('print complete paths from the filesystem root')),
3045 _('print complete paths from the filesystem root')),
3038 ('I', 'include', [], _('include names matching the given patterns')),
3046 ('I', 'include', [], _('include names matching the given patterns')),
3039 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
3047 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
3040 _('hg locate [OPTION]... [PATTERN]...')),
3048 _('hg locate [OPTION]... [PATTERN]...')),
3041 "^log|history":
3049 "^log|history":
3042 (log,
3050 (log,
3043 [('b', 'branches', None, _('show branches')),
3051 [('b', 'branches', None, _('show branches')),
3044 ('k', 'keyword', [], _('search for a keyword')),
3052 ('k', 'keyword', [], _('search for a keyword')),
3045 ('l', 'limit', '', _('limit number of changes displayed')),
3053 ('l', 'limit', '', _('limit number of changes displayed')),
3046 ('r', 'rev', [], _('show the specified revision or range')),
3054 ('r', 'rev', [], _('show the specified revision or range')),
3047 ('M', 'no-merges', None, _('do not show merges')),
3055 ('M', 'no-merges', None, _('do not show merges')),
3048 ('', 'style', '', _('display using template map file')),
3056 ('', 'style', '', _('display using template map file')),
3049 ('m', 'only-merges', None, _('show only merges')),
3057 ('m', 'only-merges', None, _('show only merges')),
3050 ('p', 'patch', None, _('show patch')),
3058 ('p', 'patch', None, _('show patch')),
3051 ('', 'template', '', _('display with template')),
3059 ('', 'template', '', _('display with template')),
3052 ('I', 'include', [], _('include names matching the given patterns')),
3060 ('I', 'include', [], _('include names matching the given patterns')),
3053 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
3061 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
3054 _('hg log [OPTION]... [FILE]')),
3062 _('hg log [OPTION]... [FILE]')),
3055 "manifest": (manifest, [], _('hg manifest [REV]')),
3063 "manifest": (manifest, [], _('hg manifest [REV]')),
3056 "merge":
3064 "merge":
3057 (merge,
3065 (merge,
3058 [('b', 'branch', '', _('merge with head of a specific branch')),
3066 [('b', 'branch', '', _('merge with head of a specific branch')),
3059 ('f', 'force', None, _('force a merge with outstanding changes'))],
3067 ('f', 'force', None, _('force a merge with outstanding changes'))],
3060 _('hg merge [-b TAG] [-f] [REV]')),
3068 _('hg merge [-b TAG] [-f] [REV]')),
3061 "outgoing|out": (outgoing,
3069 "outgoing|out": (outgoing,
3062 [('M', 'no-merges', None, _('do not show merges')),
3070 [('M', 'no-merges', None, _('do not show merges')),
3063 ('f', 'force', None,
3071 ('f', 'force', None,
3064 _('run even when remote repository is unrelated')),
3072 _('run even when remote repository is unrelated')),
3065 ('p', 'patch', None, _('show patch')),
3073 ('p', 'patch', None, _('show patch')),
3066 ('', 'style', '', _('display using template map file')),
3074 ('', 'style', '', _('display using template map file')),
3075 ('r', 'rev', [], _('a specific revision you would like to push')),
3067 ('n', 'newest-first', None, _('show newest record first')),
3076 ('n', 'newest-first', None, _('show newest record first')),
3068 ('', 'template', '', _('display with template')),
3077 ('', 'template', '', _('display with template')),
3069 ('e', 'ssh', '', _('specify ssh command to use')),
3078 ('e', 'ssh', '', _('specify ssh command to use')),
3070 ('', 'remotecmd', '',
3079 ('', 'remotecmd', '',
3071 _('specify hg command to run on the remote side'))],
3080 _('specify hg command to run on the remote side'))],
3072 _('hg outgoing [-M] [-p] [-n] [DEST]')),
3081 _('hg outgoing [-M] [-p] [-n] [-r REV]... [DEST]')),
3073 "^parents":
3082 "^parents":
3074 (parents,
3083 (parents,
3075 [('b', 'branches', None, _('show branches')),
3084 [('b', 'branches', None, _('show branches')),
3076 ('', 'style', '', _('display using template map file')),
3085 ('', 'style', '', _('display using template map file')),
3077 ('', 'template', '', _('display with template'))],
3086 ('', 'template', '', _('display with template'))],
3078 _('hg parents [-b] [REV]')),
3087 _('hg parents [-b] [REV]')),
3079 "paths": (paths, [], _('hg paths [NAME]')),
3088 "paths": (paths, [], _('hg paths [NAME]')),
3080 "^pull":
3089 "^pull":
3081 (pull,
3090 (pull,
3082 [('u', 'update', None,
3091 [('u', 'update', None,
3083 _('update the working directory to tip after pull')),
3092 _('update the working directory to tip after pull')),
3084 ('e', 'ssh', '', _('specify ssh command to use')),
3093 ('e', 'ssh', '', _('specify ssh command to use')),
3085 ('f', 'force', None,
3094 ('f', 'force', None,
3086 _('run even when remote repository is unrelated')),
3095 _('run even when remote repository is unrelated')),
3087 ('r', 'rev', [], _('a specific revision you would like to pull')),
3096 ('r', 'rev', [], _('a specific revision you would like to pull')),
3088 ('', 'remotecmd', '',
3097 ('', 'remotecmd', '',
3089 _('specify hg command to run on the remote side'))],
3098 _('specify hg command to run on the remote side'))],
3090 _('hg pull [-u] [-e FILE] [-r REV]... [--remotecmd FILE] [SOURCE]')),
3099 _('hg pull [-u] [-e FILE] [-r REV]... [--remotecmd FILE] [SOURCE]')),
3091 "^push":
3100 "^push":
3092 (push,
3101 (push,
3093 [('f', 'force', None, _('force push')),
3102 [('f', 'force', None, _('force push')),
3094 ('e', 'ssh', '', _('specify ssh command to use')),
3103 ('e', 'ssh', '', _('specify ssh command to use')),
3095 ('r', 'rev', [], _('a specific revision you would like to push')),
3104 ('r', 'rev', [], _('a specific revision you would like to push')),
3096 ('', 'remotecmd', '',
3105 ('', 'remotecmd', '',
3097 _('specify hg command to run on the remote side'))],
3106 _('specify hg command to run on the remote side'))],
3098 _('hg push [-f] [-e FILE] [-r REV]... [--remotecmd FILE] [DEST]')),
3107 _('hg push [-f] [-e FILE] [-r REV]... [--remotecmd FILE] [DEST]')),
3099 "debugrawcommit|rawcommit":
3108 "debugrawcommit|rawcommit":
3100 (rawcommit,
3109 (rawcommit,
3101 [('p', 'parent', [], _('parent')),
3110 [('p', 'parent', [], _('parent')),
3102 ('d', 'date', '', _('date code')),
3111 ('d', 'date', '', _('date code')),
3103 ('u', 'user', '', _('user')),
3112 ('u', 'user', '', _('user')),
3104 ('F', 'files', '', _('file list')),
3113 ('F', 'files', '', _('file list')),
3105 ('m', 'message', '', _('commit message')),
3114 ('m', 'message', '', _('commit message')),
3106 ('l', 'logfile', '', _('commit message file'))],
3115 ('l', 'logfile', '', _('commit message file'))],
3107 _('hg debugrawcommit [OPTION]... [FILE]...')),
3116 _('hg debugrawcommit [OPTION]... [FILE]...')),
3108 "recover": (recover, [], _('hg recover')),
3117 "recover": (recover, [], _('hg recover')),
3109 "^remove|rm":
3118 "^remove|rm":
3110 (remove,
3119 (remove,
3111 [('A', 'after', None, _('record remove that has already occurred')),
3120 [('A', 'after', None, _('record remove that has already occurred')),
3112 ('f', 'force', None, _('remove file even if modified')),
3121 ('f', 'force', None, _('remove file even if modified')),
3113 ('I', 'include', [], _('include names matching the given patterns')),
3122 ('I', 'include', [], _('include names matching the given patterns')),
3114 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
3123 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
3115 _('hg remove [OPTION]... FILE...')),
3124 _('hg remove [OPTION]... FILE...')),
3116 "rename|mv":
3125 "rename|mv":
3117 (rename,
3126 (rename,
3118 [('A', 'after', None, _('record a rename that has already occurred')),
3127 [('A', 'after', None, _('record a rename that has already occurred')),
3119 ('f', 'force', None,
3128 ('f', 'force', None,
3120 _('forcibly copy over an existing managed file')),
3129 _('forcibly copy over an existing managed file')),
3121 ('I', 'include', [], _('include names matching the given patterns')),
3130 ('I', 'include', [], _('include names matching the given patterns')),
3122 ('X', 'exclude', [], _('exclude names matching the given patterns')),
3131 ('X', 'exclude', [], _('exclude names matching the given patterns')),
3123 ('n', 'dry-run', None, _('do not perform actions, just print output'))],
3132 ('n', 'dry-run', None, _('do not perform actions, just print output'))],
3124 _('hg rename [OPTION]... SOURCE... DEST')),
3133 _('hg rename [OPTION]... SOURCE... DEST')),
3125 "^revert":
3134 "^revert":
3126 (revert,
3135 (revert,
3127 [('r', 'rev', '', _('revision to revert to')),
3136 [('r', 'rev', '', _('revision to revert to')),
3128 ('', 'no-backup', None, _('do not save backup copies of files')),
3137 ('', 'no-backup', None, _('do not save backup copies of files')),
3129 ('I', 'include', [], _('include names matching given patterns')),
3138 ('I', 'include', [], _('include names matching given patterns')),
3130 ('X', 'exclude', [], _('exclude names matching given patterns')),
3139 ('X', 'exclude', [], _('exclude names matching given patterns')),
3131 ('n', 'dry-run', None, _('do not perform actions, just print output'))],
3140 ('n', 'dry-run', None, _('do not perform actions, just print output'))],
3132 _('hg revert [-r REV] [NAME]...')),
3141 _('hg revert [-r REV] [NAME]...')),
3133 "rollback": (rollback, [], _('hg rollback')),
3142 "rollback": (rollback, [], _('hg rollback')),
3134 "root": (root, [], _('hg root')),
3143 "root": (root, [], _('hg root')),
3135 "^serve":
3144 "^serve":
3136 (serve,
3145 (serve,
3137 [('A', 'accesslog', '', _('name of access log file to write to')),
3146 [('A', 'accesslog', '', _('name of access log file to write to')),
3138 ('d', 'daemon', None, _('run server in background')),
3147 ('d', 'daemon', None, _('run server in background')),
3139 ('', 'daemon-pipefds', '', _('used internally by daemon mode')),
3148 ('', 'daemon-pipefds', '', _('used internally by daemon mode')),
3140 ('E', 'errorlog', '', _('name of error log file to write to')),
3149 ('E', 'errorlog', '', _('name of error log file to write to')),
3141 ('p', 'port', 0, _('port to use (default: 8000)')),
3150 ('p', 'port', 0, _('port to use (default: 8000)')),
3142 ('a', 'address', '', _('address to use')),
3151 ('a', 'address', '', _('address to use')),
3143 ('n', 'name', '',
3152 ('n', 'name', '',
3144 _('name to show in web pages (default: working dir)')),
3153 _('name to show in web pages (default: working dir)')),
3145 ('', 'webdir-conf', '', _('name of the webdir config file'
3154 ('', 'webdir-conf', '', _('name of the webdir config file'
3146 ' (serve more than one repo)')),
3155 ' (serve more than one repo)')),
3147 ('', 'pid-file', '', _('name of file to write process ID to')),
3156 ('', 'pid-file', '', _('name of file to write process ID to')),
3148 ('', 'stdio', None, _('for remote clients')),
3157 ('', 'stdio', None, _('for remote clients')),
3149 ('t', 'templates', '', _('web templates to use')),
3158 ('t', 'templates', '', _('web templates to use')),
3150 ('', 'style', '', _('template style to use')),
3159 ('', 'style', '', _('template style to use')),
3151 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4'))],
3160 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4'))],
3152 _('hg serve [OPTION]...')),
3161 _('hg serve [OPTION]...')),
3153 "^status|st":
3162 "^status|st":
3154 (status,
3163 (status,
3155 [('m', 'modified', None, _('show only modified files')),
3164 [('m', 'modified', None, _('show only modified files')),
3156 ('a', 'added', None, _('show only added files')),
3165 ('a', 'added', None, _('show only added files')),
3157 ('r', 'removed', None, _('show only removed files')),
3166 ('r', 'removed', None, _('show only removed files')),
3158 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
3167 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
3159 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
3168 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
3160 ('i', 'ignored', None, _('show ignored files')),
3169 ('i', 'ignored', None, _('show ignored files')),
3161 ('n', 'no-status', None, _('hide status prefix')),
3170 ('n', 'no-status', None, _('hide status prefix')),
3162 ('0', 'print0', None,
3171 ('0', 'print0', None,
3163 _('end filenames with NUL, for use with xargs')),
3172 _('end filenames with NUL, for use with xargs')),
3164 ('I', 'include', [], _('include names matching the given patterns')),
3173 ('I', 'include', [], _('include names matching the given patterns')),
3165 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
3174 ('X', 'exclude', [], _('exclude names matching the given patterns'))],
3166 _('hg status [OPTION]... [FILE]...')),
3175 _('hg status [OPTION]... [FILE]...')),
3167 "tag":
3176 "tag":
3168 (tag,
3177 (tag,
3169 [('l', 'local', None, _('make the tag local')),
3178 [('l', 'local', None, _('make the tag local')),
3170 ('m', 'message', '', _('message for tag commit log entry')),
3179 ('m', 'message', '', _('message for tag commit log entry')),
3171 ('d', 'date', '', _('record datecode as commit date')),
3180 ('d', 'date', '', _('record datecode as commit date')),
3172 ('u', 'user', '', _('record user as commiter')),
3181 ('u', 'user', '', _('record user as commiter')),
3173 ('r', 'rev', '', _('revision to tag'))],
3182 ('r', 'rev', '', _('revision to tag'))],
3174 _('hg tag [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME')),
3183 _('hg tag [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME')),
3175 "tags": (tags, [], _('hg tags')),
3184 "tags": (tags, [], _('hg tags')),
3176 "tip":
3185 "tip":
3177 (tip,
3186 (tip,
3178 [('b', 'branches', None, _('show branches')),
3187 [('b', 'branches', None, _('show branches')),
3179 ('', 'style', '', _('display using template map file')),
3188 ('', 'style', '', _('display using template map file')),
3180 ('p', 'patch', None, _('show patch')),
3189 ('p', 'patch', None, _('show patch')),
3181 ('', 'template', '', _('display with template'))],
3190 ('', 'template', '', _('display with template'))],
3182 _('hg tip [-b] [-p]')),
3191 _('hg tip [-b] [-p]')),
3183 "unbundle":
3192 "unbundle":
3184 (unbundle,
3193 (unbundle,
3185 [('u', 'update', None,
3194 [('u', 'update', None,
3186 _('update the working directory to tip after unbundle'))],
3195 _('update the working directory to tip after unbundle'))],
3187 _('hg unbundle [-u] FILE')),
3196 _('hg unbundle [-u] FILE')),
3188 "debugundo|undo": (undo, [], _('hg undo')),
3197 "debugundo|undo": (undo, [], _('hg undo')),
3189 "^update|up|checkout|co":
3198 "^update|up|checkout|co":
3190 (update,
3199 (update,
3191 [('b', 'branch', '', _('checkout the head of a specific branch')),
3200 [('b', 'branch', '', _('checkout the head of a specific branch')),
3192 ('m', 'merge', None, _('allow merging of branches (DEPRECATED)')),
3201 ('m', 'merge', None, _('allow merging of branches (DEPRECATED)')),
3193 ('C', 'clean', None, _('overwrite locally modified files')),
3202 ('C', 'clean', None, _('overwrite locally modified files')),
3194 ('f', 'force', None, _('force a merge with outstanding changes'))],
3203 ('f', 'force', None, _('force a merge with outstanding changes'))],
3195 _('hg update [-b TAG] [-m] [-C] [-f] [REV]')),
3204 _('hg update [-b TAG] [-m] [-C] [-f] [REV]')),
3196 "verify": (verify, [], _('hg verify')),
3205 "verify": (verify, [], _('hg verify')),
3197 "version": (show_version, [], _('hg version')),
3206 "version": (show_version, [], _('hg version')),
3198 }
3207 }
3199
3208
3200 globalopts = [
3209 globalopts = [
3201 ('R', 'repository', '',
3210 ('R', 'repository', '',
3202 _('repository root directory or symbolic path name')),
3211 _('repository root directory or symbolic path name')),
3203 ('', 'cwd', '', _('change working directory')),
3212 ('', 'cwd', '', _('change working directory')),
3204 ('y', 'noninteractive', None,
3213 ('y', 'noninteractive', None,
3205 _('do not prompt, assume \'yes\' for any required answers')),
3214 _('do not prompt, assume \'yes\' for any required answers')),
3206 ('q', 'quiet', None, _('suppress output')),
3215 ('q', 'quiet', None, _('suppress output')),
3207 ('v', 'verbose', None, _('enable additional output')),
3216 ('v', 'verbose', None, _('enable additional output')),
3208 ('', 'config', [], _('set/override config option')),
3217 ('', 'config', [], _('set/override config option')),
3209 ('', 'debug', None, _('enable debugging output')),
3218 ('', 'debug', None, _('enable debugging output')),
3210 ('', 'debugger', None, _('start debugger')),
3219 ('', 'debugger', None, _('start debugger')),
3211 ('', 'lsprof', None, _('print improved command execution profile')),
3220 ('', 'lsprof', None, _('print improved command execution profile')),
3212 ('', 'traceback', None, _('print traceback on exception')),
3221 ('', 'traceback', None, _('print traceback on exception')),
3213 ('', 'time', None, _('time how long the command takes')),
3222 ('', 'time', None, _('time how long the command takes')),
3214 ('', 'profile', None, _('print command execution profile')),
3223 ('', 'profile', None, _('print command execution profile')),
3215 ('', 'version', None, _('output version information and exit')),
3224 ('', 'version', None, _('output version information and exit')),
3216 ('h', 'help', None, _('display help and exit')),
3225 ('h', 'help', None, _('display help and exit')),
3217 ]
3226 ]
3218
3227
3219 norepo = ("clone init version help debugancestor debugcomplete debugdata"
3228 norepo = ("clone init version help debugancestor debugcomplete debugdata"
3220 " debugindex debugindexdot")
3229 " debugindex debugindexdot")
3221 optionalrepo = ("paths serve debugconfig")
3230 optionalrepo = ("paths serve debugconfig")
3222
3231
3223 def findpossible(cmd):
3232 def findpossible(cmd):
3224 """
3233 """
3225 Return cmd -> (aliases, command table entry)
3234 Return cmd -> (aliases, command table entry)
3226 for each matching command.
3235 for each matching command.
3227 Return debug commands (or their aliases) only if no normal command matches.
3236 Return debug commands (or their aliases) only if no normal command matches.
3228 """
3237 """
3229 choice = {}
3238 choice = {}
3230 debugchoice = {}
3239 debugchoice = {}
3231 for e in table.keys():
3240 for e in table.keys():
3232 aliases = e.lstrip("^").split("|")
3241 aliases = e.lstrip("^").split("|")
3233 found = None
3242 found = None
3234 if cmd in aliases:
3243 if cmd in aliases:
3235 found = cmd
3244 found = cmd
3236 else:
3245 else:
3237 for a in aliases:
3246 for a in aliases:
3238 if a.startswith(cmd):
3247 if a.startswith(cmd):
3239 found = a
3248 found = a
3240 break
3249 break
3241 if found is not None:
3250 if found is not None:
3242 if aliases[0].startswith("debug"):
3251 if aliases[0].startswith("debug"):
3243 debugchoice[found] = (aliases, table[e])
3252 debugchoice[found] = (aliases, table[e])
3244 else:
3253 else:
3245 choice[found] = (aliases, table[e])
3254 choice[found] = (aliases, table[e])
3246
3255
3247 if not choice and debugchoice:
3256 if not choice and debugchoice:
3248 choice = debugchoice
3257 choice = debugchoice
3249
3258
3250 return choice
3259 return choice
3251
3260
3252 def find(cmd):
3261 def find(cmd):
3253 """Return (aliases, command table entry) for command string."""
3262 """Return (aliases, command table entry) for command string."""
3254 choice = findpossible(cmd)
3263 choice = findpossible(cmd)
3255
3264
3256 if choice.has_key(cmd):
3265 if choice.has_key(cmd):
3257 return choice[cmd]
3266 return choice[cmd]
3258
3267
3259 if len(choice) > 1:
3268 if len(choice) > 1:
3260 clist = choice.keys()
3269 clist = choice.keys()
3261 clist.sort()
3270 clist.sort()
3262 raise AmbiguousCommand(cmd, clist)
3271 raise AmbiguousCommand(cmd, clist)
3263
3272
3264 if choice:
3273 if choice:
3265 return choice.values()[0]
3274 return choice.values()[0]
3266
3275
3267 raise UnknownCommand(cmd)
3276 raise UnknownCommand(cmd)
3268
3277
3269 def catchterm(*args):
3278 def catchterm(*args):
3270 raise util.SignalInterrupt
3279 raise util.SignalInterrupt
3271
3280
3272 def run():
3281 def run():
3273 sys.exit(dispatch(sys.argv[1:]))
3282 sys.exit(dispatch(sys.argv[1:]))
3274
3283
3275 class ParseError(Exception):
3284 class ParseError(Exception):
3276 """Exception raised on errors in parsing the command line."""
3285 """Exception raised on errors in parsing the command line."""
3277
3286
3278 def parse(ui, args):
3287 def parse(ui, args):
3279 options = {}
3288 options = {}
3280 cmdoptions = {}
3289 cmdoptions = {}
3281
3290
3282 try:
3291 try:
3283 args = fancyopts.fancyopts(args, globalopts, options)
3292 args = fancyopts.fancyopts(args, globalopts, options)
3284 except fancyopts.getopt.GetoptError, inst:
3293 except fancyopts.getopt.GetoptError, inst:
3285 raise ParseError(None, inst)
3294 raise ParseError(None, inst)
3286
3295
3287 if args:
3296 if args:
3288 cmd, args = args[0], args[1:]
3297 cmd, args = args[0], args[1:]
3289 aliases, i = find(cmd)
3298 aliases, i = find(cmd)
3290 cmd = aliases[0]
3299 cmd = aliases[0]
3291 defaults = ui.config("defaults", cmd)
3300 defaults = ui.config("defaults", cmd)
3292 if defaults:
3301 if defaults:
3293 args = defaults.split() + args
3302 args = defaults.split() + args
3294 c = list(i[1])
3303 c = list(i[1])
3295 else:
3304 else:
3296 cmd = None
3305 cmd = None
3297 c = []
3306 c = []
3298
3307
3299 # combine global options into local
3308 # combine global options into local
3300 for o in globalopts:
3309 for o in globalopts:
3301 c.append((o[0], o[1], options[o[1]], o[3]))
3310 c.append((o[0], o[1], options[o[1]], o[3]))
3302
3311
3303 try:
3312 try:
3304 args = fancyopts.fancyopts(args, c, cmdoptions)
3313 args = fancyopts.fancyopts(args, c, cmdoptions)
3305 except fancyopts.getopt.GetoptError, inst:
3314 except fancyopts.getopt.GetoptError, inst:
3306 raise ParseError(cmd, inst)
3315 raise ParseError(cmd, inst)
3307
3316
3308 # separate global options back out
3317 # separate global options back out
3309 for o in globalopts:
3318 for o in globalopts:
3310 n = o[1]
3319 n = o[1]
3311 options[n] = cmdoptions[n]
3320 options[n] = cmdoptions[n]
3312 del cmdoptions[n]
3321 del cmdoptions[n]
3313
3322
3314 return (cmd, cmd and i[0] or None, args, options, cmdoptions)
3323 return (cmd, cmd and i[0] or None, args, options, cmdoptions)
3315
3324
3316 def dispatch(args):
3325 def dispatch(args):
3317 for name in 'SIGBREAK', 'SIGHUP', 'SIGTERM':
3326 for name in 'SIGBREAK', 'SIGHUP', 'SIGTERM':
3318 num = getattr(signal, name, None)
3327 num = getattr(signal, name, None)
3319 if num: signal.signal(num, catchterm)
3328 if num: signal.signal(num, catchterm)
3320
3329
3321 try:
3330 try:
3322 u = ui.ui(traceback='--traceback' in sys.argv[1:])
3331 u = ui.ui(traceback='--traceback' in sys.argv[1:])
3323 except util.Abort, inst:
3332 except util.Abort, inst:
3324 sys.stderr.write(_("abort: %s\n") % inst)
3333 sys.stderr.write(_("abort: %s\n") % inst)
3325 return -1
3334 return -1
3326
3335
3327 external = []
3336 external = []
3328 for x in u.extensions():
3337 for x in u.extensions():
3329 try:
3338 try:
3330 if x[1]:
3339 if x[1]:
3331 # the module will be loaded in sys.modules
3340 # the module will be loaded in sys.modules
3332 # choose an unique name so that it doesn't
3341 # choose an unique name so that it doesn't
3333 # conflicts with other modules
3342 # conflicts with other modules
3334 module_name = "hgext_%s" % x[0].replace('.', '_')
3343 module_name = "hgext_%s" % x[0].replace('.', '_')
3335 mod = imp.load_source(module_name, x[1])
3344 mod = imp.load_source(module_name, x[1])
3336 else:
3345 else:
3337 def importh(name):
3346 def importh(name):
3338 mod = __import__(name)
3347 mod = __import__(name)
3339 components = name.split('.')
3348 components = name.split('.')
3340 for comp in components[1:]:
3349 for comp in components[1:]:
3341 mod = getattr(mod, comp)
3350 mod = getattr(mod, comp)
3342 return mod
3351 return mod
3343 try:
3352 try:
3344 mod = importh("hgext." + x[0])
3353 mod = importh("hgext." + x[0])
3345 except ImportError:
3354 except ImportError:
3346 mod = importh(x[0])
3355 mod = importh(x[0])
3347 external.append(mod)
3356 external.append(mod)
3348 except (util.SignalInterrupt, KeyboardInterrupt):
3357 except (util.SignalInterrupt, KeyboardInterrupt):
3349 raise
3358 raise
3350 except Exception, inst:
3359 except Exception, inst:
3351 u.warn(_("*** failed to import extension %s: %s\n") % (x[0], inst))
3360 u.warn(_("*** failed to import extension %s: %s\n") % (x[0], inst))
3352 if u.print_exc():
3361 if u.print_exc():
3353 return 1
3362 return 1
3354
3363
3355 for x in external:
3364 for x in external:
3356 uisetup = getattr(x, 'uisetup', None)
3365 uisetup = getattr(x, 'uisetup', None)
3357 if uisetup:
3366 if uisetup:
3358 uisetup(u)
3367 uisetup(u)
3359 cmdtable = getattr(x, 'cmdtable', {})
3368 cmdtable = getattr(x, 'cmdtable', {})
3360 for t in cmdtable:
3369 for t in cmdtable:
3361 if t in table:
3370 if t in table:
3362 u.warn(_("module %s overrides %s\n") % (x.__name__, t))
3371 u.warn(_("module %s overrides %s\n") % (x.__name__, t))
3363 table.update(cmdtable)
3372 table.update(cmdtable)
3364
3373
3365 try:
3374 try:
3366 cmd, func, args, options, cmdoptions = parse(u, args)
3375 cmd, func, args, options, cmdoptions = parse(u, args)
3367 if options["time"]:
3376 if options["time"]:
3368 def get_times():
3377 def get_times():
3369 t = os.times()
3378 t = os.times()
3370 if t[4] == 0.0: # Windows leaves this as zero, so use time.clock()
3379 if t[4] == 0.0: # Windows leaves this as zero, so use time.clock()
3371 t = (t[0], t[1], t[2], t[3], time.clock())
3380 t = (t[0], t[1], t[2], t[3], time.clock())
3372 return t
3381 return t
3373 s = get_times()
3382 s = get_times()
3374 def print_time():
3383 def print_time():
3375 t = get_times()
3384 t = get_times()
3376 u.warn(_("Time: real %.3f secs (user %.3f+%.3f sys %.3f+%.3f)\n") %
3385 u.warn(_("Time: real %.3f secs (user %.3f+%.3f sys %.3f+%.3f)\n") %
3377 (t[4]-s[4], t[0]-s[0], t[2]-s[2], t[1]-s[1], t[3]-s[3]))
3386 (t[4]-s[4], t[0]-s[0], t[2]-s[2], t[1]-s[1], t[3]-s[3]))
3378 atexit.register(print_time)
3387 atexit.register(print_time)
3379
3388
3380 u.updateopts(options["verbose"], options["debug"], options["quiet"],
3389 u.updateopts(options["verbose"], options["debug"], options["quiet"],
3381 not options["noninteractive"], options["traceback"],
3390 not options["noninteractive"], options["traceback"],
3382 options["config"])
3391 options["config"])
3383
3392
3384 # enter the debugger before command execution
3393 # enter the debugger before command execution
3385 if options['debugger']:
3394 if options['debugger']:
3386 pdb.set_trace()
3395 pdb.set_trace()
3387
3396
3388 try:
3397 try:
3389 if options['cwd']:
3398 if options['cwd']:
3390 try:
3399 try:
3391 os.chdir(options['cwd'])
3400 os.chdir(options['cwd'])
3392 except OSError, inst:
3401 except OSError, inst:
3393 raise util.Abort('%s: %s' %
3402 raise util.Abort('%s: %s' %
3394 (options['cwd'], inst.strerror))
3403 (options['cwd'], inst.strerror))
3395
3404
3396 path = u.expandpath(options["repository"]) or ""
3405 path = u.expandpath(options["repository"]) or ""
3397 repo = path and hg.repository(u, path=path) or None
3406 repo = path and hg.repository(u, path=path) or None
3398
3407
3399 if options['help']:
3408 if options['help']:
3400 return help_(u, cmd, options['version'])
3409 return help_(u, cmd, options['version'])
3401 elif options['version']:
3410 elif options['version']:
3402 return show_version(u)
3411 return show_version(u)
3403 elif not cmd:
3412 elif not cmd:
3404 return help_(u, 'shortlist')
3413 return help_(u, 'shortlist')
3405
3414
3406 if cmd not in norepo.split():
3415 if cmd not in norepo.split():
3407 try:
3416 try:
3408 if not repo:
3417 if not repo:
3409 repo = hg.repository(u, path=path)
3418 repo = hg.repository(u, path=path)
3410 u = repo.ui
3419 u = repo.ui
3411 for x in external:
3420 for x in external:
3412 if hasattr(x, 'reposetup'):
3421 if hasattr(x, 'reposetup'):
3413 x.reposetup(u, repo)
3422 x.reposetup(u, repo)
3414 except hg.RepoError:
3423 except hg.RepoError:
3415 if cmd not in optionalrepo.split():
3424 if cmd not in optionalrepo.split():
3416 raise
3425 raise
3417 d = lambda: func(u, repo, *args, **cmdoptions)
3426 d = lambda: func(u, repo, *args, **cmdoptions)
3418 else:
3427 else:
3419 d = lambda: func(u, *args, **cmdoptions)
3428 d = lambda: func(u, *args, **cmdoptions)
3420
3429
3421 try:
3430 try:
3422 if options['profile']:
3431 if options['profile']:
3423 import hotshot, hotshot.stats
3432 import hotshot, hotshot.stats
3424 prof = hotshot.Profile("hg.prof")
3433 prof = hotshot.Profile("hg.prof")
3425 try:
3434 try:
3426 try:
3435 try:
3427 return prof.runcall(d)
3436 return prof.runcall(d)
3428 except:
3437 except:
3429 try:
3438 try:
3430 u.warn(_('exception raised - generating '
3439 u.warn(_('exception raised - generating '
3431 'profile anyway\n'))
3440 'profile anyway\n'))
3432 except:
3441 except:
3433 pass
3442 pass
3434 raise
3443 raise
3435 finally:
3444 finally:
3436 prof.close()
3445 prof.close()
3437 stats = hotshot.stats.load("hg.prof")
3446 stats = hotshot.stats.load("hg.prof")
3438 stats.strip_dirs()
3447 stats.strip_dirs()
3439 stats.sort_stats('time', 'calls')
3448 stats.sort_stats('time', 'calls')
3440 stats.print_stats(40)
3449 stats.print_stats(40)
3441 elif options['lsprof']:
3450 elif options['lsprof']:
3442 try:
3451 try:
3443 from mercurial import lsprof
3452 from mercurial import lsprof
3444 except ImportError:
3453 except ImportError:
3445 raise util.Abort(_(
3454 raise util.Abort(_(
3446 'lsprof not available - install from '
3455 'lsprof not available - install from '
3447 'http://codespeak.net/svn/user/arigo/hack/misc/lsprof/'))
3456 'http://codespeak.net/svn/user/arigo/hack/misc/lsprof/'))
3448 p = lsprof.Profiler()
3457 p = lsprof.Profiler()
3449 p.enable(subcalls=True)
3458 p.enable(subcalls=True)
3450 try:
3459 try:
3451 return d()
3460 return d()
3452 finally:
3461 finally:
3453 p.disable()
3462 p.disable()
3454 stats = lsprof.Stats(p.getstats())
3463 stats = lsprof.Stats(p.getstats())
3455 stats.sort()
3464 stats.sort()
3456 stats.pprint(top=10, file=sys.stderr, climit=5)
3465 stats.pprint(top=10, file=sys.stderr, climit=5)
3457 else:
3466 else:
3458 return d()
3467 return d()
3459 finally:
3468 finally:
3460 u.flush()
3469 u.flush()
3461 except:
3470 except:
3462 # enter the debugger when we hit an exception
3471 # enter the debugger when we hit an exception
3463 if options['debugger']:
3472 if options['debugger']:
3464 pdb.post_mortem(sys.exc_info()[2])
3473 pdb.post_mortem(sys.exc_info()[2])
3465 u.print_exc()
3474 u.print_exc()
3466 raise
3475 raise
3467 except ParseError, inst:
3476 except ParseError, inst:
3468 if inst.args[0]:
3477 if inst.args[0]:
3469 u.warn(_("hg %s: %s\n") % (inst.args[0], inst.args[1]))
3478 u.warn(_("hg %s: %s\n") % (inst.args[0], inst.args[1]))
3470 help_(u, inst.args[0])
3479 help_(u, inst.args[0])
3471 else:
3480 else:
3472 u.warn(_("hg: %s\n") % inst.args[1])
3481 u.warn(_("hg: %s\n") % inst.args[1])
3473 help_(u, 'shortlist')
3482 help_(u, 'shortlist')
3474 except AmbiguousCommand, inst:
3483 except AmbiguousCommand, inst:
3475 u.warn(_("hg: command '%s' is ambiguous:\n %s\n") %
3484 u.warn(_("hg: command '%s' is ambiguous:\n %s\n") %
3476 (inst.args[0], " ".join(inst.args[1])))
3485 (inst.args[0], " ".join(inst.args[1])))
3477 except UnknownCommand, inst:
3486 except UnknownCommand, inst:
3478 u.warn(_("hg: unknown command '%s'\n") % inst.args[0])
3487 u.warn(_("hg: unknown command '%s'\n") % inst.args[0])
3479 help_(u, 'shortlist')
3488 help_(u, 'shortlist')
3480 except hg.RepoError, inst:
3489 except hg.RepoError, inst:
3481 u.warn(_("abort: %s!\n") % inst)
3490 u.warn(_("abort: %s!\n") % inst)
3482 except lock.LockHeld, inst:
3491 except lock.LockHeld, inst:
3483 if inst.errno == errno.ETIMEDOUT:
3492 if inst.errno == errno.ETIMEDOUT:
3484 reason = _('timed out waiting for lock held by %s') % inst.locker
3493 reason = _('timed out waiting for lock held by %s') % inst.locker
3485 else:
3494 else:
3486 reason = _('lock held by %s') % inst.locker
3495 reason = _('lock held by %s') % inst.locker
3487 u.warn(_("abort: %s: %s\n") % (inst.desc or inst.filename, reason))
3496 u.warn(_("abort: %s: %s\n") % (inst.desc or inst.filename, reason))
3488 except lock.LockUnavailable, inst:
3497 except lock.LockUnavailable, inst:
3489 u.warn(_("abort: could not lock %s: %s\n") %
3498 u.warn(_("abort: could not lock %s: %s\n") %
3490 (inst.desc or inst.filename, inst.strerror))
3499 (inst.desc or inst.filename, inst.strerror))
3491 except revlog.RevlogError, inst:
3500 except revlog.RevlogError, inst:
3492 u.warn(_("abort: "), inst, "!\n")
3501 u.warn(_("abort: "), inst, "!\n")
3493 except util.SignalInterrupt:
3502 except util.SignalInterrupt:
3494 u.warn(_("killed!\n"))
3503 u.warn(_("killed!\n"))
3495 except KeyboardInterrupt:
3504 except KeyboardInterrupt:
3496 try:
3505 try:
3497 u.warn(_("interrupted!\n"))
3506 u.warn(_("interrupted!\n"))
3498 except IOError, inst:
3507 except IOError, inst:
3499 if inst.errno == errno.EPIPE:
3508 if inst.errno == errno.EPIPE:
3500 if u.debugflag:
3509 if u.debugflag:
3501 u.warn(_("\nbroken pipe\n"))
3510 u.warn(_("\nbroken pipe\n"))
3502 else:
3511 else:
3503 raise
3512 raise
3504 except IOError, inst:
3513 except IOError, inst:
3505 if hasattr(inst, "code"):
3514 if hasattr(inst, "code"):
3506 u.warn(_("abort: %s\n") % inst)
3515 u.warn(_("abort: %s\n") % inst)
3507 elif hasattr(inst, "reason"):
3516 elif hasattr(inst, "reason"):
3508 u.warn(_("abort: error: %s\n") % inst.reason[1])
3517 u.warn(_("abort: error: %s\n") % inst.reason[1])
3509 elif hasattr(inst, "args") and inst[0] == errno.EPIPE:
3518 elif hasattr(inst, "args") and inst[0] == errno.EPIPE:
3510 if u.debugflag:
3519 if u.debugflag:
3511 u.warn(_("broken pipe\n"))
3520 u.warn(_("broken pipe\n"))
3512 elif getattr(inst, "strerror", None):
3521 elif getattr(inst, "strerror", None):
3513 if getattr(inst, "filename", None):
3522 if getattr(inst, "filename", None):
3514 u.warn(_("abort: %s - %s\n") % (inst.strerror, inst.filename))
3523 u.warn(_("abort: %s - %s\n") % (inst.strerror, inst.filename))
3515 else:
3524 else:
3516 u.warn(_("abort: %s\n") % inst.strerror)
3525 u.warn(_("abort: %s\n") % inst.strerror)
3517 else:
3526 else:
3518 raise
3527 raise
3519 except OSError, inst:
3528 except OSError, inst:
3520 if hasattr(inst, "filename"):
3529 if hasattr(inst, "filename"):
3521 u.warn(_("abort: %s: %s\n") % (inst.strerror, inst.filename))
3530 u.warn(_("abort: %s: %s\n") % (inst.strerror, inst.filename))
3522 else:
3531 else:
3523 u.warn(_("abort: %s\n") % inst.strerror)
3532 u.warn(_("abort: %s\n") % inst.strerror)
3524 except util.Abort, inst:
3533 except util.Abort, inst:
3525 u.warn(_('abort: '), inst.args[0] % inst.args[1:], '\n')
3534 u.warn(_('abort: '), inst.args[0] % inst.args[1:], '\n')
3526 except TypeError, inst:
3535 except TypeError, inst:
3527 # was this an argument error?
3536 # was this an argument error?
3528 tb = traceback.extract_tb(sys.exc_info()[2])
3537 tb = traceback.extract_tb(sys.exc_info()[2])
3529 if len(tb) > 2: # no
3538 if len(tb) > 2: # no
3530 raise
3539 raise
3531 u.debug(inst, "\n")
3540 u.debug(inst, "\n")
3532 u.warn(_("%s: invalid arguments\n") % cmd)
3541 u.warn(_("%s: invalid arguments\n") % cmd)
3533 help_(u, cmd)
3542 help_(u, cmd)
3534 except SystemExit, inst:
3543 except SystemExit, inst:
3535 # Commands shouldn't sys.exit directly, but give a return code.
3544 # Commands shouldn't sys.exit directly, but give a return code.
3536 # Just in case catch this and and pass exit code to caller.
3545 # Just in case catch this and and pass exit code to caller.
3537 return inst.code
3546 return inst.code
3538 except:
3547 except:
3539 u.warn(_("** unknown exception encountered, details follow\n"))
3548 u.warn(_("** unknown exception encountered, details follow\n"))
3540 u.warn(_("** report bug details to mercurial@selenic.com\n"))
3549 u.warn(_("** report bug details to mercurial@selenic.com\n"))
3541 u.warn(_("** Mercurial Distributed SCM (version %s)\n")
3550 u.warn(_("** Mercurial Distributed SCM (version %s)\n")
3542 % version.get_version())
3551 % version.get_version())
3543 raise
3552 raise
3544
3553
3545 return -1
3554 return -1
@@ -1,46 +1,49 b''
1 #!/bin/sh
1 #!/bin/sh
2
2
3 mkdir test
3 mkdir test
4 cd test
4 cd test
5 hg init
5 hg init
6 for i in 0 1 2 3 4 5 6 7 8; do
6 for i in 0 1 2 3 4 5 6 7 8; do
7 echo $i >> foo
7 echo $i >> foo
8 hg commit -A -m $i -d "1000000 0"
8 hg commit -A -m $i -d "1000000 0"
9 done
9 done
10 hg verify
10 hg verify
11 hg serve -p 20059 -d --pid-file=hg.pid
11 hg serve -p 20059 -d --pid-file=hg.pid
12 cd ..
12 cd ..
13
13
14 hg init new
14 hg init new
15 # http incoming
15 # http incoming
16 http_proxy= hg -R new incoming http://localhost:20059/
16 http_proxy= hg -R new incoming http://localhost:20059/
17 http_proxy= hg -R new incoming -r 4 http://localhost:20059/
17 # local incoming
18 # local incoming
18 hg -R new incoming test
19 hg -R new incoming test
20 hg -R new incoming -r 4 test
19
21
20 # test with --bundle
22 # test with --bundle
21 http_proxy= hg -R new incoming --bundle test.hg http://localhost:20059/
23 http_proxy= hg -R new incoming --bundle test.hg http://localhost:20059/
22 hg -R new incoming --bundle test2.hg test
24 hg -R new incoming --bundle test2.hg test
23
25
24 # test the resulting bundles
26 # test the resulting bundles
25 hg init temp
27 hg init temp
26 hg init temp2
28 hg init temp2
27 hg -R temp unbundle test.hg
29 hg -R temp unbundle test.hg
28 hg -R temp2 unbundle test2.hg
30 hg -R temp2 unbundle test2.hg
29 hg -R temp tip
31 hg -R temp tip
30 hg -R temp2 tip
32 hg -R temp2 tip
31
33
32 rm -rf temp temp2 new
34 rm -rf temp temp2 new
33
35
34 # test outgoing
36 # test outgoing
35 hg clone test test-dev
37 hg clone test test-dev
36 cd test-dev
38 cd test-dev
37 for i in 9 10 11 12 13; do
39 for i in 9 10 11 12 13; do
38 echo $i >> foo
40 echo $i >> foo
39 hg commit -A -m $i -d "1000000 0"
41 hg commit -A -m $i -d "1000000 0"
40 done
42 done
41 hg verify
43 hg verify
42 cd ..
44 cd ..
43 hg -R test-dev outgoing test
45 hg -R test-dev outgoing test
44 http_proxy= hg -R test-dev outgoing http://localhost:20059/
46 http_proxy= hg -R test-dev outgoing http://localhost:20059/
47 http_proxy= hg -R test-dev outgoing -r 11 http://localhost:20059/
45
48
46 kill `cat test/hg.pid`
49 kill `cat test/hg.pid`
@@ -1,272 +1,338 b''
1 adding foo
1 adding foo
2 checking changesets
2 checking changesets
3 checking manifests
3 checking manifests
4 crosschecking files in changesets and manifests
4 crosschecking files in changesets and manifests
5 checking files
5 checking files
6 1 files, 9 changesets, 9 total revisions
6 1 files, 9 changesets, 9 total revisions
7 changeset: 0:9cb21d99fe27
7 changeset: 0:9cb21d99fe27
8 user: test
8 user: test
9 date: Mon Jan 12 13:46:40 1970 +0000
9 date: Mon Jan 12 13:46:40 1970 +0000
10 summary: 0
10 summary: 0
11
11
12 changeset: 1:d717f5dfad6a
12 changeset: 1:d717f5dfad6a
13 user: test
13 user: test
14 date: Mon Jan 12 13:46:40 1970 +0000
14 date: Mon Jan 12 13:46:40 1970 +0000
15 summary: 1
15 summary: 1
16
16
17 changeset: 2:c0d6b86da426
17 changeset: 2:c0d6b86da426
18 user: test
18 user: test
19 date: Mon Jan 12 13:46:40 1970 +0000
19 date: Mon Jan 12 13:46:40 1970 +0000
20 summary: 2
20 summary: 2
21
21
22 changeset: 3:dfacbd43b3fe
22 changeset: 3:dfacbd43b3fe
23 user: test
23 user: test
24 date: Mon Jan 12 13:46:40 1970 +0000
24 date: Mon Jan 12 13:46:40 1970 +0000
25 summary: 3
25 summary: 3
26
26
27 changeset: 4:1f3a964b6022
27 changeset: 4:1f3a964b6022
28 user: test
28 user: test
29 date: Mon Jan 12 13:46:40 1970 +0000
29 date: Mon Jan 12 13:46:40 1970 +0000
30 summary: 4
30 summary: 4
31
31
32 changeset: 5:c028bcc7a28a
32 changeset: 5:c028bcc7a28a
33 user: test
33 user: test
34 date: Mon Jan 12 13:46:40 1970 +0000
34 date: Mon Jan 12 13:46:40 1970 +0000
35 summary: 5
35 summary: 5
36
36
37 changeset: 6:a0c0095f3389
37 changeset: 6:a0c0095f3389
38 user: test
38 user: test
39 date: Mon Jan 12 13:46:40 1970 +0000
39 date: Mon Jan 12 13:46:40 1970 +0000
40 summary: 6
40 summary: 6
41
41
42 changeset: 7:d4be65f4e891
42 changeset: 7:d4be65f4e891
43 user: test
43 user: test
44 date: Mon Jan 12 13:46:40 1970 +0000
44 date: Mon Jan 12 13:46:40 1970 +0000
45 summary: 7
45 summary: 7
46
46
47 changeset: 8:92b83e334ef8
47 changeset: 8:92b83e334ef8
48 tag: tip
48 tag: tip
49 user: test
49 user: test
50 date: Mon Jan 12 13:46:40 1970 +0000
50 date: Mon Jan 12 13:46:40 1970 +0000
51 summary: 8
51 summary: 8
52
52
53 changeset: 0:9cb21d99fe27
53 changeset: 0:9cb21d99fe27
54 user: test
54 user: test
55 date: Mon Jan 12 13:46:40 1970 +0000
55 date: Mon Jan 12 13:46:40 1970 +0000
56 summary: 0
56 summary: 0
57
57
58 changeset: 1:d717f5dfad6a
58 changeset: 1:d717f5dfad6a
59 user: test
59 user: test
60 date: Mon Jan 12 13:46:40 1970 +0000
60 date: Mon Jan 12 13:46:40 1970 +0000
61 summary: 1
61 summary: 1
62
62
63 changeset: 2:c0d6b86da426
63 changeset: 2:c0d6b86da426
64 user: test
64 user: test
65 date: Mon Jan 12 13:46:40 1970 +0000
65 date: Mon Jan 12 13:46:40 1970 +0000
66 summary: 2
66 summary: 2
67
67
68 changeset: 3:dfacbd43b3fe
68 changeset: 3:dfacbd43b3fe
69 user: test
69 user: test
70 date: Mon Jan 12 13:46:40 1970 +0000
70 date: Mon Jan 12 13:46:40 1970 +0000
71 summary: 3
71 summary: 3
72
72
73 changeset: 4:1f3a964b6022
73 changeset: 4:1f3a964b6022
74 user: test
74 user: test
75 date: Mon Jan 12 13:46:40 1970 +0000
75 date: Mon Jan 12 13:46:40 1970 +0000
76 summary: 4
76 summary: 4
77
77
78 changeset: 0:9cb21d99fe27
79 user: test
80 date: Mon Jan 12 13:46:40 1970 +0000
81 summary: 0
82
83 changeset: 1:d717f5dfad6a
84 user: test
85 date: Mon Jan 12 13:46:40 1970 +0000
86 summary: 1
87
88 changeset: 2:c0d6b86da426
89 user: test
90 date: Mon Jan 12 13:46:40 1970 +0000
91 summary: 2
92
93 changeset: 3:dfacbd43b3fe
94 user: test
95 date: Mon Jan 12 13:46:40 1970 +0000
96 summary: 3
97
98 changeset: 4:1f3a964b6022
99 user: test
100 date: Mon Jan 12 13:46:40 1970 +0000
101 summary: 4
102
78 changeset: 5:c028bcc7a28a
103 changeset: 5:c028bcc7a28a
79 user: test
104 user: test
80 date: Mon Jan 12 13:46:40 1970 +0000
105 date: Mon Jan 12 13:46:40 1970 +0000
81 summary: 5
106 summary: 5
82
107
83 changeset: 6:a0c0095f3389
108 changeset: 6:a0c0095f3389
84 user: test
109 user: test
85 date: Mon Jan 12 13:46:40 1970 +0000
110 date: Mon Jan 12 13:46:40 1970 +0000
86 summary: 6
111 summary: 6
87
112
88 changeset: 7:d4be65f4e891
113 changeset: 7:d4be65f4e891
89 user: test
114 user: test
90 date: Mon Jan 12 13:46:40 1970 +0000
115 date: Mon Jan 12 13:46:40 1970 +0000
91 summary: 7
116 summary: 7
92
117
93 changeset: 8:92b83e334ef8
118 changeset: 8:92b83e334ef8
94 tag: tip
119 tag: tip
95 user: test
120 user: test
96 date: Mon Jan 12 13:46:40 1970 +0000
121 date: Mon Jan 12 13:46:40 1970 +0000
97 summary: 8
122 summary: 8
98
123
99 changeset: 0:9cb21d99fe27
124 changeset: 0:9cb21d99fe27
100 user: test
125 user: test
101 date: Mon Jan 12 13:46:40 1970 +0000
126 date: Mon Jan 12 13:46:40 1970 +0000
102 summary: 0
127 summary: 0
103
128
104 changeset: 1:d717f5dfad6a
129 changeset: 1:d717f5dfad6a
105 user: test
130 user: test
106 date: Mon Jan 12 13:46:40 1970 +0000
131 date: Mon Jan 12 13:46:40 1970 +0000
107 summary: 1
132 summary: 1
108
133
109 changeset: 2:c0d6b86da426
134 changeset: 2:c0d6b86da426
110 user: test
135 user: test
111 date: Mon Jan 12 13:46:40 1970 +0000
136 date: Mon Jan 12 13:46:40 1970 +0000
112 summary: 2
137 summary: 2
113
138
114 changeset: 3:dfacbd43b3fe
139 changeset: 3:dfacbd43b3fe
115 user: test
140 user: test
116 date: Mon Jan 12 13:46:40 1970 +0000
141 date: Mon Jan 12 13:46:40 1970 +0000
117 summary: 3
142 summary: 3
118
143
119 changeset: 4:1f3a964b6022
144 changeset: 4:1f3a964b6022
120 user: test
145 user: test
121 date: Mon Jan 12 13:46:40 1970 +0000
146 date: Mon Jan 12 13:46:40 1970 +0000
122 summary: 4
147 summary: 4
123
148
149 changeset: 0:9cb21d99fe27
150 user: test
151 date: Mon Jan 12 13:46:40 1970 +0000
152 summary: 0
153
154 changeset: 1:d717f5dfad6a
155 user: test
156 date: Mon Jan 12 13:46:40 1970 +0000
157 summary: 1
158
159 changeset: 2:c0d6b86da426
160 user: test
161 date: Mon Jan 12 13:46:40 1970 +0000
162 summary: 2
163
164 changeset: 3:dfacbd43b3fe
165 user: test
166 date: Mon Jan 12 13:46:40 1970 +0000
167 summary: 3
168
169 changeset: 4:1f3a964b6022
170 user: test
171 date: Mon Jan 12 13:46:40 1970 +0000
172 summary: 4
173
124 changeset: 5:c028bcc7a28a
174 changeset: 5:c028bcc7a28a
125 user: test
175 user: test
126 date: Mon Jan 12 13:46:40 1970 +0000
176 date: Mon Jan 12 13:46:40 1970 +0000
127 summary: 5
177 summary: 5
128
178
129 changeset: 6:a0c0095f3389
179 changeset: 6:a0c0095f3389
130 user: test
180 user: test
131 date: Mon Jan 12 13:46:40 1970 +0000
181 date: Mon Jan 12 13:46:40 1970 +0000
132 summary: 6
182 summary: 6
133
183
134 changeset: 7:d4be65f4e891
184 changeset: 7:d4be65f4e891
135 user: test
185 user: test
136 date: Mon Jan 12 13:46:40 1970 +0000
186 date: Mon Jan 12 13:46:40 1970 +0000
137 summary: 7
187 summary: 7
138
188
139 changeset: 8:92b83e334ef8
189 changeset: 8:92b83e334ef8
140 tag: tip
190 tag: tip
141 user: test
191 user: test
142 date: Mon Jan 12 13:46:40 1970 +0000
192 date: Mon Jan 12 13:46:40 1970 +0000
143 summary: 8
193 summary: 8
144
194
145 changeset: 0:9cb21d99fe27
195 changeset: 0:9cb21d99fe27
146 user: test
196 user: test
147 date: Mon Jan 12 13:46:40 1970 +0000
197 date: Mon Jan 12 13:46:40 1970 +0000
148 summary: 0
198 summary: 0
149
199
150 changeset: 1:d717f5dfad6a
200 changeset: 1:d717f5dfad6a
151 user: test
201 user: test
152 date: Mon Jan 12 13:46:40 1970 +0000
202 date: Mon Jan 12 13:46:40 1970 +0000
153 summary: 1
203 summary: 1
154
204
155 changeset: 2:c0d6b86da426
205 changeset: 2:c0d6b86da426
156 user: test
206 user: test
157 date: Mon Jan 12 13:46:40 1970 +0000
207 date: Mon Jan 12 13:46:40 1970 +0000
158 summary: 2
208 summary: 2
159
209
160 changeset: 3:dfacbd43b3fe
210 changeset: 3:dfacbd43b3fe
161 user: test
211 user: test
162 date: Mon Jan 12 13:46:40 1970 +0000
212 date: Mon Jan 12 13:46:40 1970 +0000
163 summary: 3
213 summary: 3
164
214
165 changeset: 4:1f3a964b6022
215 changeset: 4:1f3a964b6022
166 user: test
216 user: test
167 date: Mon Jan 12 13:46:40 1970 +0000
217 date: Mon Jan 12 13:46:40 1970 +0000
168 summary: 4
218 summary: 4
169
219
170 changeset: 5:c028bcc7a28a
220 changeset: 5:c028bcc7a28a
171 user: test
221 user: test
172 date: Mon Jan 12 13:46:40 1970 +0000
222 date: Mon Jan 12 13:46:40 1970 +0000
173 summary: 5
223 summary: 5
174
224
175 changeset: 6:a0c0095f3389
225 changeset: 6:a0c0095f3389
176 user: test
226 user: test
177 date: Mon Jan 12 13:46:40 1970 +0000
227 date: Mon Jan 12 13:46:40 1970 +0000
178 summary: 6
228 summary: 6
179
229
180 changeset: 7:d4be65f4e891
230 changeset: 7:d4be65f4e891
181 user: test
231 user: test
182 date: Mon Jan 12 13:46:40 1970 +0000
232 date: Mon Jan 12 13:46:40 1970 +0000
183 summary: 7
233 summary: 7
184
234
185 changeset: 8:92b83e334ef8
235 changeset: 8:92b83e334ef8
186 tag: tip
236 tag: tip
187 user: test
237 user: test
188 date: Mon Jan 12 13:46:40 1970 +0000
238 date: Mon Jan 12 13:46:40 1970 +0000
189 summary: 8
239 summary: 8
190
240
191 adding changesets
241 adding changesets
192 adding manifests
242 adding manifests
193 adding file changes
243 adding file changes
194 added 9 changesets with 9 changes to 1 files
244 added 9 changesets with 9 changes to 1 files
195 (run 'hg update' to get a working copy)
245 (run 'hg update' to get a working copy)
196 adding changesets
246 adding changesets
197 adding manifests
247 adding manifests
198 adding file changes
248 adding file changes
199 added 9 changesets with 9 changes to 1 files
249 added 9 changesets with 9 changes to 1 files
200 (run 'hg update' to get a working copy)
250 (run 'hg update' to get a working copy)
201 changeset: 8:92b83e334ef8
251 changeset: 8:92b83e334ef8
202 tag: tip
252 tag: tip
203 user: test
253 user: test
204 date: Mon Jan 12 13:46:40 1970 +0000
254 date: Mon Jan 12 13:46:40 1970 +0000
205 summary: 8
255 summary: 8
206
256
207 changeset: 8:92b83e334ef8
257 changeset: 8:92b83e334ef8
208 tag: tip
258 tag: tip
209 user: test
259 user: test
210 date: Mon Jan 12 13:46:40 1970 +0000
260 date: Mon Jan 12 13:46:40 1970 +0000
211 summary: 8
261 summary: 8
212
262
213 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
263 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
214 checking changesets
264 checking changesets
215 checking manifests
265 checking manifests
216 crosschecking files in changesets and manifests
266 crosschecking files in changesets and manifests
217 checking files
267 checking files
218 1 files, 14 changesets, 14 total revisions
268 1 files, 14 changesets, 14 total revisions
219 searching for changes
269 searching for changes
220 changeset: 9:3741c3ad1096
270 changeset: 9:3741c3ad1096
221 user: test
271 user: test
222 date: Mon Jan 12 13:46:40 1970 +0000
272 date: Mon Jan 12 13:46:40 1970 +0000
223 summary: 9
273 summary: 9
224
274
225 changeset: 10:de4143c8d9a5
275 changeset: 10:de4143c8d9a5
226 user: test
276 user: test
227 date: Mon Jan 12 13:46:40 1970 +0000
277 date: Mon Jan 12 13:46:40 1970 +0000
228 summary: 10
278 summary: 10
229
279
230 changeset: 11:0e1c188b9a7a
280 changeset: 11:0e1c188b9a7a
231 user: test
281 user: test
232 date: Mon Jan 12 13:46:40 1970 +0000
282 date: Mon Jan 12 13:46:40 1970 +0000
233 summary: 11
283 summary: 11
234
284
235 changeset: 12:251354d0fdd3
285 changeset: 12:251354d0fdd3
236 user: test
286 user: test
237 date: Mon Jan 12 13:46:40 1970 +0000
287 date: Mon Jan 12 13:46:40 1970 +0000
238 summary: 12
288 summary: 12
239
289
240 changeset: 13:bdaadd969642
290 changeset: 13:bdaadd969642
241 tag: tip
291 tag: tip
242 user: test
292 user: test
243 date: Mon Jan 12 13:46:40 1970 +0000
293 date: Mon Jan 12 13:46:40 1970 +0000
244 summary: 13
294 summary: 13
245
295
246 searching for changes
296 searching for changes
247 changeset: 9:3741c3ad1096
297 changeset: 9:3741c3ad1096
248 user: test
298 user: test
249 date: Mon Jan 12 13:46:40 1970 +0000
299 date: Mon Jan 12 13:46:40 1970 +0000
250 summary: 9
300 summary: 9
251
301
252 changeset: 10:de4143c8d9a5
302 changeset: 10:de4143c8d9a5
253 user: test
303 user: test
254 date: Mon Jan 12 13:46:40 1970 +0000
304 date: Mon Jan 12 13:46:40 1970 +0000
255 summary: 10
305 summary: 10
256
306
257 changeset: 11:0e1c188b9a7a
307 changeset: 11:0e1c188b9a7a
258 user: test
308 user: test
259 date: Mon Jan 12 13:46:40 1970 +0000
309 date: Mon Jan 12 13:46:40 1970 +0000
260 summary: 11
310 summary: 11
261
311
262 changeset: 12:251354d0fdd3
312 changeset: 12:251354d0fdd3
263 user: test
313 user: test
264 date: Mon Jan 12 13:46:40 1970 +0000
314 date: Mon Jan 12 13:46:40 1970 +0000
265 summary: 12
315 summary: 12
266
316
267 changeset: 13:bdaadd969642
317 changeset: 13:bdaadd969642
268 tag: tip
318 tag: tip
269 user: test
319 user: test
270 date: Mon Jan 12 13:46:40 1970 +0000
320 date: Mon Jan 12 13:46:40 1970 +0000
271 summary: 13
321 summary: 13
272
322
323 searching for changes
324 changeset: 9:3741c3ad1096
325 user: test
326 date: Mon Jan 12 13:46:40 1970 +0000
327 summary: 9
328
329 changeset: 10:de4143c8d9a5
330 user: test
331 date: Mon Jan 12 13:46:40 1970 +0000
332 summary: 10
333
334 changeset: 11:0e1c188b9a7a
335 user: test
336 date: Mon Jan 12 13:46:40 1970 +0000
337 summary: 11
338
General Comments 0
You need to be logged in to leave comments. Login now