##// END OF EJS Templates
bookmarks: make track.current=True default behaviour and remove option (BC)
David Soria Parra -
r13416:5431b3f3 default
parent child Browse files
Show More
@@ -1,166 +1,160 b''
1 # Mercurial bookmark support code
1 # Mercurial bookmark support code
2 #
2 #
3 # Copyright 2008 David Soria Parra <dsp@php.net>
3 # Copyright 2008 David Soria Parra <dsp@php.net>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from mercurial.i18n import _
8 from mercurial.i18n import _
9 from mercurial.node import nullid, nullrev, bin, hex, short
9 from mercurial.node import nullid, nullrev, bin, hex, short
10 from mercurial import encoding
10 from mercurial import encoding
11 import os
11 import os
12
12
13 def read(repo):
13 def read(repo):
14 '''Parse .hg/bookmarks file and return a dictionary
14 '''Parse .hg/bookmarks file and return a dictionary
15
15
16 Bookmarks are stored as {HASH}\\s{NAME}\\n (localtags format) values
16 Bookmarks are stored as {HASH}\\s{NAME}\\n (localtags format) values
17 in the .hg/bookmarks file.
17 in the .hg/bookmarks file.
18 Read the file and return a (name=>nodeid) dictionary
18 Read the file and return a (name=>nodeid) dictionary
19 '''
19 '''
20 try:
20 try:
21 bookmarks = {}
21 bookmarks = {}
22 for line in repo.opener('bookmarks'):
22 for line in repo.opener('bookmarks'):
23 sha, refspec = line.strip().split(' ', 1)
23 sha, refspec = line.strip().split(' ', 1)
24 refspec = encoding.tolocal(refspec)
24 refspec = encoding.tolocal(refspec)
25 bookmarks[refspec] = repo.changelog.lookup(sha)
25 bookmarks[refspec] = repo.changelog.lookup(sha)
26 except:
26 except:
27 pass
27 pass
28 return bookmarks
28 return bookmarks
29
29
30 def readcurrent(repo):
30 def readcurrent(repo):
31 '''Get the current bookmark
31 '''Get the current bookmark
32
32
33 If we use gittishsh branches we have a current bookmark that
33 If we use gittishsh branches we have a current bookmark that
34 we are on. This function returns the name of the bookmark. It
34 we are on. This function returns the name of the bookmark. It
35 is stored in .hg/bookmarks.current
35 is stored in .hg/bookmarks.current
36 '''
36 '''
37 mark = None
37 mark = None
38 if os.path.exists(repo.join('bookmarks.current')):
38 if os.path.exists(repo.join('bookmarks.current')):
39 file = repo.opener('bookmarks.current')
39 file = repo.opener('bookmarks.current')
40 # No readline() in posixfile_nt, reading everything is cheap
40 # No readline() in posixfile_nt, reading everything is cheap
41 mark = encoding.tolocal((file.readlines() or [''])[0])
41 mark = encoding.tolocal((file.readlines() or [''])[0])
42 if mark == '':
42 if mark == '':
43 mark = None
43 mark = None
44 file.close()
44 file.close()
45 return mark
45 return mark
46
46
47 def write(repo):
47 def write(repo):
48 '''Write bookmarks
48 '''Write bookmarks
49
49
50 Write the given bookmark => hash dictionary to the .hg/bookmarks file
50 Write the given bookmark => hash dictionary to the .hg/bookmarks file
51 in a format equal to those of localtags.
51 in a format equal to those of localtags.
52
52
53 We also store a backup of the previous state in undo.bookmarks that
53 We also store a backup of the previous state in undo.bookmarks that
54 can be copied back on rollback.
54 can be copied back on rollback.
55 '''
55 '''
56 refs = repo._bookmarks
56 refs = repo._bookmarks
57
57
58 try:
58 try:
59 bms = repo.opener('bookmarks').read()
59 bms = repo.opener('bookmarks').read()
60 except IOError:
60 except IOError:
61 bms = ''
61 bms = ''
62 repo.opener('undo.bookmarks', 'w').write(bms)
62 repo.opener('undo.bookmarks', 'w').write(bms)
63
63
64 if repo._bookmarkcurrent not in refs:
64 if repo._bookmarkcurrent not in refs:
65 setcurrent(repo, None)
65 setcurrent(repo, None)
66 wlock = repo.wlock()
66 wlock = repo.wlock()
67 try:
67 try:
68 file = repo.opener('bookmarks', 'w', atomictemp=True)
68 file = repo.opener('bookmarks', 'w', atomictemp=True)
69 for refspec, node in refs.iteritems():
69 for refspec, node in refs.iteritems():
70 file.write("%s %s\n" % (hex(node), encoding.fromlocal(refspec)))
70 file.write("%s %s\n" % (hex(node), encoding.fromlocal(refspec)))
71 file.rename()
71 file.rename()
72
72
73 # touch 00changelog.i so hgweb reloads bookmarks (no lock needed)
73 # touch 00changelog.i so hgweb reloads bookmarks (no lock needed)
74 try:
74 try:
75 os.utime(repo.sjoin('00changelog.i'), None)
75 os.utime(repo.sjoin('00changelog.i'), None)
76 except OSError:
76 except OSError:
77 pass
77 pass
78
78
79 finally:
79 finally:
80 wlock.release()
80 wlock.release()
81
81
82 def setcurrent(repo, mark):
82 def setcurrent(repo, mark):
83 '''Set the name of the bookmark that we are currently on
83 '''Set the name of the bookmark that we are currently on
84
84
85 Set the name of the bookmark that we are on (hg update <bookmark>).
85 Set the name of the bookmark that we are on (hg update <bookmark>).
86 The name is recorded in .hg/bookmarks.current
86 The name is recorded in .hg/bookmarks.current
87 '''
87 '''
88 current = repo._bookmarkcurrent
88 current = repo._bookmarkcurrent
89 if current == mark:
89 if current == mark:
90 return
90 return
91
91
92 refs = repo._bookmarks
92 refs = repo._bookmarks
93
93
94 # do not update if we do update to a rev equal to the current bookmark
94 # do not update if we do update to a rev equal to the current bookmark
95 if (mark and mark not in refs and
95 if (mark and mark not in refs and
96 current and refs[current] == repo.changectx('.').node()):
96 current and refs[current] == repo.changectx('.').node()):
97 return
97 return
98 if mark not in refs:
98 if mark not in refs:
99 mark = ''
99 mark = ''
100 wlock = repo.wlock()
100 wlock = repo.wlock()
101 try:
101 try:
102 file = repo.opener('bookmarks.current', 'w', atomictemp=True)
102 file = repo.opener('bookmarks.current', 'w', atomictemp=True)
103 file.write(mark)
103 file.write(mark)
104 file.rename()
104 file.rename()
105 finally:
105 finally:
106 wlock.release()
106 wlock.release()
107 repo._bookmarkcurrent = mark
107 repo._bookmarkcurrent = mark
108
108
109 def update(repo, parents, node):
109 def update(repo, parents, node):
110 marks = repo._bookmarks
110 marks = repo._bookmarks
111 update = False
111 update = False
112 if repo.ui.configbool('bookmarks', 'track.current'):
112 mark = repo._bookmarkcurrent
113 mark = repo._bookmarkcurrent
113 if mark and marks[mark] in parents:
114 if mark and marks[mark] in parents:
114 marks[mark] = node
115 marks[mark] = node
115 update = True
116 update = True
117 else:
118 for mark, n in marks.items():
119 if n in parents:
120 marks[mark] = node
121 update = True
122 if update:
116 if update:
123 write(repo)
117 write(repo)
124
118
125 def listbookmarks(repo):
119 def listbookmarks(repo):
126 # We may try to list bookmarks on a repo type that does not
120 # We may try to list bookmarks on a repo type that does not
127 # support it (e.g., statichttprepository).
121 # support it (e.g., statichttprepository).
128 if not hasattr(repo, '_bookmarks'):
122 if not hasattr(repo, '_bookmarks'):
129 return {}
123 return {}
130
124
131 d = {}
125 d = {}
132 for k, v in repo._bookmarks.iteritems():
126 for k, v in repo._bookmarks.iteritems():
133 d[k] = hex(v)
127 d[k] = hex(v)
134 return d
128 return d
135
129
136 def pushbookmark(repo, key, old, new):
130 def pushbookmark(repo, key, old, new):
137 w = repo.wlock()
131 w = repo.wlock()
138 try:
132 try:
139 marks = repo._bookmarks
133 marks = repo._bookmarks
140 if hex(marks.get(key, '')) != old:
134 if hex(marks.get(key, '')) != old:
141 return False
135 return False
142 if new == '':
136 if new == '':
143 del marks[key]
137 del marks[key]
144 else:
138 else:
145 if new not in repo:
139 if new not in repo:
146 return False
140 return False
147 marks[key] = repo[new].node()
141 marks[key] = repo[new].node()
148 write(repo)
142 write(repo)
149 return True
143 return True
150 finally:
144 finally:
151 w.release()
145 w.release()
152
146
153 def diff(ui, repo, remote):
147 def diff(ui, repo, remote):
154 ui.status(_("searching for changed bookmarks\n"))
148 ui.status(_("searching for changed bookmarks\n"))
155
149
156 lmarks = repo.listkeys('bookmarks')
150 lmarks = repo.listkeys('bookmarks')
157 rmarks = remote.listkeys('bookmarks')
151 rmarks = remote.listkeys('bookmarks')
158
152
159 diff = sorted(set(rmarks) - set(lmarks))
153 diff = sorted(set(rmarks) - set(lmarks))
160 for k in diff:
154 for k in diff:
161 ui.write(" %-25s %s\n" % (k, rmarks[k][:12]))
155 ui.write(" %-25s %s\n" % (k, rmarks[k][:12]))
162
156
163 if len(diff) <= 0:
157 if len(diff) <= 0:
164 ui.status(_("no changed bookmarks found\n"))
158 ui.status(_("no changed bookmarks found\n"))
165 return 1
159 return 1
166 return 0
160 return 0
@@ -1,4727 +1,4721 b''
1 # commands.py - command processing for mercurial
1 # commands.py - command processing for mercurial
2 #
2 #
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005-2007 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 from node import hex, nullid, nullrev, short
8 from node import hex, nullid, nullrev, short
9 from lock import release
9 from lock import release
10 from i18n import _, gettext
10 from i18n import _, gettext
11 import os, re, sys, difflib, time, tempfile
11 import os, re, sys, difflib, time, tempfile
12 import hg, util, revlog, extensions, copies, error, bookmarks
12 import hg, util, revlog, extensions, copies, error, bookmarks
13 import patch, help, mdiff, url, encoding, templatekw, discovery
13 import patch, help, mdiff, url, encoding, templatekw, discovery
14 import archival, changegroup, cmdutil, sshserver, hbisect, hgweb, hgweb.server
14 import archival, changegroup, cmdutil, sshserver, hbisect, hgweb, hgweb.server
15 import merge as mergemod
15 import merge as mergemod
16 import minirst, revset
16 import minirst, revset
17 import dagparser
17 import dagparser
18
18
19 # Commands start here, listed alphabetically
19 # Commands start here, listed alphabetically
20
20
21 def add(ui, repo, *pats, **opts):
21 def add(ui, repo, *pats, **opts):
22 """add the specified files on the next commit
22 """add the specified files on the next commit
23
23
24 Schedule files to be version controlled and added to the
24 Schedule files to be version controlled and added to the
25 repository.
25 repository.
26
26
27 The files will be added to the repository at the next commit. To
27 The files will be added to the repository at the next commit. To
28 undo an add before that, see :hg:`forget`.
28 undo an add before that, see :hg:`forget`.
29
29
30 If no names are given, add all files to the repository.
30 If no names are given, add all files to the repository.
31
31
32 .. container:: verbose
32 .. container:: verbose
33
33
34 An example showing how new (unknown) files are added
34 An example showing how new (unknown) files are added
35 automatically by :hg:`add`::
35 automatically by :hg:`add`::
36
36
37 $ ls
37 $ ls
38 foo.c
38 foo.c
39 $ hg status
39 $ hg status
40 ? foo.c
40 ? foo.c
41 $ hg add
41 $ hg add
42 adding foo.c
42 adding foo.c
43 $ hg status
43 $ hg status
44 A foo.c
44 A foo.c
45
45
46 Returns 0 if all files are successfully added.
46 Returns 0 if all files are successfully added.
47 """
47 """
48
48
49 m = cmdutil.match(repo, pats, opts)
49 m = cmdutil.match(repo, pats, opts)
50 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
50 rejected = cmdutil.add(ui, repo, m, opts.get('dry_run'),
51 opts.get('subrepos'), prefix="")
51 opts.get('subrepos'), prefix="")
52 return rejected and 1 or 0
52 return rejected and 1 or 0
53
53
54 def addremove(ui, repo, *pats, **opts):
54 def addremove(ui, repo, *pats, **opts):
55 """add all new files, delete all missing files
55 """add all new files, delete all missing files
56
56
57 Add all new files and remove all missing files from the
57 Add all new files and remove all missing files from the
58 repository.
58 repository.
59
59
60 New files are ignored if they match any of the patterns in
60 New files are ignored if they match any of the patterns in
61 ``.hgignore``. As with add, these changes take effect at the next
61 ``.hgignore``. As with add, these changes take effect at the next
62 commit.
62 commit.
63
63
64 Use the -s/--similarity option to detect renamed files. With a
64 Use the -s/--similarity option to detect renamed files. With a
65 parameter greater than 0, this compares every removed file with
65 parameter greater than 0, this compares every removed file with
66 every added file and records those similar enough as renames. This
66 every added file and records those similar enough as renames. This
67 option takes a percentage between 0 (disabled) and 100 (files must
67 option takes a percentage between 0 (disabled) and 100 (files must
68 be identical) as its parameter. Detecting renamed files this way
68 be identical) as its parameter. Detecting renamed files this way
69 can be expensive. After using this option, :hg:`status -C` can be
69 can be expensive. After using this option, :hg:`status -C` can be
70 used to check which files were identified as moved or renamed.
70 used to check which files were identified as moved or renamed.
71
71
72 Returns 0 if all files are successfully added.
72 Returns 0 if all files are successfully added.
73 """
73 """
74 try:
74 try:
75 sim = float(opts.get('similarity') or 100)
75 sim = float(opts.get('similarity') or 100)
76 except ValueError:
76 except ValueError:
77 raise util.Abort(_('similarity must be a number'))
77 raise util.Abort(_('similarity must be a number'))
78 if sim < 0 or sim > 100:
78 if sim < 0 or sim > 100:
79 raise util.Abort(_('similarity must be between 0 and 100'))
79 raise util.Abort(_('similarity must be between 0 and 100'))
80 return cmdutil.addremove(repo, pats, opts, similarity=sim / 100.0)
80 return cmdutil.addremove(repo, pats, opts, similarity=sim / 100.0)
81
81
82 def annotate(ui, repo, *pats, **opts):
82 def annotate(ui, repo, *pats, **opts):
83 """show changeset information by line for each file
83 """show changeset information by line for each file
84
84
85 List changes in files, showing the revision id responsible for
85 List changes in files, showing the revision id responsible for
86 each line
86 each line
87
87
88 This command is useful for discovering when a change was made and
88 This command is useful for discovering when a change was made and
89 by whom.
89 by whom.
90
90
91 Without the -a/--text option, annotate will avoid processing files
91 Without the -a/--text option, annotate will avoid processing files
92 it detects as binary. With -a, annotate will annotate the file
92 it detects as binary. With -a, annotate will annotate the file
93 anyway, although the results will probably be neither useful
93 anyway, although the results will probably be neither useful
94 nor desirable.
94 nor desirable.
95
95
96 Returns 0 on success.
96 Returns 0 on success.
97 """
97 """
98 if opts.get('follow'):
98 if opts.get('follow'):
99 # --follow is deprecated and now just an alias for -f/--file
99 # --follow is deprecated and now just an alias for -f/--file
100 # to mimic the behavior of Mercurial before version 1.5
100 # to mimic the behavior of Mercurial before version 1.5
101 opts['file'] = 1
101 opts['file'] = 1
102
102
103 datefunc = ui.quiet and util.shortdate or util.datestr
103 datefunc = ui.quiet and util.shortdate or util.datestr
104 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
104 getdate = util.cachefunc(lambda x: datefunc(x[0].date()))
105
105
106 if not pats:
106 if not pats:
107 raise util.Abort(_('at least one filename or pattern is required'))
107 raise util.Abort(_('at least one filename or pattern is required'))
108
108
109 opmap = [('user', lambda x: ui.shortuser(x[0].user())),
109 opmap = [('user', lambda x: ui.shortuser(x[0].user())),
110 ('number', lambda x: str(x[0].rev())),
110 ('number', lambda x: str(x[0].rev())),
111 ('changeset', lambda x: short(x[0].node())),
111 ('changeset', lambda x: short(x[0].node())),
112 ('date', getdate),
112 ('date', getdate),
113 ('file', lambda x: x[0].path()),
113 ('file', lambda x: x[0].path()),
114 ]
114 ]
115
115
116 if (not opts.get('user') and not opts.get('changeset')
116 if (not opts.get('user') and not opts.get('changeset')
117 and not opts.get('date') and not opts.get('file')):
117 and not opts.get('date') and not opts.get('file')):
118 opts['number'] = 1
118 opts['number'] = 1
119
119
120 linenumber = opts.get('line_number') is not None
120 linenumber = opts.get('line_number') is not None
121 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
121 if linenumber and (not opts.get('changeset')) and (not opts.get('number')):
122 raise util.Abort(_('at least one of -n/-c is required for -l'))
122 raise util.Abort(_('at least one of -n/-c is required for -l'))
123
123
124 funcmap = [func for op, func in opmap if opts.get(op)]
124 funcmap = [func for op, func in opmap if opts.get(op)]
125 if linenumber:
125 if linenumber:
126 lastfunc = funcmap[-1]
126 lastfunc = funcmap[-1]
127 funcmap[-1] = lambda x: "%s:%s" % (lastfunc(x), x[1])
127 funcmap[-1] = lambda x: "%s:%s" % (lastfunc(x), x[1])
128
128
129 ctx = cmdutil.revsingle(repo, opts.get('rev'))
129 ctx = cmdutil.revsingle(repo, opts.get('rev'))
130 m = cmdutil.match(repo, pats, opts)
130 m = cmdutil.match(repo, pats, opts)
131 follow = not opts.get('no_follow')
131 follow = not opts.get('no_follow')
132 for abs in ctx.walk(m):
132 for abs in ctx.walk(m):
133 fctx = ctx[abs]
133 fctx = ctx[abs]
134 if not opts.get('text') and util.binary(fctx.data()):
134 if not opts.get('text') and util.binary(fctx.data()):
135 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
135 ui.write(_("%s: binary file\n") % ((pats and m.rel(abs)) or abs))
136 continue
136 continue
137
137
138 lines = fctx.annotate(follow=follow, linenumber=linenumber)
138 lines = fctx.annotate(follow=follow, linenumber=linenumber)
139 pieces = []
139 pieces = []
140
140
141 for f in funcmap:
141 for f in funcmap:
142 l = [f(n) for n, dummy in lines]
142 l = [f(n) for n, dummy in lines]
143 if l:
143 if l:
144 sized = [(x, encoding.colwidth(x)) for x in l]
144 sized = [(x, encoding.colwidth(x)) for x in l]
145 ml = max([w for x, w in sized])
145 ml = max([w for x, w in sized])
146 pieces.append(["%s%s" % (' ' * (ml - w), x) for x, w in sized])
146 pieces.append(["%s%s" % (' ' * (ml - w), x) for x, w in sized])
147
147
148 if pieces:
148 if pieces:
149 for p, l in zip(zip(*pieces), lines):
149 for p, l in zip(zip(*pieces), lines):
150 ui.write("%s: %s" % (" ".join(p), l[1]))
150 ui.write("%s: %s" % (" ".join(p), l[1]))
151
151
152 def archive(ui, repo, dest, **opts):
152 def archive(ui, repo, dest, **opts):
153 '''create an unversioned archive of a repository revision
153 '''create an unversioned archive of a repository revision
154
154
155 By default, the revision used is the parent of the working
155 By default, the revision used is the parent of the working
156 directory; use -r/--rev to specify a different revision.
156 directory; use -r/--rev to specify a different revision.
157
157
158 The archive type is automatically detected based on file
158 The archive type is automatically detected based on file
159 extension (or override using -t/--type).
159 extension (or override using -t/--type).
160
160
161 Valid types are:
161 Valid types are:
162
162
163 :``files``: a directory full of files (default)
163 :``files``: a directory full of files (default)
164 :``tar``: tar archive, uncompressed
164 :``tar``: tar archive, uncompressed
165 :``tbz2``: tar archive, compressed using bzip2
165 :``tbz2``: tar archive, compressed using bzip2
166 :``tgz``: tar archive, compressed using gzip
166 :``tgz``: tar archive, compressed using gzip
167 :``uzip``: zip archive, uncompressed
167 :``uzip``: zip archive, uncompressed
168 :``zip``: zip archive, compressed using deflate
168 :``zip``: zip archive, compressed using deflate
169
169
170 The exact name of the destination archive or directory is given
170 The exact name of the destination archive or directory is given
171 using a format string; see :hg:`help export` for details.
171 using a format string; see :hg:`help export` for details.
172
172
173 Each member added to an archive file has a directory prefix
173 Each member added to an archive file has a directory prefix
174 prepended. Use -p/--prefix to specify a format string for the
174 prepended. Use -p/--prefix to specify a format string for the
175 prefix. The default is the basename of the archive, with suffixes
175 prefix. The default is the basename of the archive, with suffixes
176 removed.
176 removed.
177
177
178 Returns 0 on success.
178 Returns 0 on success.
179 '''
179 '''
180
180
181 ctx = cmdutil.revsingle(repo, opts.get('rev'))
181 ctx = cmdutil.revsingle(repo, opts.get('rev'))
182 if not ctx:
182 if not ctx:
183 raise util.Abort(_('no working directory: please specify a revision'))
183 raise util.Abort(_('no working directory: please specify a revision'))
184 node = ctx.node()
184 node = ctx.node()
185 dest = cmdutil.make_filename(repo, dest, node)
185 dest = cmdutil.make_filename(repo, dest, node)
186 if os.path.realpath(dest) == repo.root:
186 if os.path.realpath(dest) == repo.root:
187 raise util.Abort(_('repository root cannot be destination'))
187 raise util.Abort(_('repository root cannot be destination'))
188
188
189 kind = opts.get('type') or archival.guesskind(dest) or 'files'
189 kind = opts.get('type') or archival.guesskind(dest) or 'files'
190 prefix = opts.get('prefix')
190 prefix = opts.get('prefix')
191
191
192 if dest == '-':
192 if dest == '-':
193 if kind == 'files':
193 if kind == 'files':
194 raise util.Abort(_('cannot archive plain files to stdout'))
194 raise util.Abort(_('cannot archive plain files to stdout'))
195 dest = sys.stdout
195 dest = sys.stdout
196 if not prefix:
196 if not prefix:
197 prefix = os.path.basename(repo.root) + '-%h'
197 prefix = os.path.basename(repo.root) + '-%h'
198
198
199 prefix = cmdutil.make_filename(repo, prefix, node)
199 prefix = cmdutil.make_filename(repo, prefix, node)
200 matchfn = cmdutil.match(repo, [], opts)
200 matchfn = cmdutil.match(repo, [], opts)
201 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
201 archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
202 matchfn, prefix, subrepos=opts.get('subrepos'))
202 matchfn, prefix, subrepos=opts.get('subrepos'))
203
203
204 def backout(ui, repo, node=None, rev=None, **opts):
204 def backout(ui, repo, node=None, rev=None, **opts):
205 '''reverse effect of earlier changeset
205 '''reverse effect of earlier changeset
206
206
207 Prepare a new changeset with the effect of REV undone in the
207 Prepare a new changeset with the effect of REV undone in the
208 current working directory.
208 current working directory.
209
209
210 If REV is the parent of the working directory, then this changeset
210 If REV is the parent of the working directory, then this changeset
211 is committed automatically. Otherwise, hg needs to merge the
211 is committed automatically. Otherwise, hg needs to merge the
212 changes and the merged result is left uncommitted.
212 changes and the merged result is left uncommitted.
213
213
214 By default, the pending changeset will have one parent,
214 By default, the pending changeset will have one parent,
215 maintaining a linear history. With --merge, the pending changeset
215 maintaining a linear history. With --merge, the pending changeset
216 will instead have two parents: the old parent of the working
216 will instead have two parents: the old parent of the working
217 directory and a child of REV that simply undoes REV.
217 directory and a child of REV that simply undoes REV.
218
218
219 Before version 1.7, the default behavior was equivalent to
219 Before version 1.7, the default behavior was equivalent to
220 specifying --merge followed by :hg:`update --clean .` to cancel
220 specifying --merge followed by :hg:`update --clean .` to cancel
221 the merge and leave the child of REV as a head to be merged
221 the merge and leave the child of REV as a head to be merged
222 separately.
222 separately.
223
223
224 See :hg:`help dates` for a list of formats valid for -d/--date.
224 See :hg:`help dates` for a list of formats valid for -d/--date.
225
225
226 Returns 0 on success.
226 Returns 0 on success.
227 '''
227 '''
228 if rev and node:
228 if rev and node:
229 raise util.Abort(_("please specify just one revision"))
229 raise util.Abort(_("please specify just one revision"))
230
230
231 if not rev:
231 if not rev:
232 rev = node
232 rev = node
233
233
234 if not rev:
234 if not rev:
235 raise util.Abort(_("please specify a revision to backout"))
235 raise util.Abort(_("please specify a revision to backout"))
236
236
237 date = opts.get('date')
237 date = opts.get('date')
238 if date:
238 if date:
239 opts['date'] = util.parsedate(date)
239 opts['date'] = util.parsedate(date)
240
240
241 cmdutil.bail_if_changed(repo)
241 cmdutil.bail_if_changed(repo)
242 node = cmdutil.revsingle(repo, rev).node()
242 node = cmdutil.revsingle(repo, rev).node()
243
243
244 op1, op2 = repo.dirstate.parents()
244 op1, op2 = repo.dirstate.parents()
245 a = repo.changelog.ancestor(op1, node)
245 a = repo.changelog.ancestor(op1, node)
246 if a != node:
246 if a != node:
247 raise util.Abort(_('cannot backout change on a different branch'))
247 raise util.Abort(_('cannot backout change on a different branch'))
248
248
249 p1, p2 = repo.changelog.parents(node)
249 p1, p2 = repo.changelog.parents(node)
250 if p1 == nullid:
250 if p1 == nullid:
251 raise util.Abort(_('cannot backout a change with no parents'))
251 raise util.Abort(_('cannot backout a change with no parents'))
252 if p2 != nullid:
252 if p2 != nullid:
253 if not opts.get('parent'):
253 if not opts.get('parent'):
254 raise util.Abort(_('cannot backout a merge changeset without '
254 raise util.Abort(_('cannot backout a merge changeset without '
255 '--parent'))
255 '--parent'))
256 p = repo.lookup(opts['parent'])
256 p = repo.lookup(opts['parent'])
257 if p not in (p1, p2):
257 if p not in (p1, p2):
258 raise util.Abort(_('%s is not a parent of %s') %
258 raise util.Abort(_('%s is not a parent of %s') %
259 (short(p), short(node)))
259 (short(p), short(node)))
260 parent = p
260 parent = p
261 else:
261 else:
262 if opts.get('parent'):
262 if opts.get('parent'):
263 raise util.Abort(_('cannot use --parent on non-merge changeset'))
263 raise util.Abort(_('cannot use --parent on non-merge changeset'))
264 parent = p1
264 parent = p1
265
265
266 # the backout should appear on the same branch
266 # the backout should appear on the same branch
267 branch = repo.dirstate.branch()
267 branch = repo.dirstate.branch()
268 hg.clean(repo, node, show_stats=False)
268 hg.clean(repo, node, show_stats=False)
269 repo.dirstate.setbranch(branch)
269 repo.dirstate.setbranch(branch)
270 revert_opts = opts.copy()
270 revert_opts = opts.copy()
271 revert_opts['date'] = None
271 revert_opts['date'] = None
272 revert_opts['all'] = True
272 revert_opts['all'] = True
273 revert_opts['rev'] = hex(parent)
273 revert_opts['rev'] = hex(parent)
274 revert_opts['no_backup'] = None
274 revert_opts['no_backup'] = None
275 revert(ui, repo, **revert_opts)
275 revert(ui, repo, **revert_opts)
276 if not opts.get('merge') and op1 != node:
276 if not opts.get('merge') and op1 != node:
277 try:
277 try:
278 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
278 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
279 return hg.update(repo, op1)
279 return hg.update(repo, op1)
280 finally:
280 finally:
281 ui.setconfig('ui', 'forcemerge', '')
281 ui.setconfig('ui', 'forcemerge', '')
282
282
283 commit_opts = opts.copy()
283 commit_opts = opts.copy()
284 commit_opts['addremove'] = False
284 commit_opts['addremove'] = False
285 if not commit_opts['message'] and not commit_opts['logfile']:
285 if not commit_opts['message'] and not commit_opts['logfile']:
286 # we don't translate commit messages
286 # we don't translate commit messages
287 commit_opts['message'] = "Backed out changeset %s" % short(node)
287 commit_opts['message'] = "Backed out changeset %s" % short(node)
288 commit_opts['force_editor'] = True
288 commit_opts['force_editor'] = True
289 commit(ui, repo, **commit_opts)
289 commit(ui, repo, **commit_opts)
290 def nice(node):
290 def nice(node):
291 return '%d:%s' % (repo.changelog.rev(node), short(node))
291 return '%d:%s' % (repo.changelog.rev(node), short(node))
292 ui.status(_('changeset %s backs out changeset %s\n') %
292 ui.status(_('changeset %s backs out changeset %s\n') %
293 (nice(repo.changelog.tip()), nice(node)))
293 (nice(repo.changelog.tip()), nice(node)))
294 if opts.get('merge') and op1 != node:
294 if opts.get('merge') and op1 != node:
295 hg.clean(repo, op1, show_stats=False)
295 hg.clean(repo, op1, show_stats=False)
296 ui.status(_('merging with changeset %s\n')
296 ui.status(_('merging with changeset %s\n')
297 % nice(repo.changelog.tip()))
297 % nice(repo.changelog.tip()))
298 try:
298 try:
299 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
299 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
300 return hg.merge(repo, hex(repo.changelog.tip()))
300 return hg.merge(repo, hex(repo.changelog.tip()))
301 finally:
301 finally:
302 ui.setconfig('ui', 'forcemerge', '')
302 ui.setconfig('ui', 'forcemerge', '')
303 return 0
303 return 0
304
304
305 def bisect(ui, repo, rev=None, extra=None, command=None,
305 def bisect(ui, repo, rev=None, extra=None, command=None,
306 reset=None, good=None, bad=None, skip=None, noupdate=None):
306 reset=None, good=None, bad=None, skip=None, noupdate=None):
307 """subdivision search of changesets
307 """subdivision search of changesets
308
308
309 This command helps to find changesets which introduce problems. To
309 This command helps to find changesets which introduce problems. To
310 use, mark the earliest changeset you know exhibits the problem as
310 use, mark the earliest changeset you know exhibits the problem as
311 bad, then mark the latest changeset which is free from the problem
311 bad, then mark the latest changeset which is free from the problem
312 as good. Bisect will update your working directory to a revision
312 as good. Bisect will update your working directory to a revision
313 for testing (unless the -U/--noupdate option is specified). Once
313 for testing (unless the -U/--noupdate option is specified). Once
314 you have performed tests, mark the working directory as good or
314 you have performed tests, mark the working directory as good or
315 bad, and bisect will either update to another candidate changeset
315 bad, and bisect will either update to another candidate changeset
316 or announce that it has found the bad revision.
316 or announce that it has found the bad revision.
317
317
318 As a shortcut, you can also use the revision argument to mark a
318 As a shortcut, you can also use the revision argument to mark a
319 revision as good or bad without checking it out first.
319 revision as good or bad without checking it out first.
320
320
321 If you supply a command, it will be used for automatic bisection.
321 If you supply a command, it will be used for automatic bisection.
322 Its exit status will be used to mark revisions as good or bad:
322 Its exit status will be used to mark revisions as good or bad:
323 status 0 means good, 125 means to skip the revision, 127
323 status 0 means good, 125 means to skip the revision, 127
324 (command not found) will abort the bisection, and any other
324 (command not found) will abort the bisection, and any other
325 non-zero exit status means the revision is bad.
325 non-zero exit status means the revision is bad.
326
326
327 Returns 0 on success.
327 Returns 0 on success.
328 """
328 """
329 def print_result(nodes, good):
329 def print_result(nodes, good):
330 displayer = cmdutil.show_changeset(ui, repo, {})
330 displayer = cmdutil.show_changeset(ui, repo, {})
331 if len(nodes) == 1:
331 if len(nodes) == 1:
332 # narrowed it down to a single revision
332 # narrowed it down to a single revision
333 if good:
333 if good:
334 ui.write(_("The first good revision is:\n"))
334 ui.write(_("The first good revision is:\n"))
335 else:
335 else:
336 ui.write(_("The first bad revision is:\n"))
336 ui.write(_("The first bad revision is:\n"))
337 displayer.show(repo[nodes[0]])
337 displayer.show(repo[nodes[0]])
338 parents = repo[nodes[0]].parents()
338 parents = repo[nodes[0]].parents()
339 if len(parents) > 1:
339 if len(parents) > 1:
340 side = good and state['bad'] or state['good']
340 side = good and state['bad'] or state['good']
341 num = len(set(i.node() for i in parents) & set(side))
341 num = len(set(i.node() for i in parents) & set(side))
342 if num == 1:
342 if num == 1:
343 common = parents[0].ancestor(parents[1])
343 common = parents[0].ancestor(parents[1])
344 ui.write(_('Not all ancestors of this changeset have been'
344 ui.write(_('Not all ancestors of this changeset have been'
345 ' checked.\nTo check the other ancestors, start'
345 ' checked.\nTo check the other ancestors, start'
346 ' from the common ancestor, %s.\n' % common))
346 ' from the common ancestor, %s.\n' % common))
347 else:
347 else:
348 # multiple possible revisions
348 # multiple possible revisions
349 if good:
349 if good:
350 ui.write(_("Due to skipped revisions, the first "
350 ui.write(_("Due to skipped revisions, the first "
351 "good revision could be any of:\n"))
351 "good revision could be any of:\n"))
352 else:
352 else:
353 ui.write(_("Due to skipped revisions, the first "
353 ui.write(_("Due to skipped revisions, the first "
354 "bad revision could be any of:\n"))
354 "bad revision could be any of:\n"))
355 for n in nodes:
355 for n in nodes:
356 displayer.show(repo[n])
356 displayer.show(repo[n])
357 displayer.close()
357 displayer.close()
358
358
359 def check_state(state, interactive=True):
359 def check_state(state, interactive=True):
360 if not state['good'] or not state['bad']:
360 if not state['good'] or not state['bad']:
361 if (good or bad or skip or reset) and interactive:
361 if (good or bad or skip or reset) and interactive:
362 return
362 return
363 if not state['good']:
363 if not state['good']:
364 raise util.Abort(_('cannot bisect (no known good revisions)'))
364 raise util.Abort(_('cannot bisect (no known good revisions)'))
365 else:
365 else:
366 raise util.Abort(_('cannot bisect (no known bad revisions)'))
366 raise util.Abort(_('cannot bisect (no known bad revisions)'))
367 return True
367 return True
368
368
369 # backward compatibility
369 # backward compatibility
370 if rev in "good bad reset init".split():
370 if rev in "good bad reset init".split():
371 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
371 ui.warn(_("(use of 'hg bisect <cmd>' is deprecated)\n"))
372 cmd, rev, extra = rev, extra, None
372 cmd, rev, extra = rev, extra, None
373 if cmd == "good":
373 if cmd == "good":
374 good = True
374 good = True
375 elif cmd == "bad":
375 elif cmd == "bad":
376 bad = True
376 bad = True
377 else:
377 else:
378 reset = True
378 reset = True
379 elif extra or good + bad + skip + reset + bool(command) > 1:
379 elif extra or good + bad + skip + reset + bool(command) > 1:
380 raise util.Abort(_('incompatible arguments'))
380 raise util.Abort(_('incompatible arguments'))
381
381
382 if reset:
382 if reset:
383 p = repo.join("bisect.state")
383 p = repo.join("bisect.state")
384 if os.path.exists(p):
384 if os.path.exists(p):
385 os.unlink(p)
385 os.unlink(p)
386 return
386 return
387
387
388 state = hbisect.load_state(repo)
388 state = hbisect.load_state(repo)
389
389
390 if command:
390 if command:
391 changesets = 1
391 changesets = 1
392 try:
392 try:
393 while changesets:
393 while changesets:
394 # update state
394 # update state
395 status = util.system(command)
395 status = util.system(command)
396 if status == 125:
396 if status == 125:
397 transition = "skip"
397 transition = "skip"
398 elif status == 0:
398 elif status == 0:
399 transition = "good"
399 transition = "good"
400 # status < 0 means process was killed
400 # status < 0 means process was killed
401 elif status == 127:
401 elif status == 127:
402 raise util.Abort(_("failed to execute %s") % command)
402 raise util.Abort(_("failed to execute %s") % command)
403 elif status < 0:
403 elif status < 0:
404 raise util.Abort(_("%s killed") % command)
404 raise util.Abort(_("%s killed") % command)
405 else:
405 else:
406 transition = "bad"
406 transition = "bad"
407 ctx = cmdutil.revsingle(repo, rev)
407 ctx = cmdutil.revsingle(repo, rev)
408 rev = None # clear for future iterations
408 rev = None # clear for future iterations
409 state[transition].append(ctx.node())
409 state[transition].append(ctx.node())
410 ui.status(_('Changeset %d:%s: %s\n') % (ctx, ctx, transition))
410 ui.status(_('Changeset %d:%s: %s\n') % (ctx, ctx, transition))
411 check_state(state, interactive=False)
411 check_state(state, interactive=False)
412 # bisect
412 # bisect
413 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
413 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
414 # update to next check
414 # update to next check
415 cmdutil.bail_if_changed(repo)
415 cmdutil.bail_if_changed(repo)
416 hg.clean(repo, nodes[0], show_stats=False)
416 hg.clean(repo, nodes[0], show_stats=False)
417 finally:
417 finally:
418 hbisect.save_state(repo, state)
418 hbisect.save_state(repo, state)
419 print_result(nodes, good)
419 print_result(nodes, good)
420 return
420 return
421
421
422 # update state
422 # update state
423
423
424 if rev:
424 if rev:
425 nodes = [repo.lookup(i) for i in cmdutil.revrange(repo, [rev])]
425 nodes = [repo.lookup(i) for i in cmdutil.revrange(repo, [rev])]
426 else:
426 else:
427 nodes = [repo.lookup('.')]
427 nodes = [repo.lookup('.')]
428
428
429 if good or bad or skip:
429 if good or bad or skip:
430 if good:
430 if good:
431 state['good'] += nodes
431 state['good'] += nodes
432 elif bad:
432 elif bad:
433 state['bad'] += nodes
433 state['bad'] += nodes
434 elif skip:
434 elif skip:
435 state['skip'] += nodes
435 state['skip'] += nodes
436 hbisect.save_state(repo, state)
436 hbisect.save_state(repo, state)
437
437
438 if not check_state(state):
438 if not check_state(state):
439 return
439 return
440
440
441 # actually bisect
441 # actually bisect
442 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
442 nodes, changesets, good = hbisect.bisect(repo.changelog, state)
443 if changesets == 0:
443 if changesets == 0:
444 print_result(nodes, good)
444 print_result(nodes, good)
445 else:
445 else:
446 assert len(nodes) == 1 # only a single node can be tested next
446 assert len(nodes) == 1 # only a single node can be tested next
447 node = nodes[0]
447 node = nodes[0]
448 # compute the approximate number of remaining tests
448 # compute the approximate number of remaining tests
449 tests, size = 0, 2
449 tests, size = 0, 2
450 while size <= changesets:
450 while size <= changesets:
451 tests, size = tests + 1, size * 2
451 tests, size = tests + 1, size * 2
452 rev = repo.changelog.rev(node)
452 rev = repo.changelog.rev(node)
453 ui.write(_("Testing changeset %d:%s "
453 ui.write(_("Testing changeset %d:%s "
454 "(%d changesets remaining, ~%d tests)\n")
454 "(%d changesets remaining, ~%d tests)\n")
455 % (rev, short(node), changesets, tests))
455 % (rev, short(node), changesets, tests))
456 if not noupdate:
456 if not noupdate:
457 cmdutil.bail_if_changed(repo)
457 cmdutil.bail_if_changed(repo)
458 return hg.clean(repo, node)
458 return hg.clean(repo, node)
459
459
460 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False, rename=None):
460 def bookmark(ui, repo, mark=None, rev=None, force=False, delete=False, rename=None):
461 '''track a line of development with movable markers
461 '''track a line of development with movable markers
462
462
463 Bookmarks are pointers to certain commits that move when
463 Bookmarks are pointers to certain commits that move when
464 committing. Bookmarks are local. They can be renamed, copied and
464 committing. Bookmarks are local. They can be renamed, copied and
465 deleted. It is possible to use bookmark names in :hg:`merge` and
465 deleted. It is possible to use bookmark names in :hg:`merge` and
466 :hg:`update` to merge and update respectively to a given bookmark.
466 :hg:`update` to merge and update respectively to a given bookmark.
467
467
468 You can use :hg:`bookmark NAME` to set a bookmark on the working
468 You can use :hg:`bookmark NAME` to set a bookmark on the working
469 directory's parent revision with the given name. If you specify
469 directory's parent revision with the given name. If you specify
470 a revision using -r REV (where REV may be an existing bookmark),
470 a revision using -r REV (where REV may be an existing bookmark),
471 the bookmark is assigned to that revision.
471 the bookmark is assigned to that revision.
472
472
473 Bookmarks can be pushed and pulled between repositories (see :hg:`help
473 Bookmarks can be pushed and pulled between repositories (see :hg:`help
474 push` and :hg:`help pull`). This requires both the local and remote
474 push` and :hg:`help pull`). This requires both the local and remote
475 repositories to support bookmarks. For versions prior to 1.8, this means
475 repositories to support bookmarks. For versions prior to 1.8, this means
476 the bookmarks extension must be enabled.
476 the bookmarks extension must be enabled.
477 '''
477 '''
478 hexfn = ui.debugflag and hex or short
478 hexfn = ui.debugflag and hex or short
479 marks = repo._bookmarks
479 marks = repo._bookmarks
480 cur = repo.changectx('.').node()
480 cur = repo.changectx('.').node()
481
481
482 if rename:
482 if rename:
483 if rename not in marks:
483 if rename not in marks:
484 raise util.Abort(_("a bookmark of this name does not exist"))
484 raise util.Abort(_("a bookmark of this name does not exist"))
485 if mark in marks and not force:
485 if mark in marks and not force:
486 raise util.Abort(_("a bookmark of the same name already exists"))
486 raise util.Abort(_("a bookmark of the same name already exists"))
487 if mark is None:
487 if mark is None:
488 raise util.Abort(_("new bookmark name required"))
488 raise util.Abort(_("new bookmark name required"))
489 marks[mark] = marks[rename]
489 marks[mark] = marks[rename]
490 del marks[rename]
490 del marks[rename]
491 if repo._bookmarkcurrent == rename:
491 if repo._bookmarkcurrent == rename:
492 bookmarks.setcurrent(repo, mark)
492 bookmarks.setcurrent(repo, mark)
493 bookmarks.write(repo)
493 bookmarks.write(repo)
494 return
494 return
495
495
496 if delete:
496 if delete:
497 if mark is None:
497 if mark is None:
498 raise util.Abort(_("bookmark name required"))
498 raise util.Abort(_("bookmark name required"))
499 if mark not in marks:
499 if mark not in marks:
500 raise util.Abort(_("a bookmark of this name does not exist"))
500 raise util.Abort(_("a bookmark of this name does not exist"))
501 if mark == repo._bookmarkcurrent:
501 if mark == repo._bookmarkcurrent:
502 bookmarks.setcurrent(repo, None)
502 bookmarks.setcurrent(repo, None)
503 del marks[mark]
503 del marks[mark]
504 bookmarks.write(repo)
504 bookmarks.write(repo)
505 return
505 return
506
506
507 if mark is not None:
507 if mark is not None:
508 if "\n" in mark:
508 if "\n" in mark:
509 raise util.Abort(_("bookmark name cannot contain newlines"))
509 raise util.Abort(_("bookmark name cannot contain newlines"))
510 mark = mark.strip()
510 mark = mark.strip()
511 if not mark:
511 if not mark:
512 raise util.Abort(_("bookmark names cannot consist entirely of "
512 raise util.Abort(_("bookmark names cannot consist entirely of "
513 "whitespace"))
513 "whitespace"))
514 if mark in marks and not force:
514 if mark in marks and not force:
515 raise util.Abort(_("a bookmark of the same name already exists"))
515 raise util.Abort(_("a bookmark of the same name already exists"))
516 if ((mark in repo.branchtags() or mark == repo.dirstate.branch())
516 if ((mark in repo.branchtags() or mark == repo.dirstate.branch())
517 and not force):
517 and not force):
518 raise util.Abort(
518 raise util.Abort(
519 _("a bookmark cannot have the name of an existing branch"))
519 _("a bookmark cannot have the name of an existing branch"))
520 if rev:
520 if rev:
521 marks[mark] = repo.lookup(rev)
521 marks[mark] = repo.lookup(rev)
522 else:
522 else:
523 marks[mark] = repo.changectx('.').node()
523 marks[mark] = repo.changectx('.').node()
524 bookmarks.setcurrent(repo, mark)
524 bookmarks.setcurrent(repo, mark)
525 bookmarks.write(repo)
525 bookmarks.write(repo)
526 return
526 return
527
527
528 if mark is None:
528 if mark is None:
529 if rev:
529 if rev:
530 raise util.Abort(_("bookmark name required"))
530 raise util.Abort(_("bookmark name required"))
531 if len(marks) == 0:
531 if len(marks) == 0:
532 ui.status(_("no bookmarks set\n"))
532 ui.status(_("no bookmarks set\n"))
533 else:
533 else:
534 for bmark, n in sorted(marks.iteritems()):
534 for bmark, n in sorted(marks.iteritems()):
535 if ui.configbool('bookmarks', 'track.current'):
535 current = repo._bookmarkcurrent
536 current = repo._bookmarkcurrent
536 if bmark == current and n == cur:
537 if bmark == current and n == cur:
537 prefix, label = '*', 'bookmarks.current'
538 prefix, label = '*', 'bookmarks.current'
539 else:
540 prefix, label = ' ', ''
541 else:
538 else:
542 if n == cur:
539 prefix, label = ' ', ''
543 prefix, label = '*', 'bookmarks.current'
544 else:
545 prefix, label = ' ', ''
546
540
547 if ui.quiet:
541 if ui.quiet:
548 ui.write("%s\n" % bmark, label=label)
542 ui.write("%s\n" % bmark, label=label)
549 else:
543 else:
550 ui.write(" %s %-25s %d:%s\n" % (
544 ui.write(" %s %-25s %d:%s\n" % (
551 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
545 prefix, bmark, repo.changelog.rev(n), hexfn(n)),
552 label=label)
546 label=label)
553 return
547 return
554
548
555 def branch(ui, repo, label=None, **opts):
549 def branch(ui, repo, label=None, **opts):
556 """set or show the current branch name
550 """set or show the current branch name
557
551
558 With no argument, show the current branch name. With one argument,
552 With no argument, show the current branch name. With one argument,
559 set the working directory branch name (the branch will not exist
553 set the working directory branch name (the branch will not exist
560 in the repository until the next commit). Standard practice
554 in the repository until the next commit). Standard practice
561 recommends that primary development take place on the 'default'
555 recommends that primary development take place on the 'default'
562 branch.
556 branch.
563
557
564 Unless -f/--force is specified, branch will not let you set a
558 Unless -f/--force is specified, branch will not let you set a
565 branch name that already exists, even if it's inactive.
559 branch name that already exists, even if it's inactive.
566
560
567 Use -C/--clean to reset the working directory branch to that of
561 Use -C/--clean to reset the working directory branch to that of
568 the parent of the working directory, negating a previous branch
562 the parent of the working directory, negating a previous branch
569 change.
563 change.
570
564
571 Use the command :hg:`update` to switch to an existing branch. Use
565 Use the command :hg:`update` to switch to an existing branch. Use
572 :hg:`commit --close-branch` to mark this branch as closed.
566 :hg:`commit --close-branch` to mark this branch as closed.
573
567
574 Returns 0 on success.
568 Returns 0 on success.
575 """
569 """
576
570
577 if opts.get('clean'):
571 if opts.get('clean'):
578 label = repo[None].parents()[0].branch()
572 label = repo[None].parents()[0].branch()
579 repo.dirstate.setbranch(label)
573 repo.dirstate.setbranch(label)
580 ui.status(_('reset working directory to branch %s\n') % label)
574 ui.status(_('reset working directory to branch %s\n') % label)
581 elif label:
575 elif label:
582 if not opts.get('force') and label in repo.branchtags():
576 if not opts.get('force') and label in repo.branchtags():
583 if label not in [p.branch() for p in repo.parents()]:
577 if label not in [p.branch() for p in repo.parents()]:
584 raise util.Abort(_('a branch of the same name already exists'
578 raise util.Abort(_('a branch of the same name already exists'
585 " (use 'hg update' to switch to it)"))
579 " (use 'hg update' to switch to it)"))
586 repo.dirstate.setbranch(label)
580 repo.dirstate.setbranch(label)
587 ui.status(_('marked working directory as branch %s\n') % label)
581 ui.status(_('marked working directory as branch %s\n') % label)
588 else:
582 else:
589 ui.write("%s\n" % repo.dirstate.branch())
583 ui.write("%s\n" % repo.dirstate.branch())
590
584
591 def branches(ui, repo, active=False, closed=False):
585 def branches(ui, repo, active=False, closed=False):
592 """list repository named branches
586 """list repository named branches
593
587
594 List the repository's named branches, indicating which ones are
588 List the repository's named branches, indicating which ones are
595 inactive. If -c/--closed is specified, also list branches which have
589 inactive. If -c/--closed is specified, also list branches which have
596 been marked closed (see :hg:`commit --close-branch`).
590 been marked closed (see :hg:`commit --close-branch`).
597
591
598 If -a/--active is specified, only show active branches. A branch
592 If -a/--active is specified, only show active branches. A branch
599 is considered active if it contains repository heads.
593 is considered active if it contains repository heads.
600
594
601 Use the command :hg:`update` to switch to an existing branch.
595 Use the command :hg:`update` to switch to an existing branch.
602
596
603 Returns 0.
597 Returns 0.
604 """
598 """
605
599
606 hexfunc = ui.debugflag and hex or short
600 hexfunc = ui.debugflag and hex or short
607 activebranches = [repo[n].branch() for n in repo.heads()]
601 activebranches = [repo[n].branch() for n in repo.heads()]
608 def testactive(tag, node):
602 def testactive(tag, node):
609 realhead = tag in activebranches
603 realhead = tag in activebranches
610 open = node in repo.branchheads(tag, closed=False)
604 open = node in repo.branchheads(tag, closed=False)
611 return realhead and open
605 return realhead and open
612 branches = sorted([(testactive(tag, node), repo.changelog.rev(node), tag)
606 branches = sorted([(testactive(tag, node), repo.changelog.rev(node), tag)
613 for tag, node in repo.branchtags().items()],
607 for tag, node in repo.branchtags().items()],
614 reverse=True)
608 reverse=True)
615
609
616 for isactive, node, tag in branches:
610 for isactive, node, tag in branches:
617 if (not active) or isactive:
611 if (not active) or isactive:
618 if ui.quiet:
612 if ui.quiet:
619 ui.write("%s\n" % tag)
613 ui.write("%s\n" % tag)
620 else:
614 else:
621 hn = repo.lookup(node)
615 hn = repo.lookup(node)
622 if isactive:
616 if isactive:
623 label = 'branches.active'
617 label = 'branches.active'
624 notice = ''
618 notice = ''
625 elif hn not in repo.branchheads(tag, closed=False):
619 elif hn not in repo.branchheads(tag, closed=False):
626 if not closed:
620 if not closed:
627 continue
621 continue
628 label = 'branches.closed'
622 label = 'branches.closed'
629 notice = _(' (closed)')
623 notice = _(' (closed)')
630 else:
624 else:
631 label = 'branches.inactive'
625 label = 'branches.inactive'
632 notice = _(' (inactive)')
626 notice = _(' (inactive)')
633 if tag == repo.dirstate.branch():
627 if tag == repo.dirstate.branch():
634 label = 'branches.current'
628 label = 'branches.current'
635 rev = str(node).rjust(31 - encoding.colwidth(tag))
629 rev = str(node).rjust(31 - encoding.colwidth(tag))
636 rev = ui.label('%s:%s' % (rev, hexfunc(hn)), 'log.changeset')
630 rev = ui.label('%s:%s' % (rev, hexfunc(hn)), 'log.changeset')
637 tag = ui.label(tag, label)
631 tag = ui.label(tag, label)
638 ui.write("%s %s%s\n" % (tag, rev, notice))
632 ui.write("%s %s%s\n" % (tag, rev, notice))
639
633
640 def bundle(ui, repo, fname, dest=None, **opts):
634 def bundle(ui, repo, fname, dest=None, **opts):
641 """create a changegroup file
635 """create a changegroup file
642
636
643 Generate a compressed changegroup file collecting changesets not
637 Generate a compressed changegroup file collecting changesets not
644 known to be in another repository.
638 known to be in another repository.
645
639
646 If you omit the destination repository, then hg assumes the
640 If you omit the destination repository, then hg assumes the
647 destination will have all the nodes you specify with --base
641 destination will have all the nodes you specify with --base
648 parameters. To create a bundle containing all changesets, use
642 parameters. To create a bundle containing all changesets, use
649 -a/--all (or --base null).
643 -a/--all (or --base null).
650
644
651 You can change compression method with the -t/--type option.
645 You can change compression method with the -t/--type option.
652 The available compression methods are: none, bzip2, and
646 The available compression methods are: none, bzip2, and
653 gzip (by default, bundles are compressed using bzip2).
647 gzip (by default, bundles are compressed using bzip2).
654
648
655 The bundle file can then be transferred using conventional means
649 The bundle file can then be transferred using conventional means
656 and applied to another repository with the unbundle or pull
650 and applied to another repository with the unbundle or pull
657 command. This is useful when direct push and pull are not
651 command. This is useful when direct push and pull are not
658 available or when exporting an entire repository is undesirable.
652 available or when exporting an entire repository is undesirable.
659
653
660 Applying bundles preserves all changeset contents including
654 Applying bundles preserves all changeset contents including
661 permissions, copy/rename information, and revision history.
655 permissions, copy/rename information, and revision history.
662
656
663 Returns 0 on success, 1 if no changes found.
657 Returns 0 on success, 1 if no changes found.
664 """
658 """
665 revs = None
659 revs = None
666 if 'rev' in opts:
660 if 'rev' in opts:
667 revs = cmdutil.revrange(repo, opts['rev'])
661 revs = cmdutil.revrange(repo, opts['rev'])
668
662
669 if opts.get('all'):
663 if opts.get('all'):
670 base = ['null']
664 base = ['null']
671 else:
665 else:
672 base = cmdutil.revrange(repo, opts.get('base'))
666 base = cmdutil.revrange(repo, opts.get('base'))
673 if base:
667 if base:
674 if dest:
668 if dest:
675 raise util.Abort(_("--base is incompatible with specifying "
669 raise util.Abort(_("--base is incompatible with specifying "
676 "a destination"))
670 "a destination"))
677 base = [repo.lookup(rev) for rev in base]
671 base = [repo.lookup(rev) for rev in base]
678 # create the right base
672 # create the right base
679 # XXX: nodesbetween / changegroup* should be "fixed" instead
673 # XXX: nodesbetween / changegroup* should be "fixed" instead
680 o = []
674 o = []
681 has = set((nullid,))
675 has = set((nullid,))
682 for n in base:
676 for n in base:
683 has.update(repo.changelog.reachable(n))
677 has.update(repo.changelog.reachable(n))
684 if revs:
678 if revs:
685 revs = [repo.lookup(rev) for rev in revs]
679 revs = [repo.lookup(rev) for rev in revs]
686 visit = revs[:]
680 visit = revs[:]
687 has.difference_update(visit)
681 has.difference_update(visit)
688 else:
682 else:
689 visit = repo.changelog.heads()
683 visit = repo.changelog.heads()
690 seen = {}
684 seen = {}
691 while visit:
685 while visit:
692 n = visit.pop(0)
686 n = visit.pop(0)
693 parents = [p for p in repo.changelog.parents(n) if p not in has]
687 parents = [p for p in repo.changelog.parents(n) if p not in has]
694 if len(parents) == 0:
688 if len(parents) == 0:
695 if n not in has:
689 if n not in has:
696 o.append(n)
690 o.append(n)
697 else:
691 else:
698 for p in parents:
692 for p in parents:
699 if p not in seen:
693 if p not in seen:
700 seen[p] = 1
694 seen[p] = 1
701 visit.append(p)
695 visit.append(p)
702 else:
696 else:
703 dest = ui.expandpath(dest or 'default-push', dest or 'default')
697 dest = ui.expandpath(dest or 'default-push', dest or 'default')
704 dest, branches = hg.parseurl(dest, opts.get('branch'))
698 dest, branches = hg.parseurl(dest, opts.get('branch'))
705 other = hg.repository(hg.remoteui(repo, opts), dest)
699 other = hg.repository(hg.remoteui(repo, opts), dest)
706 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
700 revs, checkout = hg.addbranchrevs(repo, other, branches, revs)
707 if revs:
701 if revs:
708 revs = [repo.lookup(rev) for rev in revs]
702 revs = [repo.lookup(rev) for rev in revs]
709 o = discovery.findoutgoing(repo, other, force=opts.get('force'))
703 o = discovery.findoutgoing(repo, other, force=opts.get('force'))
710
704
711 if not o:
705 if not o:
712 ui.status(_("no changes found\n"))
706 ui.status(_("no changes found\n"))
713 return 1
707 return 1
714
708
715 if revs:
709 if revs:
716 cg = repo.changegroupsubset(o, revs, 'bundle')
710 cg = repo.changegroupsubset(o, revs, 'bundle')
717 else:
711 else:
718 cg = repo.changegroup(o, 'bundle')
712 cg = repo.changegroup(o, 'bundle')
719
713
720 bundletype = opts.get('type', 'bzip2').lower()
714 bundletype = opts.get('type', 'bzip2').lower()
721 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
715 btypes = {'none': 'HG10UN', 'bzip2': 'HG10BZ', 'gzip': 'HG10GZ'}
722 bundletype = btypes.get(bundletype)
716 bundletype = btypes.get(bundletype)
723 if bundletype not in changegroup.bundletypes:
717 if bundletype not in changegroup.bundletypes:
724 raise util.Abort(_('unknown bundle type specified with --type'))
718 raise util.Abort(_('unknown bundle type specified with --type'))
725
719
726 changegroup.writebundle(cg, fname, bundletype)
720 changegroup.writebundle(cg, fname, bundletype)
727
721
728 def cat(ui, repo, file1, *pats, **opts):
722 def cat(ui, repo, file1, *pats, **opts):
729 """output the current or given revision of files
723 """output the current or given revision of files
730
724
731 Print the specified files as they were at the given revision. If
725 Print the specified files as they were at the given revision. If
732 no revision is given, the parent of the working directory is used,
726 no revision is given, the parent of the working directory is used,
733 or tip if no revision is checked out.
727 or tip if no revision is checked out.
734
728
735 Output may be to a file, in which case the name of the file is
729 Output may be to a file, in which case the name of the file is
736 given using a format string. The formatting rules are the same as
730 given using a format string. The formatting rules are the same as
737 for the export command, with the following additions:
731 for the export command, with the following additions:
738
732
739 :``%s``: basename of file being printed
733 :``%s``: basename of file being printed
740 :``%d``: dirname of file being printed, or '.' if in repository root
734 :``%d``: dirname of file being printed, or '.' if in repository root
741 :``%p``: root-relative path name of file being printed
735 :``%p``: root-relative path name of file being printed
742
736
743 Returns 0 on success.
737 Returns 0 on success.
744 """
738 """
745 ctx = cmdutil.revsingle(repo, opts.get('rev'))
739 ctx = cmdutil.revsingle(repo, opts.get('rev'))
746 err = 1
740 err = 1
747 m = cmdutil.match(repo, (file1,) + pats, opts)
741 m = cmdutil.match(repo, (file1,) + pats, opts)
748 for abs in ctx.walk(m):
742 for abs in ctx.walk(m):
749 fp = cmdutil.make_file(repo, opts.get('output'), ctx.node(), pathname=abs)
743 fp = cmdutil.make_file(repo, opts.get('output'), ctx.node(), pathname=abs)
750 data = ctx[abs].data()
744 data = ctx[abs].data()
751 if opts.get('decode'):
745 if opts.get('decode'):
752 data = repo.wwritedata(abs, data)
746 data = repo.wwritedata(abs, data)
753 fp.write(data)
747 fp.write(data)
754 fp.close()
748 fp.close()
755 err = 0
749 err = 0
756 return err
750 return err
757
751
758 def clone(ui, source, dest=None, **opts):
752 def clone(ui, source, dest=None, **opts):
759 """make a copy of an existing repository
753 """make a copy of an existing repository
760
754
761 Create a copy of an existing repository in a new directory.
755 Create a copy of an existing repository in a new directory.
762
756
763 If no destination directory name is specified, it defaults to the
757 If no destination directory name is specified, it defaults to the
764 basename of the source.
758 basename of the source.
765
759
766 The location of the source is added to the new repository's
760 The location of the source is added to the new repository's
767 ``.hg/hgrc`` file, as the default to be used for future pulls.
761 ``.hg/hgrc`` file, as the default to be used for future pulls.
768
762
769 See :hg:`help urls` for valid source format details.
763 See :hg:`help urls` for valid source format details.
770
764
771 It is possible to specify an ``ssh://`` URL as the destination, but no
765 It is possible to specify an ``ssh://`` URL as the destination, but no
772 ``.hg/hgrc`` and working directory will be created on the remote side.
766 ``.hg/hgrc`` and working directory will be created on the remote side.
773 Please see :hg:`help urls` for important details about ``ssh://`` URLs.
767 Please see :hg:`help urls` for important details about ``ssh://`` URLs.
774
768
775 A set of changesets (tags, or branch names) to pull may be specified
769 A set of changesets (tags, or branch names) to pull may be specified
776 by listing each changeset (tag, or branch name) with -r/--rev.
770 by listing each changeset (tag, or branch name) with -r/--rev.
777 If -r/--rev is used, the cloned repository will contain only a subset
771 If -r/--rev is used, the cloned repository will contain only a subset
778 of the changesets of the source repository. Only the set of changesets
772 of the changesets of the source repository. Only the set of changesets
779 defined by all -r/--rev options (including all their ancestors)
773 defined by all -r/--rev options (including all their ancestors)
780 will be pulled into the destination repository.
774 will be pulled into the destination repository.
781 No subsequent changesets (including subsequent tags) will be present
775 No subsequent changesets (including subsequent tags) will be present
782 in the destination.
776 in the destination.
783
777
784 Using -r/--rev (or 'clone src#rev dest') implies --pull, even for
778 Using -r/--rev (or 'clone src#rev dest') implies --pull, even for
785 local source repositories.
779 local source repositories.
786
780
787 For efficiency, hardlinks are used for cloning whenever the source
781 For efficiency, hardlinks are used for cloning whenever the source
788 and destination are on the same filesystem (note this applies only
782 and destination are on the same filesystem (note this applies only
789 to the repository data, not to the working directory). Some
783 to the repository data, not to the working directory). Some
790 filesystems, such as AFS, implement hardlinking incorrectly, but
784 filesystems, such as AFS, implement hardlinking incorrectly, but
791 do not report errors. In these cases, use the --pull option to
785 do not report errors. In these cases, use the --pull option to
792 avoid hardlinking.
786 avoid hardlinking.
793
787
794 In some cases, you can clone repositories and the working directory
788 In some cases, you can clone repositories and the working directory
795 using full hardlinks with ::
789 using full hardlinks with ::
796
790
797 $ cp -al REPO REPOCLONE
791 $ cp -al REPO REPOCLONE
798
792
799 This is the fastest way to clone, but it is not always safe. The
793 This is the fastest way to clone, but it is not always safe. The
800 operation is not atomic (making sure REPO is not modified during
794 operation is not atomic (making sure REPO is not modified during
801 the operation is up to you) and you have to make sure your editor
795 the operation is up to you) and you have to make sure your editor
802 breaks hardlinks (Emacs and most Linux Kernel tools do so). Also,
796 breaks hardlinks (Emacs and most Linux Kernel tools do so). Also,
803 this is not compatible with certain extensions that place their
797 this is not compatible with certain extensions that place their
804 metadata under the .hg directory, such as mq.
798 metadata under the .hg directory, such as mq.
805
799
806 Mercurial will update the working directory to the first applicable
800 Mercurial will update the working directory to the first applicable
807 revision from this list:
801 revision from this list:
808
802
809 a) null if -U or the source repository has no changesets
803 a) null if -U or the source repository has no changesets
810 b) if -u . and the source repository is local, the first parent of
804 b) if -u . and the source repository is local, the first parent of
811 the source repository's working directory
805 the source repository's working directory
812 c) the changeset specified with -u (if a branch name, this means the
806 c) the changeset specified with -u (if a branch name, this means the
813 latest head of that branch)
807 latest head of that branch)
814 d) the changeset specified with -r
808 d) the changeset specified with -r
815 e) the tipmost head specified with -b
809 e) the tipmost head specified with -b
816 f) the tipmost head specified with the url#branch source syntax
810 f) the tipmost head specified with the url#branch source syntax
817 g) the tipmost head of the default branch
811 g) the tipmost head of the default branch
818 h) tip
812 h) tip
819
813
820 Returns 0 on success.
814 Returns 0 on success.
821 """
815 """
822 if opts.get('noupdate') and opts.get('updaterev'):
816 if opts.get('noupdate') and opts.get('updaterev'):
823 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
817 raise util.Abort(_("cannot specify both --noupdate and --updaterev"))
824
818
825 r = hg.clone(hg.remoteui(ui, opts), source, dest,
819 r = hg.clone(hg.remoteui(ui, opts), source, dest,
826 pull=opts.get('pull'),
820 pull=opts.get('pull'),
827 stream=opts.get('uncompressed'),
821 stream=opts.get('uncompressed'),
828 rev=opts.get('rev'),
822 rev=opts.get('rev'),
829 update=opts.get('updaterev') or not opts.get('noupdate'),
823 update=opts.get('updaterev') or not opts.get('noupdate'),
830 branch=opts.get('branch'))
824 branch=opts.get('branch'))
831
825
832 return r is None
826 return r is None
833
827
834 def commit(ui, repo, *pats, **opts):
828 def commit(ui, repo, *pats, **opts):
835 """commit the specified files or all outstanding changes
829 """commit the specified files or all outstanding changes
836
830
837 Commit changes to the given files into the repository. Unlike a
831 Commit changes to the given files into the repository. Unlike a
838 centralized SCM, this operation is a local operation. See
832 centralized SCM, this operation is a local operation. See
839 :hg:`push` for a way to actively distribute your changes.
833 :hg:`push` for a way to actively distribute your changes.
840
834
841 If a list of files is omitted, all changes reported by :hg:`status`
835 If a list of files is omitted, all changes reported by :hg:`status`
842 will be committed.
836 will be committed.
843
837
844 If you are committing the result of a merge, do not provide any
838 If you are committing the result of a merge, do not provide any
845 filenames or -I/-X filters.
839 filenames or -I/-X filters.
846
840
847 If no commit message is specified, Mercurial starts your
841 If no commit message is specified, Mercurial starts your
848 configured editor where you can enter a message. In case your
842 configured editor where you can enter a message. In case your
849 commit fails, you will find a backup of your message in
843 commit fails, you will find a backup of your message in
850 ``.hg/last-message.txt``.
844 ``.hg/last-message.txt``.
851
845
852 See :hg:`help dates` for a list of formats valid for -d/--date.
846 See :hg:`help dates` for a list of formats valid for -d/--date.
853
847
854 Returns 0 on success, 1 if nothing changed.
848 Returns 0 on success, 1 if nothing changed.
855 """
849 """
856 extra = {}
850 extra = {}
857 if opts.get('close_branch'):
851 if opts.get('close_branch'):
858 if repo['.'].node() not in repo.branchheads():
852 if repo['.'].node() not in repo.branchheads():
859 # The topo heads set is included in the branch heads set of the
853 # The topo heads set is included in the branch heads set of the
860 # current branch, so it's sufficient to test branchheads
854 # current branch, so it's sufficient to test branchheads
861 raise util.Abort(_('can only close branch heads'))
855 raise util.Abort(_('can only close branch heads'))
862 extra['close'] = 1
856 extra['close'] = 1
863 e = cmdutil.commiteditor
857 e = cmdutil.commiteditor
864 if opts.get('force_editor'):
858 if opts.get('force_editor'):
865 e = cmdutil.commitforceeditor
859 e = cmdutil.commitforceeditor
866
860
867 def commitfunc(ui, repo, message, match, opts):
861 def commitfunc(ui, repo, message, match, opts):
868 return repo.commit(message, opts.get('user'), opts.get('date'), match,
862 return repo.commit(message, opts.get('user'), opts.get('date'), match,
869 editor=e, extra=extra)
863 editor=e, extra=extra)
870
864
871 branch = repo[None].branch()
865 branch = repo[None].branch()
872 bheads = repo.branchheads(branch)
866 bheads = repo.branchheads(branch)
873
867
874 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
868 node = cmdutil.commit(ui, repo, commitfunc, pats, opts)
875 if not node:
869 if not node:
876 ui.status(_("nothing changed\n"))
870 ui.status(_("nothing changed\n"))
877 return 1
871 return 1
878
872
879 ctx = repo[node]
873 ctx = repo[node]
880 parents = ctx.parents()
874 parents = ctx.parents()
881
875
882 if bheads and not [x for x in parents
876 if bheads and not [x for x in parents
883 if x.node() in bheads and x.branch() == branch]:
877 if x.node() in bheads and x.branch() == branch]:
884 ui.status(_('created new head\n'))
878 ui.status(_('created new head\n'))
885 # The message is not printed for initial roots. For the other
879 # The message is not printed for initial roots. For the other
886 # changesets, it is printed in the following situations:
880 # changesets, it is printed in the following situations:
887 #
881 #
888 # Par column: for the 2 parents with ...
882 # Par column: for the 2 parents with ...
889 # N: null or no parent
883 # N: null or no parent
890 # B: parent is on another named branch
884 # B: parent is on another named branch
891 # C: parent is a regular non head changeset
885 # C: parent is a regular non head changeset
892 # H: parent was a branch head of the current branch
886 # H: parent was a branch head of the current branch
893 # Msg column: whether we print "created new head" message
887 # Msg column: whether we print "created new head" message
894 # In the following, it is assumed that there already exists some
888 # In the following, it is assumed that there already exists some
895 # initial branch heads of the current branch, otherwise nothing is
889 # initial branch heads of the current branch, otherwise nothing is
896 # printed anyway.
890 # printed anyway.
897 #
891 #
898 # Par Msg Comment
892 # Par Msg Comment
899 # NN y additional topo root
893 # NN y additional topo root
900 #
894 #
901 # BN y additional branch root
895 # BN y additional branch root
902 # CN y additional topo head
896 # CN y additional topo head
903 # HN n usual case
897 # HN n usual case
904 #
898 #
905 # BB y weird additional branch root
899 # BB y weird additional branch root
906 # CB y branch merge
900 # CB y branch merge
907 # HB n merge with named branch
901 # HB n merge with named branch
908 #
902 #
909 # CC y additional head from merge
903 # CC y additional head from merge
910 # CH n merge with a head
904 # CH n merge with a head
911 #
905 #
912 # HH n head merge: head count decreases
906 # HH n head merge: head count decreases
913
907
914 if not opts.get('close_branch'):
908 if not opts.get('close_branch'):
915 for r in parents:
909 for r in parents:
916 if r.extra().get('close') and r.branch() == branch:
910 if r.extra().get('close') and r.branch() == branch:
917 ui.status(_('reopening closed branch head %d\n') % r)
911 ui.status(_('reopening closed branch head %d\n') % r)
918
912
919 if ui.debugflag:
913 if ui.debugflag:
920 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
914 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx.hex()))
921 elif ui.verbose:
915 elif ui.verbose:
922 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
916 ui.write(_('committed changeset %d:%s\n') % (int(ctx), ctx))
923
917
924 def copy(ui, repo, *pats, **opts):
918 def copy(ui, repo, *pats, **opts):
925 """mark files as copied for the next commit
919 """mark files as copied for the next commit
926
920
927 Mark dest as having copies of source files. If dest is a
921 Mark dest as having copies of source files. If dest is a
928 directory, copies are put in that directory. If dest is a file,
922 directory, copies are put in that directory. If dest is a file,
929 the source must be a single file.
923 the source must be a single file.
930
924
931 By default, this command copies the contents of files as they
925 By default, this command copies the contents of files as they
932 exist in the working directory. If invoked with -A/--after, the
926 exist in the working directory. If invoked with -A/--after, the
933 operation is recorded, but no copying is performed.
927 operation is recorded, but no copying is performed.
934
928
935 This command takes effect with the next commit. To undo a copy
929 This command takes effect with the next commit. To undo a copy
936 before that, see :hg:`revert`.
930 before that, see :hg:`revert`.
937
931
938 Returns 0 on success, 1 if errors are encountered.
932 Returns 0 on success, 1 if errors are encountered.
939 """
933 """
940 wlock = repo.wlock(False)
934 wlock = repo.wlock(False)
941 try:
935 try:
942 return cmdutil.copy(ui, repo, pats, opts)
936 return cmdutil.copy(ui, repo, pats, opts)
943 finally:
937 finally:
944 wlock.release()
938 wlock.release()
945
939
946 def debugancestor(ui, repo, *args):
940 def debugancestor(ui, repo, *args):
947 """find the ancestor revision of two revisions in a given index"""
941 """find the ancestor revision of two revisions in a given index"""
948 if len(args) == 3:
942 if len(args) == 3:
949 index, rev1, rev2 = args
943 index, rev1, rev2 = args
950 r = revlog.revlog(util.opener(os.getcwd(), audit=False), index)
944 r = revlog.revlog(util.opener(os.getcwd(), audit=False), index)
951 lookup = r.lookup
945 lookup = r.lookup
952 elif len(args) == 2:
946 elif len(args) == 2:
953 if not repo:
947 if not repo:
954 raise util.Abort(_("there is no Mercurial repository here "
948 raise util.Abort(_("there is no Mercurial repository here "
955 "(.hg not found)"))
949 "(.hg not found)"))
956 rev1, rev2 = args
950 rev1, rev2 = args
957 r = repo.changelog
951 r = repo.changelog
958 lookup = repo.lookup
952 lookup = repo.lookup
959 else:
953 else:
960 raise util.Abort(_('either two or three arguments required'))
954 raise util.Abort(_('either two or three arguments required'))
961 a = r.ancestor(lookup(rev1), lookup(rev2))
955 a = r.ancestor(lookup(rev1), lookup(rev2))
962 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
956 ui.write("%d:%s\n" % (r.rev(a), hex(a)))
963
957
964 def debugbuilddag(ui, repo, text,
958 def debugbuilddag(ui, repo, text,
965 mergeable_file=False,
959 mergeable_file=False,
966 appended_file=False,
960 appended_file=False,
967 overwritten_file=False,
961 overwritten_file=False,
968 new_file=False):
962 new_file=False):
969 """builds a repo with a given dag from scratch in the current empty repo
963 """builds a repo with a given dag from scratch in the current empty repo
970
964
971 Elements:
965 Elements:
972
966
973 - "+n" is a linear run of n nodes based on the current default parent
967 - "+n" is a linear run of n nodes based on the current default parent
974 - "." is a single node based on the current default parent
968 - "." is a single node based on the current default parent
975 - "$" resets the default parent to null (implied at the start);
969 - "$" resets the default parent to null (implied at the start);
976 otherwise the default parent is always the last node created
970 otherwise the default parent is always the last node created
977 - "<p" sets the default parent to the backref p
971 - "<p" sets the default parent to the backref p
978 - "*p" is a fork at parent p, which is a backref
972 - "*p" is a fork at parent p, which is a backref
979 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
973 - "*p1/p2" is a merge of parents p1 and p2, which are backrefs
980 - "/p2" is a merge of the preceding node and p2
974 - "/p2" is a merge of the preceding node and p2
981 - ":tag" defines a local tag for the preceding node
975 - ":tag" defines a local tag for the preceding node
982 - "@branch" sets the named branch for subsequent nodes
976 - "@branch" sets the named branch for subsequent nodes
983 - "!command" runs the command using your shell
977 - "!command" runs the command using your shell
984 - "!!my command\\n" is like "!", but to the end of the line
978 - "!!my command\\n" is like "!", but to the end of the line
985 - "#...\\n" is a comment up to the end of the line
979 - "#...\\n" is a comment up to the end of the line
986
980
987 Whitespace between the above elements is ignored.
981 Whitespace between the above elements is ignored.
988
982
989 A backref is either
983 A backref is either
990
984
991 - a number n, which references the node curr-n, where curr is the current
985 - a number n, which references the node curr-n, where curr is the current
992 node, or
986 node, or
993 - the name of a local tag you placed earlier using ":tag", or
987 - the name of a local tag you placed earlier using ":tag", or
994 - empty to denote the default parent.
988 - empty to denote the default parent.
995
989
996 All string valued-elements are either strictly alphanumeric, or must
990 All string valued-elements are either strictly alphanumeric, or must
997 be enclosed in double quotes ("..."), with "\\" as escape character.
991 be enclosed in double quotes ("..."), with "\\" as escape character.
998
992
999 Note that the --overwritten-file and --appended-file options imply the
993 Note that the --overwritten-file and --appended-file options imply the
1000 use of "HGMERGE=internal:local" during DAG buildup.
994 use of "HGMERGE=internal:local" during DAG buildup.
1001 """
995 """
1002
996
1003 if not (mergeable_file or appended_file or overwritten_file or new_file):
997 if not (mergeable_file or appended_file or overwritten_file or new_file):
1004 raise util.Abort(_('need at least one of -m, -a, -o, -n'))
998 raise util.Abort(_('need at least one of -m, -a, -o, -n'))
1005
999
1006 if len(repo.changelog) > 0:
1000 if len(repo.changelog) > 0:
1007 raise util.Abort(_('repository is not empty'))
1001 raise util.Abort(_('repository is not empty'))
1008
1002
1009 if overwritten_file or appended_file:
1003 if overwritten_file or appended_file:
1010 # we don't want to fail in merges during buildup
1004 # we don't want to fail in merges during buildup
1011 os.environ['HGMERGE'] = 'internal:local'
1005 os.environ['HGMERGE'] = 'internal:local'
1012
1006
1013 def writefile(fname, text, fmode="wb"):
1007 def writefile(fname, text, fmode="wb"):
1014 f = open(fname, fmode)
1008 f = open(fname, fmode)
1015 try:
1009 try:
1016 f.write(text)
1010 f.write(text)
1017 finally:
1011 finally:
1018 f.close()
1012 f.close()
1019
1013
1020 if mergeable_file:
1014 if mergeable_file:
1021 linesperrev = 2
1015 linesperrev = 2
1022 # determine number of revs in DAG
1016 # determine number of revs in DAG
1023 n = 0
1017 n = 0
1024 for type, data in dagparser.parsedag(text):
1018 for type, data in dagparser.parsedag(text):
1025 if type == 'n':
1019 if type == 'n':
1026 n += 1
1020 n += 1
1027 # make a file with k lines per rev
1021 # make a file with k lines per rev
1028 writefile("mf", "\n".join(str(i) for i in xrange(0, n * linesperrev))
1022 writefile("mf", "\n".join(str(i) for i in xrange(0, n * linesperrev))
1029 + "\n")
1023 + "\n")
1030
1024
1031 at = -1
1025 at = -1
1032 atbranch = 'default'
1026 atbranch = 'default'
1033 for type, data in dagparser.parsedag(text):
1027 for type, data in dagparser.parsedag(text):
1034 if type == 'n':
1028 if type == 'n':
1035 ui.status('node %s\n' % str(data))
1029 ui.status('node %s\n' % str(data))
1036 id, ps = data
1030 id, ps = data
1037 p1 = ps[0]
1031 p1 = ps[0]
1038 if p1 != at:
1032 if p1 != at:
1039 update(ui, repo, node=str(p1), clean=True)
1033 update(ui, repo, node=str(p1), clean=True)
1040 at = p1
1034 at = p1
1041 if repo.dirstate.branch() != atbranch:
1035 if repo.dirstate.branch() != atbranch:
1042 branch(ui, repo, atbranch, force=True)
1036 branch(ui, repo, atbranch, force=True)
1043 if len(ps) > 1:
1037 if len(ps) > 1:
1044 p2 = ps[1]
1038 p2 = ps[1]
1045 merge(ui, repo, node=p2)
1039 merge(ui, repo, node=p2)
1046
1040
1047 if mergeable_file:
1041 if mergeable_file:
1048 f = open("mf", "rb+")
1042 f = open("mf", "rb+")
1049 try:
1043 try:
1050 lines = f.read().split("\n")
1044 lines = f.read().split("\n")
1051 lines[id * linesperrev] += " r%i" % id
1045 lines[id * linesperrev] += " r%i" % id
1052 f.seek(0)
1046 f.seek(0)
1053 f.write("\n".join(lines))
1047 f.write("\n".join(lines))
1054 finally:
1048 finally:
1055 f.close()
1049 f.close()
1056
1050
1057 if appended_file:
1051 if appended_file:
1058 writefile("af", "r%i\n" % id, "ab")
1052 writefile("af", "r%i\n" % id, "ab")
1059
1053
1060 if overwritten_file:
1054 if overwritten_file:
1061 writefile("of", "r%i\n" % id)
1055 writefile("of", "r%i\n" % id)
1062
1056
1063 if new_file:
1057 if new_file:
1064 writefile("nf%i" % id, "r%i\n" % id)
1058 writefile("nf%i" % id, "r%i\n" % id)
1065
1059
1066 commit(ui, repo, addremove=True, message="r%i" % id, date=(id, 0))
1060 commit(ui, repo, addremove=True, message="r%i" % id, date=(id, 0))
1067 at = id
1061 at = id
1068 elif type == 'l':
1062 elif type == 'l':
1069 id, name = data
1063 id, name = data
1070 ui.status('tag %s\n' % name)
1064 ui.status('tag %s\n' % name)
1071 tag(ui, repo, name, local=True)
1065 tag(ui, repo, name, local=True)
1072 elif type == 'a':
1066 elif type == 'a':
1073 ui.status('branch %s\n' % data)
1067 ui.status('branch %s\n' % data)
1074 atbranch = data
1068 atbranch = data
1075 elif type in 'cC':
1069 elif type in 'cC':
1076 r = util.system(data, cwd=repo.root)
1070 r = util.system(data, cwd=repo.root)
1077 if r:
1071 if r:
1078 desc, r = util.explain_exit(r)
1072 desc, r = util.explain_exit(r)
1079 raise util.Abort(_('%s command %s') % (data, desc))
1073 raise util.Abort(_('%s command %s') % (data, desc))
1080
1074
1081 def debugcommands(ui, cmd='', *args):
1075 def debugcommands(ui, cmd='', *args):
1082 """list all available commands and options"""
1076 """list all available commands and options"""
1083 for cmd, vals in sorted(table.iteritems()):
1077 for cmd, vals in sorted(table.iteritems()):
1084 cmd = cmd.split('|')[0].strip('^')
1078 cmd = cmd.split('|')[0].strip('^')
1085 opts = ', '.join([i[1] for i in vals[1]])
1079 opts = ', '.join([i[1] for i in vals[1]])
1086 ui.write('%s: %s\n' % (cmd, opts))
1080 ui.write('%s: %s\n' % (cmd, opts))
1087
1081
1088 def debugcomplete(ui, cmd='', **opts):
1082 def debugcomplete(ui, cmd='', **opts):
1089 """returns the completion list associated with the given command"""
1083 """returns the completion list associated with the given command"""
1090
1084
1091 if opts.get('options'):
1085 if opts.get('options'):
1092 options = []
1086 options = []
1093 otables = [globalopts]
1087 otables = [globalopts]
1094 if cmd:
1088 if cmd:
1095 aliases, entry = cmdutil.findcmd(cmd, table, False)
1089 aliases, entry = cmdutil.findcmd(cmd, table, False)
1096 otables.append(entry[1])
1090 otables.append(entry[1])
1097 for t in otables:
1091 for t in otables:
1098 for o in t:
1092 for o in t:
1099 if "(DEPRECATED)" in o[3]:
1093 if "(DEPRECATED)" in o[3]:
1100 continue
1094 continue
1101 if o[0]:
1095 if o[0]:
1102 options.append('-%s' % o[0])
1096 options.append('-%s' % o[0])
1103 options.append('--%s' % o[1])
1097 options.append('--%s' % o[1])
1104 ui.write("%s\n" % "\n".join(options))
1098 ui.write("%s\n" % "\n".join(options))
1105 return
1099 return
1106
1100
1107 cmdlist = cmdutil.findpossible(cmd, table)
1101 cmdlist = cmdutil.findpossible(cmd, table)
1108 if ui.verbose:
1102 if ui.verbose:
1109 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1103 cmdlist = [' '.join(c[0]) for c in cmdlist.values()]
1110 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1104 ui.write("%s\n" % "\n".join(sorted(cmdlist)))
1111
1105
1112 def debugfsinfo(ui, path = "."):
1106 def debugfsinfo(ui, path = "."):
1113 """show information detected about current filesystem"""
1107 """show information detected about current filesystem"""
1114 open('.debugfsinfo', 'w').write('')
1108 open('.debugfsinfo', 'w').write('')
1115 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1109 ui.write('exec: %s\n' % (util.checkexec(path) and 'yes' or 'no'))
1116 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1110 ui.write('symlink: %s\n' % (util.checklink(path) and 'yes' or 'no'))
1117 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1111 ui.write('case-sensitive: %s\n' % (util.checkcase('.debugfsinfo')
1118 and 'yes' or 'no'))
1112 and 'yes' or 'no'))
1119 os.unlink('.debugfsinfo')
1113 os.unlink('.debugfsinfo')
1120
1114
1121 def debugrebuildstate(ui, repo, rev="tip"):
1115 def debugrebuildstate(ui, repo, rev="tip"):
1122 """rebuild the dirstate as it would look like for the given revision"""
1116 """rebuild the dirstate as it would look like for the given revision"""
1123 ctx = cmdutil.revsingle(repo, rev)
1117 ctx = cmdutil.revsingle(repo, rev)
1124 wlock = repo.wlock()
1118 wlock = repo.wlock()
1125 try:
1119 try:
1126 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
1120 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
1127 finally:
1121 finally:
1128 wlock.release()
1122 wlock.release()
1129
1123
1130 def debugcheckstate(ui, repo):
1124 def debugcheckstate(ui, repo):
1131 """validate the correctness of the current dirstate"""
1125 """validate the correctness of the current dirstate"""
1132 parent1, parent2 = repo.dirstate.parents()
1126 parent1, parent2 = repo.dirstate.parents()
1133 m1 = repo[parent1].manifest()
1127 m1 = repo[parent1].manifest()
1134 m2 = repo[parent2].manifest()
1128 m2 = repo[parent2].manifest()
1135 errors = 0
1129 errors = 0
1136 for f in repo.dirstate:
1130 for f in repo.dirstate:
1137 state = repo.dirstate[f]
1131 state = repo.dirstate[f]
1138 if state in "nr" and f not in m1:
1132 if state in "nr" and f not in m1:
1139 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1133 ui.warn(_("%s in state %s, but not in manifest1\n") % (f, state))
1140 errors += 1
1134 errors += 1
1141 if state in "a" and f in m1:
1135 if state in "a" and f in m1:
1142 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1136 ui.warn(_("%s in state %s, but also in manifest1\n") % (f, state))
1143 errors += 1
1137 errors += 1
1144 if state in "m" and f not in m1 and f not in m2:
1138 if state in "m" and f not in m1 and f not in m2:
1145 ui.warn(_("%s in state %s, but not in either manifest\n") %
1139 ui.warn(_("%s in state %s, but not in either manifest\n") %
1146 (f, state))
1140 (f, state))
1147 errors += 1
1141 errors += 1
1148 for f in m1:
1142 for f in m1:
1149 state = repo.dirstate[f]
1143 state = repo.dirstate[f]
1150 if state not in "nrm":
1144 if state not in "nrm":
1151 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1145 ui.warn(_("%s in manifest1, but listed as state %s") % (f, state))
1152 errors += 1
1146 errors += 1
1153 if errors:
1147 if errors:
1154 error = _(".hg/dirstate inconsistent with current parent's manifest")
1148 error = _(".hg/dirstate inconsistent with current parent's manifest")
1155 raise util.Abort(error)
1149 raise util.Abort(error)
1156
1150
1157 def showconfig(ui, repo, *values, **opts):
1151 def showconfig(ui, repo, *values, **opts):
1158 """show combined config settings from all hgrc files
1152 """show combined config settings from all hgrc files
1159
1153
1160 With no arguments, print names and values of all config items.
1154 With no arguments, print names and values of all config items.
1161
1155
1162 With one argument of the form section.name, print just the value
1156 With one argument of the form section.name, print just the value
1163 of that config item.
1157 of that config item.
1164
1158
1165 With multiple arguments, print names and values of all config
1159 With multiple arguments, print names and values of all config
1166 items with matching section names.
1160 items with matching section names.
1167
1161
1168 With --debug, the source (filename and line number) is printed
1162 With --debug, the source (filename and line number) is printed
1169 for each config item.
1163 for each config item.
1170
1164
1171 Returns 0 on success.
1165 Returns 0 on success.
1172 """
1166 """
1173
1167
1174 for f in util.rcpath():
1168 for f in util.rcpath():
1175 ui.debug(_('read config from: %s\n') % f)
1169 ui.debug(_('read config from: %s\n') % f)
1176 untrusted = bool(opts.get('untrusted'))
1170 untrusted = bool(opts.get('untrusted'))
1177 if values:
1171 if values:
1178 sections = [v for v in values if '.' not in v]
1172 sections = [v for v in values if '.' not in v]
1179 items = [v for v in values if '.' in v]
1173 items = [v for v in values if '.' in v]
1180 if len(items) > 1 or items and sections:
1174 if len(items) > 1 or items and sections:
1181 raise util.Abort(_('only one config item permitted'))
1175 raise util.Abort(_('only one config item permitted'))
1182 for section, name, value in ui.walkconfig(untrusted=untrusted):
1176 for section, name, value in ui.walkconfig(untrusted=untrusted):
1183 sectname = section + '.' + name
1177 sectname = section + '.' + name
1184 if values:
1178 if values:
1185 for v in values:
1179 for v in values:
1186 if v == section:
1180 if v == section:
1187 ui.debug('%s: ' %
1181 ui.debug('%s: ' %
1188 ui.configsource(section, name, untrusted))
1182 ui.configsource(section, name, untrusted))
1189 ui.write('%s=%s\n' % (sectname, value))
1183 ui.write('%s=%s\n' % (sectname, value))
1190 elif v == sectname:
1184 elif v == sectname:
1191 ui.debug('%s: ' %
1185 ui.debug('%s: ' %
1192 ui.configsource(section, name, untrusted))
1186 ui.configsource(section, name, untrusted))
1193 ui.write(value, '\n')
1187 ui.write(value, '\n')
1194 else:
1188 else:
1195 ui.debug('%s: ' %
1189 ui.debug('%s: ' %
1196 ui.configsource(section, name, untrusted))
1190 ui.configsource(section, name, untrusted))
1197 ui.write('%s=%s\n' % (sectname, value))
1191 ui.write('%s=%s\n' % (sectname, value))
1198
1192
1199 def debugpushkey(ui, repopath, namespace, *keyinfo):
1193 def debugpushkey(ui, repopath, namespace, *keyinfo):
1200 '''access the pushkey key/value protocol
1194 '''access the pushkey key/value protocol
1201
1195
1202 With two args, list the keys in the given namespace.
1196 With two args, list the keys in the given namespace.
1203
1197
1204 With five args, set a key to new if it currently is set to old.
1198 With five args, set a key to new if it currently is set to old.
1205 Reports success or failure.
1199 Reports success or failure.
1206 '''
1200 '''
1207
1201
1208 target = hg.repository(ui, repopath)
1202 target = hg.repository(ui, repopath)
1209 if keyinfo:
1203 if keyinfo:
1210 key, old, new = keyinfo
1204 key, old, new = keyinfo
1211 r = target.pushkey(namespace, key, old, new)
1205 r = target.pushkey(namespace, key, old, new)
1212 ui.status(str(r) + '\n')
1206 ui.status(str(r) + '\n')
1213 return not r
1207 return not r
1214 else:
1208 else:
1215 for k, v in target.listkeys(namespace).iteritems():
1209 for k, v in target.listkeys(namespace).iteritems():
1216 ui.write("%s\t%s\n" % (k.encode('string-escape'),
1210 ui.write("%s\t%s\n" % (k.encode('string-escape'),
1217 v.encode('string-escape')))
1211 v.encode('string-escape')))
1218
1212
1219 def debugrevspec(ui, repo, expr):
1213 def debugrevspec(ui, repo, expr):
1220 '''parse and apply a revision specification'''
1214 '''parse and apply a revision specification'''
1221 if ui.verbose:
1215 if ui.verbose:
1222 tree = revset.parse(expr)
1216 tree = revset.parse(expr)
1223 ui.note(tree, "\n")
1217 ui.note(tree, "\n")
1224 func = revset.match(expr)
1218 func = revset.match(expr)
1225 for c in func(repo, range(len(repo))):
1219 for c in func(repo, range(len(repo))):
1226 ui.write("%s\n" % c)
1220 ui.write("%s\n" % c)
1227
1221
1228 def debugsetparents(ui, repo, rev1, rev2=None):
1222 def debugsetparents(ui, repo, rev1, rev2=None):
1229 """manually set the parents of the current working directory
1223 """manually set the parents of the current working directory
1230
1224
1231 This is useful for writing repository conversion tools, but should
1225 This is useful for writing repository conversion tools, but should
1232 be used with care.
1226 be used with care.
1233
1227
1234 Returns 0 on success.
1228 Returns 0 on success.
1235 """
1229 """
1236
1230
1237 r1 = cmdutil.revsingle(repo, rev1).node()
1231 r1 = cmdutil.revsingle(repo, rev1).node()
1238 r2 = cmdutil.revsingle(repo, rev2, 'null').node()
1232 r2 = cmdutil.revsingle(repo, rev2, 'null').node()
1239
1233
1240 wlock = repo.wlock()
1234 wlock = repo.wlock()
1241 try:
1235 try:
1242 repo.dirstate.setparents(r1, r2)
1236 repo.dirstate.setparents(r1, r2)
1243 finally:
1237 finally:
1244 wlock.release()
1238 wlock.release()
1245
1239
1246 def debugstate(ui, repo, nodates=None):
1240 def debugstate(ui, repo, nodates=None):
1247 """show the contents of the current dirstate"""
1241 """show the contents of the current dirstate"""
1248 timestr = ""
1242 timestr = ""
1249 showdate = not nodates
1243 showdate = not nodates
1250 for file_, ent in sorted(repo.dirstate._map.iteritems()):
1244 for file_, ent in sorted(repo.dirstate._map.iteritems()):
1251 if showdate:
1245 if showdate:
1252 if ent[3] == -1:
1246 if ent[3] == -1:
1253 # Pad or slice to locale representation
1247 # Pad or slice to locale representation
1254 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
1248 locale_len = len(time.strftime("%Y-%m-%d %H:%M:%S ",
1255 time.localtime(0)))
1249 time.localtime(0)))
1256 timestr = 'unset'
1250 timestr = 'unset'
1257 timestr = (timestr[:locale_len] +
1251 timestr = (timestr[:locale_len] +
1258 ' ' * (locale_len - len(timestr)))
1252 ' ' * (locale_len - len(timestr)))
1259 else:
1253 else:
1260 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
1254 timestr = time.strftime("%Y-%m-%d %H:%M:%S ",
1261 time.localtime(ent[3]))
1255 time.localtime(ent[3]))
1262 if ent[1] & 020000:
1256 if ent[1] & 020000:
1263 mode = 'lnk'
1257 mode = 'lnk'
1264 else:
1258 else:
1265 mode = '%3o' % (ent[1] & 0777)
1259 mode = '%3o' % (ent[1] & 0777)
1266 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
1260 ui.write("%c %s %10d %s%s\n" % (ent[0], mode, ent[2], timestr, file_))
1267 for f in repo.dirstate.copies():
1261 for f in repo.dirstate.copies():
1268 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
1262 ui.write(_("copy: %s -> %s\n") % (repo.dirstate.copied(f), f))
1269
1263
1270 def debugsub(ui, repo, rev=None):
1264 def debugsub(ui, repo, rev=None):
1271 ctx = cmdutil.revsingle(repo, rev, None)
1265 ctx = cmdutil.revsingle(repo, rev, None)
1272 for k, v in sorted(ctx.substate.items()):
1266 for k, v in sorted(ctx.substate.items()):
1273 ui.write('path %s\n' % k)
1267 ui.write('path %s\n' % k)
1274 ui.write(' source %s\n' % v[0])
1268 ui.write(' source %s\n' % v[0])
1275 ui.write(' revision %s\n' % v[1])
1269 ui.write(' revision %s\n' % v[1])
1276
1270
1277 def debugdag(ui, repo, file_=None, *revs, **opts):
1271 def debugdag(ui, repo, file_=None, *revs, **opts):
1278 """format the changelog or an index DAG as a concise textual description
1272 """format the changelog or an index DAG as a concise textual description
1279
1273
1280 If you pass a revlog index, the revlog's DAG is emitted. If you list
1274 If you pass a revlog index, the revlog's DAG is emitted. If you list
1281 revision numbers, they get labelled in the output as rN.
1275 revision numbers, they get labelled in the output as rN.
1282
1276
1283 Otherwise, the changelog DAG of the current repo is emitted.
1277 Otherwise, the changelog DAG of the current repo is emitted.
1284 """
1278 """
1285 spaces = opts.get('spaces')
1279 spaces = opts.get('spaces')
1286 dots = opts.get('dots')
1280 dots = opts.get('dots')
1287 if file_:
1281 if file_:
1288 rlog = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1282 rlog = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1289 revs = set((int(r) for r in revs))
1283 revs = set((int(r) for r in revs))
1290 def events():
1284 def events():
1291 for r in rlog:
1285 for r in rlog:
1292 yield 'n', (r, list(set(p for p in rlog.parentrevs(r) if p != -1)))
1286 yield 'n', (r, list(set(p for p in rlog.parentrevs(r) if p != -1)))
1293 if r in revs:
1287 if r in revs:
1294 yield 'l', (r, "r%i" % r)
1288 yield 'l', (r, "r%i" % r)
1295 elif repo:
1289 elif repo:
1296 cl = repo.changelog
1290 cl = repo.changelog
1297 tags = opts.get('tags')
1291 tags = opts.get('tags')
1298 branches = opts.get('branches')
1292 branches = opts.get('branches')
1299 if tags:
1293 if tags:
1300 labels = {}
1294 labels = {}
1301 for l, n in repo.tags().items():
1295 for l, n in repo.tags().items():
1302 labels.setdefault(cl.rev(n), []).append(l)
1296 labels.setdefault(cl.rev(n), []).append(l)
1303 def events():
1297 def events():
1304 b = "default"
1298 b = "default"
1305 for r in cl:
1299 for r in cl:
1306 if branches:
1300 if branches:
1307 newb = cl.read(cl.node(r))[5]['branch']
1301 newb = cl.read(cl.node(r))[5]['branch']
1308 if newb != b:
1302 if newb != b:
1309 yield 'a', newb
1303 yield 'a', newb
1310 b = newb
1304 b = newb
1311 yield 'n', (r, list(set(p for p in cl.parentrevs(r) if p != -1)))
1305 yield 'n', (r, list(set(p for p in cl.parentrevs(r) if p != -1)))
1312 if tags:
1306 if tags:
1313 ls = labels.get(r)
1307 ls = labels.get(r)
1314 if ls:
1308 if ls:
1315 for l in ls:
1309 for l in ls:
1316 yield 'l', (r, l)
1310 yield 'l', (r, l)
1317 else:
1311 else:
1318 raise util.Abort(_('need repo for changelog dag'))
1312 raise util.Abort(_('need repo for changelog dag'))
1319
1313
1320 for line in dagparser.dagtextlines(events(),
1314 for line in dagparser.dagtextlines(events(),
1321 addspaces=spaces,
1315 addspaces=spaces,
1322 wraplabels=True,
1316 wraplabels=True,
1323 wrapannotations=True,
1317 wrapannotations=True,
1324 wrapnonlinear=dots,
1318 wrapnonlinear=dots,
1325 usedots=dots,
1319 usedots=dots,
1326 maxlinewidth=70):
1320 maxlinewidth=70):
1327 ui.write(line)
1321 ui.write(line)
1328 ui.write("\n")
1322 ui.write("\n")
1329
1323
1330 def debugdata(ui, repo, file_, rev):
1324 def debugdata(ui, repo, file_, rev):
1331 """dump the contents of a data file revision"""
1325 """dump the contents of a data file revision"""
1332 r = None
1326 r = None
1333 if repo:
1327 if repo:
1334 filelog = repo.file(file_)
1328 filelog = repo.file(file_)
1335 if len(filelog):
1329 if len(filelog):
1336 r = filelog
1330 r = filelog
1337 if not r:
1331 if not r:
1338 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_[:-2] + ".i")
1332 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_[:-2] + ".i")
1339 try:
1333 try:
1340 ui.write(r.revision(r.lookup(rev)))
1334 ui.write(r.revision(r.lookup(rev)))
1341 except KeyError:
1335 except KeyError:
1342 raise util.Abort(_('invalid revision identifier %s') % rev)
1336 raise util.Abort(_('invalid revision identifier %s') % rev)
1343
1337
1344 def debugdate(ui, date, range=None, **opts):
1338 def debugdate(ui, date, range=None, **opts):
1345 """parse and display a date"""
1339 """parse and display a date"""
1346 if opts["extended"]:
1340 if opts["extended"]:
1347 d = util.parsedate(date, util.extendeddateformats)
1341 d = util.parsedate(date, util.extendeddateformats)
1348 else:
1342 else:
1349 d = util.parsedate(date)
1343 d = util.parsedate(date)
1350 ui.write("internal: %s %s\n" % d)
1344 ui.write("internal: %s %s\n" % d)
1351 ui.write("standard: %s\n" % util.datestr(d))
1345 ui.write("standard: %s\n" % util.datestr(d))
1352 if range:
1346 if range:
1353 m = util.matchdate(range)
1347 m = util.matchdate(range)
1354 ui.write("match: %s\n" % m(d[0]))
1348 ui.write("match: %s\n" % m(d[0]))
1355
1349
1356 def debugignore(ui, repo, *values, **opts):
1350 def debugignore(ui, repo, *values, **opts):
1357 """display the combined ignore pattern"""
1351 """display the combined ignore pattern"""
1358 ignore = repo.dirstate._ignore
1352 ignore = repo.dirstate._ignore
1359 if hasattr(ignore, 'includepat'):
1353 if hasattr(ignore, 'includepat'):
1360 ui.write("%s\n" % ignore.includepat)
1354 ui.write("%s\n" % ignore.includepat)
1361 else:
1355 else:
1362 raise util.Abort(_("no ignore patterns found"))
1356 raise util.Abort(_("no ignore patterns found"))
1363
1357
1364 def debugindex(ui, repo, file_, **opts):
1358 def debugindex(ui, repo, file_, **opts):
1365 """dump the contents of an index file"""
1359 """dump the contents of an index file"""
1366 r = None
1360 r = None
1367 if repo:
1361 if repo:
1368 filelog = repo.file(file_)
1362 filelog = repo.file(file_)
1369 if len(filelog):
1363 if len(filelog):
1370 r = filelog
1364 r = filelog
1371
1365
1372 format = opts.get('format', 0)
1366 format = opts.get('format', 0)
1373 if format not in (0, 1):
1367 if format not in (0, 1):
1374 raise util.Abort("unknown format %d" % format)
1368 raise util.Abort("unknown format %d" % format)
1375
1369
1376 if not r:
1370 if not r:
1377 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1371 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1378
1372
1379 if format == 0:
1373 if format == 0:
1380 ui.write(" rev offset length base linkrev"
1374 ui.write(" rev offset length base linkrev"
1381 " nodeid p1 p2\n")
1375 " nodeid p1 p2\n")
1382 elif format == 1:
1376 elif format == 1:
1383 ui.write(" rev flag offset length"
1377 ui.write(" rev flag offset length"
1384 " size base link p1 p2 nodeid\n")
1378 " size base link p1 p2 nodeid\n")
1385
1379
1386 for i in r:
1380 for i in r:
1387 node = r.node(i)
1381 node = r.node(i)
1388 if format == 0:
1382 if format == 0:
1389 try:
1383 try:
1390 pp = r.parents(node)
1384 pp = r.parents(node)
1391 except:
1385 except:
1392 pp = [nullid, nullid]
1386 pp = [nullid, nullid]
1393 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1387 ui.write("% 6d % 9d % 7d % 6d % 7d %s %s %s\n" % (
1394 i, r.start(i), r.length(i), r.base(i), r.linkrev(i),
1388 i, r.start(i), r.length(i), r.base(i), r.linkrev(i),
1395 short(node), short(pp[0]), short(pp[1])))
1389 short(node), short(pp[0]), short(pp[1])))
1396 elif format == 1:
1390 elif format == 1:
1397 pr = r.parentrevs(i)
1391 pr = r.parentrevs(i)
1398 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1392 ui.write("% 6d %04x % 8d % 8d % 8d % 6d % 6d % 6d % 6d %s\n" % (
1399 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1393 i, r.flags(i), r.start(i), r.length(i), r.rawsize(i),
1400 r.base(i), r.linkrev(i), pr[0], pr[1], short(node)))
1394 r.base(i), r.linkrev(i), pr[0], pr[1], short(node)))
1401
1395
1402 def debugindexdot(ui, repo, file_):
1396 def debugindexdot(ui, repo, file_):
1403 """dump an index DAG as a graphviz dot file"""
1397 """dump an index DAG as a graphviz dot file"""
1404 r = None
1398 r = None
1405 if repo:
1399 if repo:
1406 filelog = repo.file(file_)
1400 filelog = repo.file(file_)
1407 if len(filelog):
1401 if len(filelog):
1408 r = filelog
1402 r = filelog
1409 if not r:
1403 if not r:
1410 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1404 r = revlog.revlog(util.opener(os.getcwd(), audit=False), file_)
1411 ui.write("digraph G {\n")
1405 ui.write("digraph G {\n")
1412 for i in r:
1406 for i in r:
1413 node = r.node(i)
1407 node = r.node(i)
1414 pp = r.parents(node)
1408 pp = r.parents(node)
1415 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1409 ui.write("\t%d -> %d\n" % (r.rev(pp[0]), i))
1416 if pp[1] != nullid:
1410 if pp[1] != nullid:
1417 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1411 ui.write("\t%d -> %d\n" % (r.rev(pp[1]), i))
1418 ui.write("}\n")
1412 ui.write("}\n")
1419
1413
1420 def debuginstall(ui):
1414 def debuginstall(ui):
1421 '''test Mercurial installation
1415 '''test Mercurial installation
1422
1416
1423 Returns 0 on success.
1417 Returns 0 on success.
1424 '''
1418 '''
1425
1419
1426 def writetemp(contents):
1420 def writetemp(contents):
1427 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1421 (fd, name) = tempfile.mkstemp(prefix="hg-debuginstall-")
1428 f = os.fdopen(fd, "wb")
1422 f = os.fdopen(fd, "wb")
1429 f.write(contents)
1423 f.write(contents)
1430 f.close()
1424 f.close()
1431 return name
1425 return name
1432
1426
1433 problems = 0
1427 problems = 0
1434
1428
1435 # encoding
1429 # encoding
1436 ui.status(_("Checking encoding (%s)...\n") % encoding.encoding)
1430 ui.status(_("Checking encoding (%s)...\n") % encoding.encoding)
1437 try:
1431 try:
1438 encoding.fromlocal("test")
1432 encoding.fromlocal("test")
1439 except util.Abort, inst:
1433 except util.Abort, inst:
1440 ui.write(" %s\n" % inst)
1434 ui.write(" %s\n" % inst)
1441 ui.write(_(" (check that your locale is properly set)\n"))
1435 ui.write(_(" (check that your locale is properly set)\n"))
1442 problems += 1
1436 problems += 1
1443
1437
1444 # compiled modules
1438 # compiled modules
1445 ui.status(_("Checking installed modules (%s)...\n")
1439 ui.status(_("Checking installed modules (%s)...\n")
1446 % os.path.dirname(__file__))
1440 % os.path.dirname(__file__))
1447 try:
1441 try:
1448 import bdiff, mpatch, base85, osutil
1442 import bdiff, mpatch, base85, osutil
1449 except Exception, inst:
1443 except Exception, inst:
1450 ui.write(" %s\n" % inst)
1444 ui.write(" %s\n" % inst)
1451 ui.write(_(" One or more extensions could not be found"))
1445 ui.write(_(" One or more extensions could not be found"))
1452 ui.write(_(" (check that you compiled the extensions)\n"))
1446 ui.write(_(" (check that you compiled the extensions)\n"))
1453 problems += 1
1447 problems += 1
1454
1448
1455 # templates
1449 # templates
1456 ui.status(_("Checking templates...\n"))
1450 ui.status(_("Checking templates...\n"))
1457 try:
1451 try:
1458 import templater
1452 import templater
1459 templater.templater(templater.templatepath("map-cmdline.default"))
1453 templater.templater(templater.templatepath("map-cmdline.default"))
1460 except Exception, inst:
1454 except Exception, inst:
1461 ui.write(" %s\n" % inst)
1455 ui.write(" %s\n" % inst)
1462 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
1456 ui.write(_(" (templates seem to have been installed incorrectly)\n"))
1463 problems += 1
1457 problems += 1
1464
1458
1465 # patch
1459 # patch
1466 ui.status(_("Checking patch...\n"))
1460 ui.status(_("Checking patch...\n"))
1467 patchproblems = 0
1461 patchproblems = 0
1468 a = "1\n2\n3\n4\n"
1462 a = "1\n2\n3\n4\n"
1469 b = "1\n2\n3\ninsert\n4\n"
1463 b = "1\n2\n3\ninsert\n4\n"
1470 fa = writetemp(a)
1464 fa = writetemp(a)
1471 d = mdiff.unidiff(a, None, b, None, os.path.basename(fa),
1465 d = mdiff.unidiff(a, None, b, None, os.path.basename(fa),
1472 os.path.basename(fa))
1466 os.path.basename(fa))
1473 fd = writetemp(d)
1467 fd = writetemp(d)
1474
1468
1475 files = {}
1469 files = {}
1476 try:
1470 try:
1477 patch.patch(fd, ui, cwd=os.path.dirname(fa), files=files)
1471 patch.patch(fd, ui, cwd=os.path.dirname(fa), files=files)
1478 except util.Abort, e:
1472 except util.Abort, e:
1479 ui.write(_(" patch call failed:\n"))
1473 ui.write(_(" patch call failed:\n"))
1480 ui.write(" " + str(e) + "\n")
1474 ui.write(" " + str(e) + "\n")
1481 patchproblems += 1
1475 patchproblems += 1
1482 else:
1476 else:
1483 if list(files) != [os.path.basename(fa)]:
1477 if list(files) != [os.path.basename(fa)]:
1484 ui.write(_(" unexpected patch output!\n"))
1478 ui.write(_(" unexpected patch output!\n"))
1485 patchproblems += 1
1479 patchproblems += 1
1486 a = open(fa).read()
1480 a = open(fa).read()
1487 if a != b:
1481 if a != b:
1488 ui.write(_(" patch test failed!\n"))
1482 ui.write(_(" patch test failed!\n"))
1489 patchproblems += 1
1483 patchproblems += 1
1490
1484
1491 if patchproblems:
1485 if patchproblems:
1492 if ui.config('ui', 'patch'):
1486 if ui.config('ui', 'patch'):
1493 ui.write(_(" (Current patch tool may be incompatible with patch,"
1487 ui.write(_(" (Current patch tool may be incompatible with patch,"
1494 " or misconfigured. Please check your configuration"
1488 " or misconfigured. Please check your configuration"
1495 " file)\n"))
1489 " file)\n"))
1496 else:
1490 else:
1497 ui.write(_(" Internal patcher failure, please report this error"
1491 ui.write(_(" Internal patcher failure, please report this error"
1498 " to http://mercurial.selenic.com/wiki/BugTracker\n"))
1492 " to http://mercurial.selenic.com/wiki/BugTracker\n"))
1499 problems += patchproblems
1493 problems += patchproblems
1500
1494
1501 os.unlink(fa)
1495 os.unlink(fa)
1502 os.unlink(fd)
1496 os.unlink(fd)
1503
1497
1504 # editor
1498 # editor
1505 ui.status(_("Checking commit editor...\n"))
1499 ui.status(_("Checking commit editor...\n"))
1506 editor = ui.geteditor()
1500 editor = ui.geteditor()
1507 cmdpath = util.find_exe(editor) or util.find_exe(editor.split()[0])
1501 cmdpath = util.find_exe(editor) or util.find_exe(editor.split()[0])
1508 if not cmdpath:
1502 if not cmdpath:
1509 if editor == 'vi':
1503 if editor == 'vi':
1510 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
1504 ui.write(_(" No commit editor set and can't find vi in PATH\n"))
1511 ui.write(_(" (specify a commit editor in your configuration"
1505 ui.write(_(" (specify a commit editor in your configuration"
1512 " file)\n"))
1506 " file)\n"))
1513 else:
1507 else:
1514 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
1508 ui.write(_(" Can't find editor '%s' in PATH\n") % editor)
1515 ui.write(_(" (specify a commit editor in your configuration"
1509 ui.write(_(" (specify a commit editor in your configuration"
1516 " file)\n"))
1510 " file)\n"))
1517 problems += 1
1511 problems += 1
1518
1512
1519 # check username
1513 # check username
1520 ui.status(_("Checking username...\n"))
1514 ui.status(_("Checking username...\n"))
1521 try:
1515 try:
1522 ui.username()
1516 ui.username()
1523 except util.Abort, e:
1517 except util.Abort, e:
1524 ui.write(" %s\n" % e)
1518 ui.write(" %s\n" % e)
1525 ui.write(_(" (specify a username in your configuration file)\n"))
1519 ui.write(_(" (specify a username in your configuration file)\n"))
1526 problems += 1
1520 problems += 1
1527
1521
1528 if not problems:
1522 if not problems:
1529 ui.status(_("No problems detected\n"))
1523 ui.status(_("No problems detected\n"))
1530 else:
1524 else:
1531 ui.write(_("%s problems detected,"
1525 ui.write(_("%s problems detected,"
1532 " please check your install!\n") % problems)
1526 " please check your install!\n") % problems)
1533
1527
1534 return problems
1528 return problems
1535
1529
1536 def debugrename(ui, repo, file1, *pats, **opts):
1530 def debugrename(ui, repo, file1, *pats, **opts):
1537 """dump rename information"""
1531 """dump rename information"""
1538
1532
1539 ctx = cmdutil.revsingle(repo, opts.get('rev'))
1533 ctx = cmdutil.revsingle(repo, opts.get('rev'))
1540 m = cmdutil.match(repo, (file1,) + pats, opts)
1534 m = cmdutil.match(repo, (file1,) + pats, opts)
1541 for abs in ctx.walk(m):
1535 for abs in ctx.walk(m):
1542 fctx = ctx[abs]
1536 fctx = ctx[abs]
1543 o = fctx.filelog().renamed(fctx.filenode())
1537 o = fctx.filelog().renamed(fctx.filenode())
1544 rel = m.rel(abs)
1538 rel = m.rel(abs)
1545 if o:
1539 if o:
1546 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1540 ui.write(_("%s renamed from %s:%s\n") % (rel, o[0], hex(o[1])))
1547 else:
1541 else:
1548 ui.write(_("%s not renamed\n") % rel)
1542 ui.write(_("%s not renamed\n") % rel)
1549
1543
1550 def debugwalk(ui, repo, *pats, **opts):
1544 def debugwalk(ui, repo, *pats, **opts):
1551 """show how files match on given patterns"""
1545 """show how files match on given patterns"""
1552 m = cmdutil.match(repo, pats, opts)
1546 m = cmdutil.match(repo, pats, opts)
1553 items = list(repo.walk(m))
1547 items = list(repo.walk(m))
1554 if not items:
1548 if not items:
1555 return
1549 return
1556 fmt = 'f %%-%ds %%-%ds %%s' % (
1550 fmt = 'f %%-%ds %%-%ds %%s' % (
1557 max([len(abs) for abs in items]),
1551 max([len(abs) for abs in items]),
1558 max([len(m.rel(abs)) for abs in items]))
1552 max([len(m.rel(abs)) for abs in items]))
1559 for abs in items:
1553 for abs in items:
1560 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
1554 line = fmt % (abs, m.rel(abs), m.exact(abs) and 'exact' or '')
1561 ui.write("%s\n" % line.rstrip())
1555 ui.write("%s\n" % line.rstrip())
1562
1556
1563 def diff(ui, repo, *pats, **opts):
1557 def diff(ui, repo, *pats, **opts):
1564 """diff repository (or selected files)
1558 """diff repository (or selected files)
1565
1559
1566 Show differences between revisions for the specified files.
1560 Show differences between revisions for the specified files.
1567
1561
1568 Differences between files are shown using the unified diff format.
1562 Differences between files are shown using the unified diff format.
1569
1563
1570 .. note::
1564 .. note::
1571 diff may generate unexpected results for merges, as it will
1565 diff may generate unexpected results for merges, as it will
1572 default to comparing against the working directory's first
1566 default to comparing against the working directory's first
1573 parent changeset if no revisions are specified.
1567 parent changeset if no revisions are specified.
1574
1568
1575 When two revision arguments are given, then changes are shown
1569 When two revision arguments are given, then changes are shown
1576 between those revisions. If only one revision is specified then
1570 between those revisions. If only one revision is specified then
1577 that revision is compared to the working directory, and, when no
1571 that revision is compared to the working directory, and, when no
1578 revisions are specified, the working directory files are compared
1572 revisions are specified, the working directory files are compared
1579 to its parent.
1573 to its parent.
1580
1574
1581 Alternatively you can specify -c/--change with a revision to see
1575 Alternatively you can specify -c/--change with a revision to see
1582 the changes in that changeset relative to its first parent.
1576 the changes in that changeset relative to its first parent.
1583
1577
1584 Without the -a/--text option, diff will avoid generating diffs of
1578 Without the -a/--text option, diff will avoid generating diffs of
1585 files it detects as binary. With -a, diff will generate a diff
1579 files it detects as binary. With -a, diff will generate a diff
1586 anyway, probably with undesirable results.
1580 anyway, probably with undesirable results.
1587
1581
1588 Use the -g/--git option to generate diffs in the git extended diff
1582 Use the -g/--git option to generate diffs in the git extended diff
1589 format. For more information, read :hg:`help diffs`.
1583 format. For more information, read :hg:`help diffs`.
1590
1584
1591 Returns 0 on success.
1585 Returns 0 on success.
1592 """
1586 """
1593
1587
1594 revs = opts.get('rev')
1588 revs = opts.get('rev')
1595 change = opts.get('change')
1589 change = opts.get('change')
1596 stat = opts.get('stat')
1590 stat = opts.get('stat')
1597 reverse = opts.get('reverse')
1591 reverse = opts.get('reverse')
1598
1592
1599 if revs and change:
1593 if revs and change:
1600 msg = _('cannot specify --rev and --change at the same time')
1594 msg = _('cannot specify --rev and --change at the same time')
1601 raise util.Abort(msg)
1595 raise util.Abort(msg)
1602 elif change:
1596 elif change:
1603 node2 = repo.lookup(change)
1597 node2 = repo.lookup(change)
1604 node1 = repo[node2].parents()[0].node()
1598 node1 = repo[node2].parents()[0].node()
1605 else:
1599 else:
1606 node1, node2 = cmdutil.revpair(repo, revs)
1600 node1, node2 = cmdutil.revpair(repo, revs)
1607
1601
1608 if reverse:
1602 if reverse:
1609 node1, node2 = node2, node1
1603 node1, node2 = node2, node1
1610
1604
1611 diffopts = patch.diffopts(ui, opts)
1605 diffopts = patch.diffopts(ui, opts)
1612 m = cmdutil.match(repo, pats, opts)
1606 m = cmdutil.match(repo, pats, opts)
1613 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
1607 cmdutil.diffordiffstat(ui, repo, diffopts, node1, node2, m, stat=stat,
1614 listsubrepos=opts.get('subrepos'))
1608 listsubrepos=opts.get('subrepos'))
1615
1609
1616 def export(ui, repo, *changesets, **opts):
1610 def export(ui, repo, *changesets, **opts):
1617 """dump the header and diffs for one or more changesets
1611 """dump the header and diffs for one or more changesets
1618
1612
1619 Print the changeset header and diffs for one or more revisions.
1613 Print the changeset header and diffs for one or more revisions.
1620
1614
1621 The information shown in the changeset header is: author, date,
1615 The information shown in the changeset header is: author, date,
1622 branch name (if non-default), changeset hash, parent(s) and commit
1616 branch name (if non-default), changeset hash, parent(s) and commit
1623 comment.
1617 comment.
1624
1618
1625 .. note::
1619 .. note::
1626 export may generate unexpected diff output for merge
1620 export may generate unexpected diff output for merge
1627 changesets, as it will compare the merge changeset against its
1621 changesets, as it will compare the merge changeset against its
1628 first parent only.
1622 first parent only.
1629
1623
1630 Output may be to a file, in which case the name of the file is
1624 Output may be to a file, in which case the name of the file is
1631 given using a format string. The formatting rules are as follows:
1625 given using a format string. The formatting rules are as follows:
1632
1626
1633 :``%%``: literal "%" character
1627 :``%%``: literal "%" character
1634 :``%H``: changeset hash (40 hexadecimal digits)
1628 :``%H``: changeset hash (40 hexadecimal digits)
1635 :``%N``: number of patches being generated
1629 :``%N``: number of patches being generated
1636 :``%R``: changeset revision number
1630 :``%R``: changeset revision number
1637 :``%b``: basename of the exporting repository
1631 :``%b``: basename of the exporting repository
1638 :``%h``: short-form changeset hash (12 hexadecimal digits)
1632 :``%h``: short-form changeset hash (12 hexadecimal digits)
1639 :``%n``: zero-padded sequence number, starting at 1
1633 :``%n``: zero-padded sequence number, starting at 1
1640 :``%r``: zero-padded changeset revision number
1634 :``%r``: zero-padded changeset revision number
1641
1635
1642 Without the -a/--text option, export will avoid generating diffs
1636 Without the -a/--text option, export will avoid generating diffs
1643 of files it detects as binary. With -a, export will generate a
1637 of files it detects as binary. With -a, export will generate a
1644 diff anyway, probably with undesirable results.
1638 diff anyway, probably with undesirable results.
1645
1639
1646 Use the -g/--git option to generate diffs in the git extended diff
1640 Use the -g/--git option to generate diffs in the git extended diff
1647 format. See :hg:`help diffs` for more information.
1641 format. See :hg:`help diffs` for more information.
1648
1642
1649 With the --switch-parent option, the diff will be against the
1643 With the --switch-parent option, the diff will be against the
1650 second parent. It can be useful to review a merge.
1644 second parent. It can be useful to review a merge.
1651
1645
1652 Returns 0 on success.
1646 Returns 0 on success.
1653 """
1647 """
1654 changesets += tuple(opts.get('rev', []))
1648 changesets += tuple(opts.get('rev', []))
1655 if not changesets:
1649 if not changesets:
1656 raise util.Abort(_("export requires at least one changeset"))
1650 raise util.Abort(_("export requires at least one changeset"))
1657 revs = cmdutil.revrange(repo, changesets)
1651 revs = cmdutil.revrange(repo, changesets)
1658 if len(revs) > 1:
1652 if len(revs) > 1:
1659 ui.note(_('exporting patches:\n'))
1653 ui.note(_('exporting patches:\n'))
1660 else:
1654 else:
1661 ui.note(_('exporting patch:\n'))
1655 ui.note(_('exporting patch:\n'))
1662 cmdutil.export(repo, revs, template=opts.get('output'),
1656 cmdutil.export(repo, revs, template=opts.get('output'),
1663 switch_parent=opts.get('switch_parent'),
1657 switch_parent=opts.get('switch_parent'),
1664 opts=patch.diffopts(ui, opts))
1658 opts=patch.diffopts(ui, opts))
1665
1659
1666 def forget(ui, repo, *pats, **opts):
1660 def forget(ui, repo, *pats, **opts):
1667 """forget the specified files on the next commit
1661 """forget the specified files on the next commit
1668
1662
1669 Mark the specified files so they will no longer be tracked
1663 Mark the specified files so they will no longer be tracked
1670 after the next commit.
1664 after the next commit.
1671
1665
1672 This only removes files from the current branch, not from the
1666 This only removes files from the current branch, not from the
1673 entire project history, and it does not delete them from the
1667 entire project history, and it does not delete them from the
1674 working directory.
1668 working directory.
1675
1669
1676 To undo a forget before the next commit, see :hg:`add`.
1670 To undo a forget before the next commit, see :hg:`add`.
1677
1671
1678 Returns 0 on success.
1672 Returns 0 on success.
1679 """
1673 """
1680
1674
1681 if not pats:
1675 if not pats:
1682 raise util.Abort(_('no files specified'))
1676 raise util.Abort(_('no files specified'))
1683
1677
1684 m = cmdutil.match(repo, pats, opts)
1678 m = cmdutil.match(repo, pats, opts)
1685 s = repo.status(match=m, clean=True)
1679 s = repo.status(match=m, clean=True)
1686 forget = sorted(s[0] + s[1] + s[3] + s[6])
1680 forget = sorted(s[0] + s[1] + s[3] + s[6])
1687 errs = 0
1681 errs = 0
1688
1682
1689 for f in m.files():
1683 for f in m.files():
1690 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
1684 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
1691 ui.warn(_('not removing %s: file is already untracked\n')
1685 ui.warn(_('not removing %s: file is already untracked\n')
1692 % m.rel(f))
1686 % m.rel(f))
1693 errs = 1
1687 errs = 1
1694
1688
1695 for f in forget:
1689 for f in forget:
1696 if ui.verbose or not m.exact(f):
1690 if ui.verbose or not m.exact(f):
1697 ui.status(_('removing %s\n') % m.rel(f))
1691 ui.status(_('removing %s\n') % m.rel(f))
1698
1692
1699 repo[None].remove(forget, unlink=False)
1693 repo[None].remove(forget, unlink=False)
1700 return errs
1694 return errs
1701
1695
1702 def grep(ui, repo, pattern, *pats, **opts):
1696 def grep(ui, repo, pattern, *pats, **opts):
1703 """search for a pattern in specified files and revisions
1697 """search for a pattern in specified files and revisions
1704
1698
1705 Search revisions of files for a regular expression.
1699 Search revisions of files for a regular expression.
1706
1700
1707 This command behaves differently than Unix grep. It only accepts
1701 This command behaves differently than Unix grep. It only accepts
1708 Python/Perl regexps. It searches repository history, not the
1702 Python/Perl regexps. It searches repository history, not the
1709 working directory. It always prints the revision number in which a
1703 working directory. It always prints the revision number in which a
1710 match appears.
1704 match appears.
1711
1705
1712 By default, grep only prints output for the first revision of a
1706 By default, grep only prints output for the first revision of a
1713 file in which it finds a match. To get it to print every revision
1707 file in which it finds a match. To get it to print every revision
1714 that contains a change in match status ("-" for a match that
1708 that contains a change in match status ("-" for a match that
1715 becomes a non-match, or "+" for a non-match that becomes a match),
1709 becomes a non-match, or "+" for a non-match that becomes a match),
1716 use the --all flag.
1710 use the --all flag.
1717
1711
1718 Returns 0 if a match is found, 1 otherwise.
1712 Returns 0 if a match is found, 1 otherwise.
1719 """
1713 """
1720 reflags = 0
1714 reflags = 0
1721 if opts.get('ignore_case'):
1715 if opts.get('ignore_case'):
1722 reflags |= re.I
1716 reflags |= re.I
1723 try:
1717 try:
1724 regexp = re.compile(pattern, reflags)
1718 regexp = re.compile(pattern, reflags)
1725 except re.error, inst:
1719 except re.error, inst:
1726 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
1720 ui.warn(_("grep: invalid match pattern: %s\n") % inst)
1727 return 1
1721 return 1
1728 sep, eol = ':', '\n'
1722 sep, eol = ':', '\n'
1729 if opts.get('print0'):
1723 if opts.get('print0'):
1730 sep = eol = '\0'
1724 sep = eol = '\0'
1731
1725
1732 getfile = util.lrucachefunc(repo.file)
1726 getfile = util.lrucachefunc(repo.file)
1733
1727
1734 def matchlines(body):
1728 def matchlines(body):
1735 begin = 0
1729 begin = 0
1736 linenum = 0
1730 linenum = 0
1737 while True:
1731 while True:
1738 match = regexp.search(body, begin)
1732 match = regexp.search(body, begin)
1739 if not match:
1733 if not match:
1740 break
1734 break
1741 mstart, mend = match.span()
1735 mstart, mend = match.span()
1742 linenum += body.count('\n', begin, mstart) + 1
1736 linenum += body.count('\n', begin, mstart) + 1
1743 lstart = body.rfind('\n', begin, mstart) + 1 or begin
1737 lstart = body.rfind('\n', begin, mstart) + 1 or begin
1744 begin = body.find('\n', mend) + 1 or len(body)
1738 begin = body.find('\n', mend) + 1 or len(body)
1745 lend = begin - 1
1739 lend = begin - 1
1746 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
1740 yield linenum, mstart - lstart, mend - lstart, body[lstart:lend]
1747
1741
1748 class linestate(object):
1742 class linestate(object):
1749 def __init__(self, line, linenum, colstart, colend):
1743 def __init__(self, line, linenum, colstart, colend):
1750 self.line = line
1744 self.line = line
1751 self.linenum = linenum
1745 self.linenum = linenum
1752 self.colstart = colstart
1746 self.colstart = colstart
1753 self.colend = colend
1747 self.colend = colend
1754
1748
1755 def __hash__(self):
1749 def __hash__(self):
1756 return hash((self.linenum, self.line))
1750 return hash((self.linenum, self.line))
1757
1751
1758 def __eq__(self, other):
1752 def __eq__(self, other):
1759 return self.line == other.line
1753 return self.line == other.line
1760
1754
1761 matches = {}
1755 matches = {}
1762 copies = {}
1756 copies = {}
1763 def grepbody(fn, rev, body):
1757 def grepbody(fn, rev, body):
1764 matches[rev].setdefault(fn, [])
1758 matches[rev].setdefault(fn, [])
1765 m = matches[rev][fn]
1759 m = matches[rev][fn]
1766 for lnum, cstart, cend, line in matchlines(body):
1760 for lnum, cstart, cend, line in matchlines(body):
1767 s = linestate(line, lnum, cstart, cend)
1761 s = linestate(line, lnum, cstart, cend)
1768 m.append(s)
1762 m.append(s)
1769
1763
1770 def difflinestates(a, b):
1764 def difflinestates(a, b):
1771 sm = difflib.SequenceMatcher(None, a, b)
1765 sm = difflib.SequenceMatcher(None, a, b)
1772 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
1766 for tag, alo, ahi, blo, bhi in sm.get_opcodes():
1773 if tag == 'insert':
1767 if tag == 'insert':
1774 for i in xrange(blo, bhi):
1768 for i in xrange(blo, bhi):
1775 yield ('+', b[i])
1769 yield ('+', b[i])
1776 elif tag == 'delete':
1770 elif tag == 'delete':
1777 for i in xrange(alo, ahi):
1771 for i in xrange(alo, ahi):
1778 yield ('-', a[i])
1772 yield ('-', a[i])
1779 elif tag == 'replace':
1773 elif tag == 'replace':
1780 for i in xrange(alo, ahi):
1774 for i in xrange(alo, ahi):
1781 yield ('-', a[i])
1775 yield ('-', a[i])
1782 for i in xrange(blo, bhi):
1776 for i in xrange(blo, bhi):
1783 yield ('+', b[i])
1777 yield ('+', b[i])
1784
1778
1785 def display(fn, ctx, pstates, states):
1779 def display(fn, ctx, pstates, states):
1786 rev = ctx.rev()
1780 rev = ctx.rev()
1787 datefunc = ui.quiet and util.shortdate or util.datestr
1781 datefunc = ui.quiet and util.shortdate or util.datestr
1788 found = False
1782 found = False
1789 filerevmatches = {}
1783 filerevmatches = {}
1790 if opts.get('all'):
1784 if opts.get('all'):
1791 iter = difflinestates(pstates, states)
1785 iter = difflinestates(pstates, states)
1792 else:
1786 else:
1793 iter = [('', l) for l in states]
1787 iter = [('', l) for l in states]
1794 for change, l in iter:
1788 for change, l in iter:
1795 cols = [fn, str(rev)]
1789 cols = [fn, str(rev)]
1796 before, match, after = None, None, None
1790 before, match, after = None, None, None
1797 if opts.get('line_number'):
1791 if opts.get('line_number'):
1798 cols.append(str(l.linenum))
1792 cols.append(str(l.linenum))
1799 if opts.get('all'):
1793 if opts.get('all'):
1800 cols.append(change)
1794 cols.append(change)
1801 if opts.get('user'):
1795 if opts.get('user'):
1802 cols.append(ui.shortuser(ctx.user()))
1796 cols.append(ui.shortuser(ctx.user()))
1803 if opts.get('date'):
1797 if opts.get('date'):
1804 cols.append(datefunc(ctx.date()))
1798 cols.append(datefunc(ctx.date()))
1805 if opts.get('files_with_matches'):
1799 if opts.get('files_with_matches'):
1806 c = (fn, rev)
1800 c = (fn, rev)
1807 if c in filerevmatches:
1801 if c in filerevmatches:
1808 continue
1802 continue
1809 filerevmatches[c] = 1
1803 filerevmatches[c] = 1
1810 else:
1804 else:
1811 before = l.line[:l.colstart]
1805 before = l.line[:l.colstart]
1812 match = l.line[l.colstart:l.colend]
1806 match = l.line[l.colstart:l.colend]
1813 after = l.line[l.colend:]
1807 after = l.line[l.colend:]
1814 ui.write(sep.join(cols))
1808 ui.write(sep.join(cols))
1815 if before is not None:
1809 if before is not None:
1816 ui.write(sep + before)
1810 ui.write(sep + before)
1817 ui.write(match, label='grep.match')
1811 ui.write(match, label='grep.match')
1818 ui.write(after)
1812 ui.write(after)
1819 ui.write(eol)
1813 ui.write(eol)
1820 found = True
1814 found = True
1821 return found
1815 return found
1822
1816
1823 skip = {}
1817 skip = {}
1824 revfiles = {}
1818 revfiles = {}
1825 matchfn = cmdutil.match(repo, pats, opts)
1819 matchfn = cmdutil.match(repo, pats, opts)
1826 found = False
1820 found = False
1827 follow = opts.get('follow')
1821 follow = opts.get('follow')
1828
1822
1829 def prep(ctx, fns):
1823 def prep(ctx, fns):
1830 rev = ctx.rev()
1824 rev = ctx.rev()
1831 pctx = ctx.parents()[0]
1825 pctx = ctx.parents()[0]
1832 parent = pctx.rev()
1826 parent = pctx.rev()
1833 matches.setdefault(rev, {})
1827 matches.setdefault(rev, {})
1834 matches.setdefault(parent, {})
1828 matches.setdefault(parent, {})
1835 files = revfiles.setdefault(rev, [])
1829 files = revfiles.setdefault(rev, [])
1836 for fn in fns:
1830 for fn in fns:
1837 flog = getfile(fn)
1831 flog = getfile(fn)
1838 try:
1832 try:
1839 fnode = ctx.filenode(fn)
1833 fnode = ctx.filenode(fn)
1840 except error.LookupError:
1834 except error.LookupError:
1841 continue
1835 continue
1842
1836
1843 copied = flog.renamed(fnode)
1837 copied = flog.renamed(fnode)
1844 copy = follow and copied and copied[0]
1838 copy = follow and copied and copied[0]
1845 if copy:
1839 if copy:
1846 copies.setdefault(rev, {})[fn] = copy
1840 copies.setdefault(rev, {})[fn] = copy
1847 if fn in skip:
1841 if fn in skip:
1848 if copy:
1842 if copy:
1849 skip[copy] = True
1843 skip[copy] = True
1850 continue
1844 continue
1851 files.append(fn)
1845 files.append(fn)
1852
1846
1853 if fn not in matches[rev]:
1847 if fn not in matches[rev]:
1854 grepbody(fn, rev, flog.read(fnode))
1848 grepbody(fn, rev, flog.read(fnode))
1855
1849
1856 pfn = copy or fn
1850 pfn = copy or fn
1857 if pfn not in matches[parent]:
1851 if pfn not in matches[parent]:
1858 try:
1852 try:
1859 fnode = pctx.filenode(pfn)
1853 fnode = pctx.filenode(pfn)
1860 grepbody(pfn, parent, flog.read(fnode))
1854 grepbody(pfn, parent, flog.read(fnode))
1861 except error.LookupError:
1855 except error.LookupError:
1862 pass
1856 pass
1863
1857
1864 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
1858 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
1865 rev = ctx.rev()
1859 rev = ctx.rev()
1866 parent = ctx.parents()[0].rev()
1860 parent = ctx.parents()[0].rev()
1867 for fn in sorted(revfiles.get(rev, [])):
1861 for fn in sorted(revfiles.get(rev, [])):
1868 states = matches[rev][fn]
1862 states = matches[rev][fn]
1869 copy = copies.get(rev, {}).get(fn)
1863 copy = copies.get(rev, {}).get(fn)
1870 if fn in skip:
1864 if fn in skip:
1871 if copy:
1865 if copy:
1872 skip[copy] = True
1866 skip[copy] = True
1873 continue
1867 continue
1874 pstates = matches.get(parent, {}).get(copy or fn, [])
1868 pstates = matches.get(parent, {}).get(copy or fn, [])
1875 if pstates or states:
1869 if pstates or states:
1876 r = display(fn, ctx, pstates, states)
1870 r = display(fn, ctx, pstates, states)
1877 found = found or r
1871 found = found or r
1878 if r and not opts.get('all'):
1872 if r and not opts.get('all'):
1879 skip[fn] = True
1873 skip[fn] = True
1880 if copy:
1874 if copy:
1881 skip[copy] = True
1875 skip[copy] = True
1882 del matches[rev]
1876 del matches[rev]
1883 del revfiles[rev]
1877 del revfiles[rev]
1884
1878
1885 return not found
1879 return not found
1886
1880
1887 def heads(ui, repo, *branchrevs, **opts):
1881 def heads(ui, repo, *branchrevs, **opts):
1888 """show current repository heads or show branch heads
1882 """show current repository heads or show branch heads
1889
1883
1890 With no arguments, show all repository branch heads.
1884 With no arguments, show all repository branch heads.
1891
1885
1892 Repository "heads" are changesets with no child changesets. They are
1886 Repository "heads" are changesets with no child changesets. They are
1893 where development generally takes place and are the usual targets
1887 where development generally takes place and are the usual targets
1894 for update and merge operations. Branch heads are changesets that have
1888 for update and merge operations. Branch heads are changesets that have
1895 no child changeset on the same branch.
1889 no child changeset on the same branch.
1896
1890
1897 If one or more REVs are given, only branch heads on the branches
1891 If one or more REVs are given, only branch heads on the branches
1898 associated with the specified changesets are shown.
1892 associated with the specified changesets are shown.
1899
1893
1900 If -c/--closed is specified, also show branch heads marked closed
1894 If -c/--closed is specified, also show branch heads marked closed
1901 (see :hg:`commit --close-branch`).
1895 (see :hg:`commit --close-branch`).
1902
1896
1903 If STARTREV is specified, only those heads that are descendants of
1897 If STARTREV is specified, only those heads that are descendants of
1904 STARTREV will be displayed.
1898 STARTREV will be displayed.
1905
1899
1906 If -t/--topo is specified, named branch mechanics will be ignored and only
1900 If -t/--topo is specified, named branch mechanics will be ignored and only
1907 changesets without children will be shown.
1901 changesets without children will be shown.
1908
1902
1909 Returns 0 if matching heads are found, 1 if not.
1903 Returns 0 if matching heads are found, 1 if not.
1910 """
1904 """
1911
1905
1912 start = None
1906 start = None
1913 if 'rev' in opts:
1907 if 'rev' in opts:
1914 start = cmdutil.revsingle(repo, opts['rev'], None).node()
1908 start = cmdutil.revsingle(repo, opts['rev'], None).node()
1915
1909
1916 if opts.get('topo'):
1910 if opts.get('topo'):
1917 heads = [repo[h] for h in repo.heads(start)]
1911 heads = [repo[h] for h in repo.heads(start)]
1918 else:
1912 else:
1919 heads = []
1913 heads = []
1920 for b, ls in repo.branchmap().iteritems():
1914 for b, ls in repo.branchmap().iteritems():
1921 if start is None:
1915 if start is None:
1922 heads += [repo[h] for h in ls]
1916 heads += [repo[h] for h in ls]
1923 continue
1917 continue
1924 startrev = repo.changelog.rev(start)
1918 startrev = repo.changelog.rev(start)
1925 descendants = set(repo.changelog.descendants(startrev))
1919 descendants = set(repo.changelog.descendants(startrev))
1926 descendants.add(startrev)
1920 descendants.add(startrev)
1927 rev = repo.changelog.rev
1921 rev = repo.changelog.rev
1928 heads += [repo[h] for h in ls if rev(h) in descendants]
1922 heads += [repo[h] for h in ls if rev(h) in descendants]
1929
1923
1930 if branchrevs:
1924 if branchrevs:
1931 branches = set(repo[br].branch() for br in branchrevs)
1925 branches = set(repo[br].branch() for br in branchrevs)
1932 heads = [h for h in heads if h.branch() in branches]
1926 heads = [h for h in heads if h.branch() in branches]
1933
1927
1934 if not opts.get('closed'):
1928 if not opts.get('closed'):
1935 heads = [h for h in heads if not h.extra().get('close')]
1929 heads = [h for h in heads if not h.extra().get('close')]
1936
1930
1937 if opts.get('active') and branchrevs:
1931 if opts.get('active') and branchrevs:
1938 dagheads = repo.heads(start)
1932 dagheads = repo.heads(start)
1939 heads = [h for h in heads if h.node() in dagheads]
1933 heads = [h for h in heads if h.node() in dagheads]
1940
1934
1941 if branchrevs:
1935 if branchrevs:
1942 haveheads = set(h.branch() for h in heads)
1936 haveheads = set(h.branch() for h in heads)
1943 if branches - haveheads:
1937 if branches - haveheads:
1944 headless = ', '.join(b for b in branches - haveheads)
1938 headless = ', '.join(b for b in branches - haveheads)
1945 msg = _('no open branch heads found on branches %s')
1939 msg = _('no open branch heads found on branches %s')
1946 if opts.get('rev'):
1940 if opts.get('rev'):
1947 msg += _(' (started at %s)' % opts['rev'])
1941 msg += _(' (started at %s)' % opts['rev'])
1948 ui.warn((msg + '\n') % headless)
1942 ui.warn((msg + '\n') % headless)
1949
1943
1950 if not heads:
1944 if not heads:
1951 return 1
1945 return 1
1952
1946
1953 heads = sorted(heads, key=lambda x: -x.rev())
1947 heads = sorted(heads, key=lambda x: -x.rev())
1954 displayer = cmdutil.show_changeset(ui, repo, opts)
1948 displayer = cmdutil.show_changeset(ui, repo, opts)
1955 for ctx in heads:
1949 for ctx in heads:
1956 displayer.show(ctx)
1950 displayer.show(ctx)
1957 displayer.close()
1951 displayer.close()
1958
1952
1959 def help_(ui, name=None, with_version=False, unknowncmd=False):
1953 def help_(ui, name=None, with_version=False, unknowncmd=False):
1960 """show help for a given topic or a help overview
1954 """show help for a given topic or a help overview
1961
1955
1962 With no arguments, print a list of commands with short help messages.
1956 With no arguments, print a list of commands with short help messages.
1963
1957
1964 Given a topic, extension, or command name, print help for that
1958 Given a topic, extension, or command name, print help for that
1965 topic.
1959 topic.
1966
1960
1967 Returns 0 if successful.
1961 Returns 0 if successful.
1968 """
1962 """
1969 option_lists = []
1963 option_lists = []
1970 textwidth = ui.termwidth() - 2
1964 textwidth = ui.termwidth() - 2
1971
1965
1972 def addglobalopts(aliases):
1966 def addglobalopts(aliases):
1973 if ui.verbose:
1967 if ui.verbose:
1974 option_lists.append((_("global options:"), globalopts))
1968 option_lists.append((_("global options:"), globalopts))
1975 if name == 'shortlist':
1969 if name == 'shortlist':
1976 option_lists.append((_('use "hg help" for the full list '
1970 option_lists.append((_('use "hg help" for the full list '
1977 'of commands'), ()))
1971 'of commands'), ()))
1978 else:
1972 else:
1979 if name == 'shortlist':
1973 if name == 'shortlist':
1980 msg = _('use "hg help" for the full list of commands '
1974 msg = _('use "hg help" for the full list of commands '
1981 'or "hg -v" for details')
1975 'or "hg -v" for details')
1982 elif aliases:
1976 elif aliases:
1983 msg = _('use "hg -v help%s" to show builtin aliases and '
1977 msg = _('use "hg -v help%s" to show builtin aliases and '
1984 'global options') % (name and " " + name or "")
1978 'global options') % (name and " " + name or "")
1985 else:
1979 else:
1986 msg = _('use "hg -v help %s" to show global options') % name
1980 msg = _('use "hg -v help %s" to show global options') % name
1987 option_lists.append((msg, ()))
1981 option_lists.append((msg, ()))
1988
1982
1989 def helpcmd(name):
1983 def helpcmd(name):
1990 if with_version:
1984 if with_version:
1991 version_(ui)
1985 version_(ui)
1992 ui.write('\n')
1986 ui.write('\n')
1993
1987
1994 try:
1988 try:
1995 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
1989 aliases, entry = cmdutil.findcmd(name, table, strict=unknowncmd)
1996 except error.AmbiguousCommand, inst:
1990 except error.AmbiguousCommand, inst:
1997 # py3k fix: except vars can't be used outside the scope of the
1991 # py3k fix: except vars can't be used outside the scope of the
1998 # except block, nor can be used inside a lambda. python issue4617
1992 # except block, nor can be used inside a lambda. python issue4617
1999 prefix = inst.args[0]
1993 prefix = inst.args[0]
2000 select = lambda c: c.lstrip('^').startswith(prefix)
1994 select = lambda c: c.lstrip('^').startswith(prefix)
2001 helplist(_('list of commands:\n\n'), select)
1995 helplist(_('list of commands:\n\n'), select)
2002 return
1996 return
2003
1997
2004 # check if it's an invalid alias and display its error if it is
1998 # check if it's an invalid alias and display its error if it is
2005 if getattr(entry[0], 'badalias', False):
1999 if getattr(entry[0], 'badalias', False):
2006 if not unknowncmd:
2000 if not unknowncmd:
2007 entry[0](ui)
2001 entry[0](ui)
2008 return
2002 return
2009
2003
2010 # synopsis
2004 # synopsis
2011 if len(entry) > 2:
2005 if len(entry) > 2:
2012 if entry[2].startswith('hg'):
2006 if entry[2].startswith('hg'):
2013 ui.write("%s\n" % entry[2])
2007 ui.write("%s\n" % entry[2])
2014 else:
2008 else:
2015 ui.write('hg %s %s\n' % (aliases[0], entry[2]))
2009 ui.write('hg %s %s\n' % (aliases[0], entry[2]))
2016 else:
2010 else:
2017 ui.write('hg %s\n' % aliases[0])
2011 ui.write('hg %s\n' % aliases[0])
2018
2012
2019 # aliases
2013 # aliases
2020 if not ui.quiet and len(aliases) > 1:
2014 if not ui.quiet and len(aliases) > 1:
2021 ui.write(_("\naliases: %s\n") % ', '.join(aliases[1:]))
2015 ui.write(_("\naliases: %s\n") % ', '.join(aliases[1:]))
2022
2016
2023 # description
2017 # description
2024 doc = gettext(entry[0].__doc__)
2018 doc = gettext(entry[0].__doc__)
2025 if not doc:
2019 if not doc:
2026 doc = _("(no help text available)")
2020 doc = _("(no help text available)")
2027 if hasattr(entry[0], 'definition'): # aliased command
2021 if hasattr(entry[0], 'definition'): # aliased command
2028 if entry[0].definition.startswith('!'): # shell alias
2022 if entry[0].definition.startswith('!'): # shell alias
2029 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
2023 doc = _('shell alias for::\n\n %s') % entry[0].definition[1:]
2030 else:
2024 else:
2031 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
2025 doc = _('alias for: hg %s\n\n%s') % (entry[0].definition, doc)
2032 if ui.quiet:
2026 if ui.quiet:
2033 doc = doc.splitlines()[0]
2027 doc = doc.splitlines()[0]
2034 keep = ui.verbose and ['verbose'] or []
2028 keep = ui.verbose and ['verbose'] or []
2035 formatted, pruned = minirst.format(doc, textwidth, keep=keep)
2029 formatted, pruned = minirst.format(doc, textwidth, keep=keep)
2036 ui.write("\n%s\n" % formatted)
2030 ui.write("\n%s\n" % formatted)
2037 if pruned:
2031 if pruned:
2038 ui.write(_('\nuse "hg -v help %s" to show verbose help\n') % name)
2032 ui.write(_('\nuse "hg -v help %s" to show verbose help\n') % name)
2039
2033
2040 if not ui.quiet:
2034 if not ui.quiet:
2041 # options
2035 # options
2042 if entry[1]:
2036 if entry[1]:
2043 option_lists.append((_("options:\n"), entry[1]))
2037 option_lists.append((_("options:\n"), entry[1]))
2044
2038
2045 addglobalopts(False)
2039 addglobalopts(False)
2046
2040
2047 def helplist(header, select=None):
2041 def helplist(header, select=None):
2048 h = {}
2042 h = {}
2049 cmds = {}
2043 cmds = {}
2050 for c, e in table.iteritems():
2044 for c, e in table.iteritems():
2051 f = c.split("|", 1)[0]
2045 f = c.split("|", 1)[0]
2052 if select and not select(f):
2046 if select and not select(f):
2053 continue
2047 continue
2054 if (not select and name != 'shortlist' and
2048 if (not select and name != 'shortlist' and
2055 e[0].__module__ != __name__):
2049 e[0].__module__ != __name__):
2056 continue
2050 continue
2057 if name == "shortlist" and not f.startswith("^"):
2051 if name == "shortlist" and not f.startswith("^"):
2058 continue
2052 continue
2059 f = f.lstrip("^")
2053 f = f.lstrip("^")
2060 if not ui.debugflag and f.startswith("debug"):
2054 if not ui.debugflag and f.startswith("debug"):
2061 continue
2055 continue
2062 doc = e[0].__doc__
2056 doc = e[0].__doc__
2063 if doc and 'DEPRECATED' in doc and not ui.verbose:
2057 if doc and 'DEPRECATED' in doc and not ui.verbose:
2064 continue
2058 continue
2065 doc = gettext(doc)
2059 doc = gettext(doc)
2066 if not doc:
2060 if not doc:
2067 doc = _("(no help text available)")
2061 doc = _("(no help text available)")
2068 h[f] = doc.splitlines()[0].rstrip()
2062 h[f] = doc.splitlines()[0].rstrip()
2069 cmds[f] = c.lstrip("^")
2063 cmds[f] = c.lstrip("^")
2070
2064
2071 if not h:
2065 if not h:
2072 ui.status(_('no commands defined\n'))
2066 ui.status(_('no commands defined\n'))
2073 return
2067 return
2074
2068
2075 ui.status(header)
2069 ui.status(header)
2076 fns = sorted(h)
2070 fns = sorted(h)
2077 m = max(map(len, fns))
2071 m = max(map(len, fns))
2078 for f in fns:
2072 for f in fns:
2079 if ui.verbose:
2073 if ui.verbose:
2080 commands = cmds[f].replace("|",", ")
2074 commands = cmds[f].replace("|",", ")
2081 ui.write(" %s:\n %s\n"%(commands, h[f]))
2075 ui.write(" %s:\n %s\n"%(commands, h[f]))
2082 else:
2076 else:
2083 ui.write('%s\n' % (util.wrap(h[f], textwidth,
2077 ui.write('%s\n' % (util.wrap(h[f], textwidth,
2084 initindent=' %-*s ' % (m, f),
2078 initindent=' %-*s ' % (m, f),
2085 hangindent=' ' * (m + 4))))
2079 hangindent=' ' * (m + 4))))
2086
2080
2087 if not ui.quiet:
2081 if not ui.quiet:
2088 addglobalopts(True)
2082 addglobalopts(True)
2089
2083
2090 def helptopic(name):
2084 def helptopic(name):
2091 for names, header, doc in help.helptable:
2085 for names, header, doc in help.helptable:
2092 if name in names:
2086 if name in names:
2093 break
2087 break
2094 else:
2088 else:
2095 raise error.UnknownCommand(name)
2089 raise error.UnknownCommand(name)
2096
2090
2097 # description
2091 # description
2098 if not doc:
2092 if not doc:
2099 doc = _("(no help text available)")
2093 doc = _("(no help text available)")
2100 if hasattr(doc, '__call__'):
2094 if hasattr(doc, '__call__'):
2101 doc = doc()
2095 doc = doc()
2102
2096
2103 ui.write("%s\n\n" % header)
2097 ui.write("%s\n\n" % header)
2104 ui.write("%s\n" % minirst.format(doc, textwidth, indent=4))
2098 ui.write("%s\n" % minirst.format(doc, textwidth, indent=4))
2105
2099
2106 def helpext(name):
2100 def helpext(name):
2107 try:
2101 try:
2108 mod = extensions.find(name)
2102 mod = extensions.find(name)
2109 doc = gettext(mod.__doc__) or _('no help text available')
2103 doc = gettext(mod.__doc__) or _('no help text available')
2110 except KeyError:
2104 except KeyError:
2111 mod = None
2105 mod = None
2112 doc = extensions.disabledext(name)
2106 doc = extensions.disabledext(name)
2113 if not doc:
2107 if not doc:
2114 raise error.UnknownCommand(name)
2108 raise error.UnknownCommand(name)
2115
2109
2116 if '\n' not in doc:
2110 if '\n' not in doc:
2117 head, tail = doc, ""
2111 head, tail = doc, ""
2118 else:
2112 else:
2119 head, tail = doc.split('\n', 1)
2113 head, tail = doc.split('\n', 1)
2120 ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
2114 ui.write(_('%s extension - %s\n\n') % (name.split('.')[-1], head))
2121 if tail:
2115 if tail:
2122 ui.write(minirst.format(tail, textwidth))
2116 ui.write(minirst.format(tail, textwidth))
2123 ui.status('\n\n')
2117 ui.status('\n\n')
2124
2118
2125 if mod:
2119 if mod:
2126 try:
2120 try:
2127 ct = mod.cmdtable
2121 ct = mod.cmdtable
2128 except AttributeError:
2122 except AttributeError:
2129 ct = {}
2123 ct = {}
2130 modcmds = set([c.split('|', 1)[0] for c in ct])
2124 modcmds = set([c.split('|', 1)[0] for c in ct])
2131 helplist(_('list of commands:\n\n'), modcmds.__contains__)
2125 helplist(_('list of commands:\n\n'), modcmds.__contains__)
2132 else:
2126 else:
2133 ui.write(_('use "hg help extensions" for information on enabling '
2127 ui.write(_('use "hg help extensions" for information on enabling '
2134 'extensions\n'))
2128 'extensions\n'))
2135
2129
2136 def helpextcmd(name):
2130 def helpextcmd(name):
2137 cmd, ext, mod = extensions.disabledcmd(ui, name, ui.config('ui', 'strict'))
2131 cmd, ext, mod = extensions.disabledcmd(ui, name, ui.config('ui', 'strict'))
2138 doc = gettext(mod.__doc__).splitlines()[0]
2132 doc = gettext(mod.__doc__).splitlines()[0]
2139
2133
2140 msg = help.listexts(_("'%s' is provided by the following "
2134 msg = help.listexts(_("'%s' is provided by the following "
2141 "extension:") % cmd, {ext: doc}, len(ext),
2135 "extension:") % cmd, {ext: doc}, len(ext),
2142 indent=4)
2136 indent=4)
2143 ui.write(minirst.format(msg, textwidth))
2137 ui.write(minirst.format(msg, textwidth))
2144 ui.write('\n\n')
2138 ui.write('\n\n')
2145 ui.write(_('use "hg help extensions" for information on enabling '
2139 ui.write(_('use "hg help extensions" for information on enabling '
2146 'extensions\n'))
2140 'extensions\n'))
2147
2141
2148 help.addtopichook('revsets', revset.makedoc)
2142 help.addtopichook('revsets', revset.makedoc)
2149
2143
2150 if name and name != 'shortlist':
2144 if name and name != 'shortlist':
2151 i = None
2145 i = None
2152 if unknowncmd:
2146 if unknowncmd:
2153 queries = (helpextcmd,)
2147 queries = (helpextcmd,)
2154 else:
2148 else:
2155 queries = (helptopic, helpcmd, helpext, helpextcmd)
2149 queries = (helptopic, helpcmd, helpext, helpextcmd)
2156 for f in queries:
2150 for f in queries:
2157 try:
2151 try:
2158 f(name)
2152 f(name)
2159 i = None
2153 i = None
2160 break
2154 break
2161 except error.UnknownCommand, inst:
2155 except error.UnknownCommand, inst:
2162 i = inst
2156 i = inst
2163 if i:
2157 if i:
2164 raise i
2158 raise i
2165
2159
2166 else:
2160 else:
2167 # program name
2161 # program name
2168 if ui.verbose or with_version:
2162 if ui.verbose or with_version:
2169 version_(ui)
2163 version_(ui)
2170 else:
2164 else:
2171 ui.status(_("Mercurial Distributed SCM\n"))
2165 ui.status(_("Mercurial Distributed SCM\n"))
2172 ui.status('\n')
2166 ui.status('\n')
2173
2167
2174 # list of commands
2168 # list of commands
2175 if name == "shortlist":
2169 if name == "shortlist":
2176 header = _('basic commands:\n\n')
2170 header = _('basic commands:\n\n')
2177 else:
2171 else:
2178 header = _('list of commands:\n\n')
2172 header = _('list of commands:\n\n')
2179
2173
2180 helplist(header)
2174 helplist(header)
2181 if name != 'shortlist':
2175 if name != 'shortlist':
2182 exts, maxlength = extensions.enabled()
2176 exts, maxlength = extensions.enabled()
2183 text = help.listexts(_('enabled extensions:'), exts, maxlength)
2177 text = help.listexts(_('enabled extensions:'), exts, maxlength)
2184 if text:
2178 if text:
2185 ui.write("\n%s\n" % minirst.format(text, textwidth))
2179 ui.write("\n%s\n" % minirst.format(text, textwidth))
2186
2180
2187 # list all option lists
2181 # list all option lists
2188 opt_output = []
2182 opt_output = []
2189 multioccur = False
2183 multioccur = False
2190 for title, options in option_lists:
2184 for title, options in option_lists:
2191 opt_output.append(("\n%s" % title, None))
2185 opt_output.append(("\n%s" % title, None))
2192 for option in options:
2186 for option in options:
2193 if len(option) == 5:
2187 if len(option) == 5:
2194 shortopt, longopt, default, desc, optlabel = option
2188 shortopt, longopt, default, desc, optlabel = option
2195 else:
2189 else:
2196 shortopt, longopt, default, desc = option
2190 shortopt, longopt, default, desc = option
2197 optlabel = _("VALUE") # default label
2191 optlabel = _("VALUE") # default label
2198
2192
2199 if _("DEPRECATED") in desc and not ui.verbose:
2193 if _("DEPRECATED") in desc and not ui.verbose:
2200 continue
2194 continue
2201 if isinstance(default, list):
2195 if isinstance(default, list):
2202 numqualifier = " %s [+]" % optlabel
2196 numqualifier = " %s [+]" % optlabel
2203 multioccur = True
2197 multioccur = True
2204 elif (default is not None) and not isinstance(default, bool):
2198 elif (default is not None) and not isinstance(default, bool):
2205 numqualifier = " %s" % optlabel
2199 numqualifier = " %s" % optlabel
2206 else:
2200 else:
2207 numqualifier = ""
2201 numqualifier = ""
2208 opt_output.append(("%2s%s" %
2202 opt_output.append(("%2s%s" %
2209 (shortopt and "-%s" % shortopt,
2203 (shortopt and "-%s" % shortopt,
2210 longopt and " --%s%s" %
2204 longopt and " --%s%s" %
2211 (longopt, numqualifier)),
2205 (longopt, numqualifier)),
2212 "%s%s" % (desc,
2206 "%s%s" % (desc,
2213 default
2207 default
2214 and _(" (default: %s)") % default
2208 and _(" (default: %s)") % default
2215 or "")))
2209 or "")))
2216 if multioccur:
2210 if multioccur:
2217 msg = _("\n[+] marked option can be specified multiple times")
2211 msg = _("\n[+] marked option can be specified multiple times")
2218 if ui.verbose and name != 'shortlist':
2212 if ui.verbose and name != 'shortlist':
2219 opt_output.append((msg, None))
2213 opt_output.append((msg, None))
2220 else:
2214 else:
2221 opt_output.insert(-1, (msg, None))
2215 opt_output.insert(-1, (msg, None))
2222
2216
2223 if not name:
2217 if not name:
2224 ui.write(_("\nadditional help topics:\n\n"))
2218 ui.write(_("\nadditional help topics:\n\n"))
2225 topics = []
2219 topics = []
2226 for names, header, doc in help.helptable:
2220 for names, header, doc in help.helptable:
2227 topics.append((sorted(names, key=len, reverse=True)[0], header))
2221 topics.append((sorted(names, key=len, reverse=True)[0], header))
2228 topics_len = max([len(s[0]) for s in topics])
2222 topics_len = max([len(s[0]) for s in topics])
2229 for t, desc in topics:
2223 for t, desc in topics:
2230 ui.write(" %-*s %s\n" % (topics_len, t, desc))
2224 ui.write(" %-*s %s\n" % (topics_len, t, desc))
2231
2225
2232 if opt_output:
2226 if opt_output:
2233 colwidth = encoding.colwidth
2227 colwidth = encoding.colwidth
2234 # normalize: (opt or message, desc or None, width of opt)
2228 # normalize: (opt or message, desc or None, width of opt)
2235 entries = [desc and (opt, desc, colwidth(opt)) or (opt, None, 0)
2229 entries = [desc and (opt, desc, colwidth(opt)) or (opt, None, 0)
2236 for opt, desc in opt_output]
2230 for opt, desc in opt_output]
2237 hanging = max([e[2] for e in entries])
2231 hanging = max([e[2] for e in entries])
2238 for opt, desc, width in entries:
2232 for opt, desc, width in entries:
2239 if desc:
2233 if desc:
2240 initindent = ' %s%s ' % (opt, ' ' * (hanging - width))
2234 initindent = ' %s%s ' % (opt, ' ' * (hanging - width))
2241 hangindent = ' ' * (hanging + 3)
2235 hangindent = ' ' * (hanging + 3)
2242 ui.write('%s\n' % (util.wrap(desc, textwidth,
2236 ui.write('%s\n' % (util.wrap(desc, textwidth,
2243 initindent=initindent,
2237 initindent=initindent,
2244 hangindent=hangindent)))
2238 hangindent=hangindent)))
2245 else:
2239 else:
2246 ui.write("%s\n" % opt)
2240 ui.write("%s\n" % opt)
2247
2241
2248 def identify(ui, repo, source=None,
2242 def identify(ui, repo, source=None,
2249 rev=None, num=None, id=None, branch=None, tags=None):
2243 rev=None, num=None, id=None, branch=None, tags=None):
2250 """identify the working copy or specified revision
2244 """identify the working copy or specified revision
2251
2245
2252 With no revision, print a summary of the current state of the
2246 With no revision, print a summary of the current state of the
2253 repository.
2247 repository.
2254
2248
2255 Specifying a path to a repository root or Mercurial bundle will
2249 Specifying a path to a repository root or Mercurial bundle will
2256 cause lookup to operate on that repository/bundle.
2250 cause lookup to operate on that repository/bundle.
2257
2251
2258 This summary identifies the repository state using one or two
2252 This summary identifies the repository state using one or two
2259 parent hash identifiers, followed by a "+" if there are
2253 parent hash identifiers, followed by a "+" if there are
2260 uncommitted changes in the working directory, a list of tags for
2254 uncommitted changes in the working directory, a list of tags for
2261 this revision and a branch name for non-default branches.
2255 this revision and a branch name for non-default branches.
2262
2256
2263 Returns 0 if successful.
2257 Returns 0 if successful.
2264 """
2258 """
2265
2259
2266 if not repo and not source:
2260 if not repo and not source:
2267 raise util.Abort(_("there is no Mercurial repository here "
2261 raise util.Abort(_("there is no Mercurial repository here "
2268 "(.hg not found)"))
2262 "(.hg not found)"))
2269
2263
2270 hexfunc = ui.debugflag and hex or short
2264 hexfunc = ui.debugflag and hex or short
2271 default = not (num or id or branch or tags)
2265 default = not (num or id or branch or tags)
2272 output = []
2266 output = []
2273
2267
2274 revs = []
2268 revs = []
2275 if source:
2269 if source:
2276 source, branches = hg.parseurl(ui.expandpath(source))
2270 source, branches = hg.parseurl(ui.expandpath(source))
2277 repo = hg.repository(ui, source)
2271 repo = hg.repository(ui, source)
2278 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
2272 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
2279
2273
2280 if not repo.local():
2274 if not repo.local():
2281 if not rev and revs:
2275 if not rev and revs:
2282 rev = revs[0]
2276 rev = revs[0]
2283 if not rev:
2277 if not rev:
2284 rev = "tip"
2278 rev = "tip"
2285 if num or branch or tags:
2279 if num or branch or tags:
2286 raise util.Abort(
2280 raise util.Abort(
2287 "can't query remote revision number, branch, or tags")
2281 "can't query remote revision number, branch, or tags")
2288 output = [hexfunc(repo.lookup(rev))]
2282 output = [hexfunc(repo.lookup(rev))]
2289 elif not rev:
2283 elif not rev:
2290 ctx = repo[None]
2284 ctx = repo[None]
2291 parents = ctx.parents()
2285 parents = ctx.parents()
2292 changed = False
2286 changed = False
2293 if default or id or num:
2287 if default or id or num:
2294 changed = util.any(repo.status())
2288 changed = util.any(repo.status())
2295 if default or id:
2289 if default or id:
2296 output = ["%s%s" % ('+'.join([hexfunc(p.node()) for p in parents]),
2290 output = ["%s%s" % ('+'.join([hexfunc(p.node()) for p in parents]),
2297 (changed) and "+" or "")]
2291 (changed) and "+" or "")]
2298 if num:
2292 if num:
2299 output.append("%s%s" % ('+'.join([str(p.rev()) for p in parents]),
2293 output.append("%s%s" % ('+'.join([str(p.rev()) for p in parents]),
2300 (changed) and "+" or ""))
2294 (changed) and "+" or ""))
2301 else:
2295 else:
2302 ctx = cmdutil.revsingle(repo, rev)
2296 ctx = cmdutil.revsingle(repo, rev)
2303 if default or id:
2297 if default or id:
2304 output = [hexfunc(ctx.node())]
2298 output = [hexfunc(ctx.node())]
2305 if num:
2299 if num:
2306 output.append(str(ctx.rev()))
2300 output.append(str(ctx.rev()))
2307
2301
2308 if repo.local() and default and not ui.quiet:
2302 if repo.local() and default and not ui.quiet:
2309 b = ctx.branch()
2303 b = ctx.branch()
2310 if b != 'default':
2304 if b != 'default':
2311 output.append("(%s)" % b)
2305 output.append("(%s)" % b)
2312
2306
2313 # multiple tags for a single parent separated by '/'
2307 # multiple tags for a single parent separated by '/'
2314 t = "/".join(ctx.tags())
2308 t = "/".join(ctx.tags())
2315 if t:
2309 if t:
2316 output.append(t)
2310 output.append(t)
2317
2311
2318 if branch:
2312 if branch:
2319 output.append(ctx.branch())
2313 output.append(ctx.branch())
2320
2314
2321 if tags:
2315 if tags:
2322 output.extend(ctx.tags())
2316 output.extend(ctx.tags())
2323
2317
2324 ui.write("%s\n" % ' '.join(output))
2318 ui.write("%s\n" % ' '.join(output))
2325
2319
2326 def import_(ui, repo, patch1, *patches, **opts):
2320 def import_(ui, repo, patch1, *patches, **opts):
2327 """import an ordered set of patches
2321 """import an ordered set of patches
2328
2322
2329 Import a list of patches and commit them individually (unless
2323 Import a list of patches and commit them individually (unless
2330 --no-commit is specified).
2324 --no-commit is specified).
2331
2325
2332 If there are outstanding changes in the working directory, import
2326 If there are outstanding changes in the working directory, import
2333 will abort unless given the -f/--force flag.
2327 will abort unless given the -f/--force flag.
2334
2328
2335 You can import a patch straight from a mail message. Even patches
2329 You can import a patch straight from a mail message. Even patches
2336 as attachments work (to use the body part, it must have type
2330 as attachments work (to use the body part, it must have type
2337 text/plain or text/x-patch). From and Subject headers of email
2331 text/plain or text/x-patch). From and Subject headers of email
2338 message are used as default committer and commit message. All
2332 message are used as default committer and commit message. All
2339 text/plain body parts before first diff are added to commit
2333 text/plain body parts before first diff are added to commit
2340 message.
2334 message.
2341
2335
2342 If the imported patch was generated by :hg:`export`, user and
2336 If the imported patch was generated by :hg:`export`, user and
2343 description from patch override values from message headers and
2337 description from patch override values from message headers and
2344 body. Values given on command line with -m/--message and -u/--user
2338 body. Values given on command line with -m/--message and -u/--user
2345 override these.
2339 override these.
2346
2340
2347 If --exact is specified, import will set the working directory to
2341 If --exact is specified, import will set the working directory to
2348 the parent of each patch before applying it, and will abort if the
2342 the parent of each patch before applying it, and will abort if the
2349 resulting changeset has a different ID than the one recorded in
2343 resulting changeset has a different ID than the one recorded in
2350 the patch. This may happen due to character set problems or other
2344 the patch. This may happen due to character set problems or other
2351 deficiencies in the text patch format.
2345 deficiencies in the text patch format.
2352
2346
2353 With -s/--similarity, hg will attempt to discover renames and
2347 With -s/--similarity, hg will attempt to discover renames and
2354 copies in the patch in the same way as 'addremove'.
2348 copies in the patch in the same way as 'addremove'.
2355
2349
2356 To read a patch from standard input, use "-" as the patch name. If
2350 To read a patch from standard input, use "-" as the patch name. If
2357 a URL is specified, the patch will be downloaded from it.
2351 a URL is specified, the patch will be downloaded from it.
2358 See :hg:`help dates` for a list of formats valid for -d/--date.
2352 See :hg:`help dates` for a list of formats valid for -d/--date.
2359
2353
2360 Returns 0 on success.
2354 Returns 0 on success.
2361 """
2355 """
2362 patches = (patch1,) + patches
2356 patches = (patch1,) + patches
2363
2357
2364 date = opts.get('date')
2358 date = opts.get('date')
2365 if date:
2359 if date:
2366 opts['date'] = util.parsedate(date)
2360 opts['date'] = util.parsedate(date)
2367
2361
2368 try:
2362 try:
2369 sim = float(opts.get('similarity') or 0)
2363 sim = float(opts.get('similarity') or 0)
2370 except ValueError:
2364 except ValueError:
2371 raise util.Abort(_('similarity must be a number'))
2365 raise util.Abort(_('similarity must be a number'))
2372 if sim < 0 or sim > 100:
2366 if sim < 0 or sim > 100:
2373 raise util.Abort(_('similarity must be between 0 and 100'))
2367 raise util.Abort(_('similarity must be between 0 and 100'))
2374
2368
2375 if opts.get('exact') or not opts.get('force'):
2369 if opts.get('exact') or not opts.get('force'):
2376 cmdutil.bail_if_changed(repo)
2370 cmdutil.bail_if_changed(repo)
2377
2371
2378 d = opts["base"]
2372 d = opts["base"]
2379 strip = opts["strip"]
2373 strip = opts["strip"]
2380 wlock = lock = None
2374 wlock = lock = None
2381 msgs = []
2375 msgs = []
2382
2376
2383 def tryone(ui, hunk):
2377 def tryone(ui, hunk):
2384 tmpname, message, user, date, branch, nodeid, p1, p2 = \
2378 tmpname, message, user, date, branch, nodeid, p1, p2 = \
2385 patch.extract(ui, hunk)
2379 patch.extract(ui, hunk)
2386
2380
2387 if not tmpname:
2381 if not tmpname:
2388 return None
2382 return None
2389 commitid = _('to working directory')
2383 commitid = _('to working directory')
2390
2384
2391 try:
2385 try:
2392 cmdline_message = cmdutil.logmessage(opts)
2386 cmdline_message = cmdutil.logmessage(opts)
2393 if cmdline_message:
2387 if cmdline_message:
2394 # pickup the cmdline msg
2388 # pickup the cmdline msg
2395 message = cmdline_message
2389 message = cmdline_message
2396 elif message:
2390 elif message:
2397 # pickup the patch msg
2391 # pickup the patch msg
2398 message = message.strip()
2392 message = message.strip()
2399 else:
2393 else:
2400 # launch the editor
2394 # launch the editor
2401 message = None
2395 message = None
2402 ui.debug('message:\n%s\n' % message)
2396 ui.debug('message:\n%s\n' % message)
2403
2397
2404 wp = repo.parents()
2398 wp = repo.parents()
2405 if opts.get('exact'):
2399 if opts.get('exact'):
2406 if not nodeid or not p1:
2400 if not nodeid or not p1:
2407 raise util.Abort(_('not a Mercurial patch'))
2401 raise util.Abort(_('not a Mercurial patch'))
2408 p1 = repo.lookup(p1)
2402 p1 = repo.lookup(p1)
2409 p2 = repo.lookup(p2 or hex(nullid))
2403 p2 = repo.lookup(p2 or hex(nullid))
2410
2404
2411 if p1 != wp[0].node():
2405 if p1 != wp[0].node():
2412 hg.clean(repo, p1)
2406 hg.clean(repo, p1)
2413 repo.dirstate.setparents(p1, p2)
2407 repo.dirstate.setparents(p1, p2)
2414 elif p2:
2408 elif p2:
2415 try:
2409 try:
2416 p1 = repo.lookup(p1)
2410 p1 = repo.lookup(p1)
2417 p2 = repo.lookup(p2)
2411 p2 = repo.lookup(p2)
2418 if p1 == wp[0].node():
2412 if p1 == wp[0].node():
2419 repo.dirstate.setparents(p1, p2)
2413 repo.dirstate.setparents(p1, p2)
2420 except error.RepoError:
2414 except error.RepoError:
2421 pass
2415 pass
2422 if opts.get('exact') or opts.get('import_branch'):
2416 if opts.get('exact') or opts.get('import_branch'):
2423 repo.dirstate.setbranch(branch or 'default')
2417 repo.dirstate.setbranch(branch or 'default')
2424
2418
2425 files = {}
2419 files = {}
2426 try:
2420 try:
2427 patch.patch(tmpname, ui, strip=strip, cwd=repo.root,
2421 patch.patch(tmpname, ui, strip=strip, cwd=repo.root,
2428 files=files, eolmode=None)
2422 files=files, eolmode=None)
2429 finally:
2423 finally:
2430 files = cmdutil.updatedir(ui, repo, files,
2424 files = cmdutil.updatedir(ui, repo, files,
2431 similarity=sim / 100.0)
2425 similarity=sim / 100.0)
2432 if opts.get('no_commit'):
2426 if opts.get('no_commit'):
2433 if message:
2427 if message:
2434 msgs.append(message)
2428 msgs.append(message)
2435 else:
2429 else:
2436 if opts.get('exact'):
2430 if opts.get('exact'):
2437 m = None
2431 m = None
2438 else:
2432 else:
2439 m = cmdutil.matchfiles(repo, files or [])
2433 m = cmdutil.matchfiles(repo, files or [])
2440 n = repo.commit(message, opts.get('user') or user,
2434 n = repo.commit(message, opts.get('user') or user,
2441 opts.get('date') or date, match=m,
2435 opts.get('date') or date, match=m,
2442 editor=cmdutil.commiteditor)
2436 editor=cmdutil.commiteditor)
2443 if opts.get('exact'):
2437 if opts.get('exact'):
2444 if hex(n) != nodeid:
2438 if hex(n) != nodeid:
2445 repo.rollback()
2439 repo.rollback()
2446 raise util.Abort(_('patch is damaged'
2440 raise util.Abort(_('patch is damaged'
2447 ' or loses information'))
2441 ' or loses information'))
2448 # Force a dirstate write so that the next transaction
2442 # Force a dirstate write so that the next transaction
2449 # backups an up-do-date file.
2443 # backups an up-do-date file.
2450 repo.dirstate.write()
2444 repo.dirstate.write()
2451 if n:
2445 if n:
2452 commitid = short(n)
2446 commitid = short(n)
2453
2447
2454 return commitid
2448 return commitid
2455 finally:
2449 finally:
2456 os.unlink(tmpname)
2450 os.unlink(tmpname)
2457
2451
2458 try:
2452 try:
2459 wlock = repo.wlock()
2453 wlock = repo.wlock()
2460 lock = repo.lock()
2454 lock = repo.lock()
2461 lastcommit = None
2455 lastcommit = None
2462 for p in patches:
2456 for p in patches:
2463 pf = os.path.join(d, p)
2457 pf = os.path.join(d, p)
2464
2458
2465 if pf == '-':
2459 if pf == '-':
2466 ui.status(_("applying patch from stdin\n"))
2460 ui.status(_("applying patch from stdin\n"))
2467 pf = sys.stdin
2461 pf = sys.stdin
2468 else:
2462 else:
2469 ui.status(_("applying %s\n") % p)
2463 ui.status(_("applying %s\n") % p)
2470 pf = url.open(ui, pf)
2464 pf = url.open(ui, pf)
2471
2465
2472 haspatch = False
2466 haspatch = False
2473 for hunk in patch.split(pf):
2467 for hunk in patch.split(pf):
2474 commitid = tryone(ui, hunk)
2468 commitid = tryone(ui, hunk)
2475 if commitid:
2469 if commitid:
2476 haspatch = True
2470 haspatch = True
2477 if lastcommit:
2471 if lastcommit:
2478 ui.status(_('applied %s\n') % lastcommit)
2472 ui.status(_('applied %s\n') % lastcommit)
2479 lastcommit = commitid
2473 lastcommit = commitid
2480
2474
2481 if not haspatch:
2475 if not haspatch:
2482 raise util.Abort(_('no diffs found'))
2476 raise util.Abort(_('no diffs found'))
2483
2477
2484 if msgs:
2478 if msgs:
2485 repo.opener('last-message.txt', 'wb').write('\n* * *\n'.join(msgs))
2479 repo.opener('last-message.txt', 'wb').write('\n* * *\n'.join(msgs))
2486 finally:
2480 finally:
2487 release(lock, wlock)
2481 release(lock, wlock)
2488
2482
2489 def incoming(ui, repo, source="default", **opts):
2483 def incoming(ui, repo, source="default", **opts):
2490 """show new changesets found in source
2484 """show new changesets found in source
2491
2485
2492 Show new changesets found in the specified path/URL or the default
2486 Show new changesets found in the specified path/URL or the default
2493 pull location. These are the changesets that would have been pulled
2487 pull location. These are the changesets that would have been pulled
2494 if a pull at the time you issued this command.
2488 if a pull at the time you issued this command.
2495
2489
2496 For remote repository, using --bundle avoids downloading the
2490 For remote repository, using --bundle avoids downloading the
2497 changesets twice if the incoming is followed by a pull.
2491 changesets twice if the incoming is followed by a pull.
2498
2492
2499 See pull for valid source format details.
2493 See pull for valid source format details.
2500
2494
2501 Returns 0 if there are incoming changes, 1 otherwise.
2495 Returns 0 if there are incoming changes, 1 otherwise.
2502 """
2496 """
2503 if opts.get('bundle') and opts.get('subrepos'):
2497 if opts.get('bundle') and opts.get('subrepos'):
2504 raise util.Abort(_('cannot combine --bundle and --subrepos'))
2498 raise util.Abort(_('cannot combine --bundle and --subrepos'))
2505
2499
2506 if opts.get('bookmarks'):
2500 if opts.get('bookmarks'):
2507 source, branches = hg.parseurl(ui.expandpath(source),
2501 source, branches = hg.parseurl(ui.expandpath(source),
2508 opts.get('branch'))
2502 opts.get('branch'))
2509 other = hg.repository(hg.remoteui(repo, opts), source)
2503 other = hg.repository(hg.remoteui(repo, opts), source)
2510 ui.status(_('comparing with %s\n') % url.hidepassword(source))
2504 ui.status(_('comparing with %s\n') % url.hidepassword(source))
2511 return bookmarks.diff(ui, repo, other)
2505 return bookmarks.diff(ui, repo, other)
2512
2506
2513 ret = hg.incoming(ui, repo, source, opts)
2507 ret = hg.incoming(ui, repo, source, opts)
2514 return ret
2508 return ret
2515
2509
2516 def init(ui, dest=".", **opts):
2510 def init(ui, dest=".", **opts):
2517 """create a new repository in the given directory
2511 """create a new repository in the given directory
2518
2512
2519 Initialize a new repository in the given directory. If the given
2513 Initialize a new repository in the given directory. If the given
2520 directory does not exist, it will be created.
2514 directory does not exist, it will be created.
2521
2515
2522 If no directory is given, the current directory is used.
2516 If no directory is given, the current directory is used.
2523
2517
2524 It is possible to specify an ``ssh://`` URL as the destination.
2518 It is possible to specify an ``ssh://`` URL as the destination.
2525 See :hg:`help urls` for more information.
2519 See :hg:`help urls` for more information.
2526
2520
2527 Returns 0 on success.
2521 Returns 0 on success.
2528 """
2522 """
2529 hg.repository(hg.remoteui(ui, opts), ui.expandpath(dest), create=1)
2523 hg.repository(hg.remoteui(ui, opts), ui.expandpath(dest), create=1)
2530
2524
2531 def locate(ui, repo, *pats, **opts):
2525 def locate(ui, repo, *pats, **opts):
2532 """locate files matching specific patterns
2526 """locate files matching specific patterns
2533
2527
2534 Print files under Mercurial control in the working directory whose
2528 Print files under Mercurial control in the working directory whose
2535 names match the given patterns.
2529 names match the given patterns.
2536
2530
2537 By default, this command searches all directories in the working
2531 By default, this command searches all directories in the working
2538 directory. To search just the current directory and its
2532 directory. To search just the current directory and its
2539 subdirectories, use "--include .".
2533 subdirectories, use "--include .".
2540
2534
2541 If no patterns are given to match, this command prints the names
2535 If no patterns are given to match, this command prints the names
2542 of all files under Mercurial control in the working directory.
2536 of all files under Mercurial control in the working directory.
2543
2537
2544 If you want to feed the output of this command into the "xargs"
2538 If you want to feed the output of this command into the "xargs"
2545 command, use the -0 option to both this command and "xargs". This
2539 command, use the -0 option to both this command and "xargs". This
2546 will avoid the problem of "xargs" treating single filenames that
2540 will avoid the problem of "xargs" treating single filenames that
2547 contain whitespace as multiple filenames.
2541 contain whitespace as multiple filenames.
2548
2542
2549 Returns 0 if a match is found, 1 otherwise.
2543 Returns 0 if a match is found, 1 otherwise.
2550 """
2544 """
2551 end = opts.get('print0') and '\0' or '\n'
2545 end = opts.get('print0') and '\0' or '\n'
2552 rev = cmdutil.revsingle(repo, opts.get('rev'), None).node()
2546 rev = cmdutil.revsingle(repo, opts.get('rev'), None).node()
2553
2547
2554 ret = 1
2548 ret = 1
2555 m = cmdutil.match(repo, pats, opts, default='relglob')
2549 m = cmdutil.match(repo, pats, opts, default='relglob')
2556 m.bad = lambda x, y: False
2550 m.bad = lambda x, y: False
2557 for abs in repo[rev].walk(m):
2551 for abs in repo[rev].walk(m):
2558 if not rev and abs not in repo.dirstate:
2552 if not rev and abs not in repo.dirstate:
2559 continue
2553 continue
2560 if opts.get('fullpath'):
2554 if opts.get('fullpath'):
2561 ui.write(repo.wjoin(abs), end)
2555 ui.write(repo.wjoin(abs), end)
2562 else:
2556 else:
2563 ui.write(((pats and m.rel(abs)) or abs), end)
2557 ui.write(((pats and m.rel(abs)) or abs), end)
2564 ret = 0
2558 ret = 0
2565
2559
2566 return ret
2560 return ret
2567
2561
2568 def log(ui, repo, *pats, **opts):
2562 def log(ui, repo, *pats, **opts):
2569 """show revision history of entire repository or files
2563 """show revision history of entire repository or files
2570
2564
2571 Print the revision history of the specified files or the entire
2565 Print the revision history of the specified files or the entire
2572 project.
2566 project.
2573
2567
2574 File history is shown without following rename or copy history of
2568 File history is shown without following rename or copy history of
2575 files. Use -f/--follow with a filename to follow history across
2569 files. Use -f/--follow with a filename to follow history across
2576 renames and copies. --follow without a filename will only show
2570 renames and copies. --follow without a filename will only show
2577 ancestors or descendants of the starting revision. --follow-first
2571 ancestors or descendants of the starting revision. --follow-first
2578 only follows the first parent of merge revisions.
2572 only follows the first parent of merge revisions.
2579
2573
2580 If no revision range is specified, the default is ``tip:0`` unless
2574 If no revision range is specified, the default is ``tip:0`` unless
2581 --follow is set, in which case the working directory parent is
2575 --follow is set, in which case the working directory parent is
2582 used as the starting revision. You can specify a revision set for
2576 used as the starting revision. You can specify a revision set for
2583 log, see :hg:`help revsets` for more information.
2577 log, see :hg:`help revsets` for more information.
2584
2578
2585 See :hg:`help dates` for a list of formats valid for -d/--date.
2579 See :hg:`help dates` for a list of formats valid for -d/--date.
2586
2580
2587 By default this command prints revision number and changeset id,
2581 By default this command prints revision number and changeset id,
2588 tags, non-trivial parents, user, date and time, and a summary for
2582 tags, non-trivial parents, user, date and time, and a summary for
2589 each commit. When the -v/--verbose switch is used, the list of
2583 each commit. When the -v/--verbose switch is used, the list of
2590 changed files and full commit message are shown.
2584 changed files and full commit message are shown.
2591
2585
2592 .. note::
2586 .. note::
2593 log -p/--patch may generate unexpected diff output for merge
2587 log -p/--patch may generate unexpected diff output for merge
2594 changesets, as it will only compare the merge changeset against
2588 changesets, as it will only compare the merge changeset against
2595 its first parent. Also, only files different from BOTH parents
2589 its first parent. Also, only files different from BOTH parents
2596 will appear in files:.
2590 will appear in files:.
2597
2591
2598 Returns 0 on success.
2592 Returns 0 on success.
2599 """
2593 """
2600
2594
2601 matchfn = cmdutil.match(repo, pats, opts)
2595 matchfn = cmdutil.match(repo, pats, opts)
2602 limit = cmdutil.loglimit(opts)
2596 limit = cmdutil.loglimit(opts)
2603 count = 0
2597 count = 0
2604
2598
2605 endrev = None
2599 endrev = None
2606 if opts.get('copies') and opts.get('rev'):
2600 if opts.get('copies') and opts.get('rev'):
2607 endrev = max(cmdutil.revrange(repo, opts.get('rev'))) + 1
2601 endrev = max(cmdutil.revrange(repo, opts.get('rev'))) + 1
2608
2602
2609 df = False
2603 df = False
2610 if opts["date"]:
2604 if opts["date"]:
2611 df = util.matchdate(opts["date"])
2605 df = util.matchdate(opts["date"])
2612
2606
2613 branches = opts.get('branch', []) + opts.get('only_branch', [])
2607 branches = opts.get('branch', []) + opts.get('only_branch', [])
2614 opts['branch'] = [repo.lookupbranch(b) for b in branches]
2608 opts['branch'] = [repo.lookupbranch(b) for b in branches]
2615
2609
2616 displayer = cmdutil.show_changeset(ui, repo, opts, True)
2610 displayer = cmdutil.show_changeset(ui, repo, opts, True)
2617 def prep(ctx, fns):
2611 def prep(ctx, fns):
2618 rev = ctx.rev()
2612 rev = ctx.rev()
2619 parents = [p for p in repo.changelog.parentrevs(rev)
2613 parents = [p for p in repo.changelog.parentrevs(rev)
2620 if p != nullrev]
2614 if p != nullrev]
2621 if opts.get('no_merges') and len(parents) == 2:
2615 if opts.get('no_merges') and len(parents) == 2:
2622 return
2616 return
2623 if opts.get('only_merges') and len(parents) != 2:
2617 if opts.get('only_merges') and len(parents) != 2:
2624 return
2618 return
2625 if opts.get('branch') and ctx.branch() not in opts['branch']:
2619 if opts.get('branch') and ctx.branch() not in opts['branch']:
2626 return
2620 return
2627 if df and not df(ctx.date()[0]):
2621 if df and not df(ctx.date()[0]):
2628 return
2622 return
2629 if opts['user'] and not [k for k in opts['user']
2623 if opts['user'] and not [k for k in opts['user']
2630 if k.lower() in ctx.user().lower()]:
2624 if k.lower() in ctx.user().lower()]:
2631 return
2625 return
2632 if opts.get('keyword'):
2626 if opts.get('keyword'):
2633 for k in [kw.lower() for kw in opts['keyword']]:
2627 for k in [kw.lower() for kw in opts['keyword']]:
2634 if (k in ctx.user().lower() or
2628 if (k in ctx.user().lower() or
2635 k in ctx.description().lower() or
2629 k in ctx.description().lower() or
2636 k in " ".join(ctx.files()).lower()):
2630 k in " ".join(ctx.files()).lower()):
2637 break
2631 break
2638 else:
2632 else:
2639 return
2633 return
2640
2634
2641 copies = None
2635 copies = None
2642 if opts.get('copies') and rev:
2636 if opts.get('copies') and rev:
2643 copies = []
2637 copies = []
2644 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
2638 getrenamed = templatekw.getrenamedfn(repo, endrev=endrev)
2645 for fn in ctx.files():
2639 for fn in ctx.files():
2646 rename = getrenamed(fn, rev)
2640 rename = getrenamed(fn, rev)
2647 if rename:
2641 if rename:
2648 copies.append((fn, rename[0]))
2642 copies.append((fn, rename[0]))
2649
2643
2650 revmatchfn = None
2644 revmatchfn = None
2651 if opts.get('patch') or opts.get('stat'):
2645 if opts.get('patch') or opts.get('stat'):
2652 if opts.get('follow') or opts.get('follow_first'):
2646 if opts.get('follow') or opts.get('follow_first'):
2653 # note: this might be wrong when following through merges
2647 # note: this might be wrong when following through merges
2654 revmatchfn = cmdutil.match(repo, fns, default='path')
2648 revmatchfn = cmdutil.match(repo, fns, default='path')
2655 else:
2649 else:
2656 revmatchfn = matchfn
2650 revmatchfn = matchfn
2657
2651
2658 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
2652 displayer.show(ctx, copies=copies, matchfn=revmatchfn)
2659
2653
2660 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2654 for ctx in cmdutil.walkchangerevs(repo, matchfn, opts, prep):
2661 if count == limit:
2655 if count == limit:
2662 break
2656 break
2663 if displayer.flush(ctx.rev()):
2657 if displayer.flush(ctx.rev()):
2664 count += 1
2658 count += 1
2665 displayer.close()
2659 displayer.close()
2666
2660
2667 def manifest(ui, repo, node=None, rev=None):
2661 def manifest(ui, repo, node=None, rev=None):
2668 """output the current or given revision of the project manifest
2662 """output the current or given revision of the project manifest
2669
2663
2670 Print a list of version controlled files for the given revision.
2664 Print a list of version controlled files for the given revision.
2671 If no revision is given, the first parent of the working directory
2665 If no revision is given, the first parent of the working directory
2672 is used, or the null revision if no revision is checked out.
2666 is used, or the null revision if no revision is checked out.
2673
2667
2674 With -v, print file permissions, symlink and executable bits.
2668 With -v, print file permissions, symlink and executable bits.
2675 With --debug, print file revision hashes.
2669 With --debug, print file revision hashes.
2676
2670
2677 Returns 0 on success.
2671 Returns 0 on success.
2678 """
2672 """
2679
2673
2680 if rev and node:
2674 if rev and node:
2681 raise util.Abort(_("please specify just one revision"))
2675 raise util.Abort(_("please specify just one revision"))
2682
2676
2683 if not node:
2677 if not node:
2684 node = rev
2678 node = rev
2685
2679
2686 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
2680 decor = {'l':'644 @ ', 'x':'755 * ', '':'644 '}
2687 ctx = cmdutil.revsingle(repo, node)
2681 ctx = cmdutil.revsingle(repo, node)
2688 for f in ctx:
2682 for f in ctx:
2689 if ui.debugflag:
2683 if ui.debugflag:
2690 ui.write("%40s " % hex(ctx.manifest()[f]))
2684 ui.write("%40s " % hex(ctx.manifest()[f]))
2691 if ui.verbose:
2685 if ui.verbose:
2692 ui.write(decor[ctx.flags(f)])
2686 ui.write(decor[ctx.flags(f)])
2693 ui.write("%s\n" % f)
2687 ui.write("%s\n" % f)
2694
2688
2695 def merge(ui, repo, node=None, **opts):
2689 def merge(ui, repo, node=None, **opts):
2696 """merge working directory with another revision
2690 """merge working directory with another revision
2697
2691
2698 The current working directory is updated with all changes made in
2692 The current working directory is updated with all changes made in
2699 the requested revision since the last common predecessor revision.
2693 the requested revision since the last common predecessor revision.
2700
2694
2701 Files that changed between either parent are marked as changed for
2695 Files that changed between either parent are marked as changed for
2702 the next commit and a commit must be performed before any further
2696 the next commit and a commit must be performed before any further
2703 updates to the repository are allowed. The next commit will have
2697 updates to the repository are allowed. The next commit will have
2704 two parents.
2698 two parents.
2705
2699
2706 ``--tool`` can be used to specify the merge tool used for file
2700 ``--tool`` can be used to specify the merge tool used for file
2707 merges. It overrides the HGMERGE environment variable and your
2701 merges. It overrides the HGMERGE environment variable and your
2708 configuration files.
2702 configuration files.
2709
2703
2710 If no revision is specified, the working directory's parent is a
2704 If no revision is specified, the working directory's parent is a
2711 head revision, and the current branch contains exactly one other
2705 head revision, and the current branch contains exactly one other
2712 head, the other head is merged with by default. Otherwise, an
2706 head, the other head is merged with by default. Otherwise, an
2713 explicit revision with which to merge with must be provided.
2707 explicit revision with which to merge with must be provided.
2714
2708
2715 :hg:`resolve` must be used to resolve unresolved files.
2709 :hg:`resolve` must be used to resolve unresolved files.
2716
2710
2717 To undo an uncommitted merge, use :hg:`update --clean .` which
2711 To undo an uncommitted merge, use :hg:`update --clean .` which
2718 will check out a clean copy of the original merge parent, losing
2712 will check out a clean copy of the original merge parent, losing
2719 all changes.
2713 all changes.
2720
2714
2721 Returns 0 on success, 1 if there are unresolved files.
2715 Returns 0 on success, 1 if there are unresolved files.
2722 """
2716 """
2723
2717
2724 if opts.get('rev') and node:
2718 if opts.get('rev') and node:
2725 raise util.Abort(_("please specify just one revision"))
2719 raise util.Abort(_("please specify just one revision"))
2726 if not node:
2720 if not node:
2727 node = opts.get('rev')
2721 node = opts.get('rev')
2728
2722
2729 if not node:
2723 if not node:
2730 branch = repo[None].branch()
2724 branch = repo[None].branch()
2731 bheads = repo.branchheads(branch)
2725 bheads = repo.branchheads(branch)
2732 if len(bheads) > 2:
2726 if len(bheads) > 2:
2733 raise util.Abort(_(
2727 raise util.Abort(_(
2734 'branch \'%s\' has %d heads - '
2728 'branch \'%s\' has %d heads - '
2735 'please merge with an explicit rev\n'
2729 'please merge with an explicit rev\n'
2736 '(run \'hg heads .\' to see heads)')
2730 '(run \'hg heads .\' to see heads)')
2737 % (branch, len(bheads)))
2731 % (branch, len(bheads)))
2738
2732
2739 parent = repo.dirstate.parents()[0]
2733 parent = repo.dirstate.parents()[0]
2740 if len(bheads) == 1:
2734 if len(bheads) == 1:
2741 if len(repo.heads()) > 1:
2735 if len(repo.heads()) > 1:
2742 raise util.Abort(_(
2736 raise util.Abort(_(
2743 'branch \'%s\' has one head - '
2737 'branch \'%s\' has one head - '
2744 'please merge with an explicit rev\n'
2738 'please merge with an explicit rev\n'
2745 '(run \'hg heads\' to see all heads)')
2739 '(run \'hg heads\' to see all heads)')
2746 % branch)
2740 % branch)
2747 msg = _('there is nothing to merge')
2741 msg = _('there is nothing to merge')
2748 if parent != repo.lookup(repo[None].branch()):
2742 if parent != repo.lookup(repo[None].branch()):
2749 msg = _('%s - use "hg update" instead') % msg
2743 msg = _('%s - use "hg update" instead') % msg
2750 raise util.Abort(msg)
2744 raise util.Abort(msg)
2751
2745
2752 if parent not in bheads:
2746 if parent not in bheads:
2753 raise util.Abort(_('working dir not at a head rev - '
2747 raise util.Abort(_('working dir not at a head rev - '
2754 'use "hg update" or merge with an explicit rev'))
2748 'use "hg update" or merge with an explicit rev'))
2755 node = parent == bheads[0] and bheads[-1] or bheads[0]
2749 node = parent == bheads[0] and bheads[-1] or bheads[0]
2756 else:
2750 else:
2757 node = cmdutil.revsingle(repo, node).node()
2751 node = cmdutil.revsingle(repo, node).node()
2758
2752
2759 if opts.get('preview'):
2753 if opts.get('preview'):
2760 # find nodes that are ancestors of p2 but not of p1
2754 # find nodes that are ancestors of p2 but not of p1
2761 p1 = repo.lookup('.')
2755 p1 = repo.lookup('.')
2762 p2 = repo.lookup(node)
2756 p2 = repo.lookup(node)
2763 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
2757 nodes = repo.changelog.findmissing(common=[p1], heads=[p2])
2764
2758
2765 displayer = cmdutil.show_changeset(ui, repo, opts)
2759 displayer = cmdutil.show_changeset(ui, repo, opts)
2766 for node in nodes:
2760 for node in nodes:
2767 displayer.show(repo[node])
2761 displayer.show(repo[node])
2768 displayer.close()
2762 displayer.close()
2769 return 0
2763 return 0
2770
2764
2771 try:
2765 try:
2772 # ui.forcemerge is an internal variable, do not document
2766 # ui.forcemerge is an internal variable, do not document
2773 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2767 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
2774 return hg.merge(repo, node, force=opts.get('force'))
2768 return hg.merge(repo, node, force=opts.get('force'))
2775 finally:
2769 finally:
2776 ui.setconfig('ui', 'forcemerge', '')
2770 ui.setconfig('ui', 'forcemerge', '')
2777
2771
2778 def outgoing(ui, repo, dest=None, **opts):
2772 def outgoing(ui, repo, dest=None, **opts):
2779 """show changesets not found in the destination
2773 """show changesets not found in the destination
2780
2774
2781 Show changesets not found in the specified destination repository
2775 Show changesets not found in the specified destination repository
2782 or the default push location. These are the changesets that would
2776 or the default push location. These are the changesets that would
2783 be pushed if a push was requested.
2777 be pushed if a push was requested.
2784
2778
2785 See pull for details of valid destination formats.
2779 See pull for details of valid destination formats.
2786
2780
2787 Returns 0 if there are outgoing changes, 1 otherwise.
2781 Returns 0 if there are outgoing changes, 1 otherwise.
2788 """
2782 """
2789
2783
2790 if opts.get('bookmarks'):
2784 if opts.get('bookmarks'):
2791 dest = ui.expandpath(dest or 'default-push', dest or 'default')
2785 dest = ui.expandpath(dest or 'default-push', dest or 'default')
2792 dest, branches = hg.parseurl(dest, opts.get('branch'))
2786 dest, branches = hg.parseurl(dest, opts.get('branch'))
2793 other = hg.repository(hg.remoteui(repo, opts), dest)
2787 other = hg.repository(hg.remoteui(repo, opts), dest)
2794 ui.status(_('comparing with %s\n') % url.hidepassword(dest))
2788 ui.status(_('comparing with %s\n') % url.hidepassword(dest))
2795 return bookmarks.diff(ui, other, repo)
2789 return bookmarks.diff(ui, other, repo)
2796
2790
2797 ret = hg.outgoing(ui, repo, dest, opts)
2791 ret = hg.outgoing(ui, repo, dest, opts)
2798 return ret
2792 return ret
2799
2793
2800 def parents(ui, repo, file_=None, **opts):
2794 def parents(ui, repo, file_=None, **opts):
2801 """show the parents of the working directory or revision
2795 """show the parents of the working directory or revision
2802
2796
2803 Print the working directory's parent revisions. If a revision is
2797 Print the working directory's parent revisions. If a revision is
2804 given via -r/--rev, the parent of that revision will be printed.
2798 given via -r/--rev, the parent of that revision will be printed.
2805 If a file argument is given, the revision in which the file was
2799 If a file argument is given, the revision in which the file was
2806 last changed (before the working directory revision or the
2800 last changed (before the working directory revision or the
2807 argument to --rev if given) is printed.
2801 argument to --rev if given) is printed.
2808
2802
2809 Returns 0 on success.
2803 Returns 0 on success.
2810 """
2804 """
2811
2805
2812 ctx = cmdutil.revsingle(repo, opts.get('rev'), None)
2806 ctx = cmdutil.revsingle(repo, opts.get('rev'), None)
2813
2807
2814 if file_:
2808 if file_:
2815 m = cmdutil.match(repo, (file_,), opts)
2809 m = cmdutil.match(repo, (file_,), opts)
2816 if m.anypats() or len(m.files()) != 1:
2810 if m.anypats() or len(m.files()) != 1:
2817 raise util.Abort(_('can only specify an explicit filename'))
2811 raise util.Abort(_('can only specify an explicit filename'))
2818 file_ = m.files()[0]
2812 file_ = m.files()[0]
2819 filenodes = []
2813 filenodes = []
2820 for cp in ctx.parents():
2814 for cp in ctx.parents():
2821 if not cp:
2815 if not cp:
2822 continue
2816 continue
2823 try:
2817 try:
2824 filenodes.append(cp.filenode(file_))
2818 filenodes.append(cp.filenode(file_))
2825 except error.LookupError:
2819 except error.LookupError:
2826 pass
2820 pass
2827 if not filenodes:
2821 if not filenodes:
2828 raise util.Abort(_("'%s' not found in manifest!") % file_)
2822 raise util.Abort(_("'%s' not found in manifest!") % file_)
2829 fl = repo.file(file_)
2823 fl = repo.file(file_)
2830 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
2824 p = [repo.lookup(fl.linkrev(fl.rev(fn))) for fn in filenodes]
2831 else:
2825 else:
2832 p = [cp.node() for cp in ctx.parents()]
2826 p = [cp.node() for cp in ctx.parents()]
2833
2827
2834 displayer = cmdutil.show_changeset(ui, repo, opts)
2828 displayer = cmdutil.show_changeset(ui, repo, opts)
2835 for n in p:
2829 for n in p:
2836 if n != nullid:
2830 if n != nullid:
2837 displayer.show(repo[n])
2831 displayer.show(repo[n])
2838 displayer.close()
2832 displayer.close()
2839
2833
2840 def paths(ui, repo, search=None):
2834 def paths(ui, repo, search=None):
2841 """show aliases for remote repositories
2835 """show aliases for remote repositories
2842
2836
2843 Show definition of symbolic path name NAME. If no name is given,
2837 Show definition of symbolic path name NAME. If no name is given,
2844 show definition of all available names.
2838 show definition of all available names.
2845
2839
2846 Path names are defined in the [paths] section of your
2840 Path names are defined in the [paths] section of your
2847 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
2841 configuration file and in ``/etc/mercurial/hgrc``. If run inside a
2848 repository, ``.hg/hgrc`` is used, too.
2842 repository, ``.hg/hgrc`` is used, too.
2849
2843
2850 The path names ``default`` and ``default-push`` have a special
2844 The path names ``default`` and ``default-push`` have a special
2851 meaning. When performing a push or pull operation, they are used
2845 meaning. When performing a push or pull operation, they are used
2852 as fallbacks if no location is specified on the command-line.
2846 as fallbacks if no location is specified on the command-line.
2853 When ``default-push`` is set, it will be used for push and
2847 When ``default-push`` is set, it will be used for push and
2854 ``default`` will be used for pull; otherwise ``default`` is used
2848 ``default`` will be used for pull; otherwise ``default`` is used
2855 as the fallback for both. When cloning a repository, the clone
2849 as the fallback for both. When cloning a repository, the clone
2856 source is written as ``default`` in ``.hg/hgrc``. Note that
2850 source is written as ``default`` in ``.hg/hgrc``. Note that
2857 ``default`` and ``default-push`` apply to all inbound (e.g.
2851 ``default`` and ``default-push`` apply to all inbound (e.g.
2858 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
2852 :hg:`incoming`) and outbound (e.g. :hg:`outgoing`, :hg:`email` and
2859 :hg:`bundle`) operations.
2853 :hg:`bundle`) operations.
2860
2854
2861 See :hg:`help urls` for more information.
2855 See :hg:`help urls` for more information.
2862
2856
2863 Returns 0 on success.
2857 Returns 0 on success.
2864 """
2858 """
2865 if search:
2859 if search:
2866 for name, path in ui.configitems("paths"):
2860 for name, path in ui.configitems("paths"):
2867 if name == search:
2861 if name == search:
2868 ui.write("%s\n" % url.hidepassword(path))
2862 ui.write("%s\n" % url.hidepassword(path))
2869 return
2863 return
2870 ui.warn(_("not found!\n"))
2864 ui.warn(_("not found!\n"))
2871 return 1
2865 return 1
2872 else:
2866 else:
2873 for name, path in ui.configitems("paths"):
2867 for name, path in ui.configitems("paths"):
2874 ui.write("%s = %s\n" % (name, url.hidepassword(path)))
2868 ui.write("%s = %s\n" % (name, url.hidepassword(path)))
2875
2869
2876 def postincoming(ui, repo, modheads, optupdate, checkout):
2870 def postincoming(ui, repo, modheads, optupdate, checkout):
2877 if modheads == 0:
2871 if modheads == 0:
2878 return
2872 return
2879 if optupdate:
2873 if optupdate:
2880 if (modheads <= 1 or len(repo.branchheads()) == 1) or checkout:
2874 if (modheads <= 1 or len(repo.branchheads()) == 1) or checkout:
2881 return hg.update(repo, checkout)
2875 return hg.update(repo, checkout)
2882 else:
2876 else:
2883 ui.status(_("not updating, since new heads added\n"))
2877 ui.status(_("not updating, since new heads added\n"))
2884 if modheads > 1:
2878 if modheads > 1:
2885 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
2879 ui.status(_("(run 'hg heads' to see heads, 'hg merge' to merge)\n"))
2886 else:
2880 else:
2887 ui.status(_("(run 'hg update' to get a working copy)\n"))
2881 ui.status(_("(run 'hg update' to get a working copy)\n"))
2888
2882
2889 def pull(ui, repo, source="default", **opts):
2883 def pull(ui, repo, source="default", **opts):
2890 """pull changes from the specified source
2884 """pull changes from the specified source
2891
2885
2892 Pull changes from a remote repository to a local one.
2886 Pull changes from a remote repository to a local one.
2893
2887
2894 This finds all changes from the repository at the specified path
2888 This finds all changes from the repository at the specified path
2895 or URL and adds them to a local repository (the current one unless
2889 or URL and adds them to a local repository (the current one unless
2896 -R is specified). By default, this does not update the copy of the
2890 -R is specified). By default, this does not update the copy of the
2897 project in the working directory.
2891 project in the working directory.
2898
2892
2899 Use :hg:`incoming` if you want to see what would have been added
2893 Use :hg:`incoming` if you want to see what would have been added
2900 by a pull at the time you issued this command. If you then decide
2894 by a pull at the time you issued this command. If you then decide
2901 to add those changes to the repository, you should use :hg:`pull
2895 to add those changes to the repository, you should use :hg:`pull
2902 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
2896 -r X` where ``X`` is the last changeset listed by :hg:`incoming`.
2903
2897
2904 If SOURCE is omitted, the 'default' path will be used.
2898 If SOURCE is omitted, the 'default' path will be used.
2905 See :hg:`help urls` for more information.
2899 See :hg:`help urls` for more information.
2906
2900
2907 Returns 0 on success, 1 if an update had unresolved files.
2901 Returns 0 on success, 1 if an update had unresolved files.
2908 """
2902 """
2909 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
2903 source, branches = hg.parseurl(ui.expandpath(source), opts.get('branch'))
2910 other = hg.repository(hg.remoteui(repo, opts), source)
2904 other = hg.repository(hg.remoteui(repo, opts), source)
2911 ui.status(_('pulling from %s\n') % url.hidepassword(source))
2905 ui.status(_('pulling from %s\n') % url.hidepassword(source))
2912 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
2906 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
2913
2907
2914 if opts.get('bookmark'):
2908 if opts.get('bookmark'):
2915 if not revs:
2909 if not revs:
2916 revs = []
2910 revs = []
2917 rb = other.listkeys('bookmarks')
2911 rb = other.listkeys('bookmarks')
2918 for b in opts['bookmark']:
2912 for b in opts['bookmark']:
2919 if b not in rb:
2913 if b not in rb:
2920 raise util.Abort(_('remote bookmark %s not found!') % b)
2914 raise util.Abort(_('remote bookmark %s not found!') % b)
2921 revs.append(rb[b])
2915 revs.append(rb[b])
2922
2916
2923 if revs:
2917 if revs:
2924 try:
2918 try:
2925 revs = [other.lookup(rev) for rev in revs]
2919 revs = [other.lookup(rev) for rev in revs]
2926 except error.CapabilityError:
2920 except error.CapabilityError:
2927 err = _("other repository doesn't support revision lookup, "
2921 err = _("other repository doesn't support revision lookup, "
2928 "so a rev cannot be specified.")
2922 "so a rev cannot be specified.")
2929 raise util.Abort(err)
2923 raise util.Abort(err)
2930
2924
2931 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
2925 modheads = repo.pull(other, heads=revs, force=opts.get('force'))
2932 if checkout:
2926 if checkout:
2933 checkout = str(repo.changelog.rev(other.lookup(checkout)))
2927 checkout = str(repo.changelog.rev(other.lookup(checkout)))
2934 repo._subtoppath = source
2928 repo._subtoppath = source
2935 try:
2929 try:
2936 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
2930 ret = postincoming(ui, repo, modheads, opts.get('update'), checkout)
2937
2931
2938 finally:
2932 finally:
2939 del repo._subtoppath
2933 del repo._subtoppath
2940
2934
2941 # update specified bookmarks
2935 # update specified bookmarks
2942 if opts.get('bookmark'):
2936 if opts.get('bookmark'):
2943 for b in opts['bookmark']:
2937 for b in opts['bookmark']:
2944 # explicit pull overrides local bookmark if any
2938 # explicit pull overrides local bookmark if any
2945 ui.status(_("importing bookmark %s\n") % b)
2939 ui.status(_("importing bookmark %s\n") % b)
2946 repo._bookmarks[b] = repo[rb[b]].node()
2940 repo._bookmarks[b] = repo[rb[b]].node()
2947 bookmarks.write(repo)
2941 bookmarks.write(repo)
2948
2942
2949 return ret
2943 return ret
2950
2944
2951 def push(ui, repo, dest=None, **opts):
2945 def push(ui, repo, dest=None, **opts):
2952 """push changes to the specified destination
2946 """push changes to the specified destination
2953
2947
2954 Push changesets from the local repository to the specified
2948 Push changesets from the local repository to the specified
2955 destination.
2949 destination.
2956
2950
2957 This operation is symmetrical to pull: it is identical to a pull
2951 This operation is symmetrical to pull: it is identical to a pull
2958 in the destination repository from the current one.
2952 in the destination repository from the current one.
2959
2953
2960 By default, push will not allow creation of new heads at the
2954 By default, push will not allow creation of new heads at the
2961 destination, since multiple heads would make it unclear which head
2955 destination, since multiple heads would make it unclear which head
2962 to use. In this situation, it is recommended to pull and merge
2956 to use. In this situation, it is recommended to pull and merge
2963 before pushing.
2957 before pushing.
2964
2958
2965 Use --new-branch if you want to allow push to create a new named
2959 Use --new-branch if you want to allow push to create a new named
2966 branch that is not present at the destination. This allows you to
2960 branch that is not present at the destination. This allows you to
2967 only create a new branch without forcing other changes.
2961 only create a new branch without forcing other changes.
2968
2962
2969 Use -f/--force to override the default behavior and push all
2963 Use -f/--force to override the default behavior and push all
2970 changesets on all branches.
2964 changesets on all branches.
2971
2965
2972 If -r/--rev is used, the specified revision and all its ancestors
2966 If -r/--rev is used, the specified revision and all its ancestors
2973 will be pushed to the remote repository.
2967 will be pushed to the remote repository.
2974
2968
2975 Please see :hg:`help urls` for important details about ``ssh://``
2969 Please see :hg:`help urls` for important details about ``ssh://``
2976 URLs. If DESTINATION is omitted, a default path will be used.
2970 URLs. If DESTINATION is omitted, a default path will be used.
2977
2971
2978 Returns 0 if push was successful, 1 if nothing to push.
2972 Returns 0 if push was successful, 1 if nothing to push.
2979 """
2973 """
2980
2974
2981 if opts.get('bookmark'):
2975 if opts.get('bookmark'):
2982 for b in opts['bookmark']:
2976 for b in opts['bookmark']:
2983 # translate -B options to -r so changesets get pushed
2977 # translate -B options to -r so changesets get pushed
2984 if b in repo._bookmarks:
2978 if b in repo._bookmarks:
2985 opts.setdefault('rev', []).append(b)
2979 opts.setdefault('rev', []).append(b)
2986 else:
2980 else:
2987 # if we try to push a deleted bookmark, translate it to null
2981 # if we try to push a deleted bookmark, translate it to null
2988 # this lets simultaneous -r, -b options continue working
2982 # this lets simultaneous -r, -b options continue working
2989 opts.setdefault('rev', []).append("null")
2983 opts.setdefault('rev', []).append("null")
2990
2984
2991 dest = ui.expandpath(dest or 'default-push', dest or 'default')
2985 dest = ui.expandpath(dest or 'default-push', dest or 'default')
2992 dest, branches = hg.parseurl(dest, opts.get('branch'))
2986 dest, branches = hg.parseurl(dest, opts.get('branch'))
2993 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
2987 revs, checkout = hg.addbranchrevs(repo, repo, branches, opts.get('rev'))
2994 other = hg.repository(hg.remoteui(repo, opts), dest)
2988 other = hg.repository(hg.remoteui(repo, opts), dest)
2995 ui.status(_('pushing to %s\n') % url.hidepassword(dest))
2989 ui.status(_('pushing to %s\n') % url.hidepassword(dest))
2996 if revs:
2990 if revs:
2997 revs = [repo.lookup(rev) for rev in revs]
2991 revs = [repo.lookup(rev) for rev in revs]
2998
2992
2999 repo._subtoppath = dest
2993 repo._subtoppath = dest
3000 try:
2994 try:
3001 # push subrepos depth-first for coherent ordering
2995 # push subrepos depth-first for coherent ordering
3002 c = repo['']
2996 c = repo['']
3003 subs = c.substate # only repos that are committed
2997 subs = c.substate # only repos that are committed
3004 for s in sorted(subs):
2998 for s in sorted(subs):
3005 if not c.sub(s).push(opts.get('force')):
2999 if not c.sub(s).push(opts.get('force')):
3006 return False
3000 return False
3007 finally:
3001 finally:
3008 del repo._subtoppath
3002 del repo._subtoppath
3009 result = repo.push(other, opts.get('force'), revs=revs,
3003 result = repo.push(other, opts.get('force'), revs=revs,
3010 newbranch=opts.get('new_branch'))
3004 newbranch=opts.get('new_branch'))
3011
3005
3012 result = (result == 0)
3006 result = (result == 0)
3013
3007
3014 if opts.get('bookmark'):
3008 if opts.get('bookmark'):
3015 rb = other.listkeys('bookmarks')
3009 rb = other.listkeys('bookmarks')
3016 for b in opts['bookmark']:
3010 for b in opts['bookmark']:
3017 # explicit push overrides remote bookmark if any
3011 # explicit push overrides remote bookmark if any
3018 if b in repo._bookmarks:
3012 if b in repo._bookmarks:
3019 ui.status(_("exporting bookmark %s\n") % b)
3013 ui.status(_("exporting bookmark %s\n") % b)
3020 new = repo[b].hex()
3014 new = repo[b].hex()
3021 elif b in rb:
3015 elif b in rb:
3022 ui.status(_("deleting remote bookmark %s\n") % b)
3016 ui.status(_("deleting remote bookmark %s\n") % b)
3023 new = '' # delete
3017 new = '' # delete
3024 else:
3018 else:
3025 ui.warn(_('bookmark %s does not exist on the local '
3019 ui.warn(_('bookmark %s does not exist on the local '
3026 'or remote repository!\n') % b)
3020 'or remote repository!\n') % b)
3027 return 2
3021 return 2
3028 old = rb.get(b, '')
3022 old = rb.get(b, '')
3029 r = other.pushkey('bookmarks', b, old, new)
3023 r = other.pushkey('bookmarks', b, old, new)
3030 if not r:
3024 if not r:
3031 ui.warn(_('updating bookmark %s failed!\n') % b)
3025 ui.warn(_('updating bookmark %s failed!\n') % b)
3032 if not result:
3026 if not result:
3033 result = 2
3027 result = 2
3034
3028
3035 return result
3029 return result
3036
3030
3037 def recover(ui, repo):
3031 def recover(ui, repo):
3038 """roll back an interrupted transaction
3032 """roll back an interrupted transaction
3039
3033
3040 Recover from an interrupted commit or pull.
3034 Recover from an interrupted commit or pull.
3041
3035
3042 This command tries to fix the repository status after an
3036 This command tries to fix the repository status after an
3043 interrupted operation. It should only be necessary when Mercurial
3037 interrupted operation. It should only be necessary when Mercurial
3044 suggests it.
3038 suggests it.
3045
3039
3046 Returns 0 if successful, 1 if nothing to recover or verify fails.
3040 Returns 0 if successful, 1 if nothing to recover or verify fails.
3047 """
3041 """
3048 if repo.recover():
3042 if repo.recover():
3049 return hg.verify(repo)
3043 return hg.verify(repo)
3050 return 1
3044 return 1
3051
3045
3052 def remove(ui, repo, *pats, **opts):
3046 def remove(ui, repo, *pats, **opts):
3053 """remove the specified files on the next commit
3047 """remove the specified files on the next commit
3054
3048
3055 Schedule the indicated files for removal from the repository.
3049 Schedule the indicated files for removal from the repository.
3056
3050
3057 This only removes files from the current branch, not from the
3051 This only removes files from the current branch, not from the
3058 entire project history. -A/--after can be used to remove only
3052 entire project history. -A/--after can be used to remove only
3059 files that have already been deleted, -f/--force can be used to
3053 files that have already been deleted, -f/--force can be used to
3060 force deletion, and -Af can be used to remove files from the next
3054 force deletion, and -Af can be used to remove files from the next
3061 revision without deleting them from the working directory.
3055 revision without deleting them from the working directory.
3062
3056
3063 The following table details the behavior of remove for different
3057 The following table details the behavior of remove for different
3064 file states (columns) and option combinations (rows). The file
3058 file states (columns) and option combinations (rows). The file
3065 states are Added [A], Clean [C], Modified [M] and Missing [!] (as
3059 states are Added [A], Clean [C], Modified [M] and Missing [!] (as
3066 reported by :hg:`status`). The actions are Warn, Remove (from
3060 reported by :hg:`status`). The actions are Warn, Remove (from
3067 branch) and Delete (from disk)::
3061 branch) and Delete (from disk)::
3068
3062
3069 A C M !
3063 A C M !
3070 none W RD W R
3064 none W RD W R
3071 -f R RD RD R
3065 -f R RD RD R
3072 -A W W W R
3066 -A W W W R
3073 -Af R R R R
3067 -Af R R R R
3074
3068
3075 This command schedules the files to be removed at the next commit.
3069 This command schedules the files to be removed at the next commit.
3076 To undo a remove before that, see :hg:`revert`.
3070 To undo a remove before that, see :hg:`revert`.
3077
3071
3078 Returns 0 on success, 1 if any warnings encountered.
3072 Returns 0 on success, 1 if any warnings encountered.
3079 """
3073 """
3080
3074
3081 ret = 0
3075 ret = 0
3082 after, force = opts.get('after'), opts.get('force')
3076 after, force = opts.get('after'), opts.get('force')
3083 if not pats and not after:
3077 if not pats and not after:
3084 raise util.Abort(_('no files specified'))
3078 raise util.Abort(_('no files specified'))
3085
3079
3086 m = cmdutil.match(repo, pats, opts)
3080 m = cmdutil.match(repo, pats, opts)
3087 s = repo.status(match=m, clean=True)
3081 s = repo.status(match=m, clean=True)
3088 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
3082 modified, added, deleted, clean = s[0], s[1], s[3], s[6]
3089
3083
3090 for f in m.files():
3084 for f in m.files():
3091 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
3085 if f not in repo.dirstate and not os.path.isdir(m.rel(f)):
3092 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
3086 ui.warn(_('not removing %s: file is untracked\n') % m.rel(f))
3093 ret = 1
3087 ret = 1
3094
3088
3095 if force:
3089 if force:
3096 remove, forget = modified + deleted + clean, added
3090 remove, forget = modified + deleted + clean, added
3097 elif after:
3091 elif after:
3098 remove, forget = deleted, []
3092 remove, forget = deleted, []
3099 for f in modified + added + clean:
3093 for f in modified + added + clean:
3100 ui.warn(_('not removing %s: file still exists (use -f'
3094 ui.warn(_('not removing %s: file still exists (use -f'
3101 ' to force removal)\n') % m.rel(f))
3095 ' to force removal)\n') % m.rel(f))
3102 ret = 1
3096 ret = 1
3103 else:
3097 else:
3104 remove, forget = deleted + clean, []
3098 remove, forget = deleted + clean, []
3105 for f in modified:
3099 for f in modified:
3106 ui.warn(_('not removing %s: file is modified (use -f'
3100 ui.warn(_('not removing %s: file is modified (use -f'
3107 ' to force removal)\n') % m.rel(f))
3101 ' to force removal)\n') % m.rel(f))
3108 ret = 1
3102 ret = 1
3109 for f in added:
3103 for f in added:
3110 ui.warn(_('not removing %s: file has been marked for add (use -f'
3104 ui.warn(_('not removing %s: file has been marked for add (use -f'
3111 ' to force removal)\n') % m.rel(f))
3105 ' to force removal)\n') % m.rel(f))
3112 ret = 1
3106 ret = 1
3113
3107
3114 for f in sorted(remove + forget):
3108 for f in sorted(remove + forget):
3115 if ui.verbose or not m.exact(f):
3109 if ui.verbose or not m.exact(f):
3116 ui.status(_('removing %s\n') % m.rel(f))
3110 ui.status(_('removing %s\n') % m.rel(f))
3117
3111
3118 repo[None].forget(forget)
3112 repo[None].forget(forget)
3119 repo[None].remove(remove, unlink=not after)
3113 repo[None].remove(remove, unlink=not after)
3120 return ret
3114 return ret
3121
3115
3122 def rename(ui, repo, *pats, **opts):
3116 def rename(ui, repo, *pats, **opts):
3123 """rename files; equivalent of copy + remove
3117 """rename files; equivalent of copy + remove
3124
3118
3125 Mark dest as copies of sources; mark sources for deletion. If dest
3119 Mark dest as copies of sources; mark sources for deletion. If dest
3126 is a directory, copies are put in that directory. If dest is a
3120 is a directory, copies are put in that directory. If dest is a
3127 file, there can only be one source.
3121 file, there can only be one source.
3128
3122
3129 By default, this command copies the contents of files as they
3123 By default, this command copies the contents of files as they
3130 exist in the working directory. If invoked with -A/--after, the
3124 exist in the working directory. If invoked with -A/--after, the
3131 operation is recorded, but no copying is performed.
3125 operation is recorded, but no copying is performed.
3132
3126
3133 This command takes effect at the next commit. To undo a rename
3127 This command takes effect at the next commit. To undo a rename
3134 before that, see :hg:`revert`.
3128 before that, see :hg:`revert`.
3135
3129
3136 Returns 0 on success, 1 if errors are encountered.
3130 Returns 0 on success, 1 if errors are encountered.
3137 """
3131 """
3138 wlock = repo.wlock(False)
3132 wlock = repo.wlock(False)
3139 try:
3133 try:
3140 return cmdutil.copy(ui, repo, pats, opts, rename=True)
3134 return cmdutil.copy(ui, repo, pats, opts, rename=True)
3141 finally:
3135 finally:
3142 wlock.release()
3136 wlock.release()
3143
3137
3144 def resolve(ui, repo, *pats, **opts):
3138 def resolve(ui, repo, *pats, **opts):
3145 """redo merges or set/view the merge status of files
3139 """redo merges or set/view the merge status of files
3146
3140
3147 Merges with unresolved conflicts are often the result of
3141 Merges with unresolved conflicts are often the result of
3148 non-interactive merging using the ``internal:merge`` configuration
3142 non-interactive merging using the ``internal:merge`` configuration
3149 setting, or a command-line merge tool like ``diff3``. The resolve
3143 setting, or a command-line merge tool like ``diff3``. The resolve
3150 command is used to manage the files involved in a merge, after
3144 command is used to manage the files involved in a merge, after
3151 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
3145 :hg:`merge` has been run, and before :hg:`commit` is run (i.e. the
3152 working directory must have two parents).
3146 working directory must have two parents).
3153
3147
3154 The resolve command can be used in the following ways:
3148 The resolve command can be used in the following ways:
3155
3149
3156 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
3150 - :hg:`resolve [--tool TOOL] FILE...`: attempt to re-merge the specified
3157 files, discarding any previous merge attempts. Re-merging is not
3151 files, discarding any previous merge attempts. Re-merging is not
3158 performed for files already marked as resolved. Use ``--all/-a``
3152 performed for files already marked as resolved. Use ``--all/-a``
3159 to selects all unresolved files. ``--tool`` can be used to specify
3153 to selects all unresolved files. ``--tool`` can be used to specify
3160 the merge tool used for the given files. It overrides the HGMERGE
3154 the merge tool used for the given files. It overrides the HGMERGE
3161 environment variable and your configuration files.
3155 environment variable and your configuration files.
3162
3156
3163 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
3157 - :hg:`resolve -m [FILE]`: mark a file as having been resolved
3164 (e.g. after having manually fixed-up the files). The default is
3158 (e.g. after having manually fixed-up the files). The default is
3165 to mark all unresolved files.
3159 to mark all unresolved files.
3166
3160
3167 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
3161 - :hg:`resolve -u [FILE]...`: mark a file as unresolved. The
3168 default is to mark all resolved files.
3162 default is to mark all resolved files.
3169
3163
3170 - :hg:`resolve -l`: list files which had or still have conflicts.
3164 - :hg:`resolve -l`: list files which had or still have conflicts.
3171 In the printed list, ``U`` = unresolved and ``R`` = resolved.
3165 In the printed list, ``U`` = unresolved and ``R`` = resolved.
3172
3166
3173 Note that Mercurial will not let you commit files with unresolved
3167 Note that Mercurial will not let you commit files with unresolved
3174 merge conflicts. You must use :hg:`resolve -m ...` before you can
3168 merge conflicts. You must use :hg:`resolve -m ...` before you can
3175 commit after a conflicting merge.
3169 commit after a conflicting merge.
3176
3170
3177 Returns 0 on success, 1 if any files fail a resolve attempt.
3171 Returns 0 on success, 1 if any files fail a resolve attempt.
3178 """
3172 """
3179
3173
3180 all, mark, unmark, show, nostatus = \
3174 all, mark, unmark, show, nostatus = \
3181 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
3175 [opts.get(o) for o in 'all mark unmark list no_status'.split()]
3182
3176
3183 if (show and (mark or unmark)) or (mark and unmark):
3177 if (show and (mark or unmark)) or (mark and unmark):
3184 raise util.Abort(_("too many options specified"))
3178 raise util.Abort(_("too many options specified"))
3185 if pats and all:
3179 if pats and all:
3186 raise util.Abort(_("can't specify --all and patterns"))
3180 raise util.Abort(_("can't specify --all and patterns"))
3187 if not (all or pats or show or mark or unmark):
3181 if not (all or pats or show or mark or unmark):
3188 raise util.Abort(_('no files or directories specified; '
3182 raise util.Abort(_('no files or directories specified; '
3189 'use --all to remerge all files'))
3183 'use --all to remerge all files'))
3190
3184
3191 ms = mergemod.mergestate(repo)
3185 ms = mergemod.mergestate(repo)
3192 m = cmdutil.match(repo, pats, opts)
3186 m = cmdutil.match(repo, pats, opts)
3193 ret = 0
3187 ret = 0
3194
3188
3195 for f in ms:
3189 for f in ms:
3196 if m(f):
3190 if m(f):
3197 if show:
3191 if show:
3198 if nostatus:
3192 if nostatus:
3199 ui.write("%s\n" % f)
3193 ui.write("%s\n" % f)
3200 else:
3194 else:
3201 ui.write("%s %s\n" % (ms[f].upper(), f),
3195 ui.write("%s %s\n" % (ms[f].upper(), f),
3202 label='resolve.' +
3196 label='resolve.' +
3203 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
3197 {'u': 'unresolved', 'r': 'resolved'}[ms[f]])
3204 elif mark:
3198 elif mark:
3205 ms.mark(f, "r")
3199 ms.mark(f, "r")
3206 elif unmark:
3200 elif unmark:
3207 ms.mark(f, "u")
3201 ms.mark(f, "u")
3208 else:
3202 else:
3209 wctx = repo[None]
3203 wctx = repo[None]
3210 mctx = wctx.parents()[-1]
3204 mctx = wctx.parents()[-1]
3211
3205
3212 # backup pre-resolve (merge uses .orig for its own purposes)
3206 # backup pre-resolve (merge uses .orig for its own purposes)
3213 a = repo.wjoin(f)
3207 a = repo.wjoin(f)
3214 util.copyfile(a, a + ".resolve")
3208 util.copyfile(a, a + ".resolve")
3215
3209
3216 try:
3210 try:
3217 # resolve file
3211 # resolve file
3218 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3212 ui.setconfig('ui', 'forcemerge', opts.get('tool', ''))
3219 if ms.resolve(f, wctx, mctx):
3213 if ms.resolve(f, wctx, mctx):
3220 ret = 1
3214 ret = 1
3221 finally:
3215 finally:
3222 ui.setconfig('ui', 'forcemerge', '')
3216 ui.setconfig('ui', 'forcemerge', '')
3223
3217
3224 # replace filemerge's .orig file with our resolve file
3218 # replace filemerge's .orig file with our resolve file
3225 util.rename(a + ".resolve", a + ".orig")
3219 util.rename(a + ".resolve", a + ".orig")
3226
3220
3227 ms.commit()
3221 ms.commit()
3228 return ret
3222 return ret
3229
3223
3230 def revert(ui, repo, *pats, **opts):
3224 def revert(ui, repo, *pats, **opts):
3231 """restore individual files or directories to an earlier state
3225 """restore individual files or directories to an earlier state
3232
3226
3233 .. note::
3227 .. note::
3234 This command is most likely not what you are looking for.
3228 This command is most likely not what you are looking for.
3235 Revert will partially overwrite content in the working
3229 Revert will partially overwrite content in the working
3236 directory without changing the working directory parents. Use
3230 directory without changing the working directory parents. Use
3237 :hg:`update -r rev` to check out earlier revisions, or
3231 :hg:`update -r rev` to check out earlier revisions, or
3238 :hg:`update --clean .` to undo a merge which has added another
3232 :hg:`update --clean .` to undo a merge which has added another
3239 parent.
3233 parent.
3240
3234
3241 With no revision specified, revert the named files or directories
3235 With no revision specified, revert the named files or directories
3242 to the contents they had in the parent of the working directory.
3236 to the contents they had in the parent of the working directory.
3243 This restores the contents of the affected files to an unmodified
3237 This restores the contents of the affected files to an unmodified
3244 state and unschedules adds, removes, copies, and renames. If the
3238 state and unschedules adds, removes, copies, and renames. If the
3245 working directory has two parents, you must explicitly specify a
3239 working directory has two parents, you must explicitly specify a
3246 revision.
3240 revision.
3247
3241
3248 Using the -r/--rev option, revert the given files or directories
3242 Using the -r/--rev option, revert the given files or directories
3249 to their contents as of a specific revision. This can be helpful
3243 to their contents as of a specific revision. This can be helpful
3250 to "roll back" some or all of an earlier change. See :hg:`help
3244 to "roll back" some or all of an earlier change. See :hg:`help
3251 dates` for a list of formats valid for -d/--date.
3245 dates` for a list of formats valid for -d/--date.
3252
3246
3253 Revert modifies the working directory. It does not commit any
3247 Revert modifies the working directory. It does not commit any
3254 changes, or change the parent of the working directory. If you
3248 changes, or change the parent of the working directory. If you
3255 revert to a revision other than the parent of the working
3249 revert to a revision other than the parent of the working
3256 directory, the reverted files will thus appear modified
3250 directory, the reverted files will thus appear modified
3257 afterwards.
3251 afterwards.
3258
3252
3259 If a file has been deleted, it is restored. If the executable mode
3253 If a file has been deleted, it is restored. If the executable mode
3260 of a file was changed, it is reset.
3254 of a file was changed, it is reset.
3261
3255
3262 If names are given, all files matching the names are reverted.
3256 If names are given, all files matching the names are reverted.
3263 If no arguments are given, no files are reverted.
3257 If no arguments are given, no files are reverted.
3264
3258
3265 Modified files are saved with a .orig suffix before reverting.
3259 Modified files are saved with a .orig suffix before reverting.
3266 To disable these backups, use --no-backup.
3260 To disable these backups, use --no-backup.
3267
3261
3268 Returns 0 on success.
3262 Returns 0 on success.
3269 """
3263 """
3270
3264
3271 if opts.get("date"):
3265 if opts.get("date"):
3272 if opts.get("rev"):
3266 if opts.get("rev"):
3273 raise util.Abort(_("you can't specify a revision and a date"))
3267 raise util.Abort(_("you can't specify a revision and a date"))
3274 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
3268 opts["rev"] = cmdutil.finddate(ui, repo, opts["date"])
3275
3269
3276 parent, p2 = repo.dirstate.parents()
3270 parent, p2 = repo.dirstate.parents()
3277 if not opts.get('rev') and p2 != nullid:
3271 if not opts.get('rev') and p2 != nullid:
3278 raise util.Abort(_('uncommitted merge - '
3272 raise util.Abort(_('uncommitted merge - '
3279 'use "hg update", see "hg help revert"'))
3273 'use "hg update", see "hg help revert"'))
3280
3274
3281 if not pats and not opts.get('all'):
3275 if not pats and not opts.get('all'):
3282 raise util.Abort(_('no files or directories specified; '
3276 raise util.Abort(_('no files or directories specified; '
3283 'use --all to revert the whole repo'))
3277 'use --all to revert the whole repo'))
3284
3278
3285 ctx = cmdutil.revsingle(repo, opts.get('rev'))
3279 ctx = cmdutil.revsingle(repo, opts.get('rev'))
3286 node = ctx.node()
3280 node = ctx.node()
3287 mf = ctx.manifest()
3281 mf = ctx.manifest()
3288 if node == parent:
3282 if node == parent:
3289 pmf = mf
3283 pmf = mf
3290 else:
3284 else:
3291 pmf = None
3285 pmf = None
3292
3286
3293 # need all matching names in dirstate and manifest of target rev,
3287 # need all matching names in dirstate and manifest of target rev,
3294 # so have to walk both. do not print errors if files exist in one
3288 # so have to walk both. do not print errors if files exist in one
3295 # but not other.
3289 # but not other.
3296
3290
3297 names = {}
3291 names = {}
3298
3292
3299 wlock = repo.wlock()
3293 wlock = repo.wlock()
3300 try:
3294 try:
3301 # walk dirstate.
3295 # walk dirstate.
3302
3296
3303 m = cmdutil.match(repo, pats, opts)
3297 m = cmdutil.match(repo, pats, opts)
3304 m.bad = lambda x, y: False
3298 m.bad = lambda x, y: False
3305 for abs in repo.walk(m):
3299 for abs in repo.walk(m):
3306 names[abs] = m.rel(abs), m.exact(abs)
3300 names[abs] = m.rel(abs), m.exact(abs)
3307
3301
3308 # walk target manifest.
3302 # walk target manifest.
3309
3303
3310 def badfn(path, msg):
3304 def badfn(path, msg):
3311 if path in names:
3305 if path in names:
3312 return
3306 return
3313 path_ = path + '/'
3307 path_ = path + '/'
3314 for f in names:
3308 for f in names:
3315 if f.startswith(path_):
3309 if f.startswith(path_):
3316 return
3310 return
3317 ui.warn("%s: %s\n" % (m.rel(path), msg))
3311 ui.warn("%s: %s\n" % (m.rel(path), msg))
3318
3312
3319 m = cmdutil.match(repo, pats, opts)
3313 m = cmdutil.match(repo, pats, opts)
3320 m.bad = badfn
3314 m.bad = badfn
3321 for abs in repo[node].walk(m):
3315 for abs in repo[node].walk(m):
3322 if abs not in names:
3316 if abs not in names:
3323 names[abs] = m.rel(abs), m.exact(abs)
3317 names[abs] = m.rel(abs), m.exact(abs)
3324
3318
3325 m = cmdutil.matchfiles(repo, names)
3319 m = cmdutil.matchfiles(repo, names)
3326 changes = repo.status(match=m)[:4]
3320 changes = repo.status(match=m)[:4]
3327 modified, added, removed, deleted = map(set, changes)
3321 modified, added, removed, deleted = map(set, changes)
3328
3322
3329 # if f is a rename, also revert the source
3323 # if f is a rename, also revert the source
3330 cwd = repo.getcwd()
3324 cwd = repo.getcwd()
3331 for f in added:
3325 for f in added:
3332 src = repo.dirstate.copied(f)
3326 src = repo.dirstate.copied(f)
3333 if src and src not in names and repo.dirstate[src] == 'r':
3327 if src and src not in names and repo.dirstate[src] == 'r':
3334 removed.add(src)
3328 removed.add(src)
3335 names[src] = (repo.pathto(src, cwd), True)
3329 names[src] = (repo.pathto(src, cwd), True)
3336
3330
3337 def removeforget(abs):
3331 def removeforget(abs):
3338 if repo.dirstate[abs] == 'a':
3332 if repo.dirstate[abs] == 'a':
3339 return _('forgetting %s\n')
3333 return _('forgetting %s\n')
3340 return _('removing %s\n')
3334 return _('removing %s\n')
3341
3335
3342 revert = ([], _('reverting %s\n'))
3336 revert = ([], _('reverting %s\n'))
3343 add = ([], _('adding %s\n'))
3337 add = ([], _('adding %s\n'))
3344 remove = ([], removeforget)
3338 remove = ([], removeforget)
3345 undelete = ([], _('undeleting %s\n'))
3339 undelete = ([], _('undeleting %s\n'))
3346
3340
3347 disptable = (
3341 disptable = (
3348 # dispatch table:
3342 # dispatch table:
3349 # file state
3343 # file state
3350 # action if in target manifest
3344 # action if in target manifest
3351 # action if not in target manifest
3345 # action if not in target manifest
3352 # make backup if in target manifest
3346 # make backup if in target manifest
3353 # make backup if not in target manifest
3347 # make backup if not in target manifest
3354 (modified, revert, remove, True, True),
3348 (modified, revert, remove, True, True),
3355 (added, revert, remove, True, False),
3349 (added, revert, remove, True, False),
3356 (removed, undelete, None, False, False),
3350 (removed, undelete, None, False, False),
3357 (deleted, revert, remove, False, False),
3351 (deleted, revert, remove, False, False),
3358 )
3352 )
3359
3353
3360 for abs, (rel, exact) in sorted(names.items()):
3354 for abs, (rel, exact) in sorted(names.items()):
3361 mfentry = mf.get(abs)
3355 mfentry = mf.get(abs)
3362 target = repo.wjoin(abs)
3356 target = repo.wjoin(abs)
3363 def handle(xlist, dobackup):
3357 def handle(xlist, dobackup):
3364 xlist[0].append(abs)
3358 xlist[0].append(abs)
3365 if (dobackup and not opts.get('no_backup') and
3359 if (dobackup and not opts.get('no_backup') and
3366 os.path.lexists(target)):
3360 os.path.lexists(target)):
3367 bakname = "%s.orig" % rel
3361 bakname = "%s.orig" % rel
3368 ui.note(_('saving current version of %s as %s\n') %
3362 ui.note(_('saving current version of %s as %s\n') %
3369 (rel, bakname))
3363 (rel, bakname))
3370 if not opts.get('dry_run'):
3364 if not opts.get('dry_run'):
3371 util.rename(target, bakname)
3365 util.rename(target, bakname)
3372 if ui.verbose or not exact:
3366 if ui.verbose or not exact:
3373 msg = xlist[1]
3367 msg = xlist[1]
3374 if not isinstance(msg, basestring):
3368 if not isinstance(msg, basestring):
3375 msg = msg(abs)
3369 msg = msg(abs)
3376 ui.status(msg % rel)
3370 ui.status(msg % rel)
3377 for table, hitlist, misslist, backuphit, backupmiss in disptable:
3371 for table, hitlist, misslist, backuphit, backupmiss in disptable:
3378 if abs not in table:
3372 if abs not in table:
3379 continue
3373 continue
3380 # file has changed in dirstate
3374 # file has changed in dirstate
3381 if mfentry:
3375 if mfentry:
3382 handle(hitlist, backuphit)
3376 handle(hitlist, backuphit)
3383 elif misslist is not None:
3377 elif misslist is not None:
3384 handle(misslist, backupmiss)
3378 handle(misslist, backupmiss)
3385 break
3379 break
3386 else:
3380 else:
3387 if abs not in repo.dirstate:
3381 if abs not in repo.dirstate:
3388 if mfentry:
3382 if mfentry:
3389 handle(add, True)
3383 handle(add, True)
3390 elif exact:
3384 elif exact:
3391 ui.warn(_('file not managed: %s\n') % rel)
3385 ui.warn(_('file not managed: %s\n') % rel)
3392 continue
3386 continue
3393 # file has not changed in dirstate
3387 # file has not changed in dirstate
3394 if node == parent:
3388 if node == parent:
3395 if exact:
3389 if exact:
3396 ui.warn(_('no changes needed to %s\n') % rel)
3390 ui.warn(_('no changes needed to %s\n') % rel)
3397 continue
3391 continue
3398 if pmf is None:
3392 if pmf is None:
3399 # only need parent manifest in this unlikely case,
3393 # only need parent manifest in this unlikely case,
3400 # so do not read by default
3394 # so do not read by default
3401 pmf = repo[parent].manifest()
3395 pmf = repo[parent].manifest()
3402 if abs in pmf:
3396 if abs in pmf:
3403 if mfentry:
3397 if mfentry:
3404 # if version of file is same in parent and target
3398 # if version of file is same in parent and target
3405 # manifests, do nothing
3399 # manifests, do nothing
3406 if (pmf[abs] != mfentry or
3400 if (pmf[abs] != mfentry or
3407 pmf.flags(abs) != mf.flags(abs)):
3401 pmf.flags(abs) != mf.flags(abs)):
3408 handle(revert, False)
3402 handle(revert, False)
3409 else:
3403 else:
3410 handle(remove, False)
3404 handle(remove, False)
3411
3405
3412 if not opts.get('dry_run'):
3406 if not opts.get('dry_run'):
3413 def checkout(f):
3407 def checkout(f):
3414 fc = ctx[f]
3408 fc = ctx[f]
3415 repo.wwrite(f, fc.data(), fc.flags())
3409 repo.wwrite(f, fc.data(), fc.flags())
3416
3410
3417 audit_path = util.path_auditor(repo.root)
3411 audit_path = util.path_auditor(repo.root)
3418 for f in remove[0]:
3412 for f in remove[0]:
3419 if repo.dirstate[f] == 'a':
3413 if repo.dirstate[f] == 'a':
3420 repo.dirstate.forget(f)
3414 repo.dirstate.forget(f)
3421 continue
3415 continue
3422 audit_path(f)
3416 audit_path(f)
3423 try:
3417 try:
3424 util.unlinkpath(repo.wjoin(f))
3418 util.unlinkpath(repo.wjoin(f))
3425 except OSError:
3419 except OSError:
3426 pass
3420 pass
3427 repo.dirstate.remove(f)
3421 repo.dirstate.remove(f)
3428
3422
3429 normal = None
3423 normal = None
3430 if node == parent:
3424 if node == parent:
3431 # We're reverting to our parent. If possible, we'd like status
3425 # We're reverting to our parent. If possible, we'd like status
3432 # to report the file as clean. We have to use normallookup for
3426 # to report the file as clean. We have to use normallookup for
3433 # merges to avoid losing information about merged/dirty files.
3427 # merges to avoid losing information about merged/dirty files.
3434 if p2 != nullid:
3428 if p2 != nullid:
3435 normal = repo.dirstate.normallookup
3429 normal = repo.dirstate.normallookup
3436 else:
3430 else:
3437 normal = repo.dirstate.normal
3431 normal = repo.dirstate.normal
3438 for f in revert[0]:
3432 for f in revert[0]:
3439 checkout(f)
3433 checkout(f)
3440 if normal:
3434 if normal:
3441 normal(f)
3435 normal(f)
3442
3436
3443 for f in add[0]:
3437 for f in add[0]:
3444 checkout(f)
3438 checkout(f)
3445 repo.dirstate.add(f)
3439 repo.dirstate.add(f)
3446
3440
3447 normal = repo.dirstate.normallookup
3441 normal = repo.dirstate.normallookup
3448 if node == parent and p2 == nullid:
3442 if node == parent and p2 == nullid:
3449 normal = repo.dirstate.normal
3443 normal = repo.dirstate.normal
3450 for f in undelete[0]:
3444 for f in undelete[0]:
3451 checkout(f)
3445 checkout(f)
3452 normal(f)
3446 normal(f)
3453
3447
3454 finally:
3448 finally:
3455 wlock.release()
3449 wlock.release()
3456
3450
3457 def rollback(ui, repo, **opts):
3451 def rollback(ui, repo, **opts):
3458 """roll back the last transaction (dangerous)
3452 """roll back the last transaction (dangerous)
3459
3453
3460 This command should be used with care. There is only one level of
3454 This command should be used with care. There is only one level of
3461 rollback, and there is no way to undo a rollback. It will also
3455 rollback, and there is no way to undo a rollback. It will also
3462 restore the dirstate at the time of the last transaction, losing
3456 restore the dirstate at the time of the last transaction, losing
3463 any dirstate changes since that time. This command does not alter
3457 any dirstate changes since that time. This command does not alter
3464 the working directory.
3458 the working directory.
3465
3459
3466 Transactions are used to encapsulate the effects of all commands
3460 Transactions are used to encapsulate the effects of all commands
3467 that create new changesets or propagate existing changesets into a
3461 that create new changesets or propagate existing changesets into a
3468 repository. For example, the following commands are transactional,
3462 repository. For example, the following commands are transactional,
3469 and their effects can be rolled back:
3463 and their effects can be rolled back:
3470
3464
3471 - commit
3465 - commit
3472 - import
3466 - import
3473 - pull
3467 - pull
3474 - push (with this repository as the destination)
3468 - push (with this repository as the destination)
3475 - unbundle
3469 - unbundle
3476
3470
3477 This command is not intended for use on public repositories. Once
3471 This command is not intended for use on public repositories. Once
3478 changes are visible for pull by other users, rolling a transaction
3472 changes are visible for pull by other users, rolling a transaction
3479 back locally is ineffective (someone else may already have pulled
3473 back locally is ineffective (someone else may already have pulled
3480 the changes). Furthermore, a race is possible with readers of the
3474 the changes). Furthermore, a race is possible with readers of the
3481 repository; for example an in-progress pull from the repository
3475 repository; for example an in-progress pull from the repository
3482 may fail if a rollback is performed.
3476 may fail if a rollback is performed.
3483
3477
3484 Returns 0 on success, 1 if no rollback data is available.
3478 Returns 0 on success, 1 if no rollback data is available.
3485 """
3479 """
3486 return repo.rollback(opts.get('dry_run'))
3480 return repo.rollback(opts.get('dry_run'))
3487
3481
3488 def root(ui, repo):
3482 def root(ui, repo):
3489 """print the root (top) of the current working directory
3483 """print the root (top) of the current working directory
3490
3484
3491 Print the root directory of the current repository.
3485 Print the root directory of the current repository.
3492
3486
3493 Returns 0 on success.
3487 Returns 0 on success.
3494 """
3488 """
3495 ui.write(repo.root + "\n")
3489 ui.write(repo.root + "\n")
3496
3490
3497 def serve(ui, repo, **opts):
3491 def serve(ui, repo, **opts):
3498 """start stand-alone webserver
3492 """start stand-alone webserver
3499
3493
3500 Start a local HTTP repository browser and pull server. You can use
3494 Start a local HTTP repository browser and pull server. You can use
3501 this for ad-hoc sharing and browsing of repositories. It is
3495 this for ad-hoc sharing and browsing of repositories. It is
3502 recommended to use a real web server to serve a repository for
3496 recommended to use a real web server to serve a repository for
3503 longer periods of time.
3497 longer periods of time.
3504
3498
3505 Please note that the server does not implement access control.
3499 Please note that the server does not implement access control.
3506 This means that, by default, anybody can read from the server and
3500 This means that, by default, anybody can read from the server and
3507 nobody can write to it by default. Set the ``web.allow_push``
3501 nobody can write to it by default. Set the ``web.allow_push``
3508 option to ``*`` to allow everybody to push to the server. You
3502 option to ``*`` to allow everybody to push to the server. You
3509 should use a real web server if you need to authenticate users.
3503 should use a real web server if you need to authenticate users.
3510
3504
3511 By default, the server logs accesses to stdout and errors to
3505 By default, the server logs accesses to stdout and errors to
3512 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
3506 stderr. Use the -A/--accesslog and -E/--errorlog options to log to
3513 files.
3507 files.
3514
3508
3515 To have the server choose a free port number to listen on, specify
3509 To have the server choose a free port number to listen on, specify
3516 a port number of 0; in this case, the server will print the port
3510 a port number of 0; in this case, the server will print the port
3517 number it uses.
3511 number it uses.
3518
3512
3519 Returns 0 on success.
3513 Returns 0 on success.
3520 """
3514 """
3521
3515
3522 if opts["stdio"]:
3516 if opts["stdio"]:
3523 if repo is None:
3517 if repo is None:
3524 raise error.RepoError(_("There is no Mercurial repository here"
3518 raise error.RepoError(_("There is no Mercurial repository here"
3525 " (.hg not found)"))
3519 " (.hg not found)"))
3526 s = sshserver.sshserver(ui, repo)
3520 s = sshserver.sshserver(ui, repo)
3527 s.serve_forever()
3521 s.serve_forever()
3528
3522
3529 # this way we can check if something was given in the command-line
3523 # this way we can check if something was given in the command-line
3530 if opts.get('port'):
3524 if opts.get('port'):
3531 opts['port'] = util.getport(opts.get('port'))
3525 opts['port'] = util.getport(opts.get('port'))
3532
3526
3533 baseui = repo and repo.baseui or ui
3527 baseui = repo and repo.baseui or ui
3534 optlist = ("name templates style address port prefix ipv6"
3528 optlist = ("name templates style address port prefix ipv6"
3535 " accesslog errorlog certificate encoding")
3529 " accesslog errorlog certificate encoding")
3536 for o in optlist.split():
3530 for o in optlist.split():
3537 val = opts.get(o, '')
3531 val = opts.get(o, '')
3538 if val in (None, ''): # should check against default options instead
3532 if val in (None, ''): # should check against default options instead
3539 continue
3533 continue
3540 baseui.setconfig("web", o, val)
3534 baseui.setconfig("web", o, val)
3541 if repo and repo.ui != baseui:
3535 if repo and repo.ui != baseui:
3542 repo.ui.setconfig("web", o, val)
3536 repo.ui.setconfig("web", o, val)
3543
3537
3544 o = opts.get('web_conf') or opts.get('webdir_conf')
3538 o = opts.get('web_conf') or opts.get('webdir_conf')
3545 if not o:
3539 if not o:
3546 if not repo:
3540 if not repo:
3547 raise error.RepoError(_("There is no Mercurial repository"
3541 raise error.RepoError(_("There is no Mercurial repository"
3548 " here (.hg not found)"))
3542 " here (.hg not found)"))
3549 o = repo.root
3543 o = repo.root
3550
3544
3551 app = hgweb.hgweb(o, baseui=ui)
3545 app = hgweb.hgweb(o, baseui=ui)
3552
3546
3553 class service(object):
3547 class service(object):
3554 def init(self):
3548 def init(self):
3555 util.set_signal_handler()
3549 util.set_signal_handler()
3556 self.httpd = hgweb.server.create_server(ui, app)
3550 self.httpd = hgweb.server.create_server(ui, app)
3557
3551
3558 if opts['port'] and not ui.verbose:
3552 if opts['port'] and not ui.verbose:
3559 return
3553 return
3560
3554
3561 if self.httpd.prefix:
3555 if self.httpd.prefix:
3562 prefix = self.httpd.prefix.strip('/') + '/'
3556 prefix = self.httpd.prefix.strip('/') + '/'
3563 else:
3557 else:
3564 prefix = ''
3558 prefix = ''
3565
3559
3566 port = ':%d' % self.httpd.port
3560 port = ':%d' % self.httpd.port
3567 if port == ':80':
3561 if port == ':80':
3568 port = ''
3562 port = ''
3569
3563
3570 bindaddr = self.httpd.addr
3564 bindaddr = self.httpd.addr
3571 if bindaddr == '0.0.0.0':
3565 if bindaddr == '0.0.0.0':
3572 bindaddr = '*'
3566 bindaddr = '*'
3573 elif ':' in bindaddr: # IPv6
3567 elif ':' in bindaddr: # IPv6
3574 bindaddr = '[%s]' % bindaddr
3568 bindaddr = '[%s]' % bindaddr
3575
3569
3576 fqaddr = self.httpd.fqaddr
3570 fqaddr = self.httpd.fqaddr
3577 if ':' in fqaddr:
3571 if ':' in fqaddr:
3578 fqaddr = '[%s]' % fqaddr
3572 fqaddr = '[%s]' % fqaddr
3579 if opts['port']:
3573 if opts['port']:
3580 write = ui.status
3574 write = ui.status
3581 else:
3575 else:
3582 write = ui.write
3576 write = ui.write
3583 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
3577 write(_('listening at http://%s%s/%s (bound to %s:%d)\n') %
3584 (fqaddr, port, prefix, bindaddr, self.httpd.port))
3578 (fqaddr, port, prefix, bindaddr, self.httpd.port))
3585
3579
3586 def run(self):
3580 def run(self):
3587 self.httpd.serve_forever()
3581 self.httpd.serve_forever()
3588
3582
3589 service = service()
3583 service = service()
3590
3584
3591 cmdutil.service(opts, initfn=service.init, runfn=service.run)
3585 cmdutil.service(opts, initfn=service.init, runfn=service.run)
3592
3586
3593 def status(ui, repo, *pats, **opts):
3587 def status(ui, repo, *pats, **opts):
3594 """show changed files in the working directory
3588 """show changed files in the working directory
3595
3589
3596 Show status of files in the repository. If names are given, only
3590 Show status of files in the repository. If names are given, only
3597 files that match are shown. Files that are clean or ignored or
3591 files that match are shown. Files that are clean or ignored or
3598 the source of a copy/move operation, are not listed unless
3592 the source of a copy/move operation, are not listed unless
3599 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
3593 -c/--clean, -i/--ignored, -C/--copies or -A/--all are given.
3600 Unless options described with "show only ..." are given, the
3594 Unless options described with "show only ..." are given, the
3601 options -mardu are used.
3595 options -mardu are used.
3602
3596
3603 Option -q/--quiet hides untracked (unknown and ignored) files
3597 Option -q/--quiet hides untracked (unknown and ignored) files
3604 unless explicitly requested with -u/--unknown or -i/--ignored.
3598 unless explicitly requested with -u/--unknown or -i/--ignored.
3605
3599
3606 .. note::
3600 .. note::
3607 status may appear to disagree with diff if permissions have
3601 status may appear to disagree with diff if permissions have
3608 changed or a merge has occurred. The standard diff format does
3602 changed or a merge has occurred. The standard diff format does
3609 not report permission changes and diff only reports changes
3603 not report permission changes and diff only reports changes
3610 relative to one merge parent.
3604 relative to one merge parent.
3611
3605
3612 If one revision is given, it is used as the base revision.
3606 If one revision is given, it is used as the base revision.
3613 If two revisions are given, the differences between them are
3607 If two revisions are given, the differences between them are
3614 shown. The --change option can also be used as a shortcut to list
3608 shown. The --change option can also be used as a shortcut to list
3615 the changed files of a revision from its first parent.
3609 the changed files of a revision from its first parent.
3616
3610
3617 The codes used to show the status of files are::
3611 The codes used to show the status of files are::
3618
3612
3619 M = modified
3613 M = modified
3620 A = added
3614 A = added
3621 R = removed
3615 R = removed
3622 C = clean
3616 C = clean
3623 ! = missing (deleted by non-hg command, but still tracked)
3617 ! = missing (deleted by non-hg command, but still tracked)
3624 ? = not tracked
3618 ? = not tracked
3625 I = ignored
3619 I = ignored
3626 = origin of the previous file listed as A (added)
3620 = origin of the previous file listed as A (added)
3627
3621
3628 Returns 0 on success.
3622 Returns 0 on success.
3629 """
3623 """
3630
3624
3631 revs = opts.get('rev')
3625 revs = opts.get('rev')
3632 change = opts.get('change')
3626 change = opts.get('change')
3633
3627
3634 if revs and change:
3628 if revs and change:
3635 msg = _('cannot specify --rev and --change at the same time')
3629 msg = _('cannot specify --rev and --change at the same time')
3636 raise util.Abort(msg)
3630 raise util.Abort(msg)
3637 elif change:
3631 elif change:
3638 node2 = repo.lookup(change)
3632 node2 = repo.lookup(change)
3639 node1 = repo[node2].parents()[0].node()
3633 node1 = repo[node2].parents()[0].node()
3640 else:
3634 else:
3641 node1, node2 = cmdutil.revpair(repo, revs)
3635 node1, node2 = cmdutil.revpair(repo, revs)
3642
3636
3643 cwd = (pats and repo.getcwd()) or ''
3637 cwd = (pats and repo.getcwd()) or ''
3644 end = opts.get('print0') and '\0' or '\n'
3638 end = opts.get('print0') and '\0' or '\n'
3645 copy = {}
3639 copy = {}
3646 states = 'modified added removed deleted unknown ignored clean'.split()
3640 states = 'modified added removed deleted unknown ignored clean'.split()
3647 show = [k for k in states if opts.get(k)]
3641 show = [k for k in states if opts.get(k)]
3648 if opts.get('all'):
3642 if opts.get('all'):
3649 show += ui.quiet and (states[:4] + ['clean']) or states
3643 show += ui.quiet and (states[:4] + ['clean']) or states
3650 if not show:
3644 if not show:
3651 show = ui.quiet and states[:4] or states[:5]
3645 show = ui.quiet and states[:4] or states[:5]
3652
3646
3653 stat = repo.status(node1, node2, cmdutil.match(repo, pats, opts),
3647 stat = repo.status(node1, node2, cmdutil.match(repo, pats, opts),
3654 'ignored' in show, 'clean' in show, 'unknown' in show,
3648 'ignored' in show, 'clean' in show, 'unknown' in show,
3655 opts.get('subrepos'))
3649 opts.get('subrepos'))
3656 changestates = zip(states, 'MAR!?IC', stat)
3650 changestates = zip(states, 'MAR!?IC', stat)
3657
3651
3658 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
3652 if (opts.get('all') or opts.get('copies')) and not opts.get('no_status'):
3659 ctxn = repo[nullid]
3653 ctxn = repo[nullid]
3660 ctx1 = repo[node1]
3654 ctx1 = repo[node1]
3661 ctx2 = repo[node2]
3655 ctx2 = repo[node2]
3662 added = stat[1]
3656 added = stat[1]
3663 if node2 is None:
3657 if node2 is None:
3664 added = stat[0] + stat[1] # merged?
3658 added = stat[0] + stat[1] # merged?
3665
3659
3666 for k, v in copies.copies(repo, ctx1, ctx2, ctxn)[0].iteritems():
3660 for k, v in copies.copies(repo, ctx1, ctx2, ctxn)[0].iteritems():
3667 if k in added:
3661 if k in added:
3668 copy[k] = v
3662 copy[k] = v
3669 elif v in added:
3663 elif v in added:
3670 copy[v] = k
3664 copy[v] = k
3671
3665
3672 for state, char, files in changestates:
3666 for state, char, files in changestates:
3673 if state in show:
3667 if state in show:
3674 format = "%s %%s%s" % (char, end)
3668 format = "%s %%s%s" % (char, end)
3675 if opts.get('no_status'):
3669 if opts.get('no_status'):
3676 format = "%%s%s" % end
3670 format = "%%s%s" % end
3677
3671
3678 for f in files:
3672 for f in files:
3679 ui.write(format % repo.pathto(f, cwd),
3673 ui.write(format % repo.pathto(f, cwd),
3680 label='status.' + state)
3674 label='status.' + state)
3681 if f in copy:
3675 if f in copy:
3682 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end),
3676 ui.write(' %s%s' % (repo.pathto(copy[f], cwd), end),
3683 label='status.copied')
3677 label='status.copied')
3684
3678
3685 def summary(ui, repo, **opts):
3679 def summary(ui, repo, **opts):
3686 """summarize working directory state
3680 """summarize working directory state
3687
3681
3688 This generates a brief summary of the working directory state,
3682 This generates a brief summary of the working directory state,
3689 including parents, branch, commit status, and available updates.
3683 including parents, branch, commit status, and available updates.
3690
3684
3691 With the --remote option, this will check the default paths for
3685 With the --remote option, this will check the default paths for
3692 incoming and outgoing changes. This can be time-consuming.
3686 incoming and outgoing changes. This can be time-consuming.
3693
3687
3694 Returns 0 on success.
3688 Returns 0 on success.
3695 """
3689 """
3696
3690
3697 ctx = repo[None]
3691 ctx = repo[None]
3698 parents = ctx.parents()
3692 parents = ctx.parents()
3699 pnode = parents[0].node()
3693 pnode = parents[0].node()
3700
3694
3701 for p in parents:
3695 for p in parents:
3702 # label with log.changeset (instead of log.parent) since this
3696 # label with log.changeset (instead of log.parent) since this
3703 # shows a working directory parent *changeset*:
3697 # shows a working directory parent *changeset*:
3704 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
3698 ui.write(_('parent: %d:%s ') % (p.rev(), str(p)),
3705 label='log.changeset')
3699 label='log.changeset')
3706 ui.write(' '.join(p.tags()), label='log.tag')
3700 ui.write(' '.join(p.tags()), label='log.tag')
3707 if p.rev() == -1:
3701 if p.rev() == -1:
3708 if not len(repo):
3702 if not len(repo):
3709 ui.write(_(' (empty repository)'))
3703 ui.write(_(' (empty repository)'))
3710 else:
3704 else:
3711 ui.write(_(' (no revision checked out)'))
3705 ui.write(_(' (no revision checked out)'))
3712 ui.write('\n')
3706 ui.write('\n')
3713 if p.description():
3707 if p.description():
3714 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
3708 ui.status(' ' + p.description().splitlines()[0].strip() + '\n',
3715 label='log.summary')
3709 label='log.summary')
3716
3710
3717 branch = ctx.branch()
3711 branch = ctx.branch()
3718 bheads = repo.branchheads(branch)
3712 bheads = repo.branchheads(branch)
3719 m = _('branch: %s\n') % branch
3713 m = _('branch: %s\n') % branch
3720 if branch != 'default':
3714 if branch != 'default':
3721 ui.write(m, label='log.branch')
3715 ui.write(m, label='log.branch')
3722 else:
3716 else:
3723 ui.status(m, label='log.branch')
3717 ui.status(m, label='log.branch')
3724
3718
3725 st = list(repo.status(unknown=True))[:6]
3719 st = list(repo.status(unknown=True))[:6]
3726
3720
3727 c = repo.dirstate.copies()
3721 c = repo.dirstate.copies()
3728 copied, renamed = [], []
3722 copied, renamed = [], []
3729 for d, s in c.iteritems():
3723 for d, s in c.iteritems():
3730 if s in st[2]:
3724 if s in st[2]:
3731 st[2].remove(s)
3725 st[2].remove(s)
3732 renamed.append(d)
3726 renamed.append(d)
3733 else:
3727 else:
3734 copied.append(d)
3728 copied.append(d)
3735 if d in st[1]:
3729 if d in st[1]:
3736 st[1].remove(d)
3730 st[1].remove(d)
3737 st.insert(3, renamed)
3731 st.insert(3, renamed)
3738 st.insert(4, copied)
3732 st.insert(4, copied)
3739
3733
3740 ms = mergemod.mergestate(repo)
3734 ms = mergemod.mergestate(repo)
3741 st.append([f for f in ms if ms[f] == 'u'])
3735 st.append([f for f in ms if ms[f] == 'u'])
3742
3736
3743 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
3737 subs = [s for s in ctx.substate if ctx.sub(s).dirty()]
3744 st.append(subs)
3738 st.append(subs)
3745
3739
3746 labels = [ui.label(_('%d modified'), 'status.modified'),
3740 labels = [ui.label(_('%d modified'), 'status.modified'),
3747 ui.label(_('%d added'), 'status.added'),
3741 ui.label(_('%d added'), 'status.added'),
3748 ui.label(_('%d removed'), 'status.removed'),
3742 ui.label(_('%d removed'), 'status.removed'),
3749 ui.label(_('%d renamed'), 'status.copied'),
3743 ui.label(_('%d renamed'), 'status.copied'),
3750 ui.label(_('%d copied'), 'status.copied'),
3744 ui.label(_('%d copied'), 'status.copied'),
3751 ui.label(_('%d deleted'), 'status.deleted'),
3745 ui.label(_('%d deleted'), 'status.deleted'),
3752 ui.label(_('%d unknown'), 'status.unknown'),
3746 ui.label(_('%d unknown'), 'status.unknown'),
3753 ui.label(_('%d ignored'), 'status.ignored'),
3747 ui.label(_('%d ignored'), 'status.ignored'),
3754 ui.label(_('%d unresolved'), 'resolve.unresolved'),
3748 ui.label(_('%d unresolved'), 'resolve.unresolved'),
3755 ui.label(_('%d subrepos'), 'status.modified')]
3749 ui.label(_('%d subrepos'), 'status.modified')]
3756 t = []
3750 t = []
3757 for s, l in zip(st, labels):
3751 for s, l in zip(st, labels):
3758 if s:
3752 if s:
3759 t.append(l % len(s))
3753 t.append(l % len(s))
3760
3754
3761 t = ', '.join(t)
3755 t = ', '.join(t)
3762 cleanworkdir = False
3756 cleanworkdir = False
3763
3757
3764 if len(parents) > 1:
3758 if len(parents) > 1:
3765 t += _(' (merge)')
3759 t += _(' (merge)')
3766 elif branch != parents[0].branch():
3760 elif branch != parents[0].branch():
3767 t += _(' (new branch)')
3761 t += _(' (new branch)')
3768 elif (parents[0].extra().get('close') and
3762 elif (parents[0].extra().get('close') and
3769 pnode in repo.branchheads(branch, closed=True)):
3763 pnode in repo.branchheads(branch, closed=True)):
3770 t += _(' (head closed)')
3764 t += _(' (head closed)')
3771 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
3765 elif not (st[0] or st[1] or st[2] or st[3] or st[4] or st[9]):
3772 t += _(' (clean)')
3766 t += _(' (clean)')
3773 cleanworkdir = True
3767 cleanworkdir = True
3774 elif pnode not in bheads:
3768 elif pnode not in bheads:
3775 t += _(' (new branch head)')
3769 t += _(' (new branch head)')
3776
3770
3777 if cleanworkdir:
3771 if cleanworkdir:
3778 ui.status(_('commit: %s\n') % t.strip())
3772 ui.status(_('commit: %s\n') % t.strip())
3779 else:
3773 else:
3780 ui.write(_('commit: %s\n') % t.strip())
3774 ui.write(_('commit: %s\n') % t.strip())
3781
3775
3782 # all ancestors of branch heads - all ancestors of parent = new csets
3776 # all ancestors of branch heads - all ancestors of parent = new csets
3783 new = [0] * len(repo)
3777 new = [0] * len(repo)
3784 cl = repo.changelog
3778 cl = repo.changelog
3785 for a in [cl.rev(n) for n in bheads]:
3779 for a in [cl.rev(n) for n in bheads]:
3786 new[a] = 1
3780 new[a] = 1
3787 for a in cl.ancestors(*[cl.rev(n) for n in bheads]):
3781 for a in cl.ancestors(*[cl.rev(n) for n in bheads]):
3788 new[a] = 1
3782 new[a] = 1
3789 for a in [p.rev() for p in parents]:
3783 for a in [p.rev() for p in parents]:
3790 if a >= 0:
3784 if a >= 0:
3791 new[a] = 0
3785 new[a] = 0
3792 for a in cl.ancestors(*[p.rev() for p in parents]):
3786 for a in cl.ancestors(*[p.rev() for p in parents]):
3793 new[a] = 0
3787 new[a] = 0
3794 new = sum(new)
3788 new = sum(new)
3795
3789
3796 if new == 0:
3790 if new == 0:
3797 ui.status(_('update: (current)\n'))
3791 ui.status(_('update: (current)\n'))
3798 elif pnode not in bheads:
3792 elif pnode not in bheads:
3799 ui.write(_('update: %d new changesets (update)\n') % new)
3793 ui.write(_('update: %d new changesets (update)\n') % new)
3800 else:
3794 else:
3801 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
3795 ui.write(_('update: %d new changesets, %d branch heads (merge)\n') %
3802 (new, len(bheads)))
3796 (new, len(bheads)))
3803
3797
3804 if opts.get('remote'):
3798 if opts.get('remote'):
3805 t = []
3799 t = []
3806 source, branches = hg.parseurl(ui.expandpath('default'))
3800 source, branches = hg.parseurl(ui.expandpath('default'))
3807 other = hg.repository(hg.remoteui(repo, {}), source)
3801 other = hg.repository(hg.remoteui(repo, {}), source)
3808 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
3802 revs, checkout = hg.addbranchrevs(repo, other, branches, opts.get('rev'))
3809 ui.debug('comparing with %s\n' % url.hidepassword(source))
3803 ui.debug('comparing with %s\n' % url.hidepassword(source))
3810 repo.ui.pushbuffer()
3804 repo.ui.pushbuffer()
3811 common, incoming, rheads = discovery.findcommonincoming(repo, other)
3805 common, incoming, rheads = discovery.findcommonincoming(repo, other)
3812 repo.ui.popbuffer()
3806 repo.ui.popbuffer()
3813 if incoming:
3807 if incoming:
3814 t.append(_('1 or more incoming'))
3808 t.append(_('1 or more incoming'))
3815
3809
3816 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
3810 dest, branches = hg.parseurl(ui.expandpath('default-push', 'default'))
3817 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
3811 revs, checkout = hg.addbranchrevs(repo, repo, branches, None)
3818 other = hg.repository(hg.remoteui(repo, {}), dest)
3812 other = hg.repository(hg.remoteui(repo, {}), dest)
3819 ui.debug('comparing with %s\n' % url.hidepassword(dest))
3813 ui.debug('comparing with %s\n' % url.hidepassword(dest))
3820 repo.ui.pushbuffer()
3814 repo.ui.pushbuffer()
3821 o = discovery.findoutgoing(repo, other)
3815 o = discovery.findoutgoing(repo, other)
3822 repo.ui.popbuffer()
3816 repo.ui.popbuffer()
3823 o = repo.changelog.nodesbetween(o, None)[0]
3817 o = repo.changelog.nodesbetween(o, None)[0]
3824 if o:
3818 if o:
3825 t.append(_('%d outgoing') % len(o))
3819 t.append(_('%d outgoing') % len(o))
3826
3820
3827 if t:
3821 if t:
3828 ui.write(_('remote: %s\n') % (', '.join(t)))
3822 ui.write(_('remote: %s\n') % (', '.join(t)))
3829 else:
3823 else:
3830 ui.status(_('remote: (synced)\n'))
3824 ui.status(_('remote: (synced)\n'))
3831
3825
3832 def tag(ui, repo, name1, *names, **opts):
3826 def tag(ui, repo, name1, *names, **opts):
3833 """add one or more tags for the current or given revision
3827 """add one or more tags for the current or given revision
3834
3828
3835 Name a particular revision using <name>.
3829 Name a particular revision using <name>.
3836
3830
3837 Tags are used to name particular revisions of the repository and are
3831 Tags are used to name particular revisions of the repository and are
3838 very useful to compare different revisions, to go back to significant
3832 very useful to compare different revisions, to go back to significant
3839 earlier versions or to mark branch points as releases, etc. Changing
3833 earlier versions or to mark branch points as releases, etc. Changing
3840 an existing tag is normally disallowed; use -f/--force to override.
3834 an existing tag is normally disallowed; use -f/--force to override.
3841
3835
3842 If no revision is given, the parent of the working directory is
3836 If no revision is given, the parent of the working directory is
3843 used, or tip if no revision is checked out.
3837 used, or tip if no revision is checked out.
3844
3838
3845 To facilitate version control, distribution, and merging of tags,
3839 To facilitate version control, distribution, and merging of tags,
3846 they are stored as a file named ".hgtags" which is managed similarly
3840 they are stored as a file named ".hgtags" which is managed similarly
3847 to other project files and can be hand-edited if necessary. This
3841 to other project files and can be hand-edited if necessary. This
3848 also means that tagging creates a new commit. The file
3842 also means that tagging creates a new commit. The file
3849 ".hg/localtags" is used for local tags (not shared among
3843 ".hg/localtags" is used for local tags (not shared among
3850 repositories).
3844 repositories).
3851
3845
3852 Tag commits are usually made at the head of a branch. If the parent
3846 Tag commits are usually made at the head of a branch. If the parent
3853 of the working directory is not a branch head, :hg:`tag` aborts; use
3847 of the working directory is not a branch head, :hg:`tag` aborts; use
3854 -f/--force to force the tag commit to be based on a non-head
3848 -f/--force to force the tag commit to be based on a non-head
3855 changeset.
3849 changeset.
3856
3850
3857 See :hg:`help dates` for a list of formats valid for -d/--date.
3851 See :hg:`help dates` for a list of formats valid for -d/--date.
3858
3852
3859 Since tag names have priority over branch names during revision
3853 Since tag names have priority over branch names during revision
3860 lookup, using an existing branch name as a tag name is discouraged.
3854 lookup, using an existing branch name as a tag name is discouraged.
3861
3855
3862 Returns 0 on success.
3856 Returns 0 on success.
3863 """
3857 """
3864
3858
3865 rev_ = "."
3859 rev_ = "."
3866 names = [t.strip() for t in (name1,) + names]
3860 names = [t.strip() for t in (name1,) + names]
3867 if len(names) != len(set(names)):
3861 if len(names) != len(set(names)):
3868 raise util.Abort(_('tag names must be unique'))
3862 raise util.Abort(_('tag names must be unique'))
3869 for n in names:
3863 for n in names:
3870 if n in ['tip', '.', 'null']:
3864 if n in ['tip', '.', 'null']:
3871 raise util.Abort(_('the name \'%s\' is reserved') % n)
3865 raise util.Abort(_('the name \'%s\' is reserved') % n)
3872 if not n:
3866 if not n:
3873 raise util.Abort(_('tag names cannot consist entirely of whitespace'))
3867 raise util.Abort(_('tag names cannot consist entirely of whitespace'))
3874 if opts.get('rev') and opts.get('remove'):
3868 if opts.get('rev') and opts.get('remove'):
3875 raise util.Abort(_("--rev and --remove are incompatible"))
3869 raise util.Abort(_("--rev and --remove are incompatible"))
3876 if opts.get('rev'):
3870 if opts.get('rev'):
3877 rev_ = opts['rev']
3871 rev_ = opts['rev']
3878 message = opts.get('message')
3872 message = opts.get('message')
3879 if opts.get('remove'):
3873 if opts.get('remove'):
3880 expectedtype = opts.get('local') and 'local' or 'global'
3874 expectedtype = opts.get('local') and 'local' or 'global'
3881 for n in names:
3875 for n in names:
3882 if not repo.tagtype(n):
3876 if not repo.tagtype(n):
3883 raise util.Abort(_('tag \'%s\' does not exist') % n)
3877 raise util.Abort(_('tag \'%s\' does not exist') % n)
3884 if repo.tagtype(n) != expectedtype:
3878 if repo.tagtype(n) != expectedtype:
3885 if expectedtype == 'global':
3879 if expectedtype == 'global':
3886 raise util.Abort(_('tag \'%s\' is not a global tag') % n)
3880 raise util.Abort(_('tag \'%s\' is not a global tag') % n)
3887 else:
3881 else:
3888 raise util.Abort(_('tag \'%s\' is not a local tag') % n)
3882 raise util.Abort(_('tag \'%s\' is not a local tag') % n)
3889 rev_ = nullid
3883 rev_ = nullid
3890 if not message:
3884 if not message:
3891 # we don't translate commit messages
3885 # we don't translate commit messages
3892 message = 'Removed tag %s' % ', '.join(names)
3886 message = 'Removed tag %s' % ', '.join(names)
3893 elif not opts.get('force'):
3887 elif not opts.get('force'):
3894 for n in names:
3888 for n in names:
3895 if n in repo.tags():
3889 if n in repo.tags():
3896 raise util.Abort(_('tag \'%s\' already exists '
3890 raise util.Abort(_('tag \'%s\' already exists '
3897 '(use -f to force)') % n)
3891 '(use -f to force)') % n)
3898 if not opts.get('local'):
3892 if not opts.get('local'):
3899 p1, p2 = repo.dirstate.parents()
3893 p1, p2 = repo.dirstate.parents()
3900 if p2 != nullid:
3894 if p2 != nullid:
3901 raise util.Abort(_('uncommitted merge'))
3895 raise util.Abort(_('uncommitted merge'))
3902 bheads = repo.branchheads()
3896 bheads = repo.branchheads()
3903 if not opts.get('force') and bheads and p1 not in bheads:
3897 if not opts.get('force') and bheads and p1 not in bheads:
3904 raise util.Abort(_('not at a branch head (use -f to force)'))
3898 raise util.Abort(_('not at a branch head (use -f to force)'))
3905 r = cmdutil.revsingle(repo, rev_).node()
3899 r = cmdutil.revsingle(repo, rev_).node()
3906
3900
3907 if not message:
3901 if not message:
3908 # we don't translate commit messages
3902 # we don't translate commit messages
3909 message = ('Added tag %s for changeset %s' %
3903 message = ('Added tag %s for changeset %s' %
3910 (', '.join(names), short(r)))
3904 (', '.join(names), short(r)))
3911
3905
3912 date = opts.get('date')
3906 date = opts.get('date')
3913 if date:
3907 if date:
3914 date = util.parsedate(date)
3908 date = util.parsedate(date)
3915
3909
3916 if opts.get('edit'):
3910 if opts.get('edit'):
3917 message = ui.edit(message, ui.username())
3911 message = ui.edit(message, ui.username())
3918
3912
3919 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
3913 repo.tag(names, r, message, opts.get('local'), opts.get('user'), date)
3920
3914
3921 def tags(ui, repo):
3915 def tags(ui, repo):
3922 """list repository tags
3916 """list repository tags
3923
3917
3924 This lists both regular and local tags. When the -v/--verbose
3918 This lists both regular and local tags. When the -v/--verbose
3925 switch is used, a third column "local" is printed for local tags.
3919 switch is used, a third column "local" is printed for local tags.
3926
3920
3927 Returns 0 on success.
3921 Returns 0 on success.
3928 """
3922 """
3929
3923
3930 hexfunc = ui.debugflag and hex or short
3924 hexfunc = ui.debugflag and hex or short
3931 tagtype = ""
3925 tagtype = ""
3932
3926
3933 for t, n in reversed(repo.tagslist()):
3927 for t, n in reversed(repo.tagslist()):
3934 if ui.quiet:
3928 if ui.quiet:
3935 ui.write("%s\n" % t)
3929 ui.write("%s\n" % t)
3936 continue
3930 continue
3937
3931
3938 try:
3932 try:
3939 hn = hexfunc(n)
3933 hn = hexfunc(n)
3940 r = "%5d:%s" % (repo.changelog.rev(n), hn)
3934 r = "%5d:%s" % (repo.changelog.rev(n), hn)
3941 except error.LookupError:
3935 except error.LookupError:
3942 r = " ?:%s" % hn
3936 r = " ?:%s" % hn
3943 else:
3937 else:
3944 spaces = " " * (30 - encoding.colwidth(t))
3938 spaces = " " * (30 - encoding.colwidth(t))
3945 if ui.verbose:
3939 if ui.verbose:
3946 if repo.tagtype(t) == 'local':
3940 if repo.tagtype(t) == 'local':
3947 tagtype = " local"
3941 tagtype = " local"
3948 else:
3942 else:
3949 tagtype = ""
3943 tagtype = ""
3950 ui.write("%s%s %s%s\n" % (t, spaces, r, tagtype))
3944 ui.write("%s%s %s%s\n" % (t, spaces, r, tagtype))
3951
3945
3952 def tip(ui, repo, **opts):
3946 def tip(ui, repo, **opts):
3953 """show the tip revision
3947 """show the tip revision
3954
3948
3955 The tip revision (usually just called the tip) is the changeset
3949 The tip revision (usually just called the tip) is the changeset
3956 most recently added to the repository (and therefore the most
3950 most recently added to the repository (and therefore the most
3957 recently changed head).
3951 recently changed head).
3958
3952
3959 If you have just made a commit, that commit will be the tip. If
3953 If you have just made a commit, that commit will be the tip. If
3960 you have just pulled changes from another repository, the tip of
3954 you have just pulled changes from another repository, the tip of
3961 that repository becomes the current tip. The "tip" tag is special
3955 that repository becomes the current tip. The "tip" tag is special
3962 and cannot be renamed or assigned to a different changeset.
3956 and cannot be renamed or assigned to a different changeset.
3963
3957
3964 Returns 0 on success.
3958 Returns 0 on success.
3965 """
3959 """
3966 displayer = cmdutil.show_changeset(ui, repo, opts)
3960 displayer = cmdutil.show_changeset(ui, repo, opts)
3967 displayer.show(repo[len(repo) - 1])
3961 displayer.show(repo[len(repo) - 1])
3968 displayer.close()
3962 displayer.close()
3969
3963
3970 def unbundle(ui, repo, fname1, *fnames, **opts):
3964 def unbundle(ui, repo, fname1, *fnames, **opts):
3971 """apply one or more changegroup files
3965 """apply one or more changegroup files
3972
3966
3973 Apply one or more compressed changegroup files generated by the
3967 Apply one or more compressed changegroup files generated by the
3974 bundle command.
3968 bundle command.
3975
3969
3976 Returns 0 on success, 1 if an update has unresolved files.
3970 Returns 0 on success, 1 if an update has unresolved files.
3977 """
3971 """
3978 fnames = (fname1,) + fnames
3972 fnames = (fname1,) + fnames
3979
3973
3980 lock = repo.lock()
3974 lock = repo.lock()
3981 try:
3975 try:
3982 for fname in fnames:
3976 for fname in fnames:
3983 f = url.open(ui, fname)
3977 f = url.open(ui, fname)
3984 gen = changegroup.readbundle(f, fname)
3978 gen = changegroup.readbundle(f, fname)
3985 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname,
3979 modheads = repo.addchangegroup(gen, 'unbundle', 'bundle:' + fname,
3986 lock=lock)
3980 lock=lock)
3987 finally:
3981 finally:
3988 lock.release()
3982 lock.release()
3989
3983
3990 return postincoming(ui, repo, modheads, opts.get('update'), None)
3984 return postincoming(ui, repo, modheads, opts.get('update'), None)
3991
3985
3992 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
3986 def update(ui, repo, node=None, rev=None, clean=False, date=None, check=False):
3993 """update working directory (or switch revisions)
3987 """update working directory (or switch revisions)
3994
3988
3995 Update the repository's working directory to the specified
3989 Update the repository's working directory to the specified
3996 changeset. If no changeset is specified, update to the tip of the
3990 changeset. If no changeset is specified, update to the tip of the
3997 current named branch.
3991 current named branch.
3998
3992
3999 If the changeset is not a descendant of the working directory's
3993 If the changeset is not a descendant of the working directory's
4000 parent, the update is aborted. With the -c/--check option, the
3994 parent, the update is aborted. With the -c/--check option, the
4001 working directory is checked for uncommitted changes; if none are
3995 working directory is checked for uncommitted changes; if none are
4002 found, the working directory is updated to the specified
3996 found, the working directory is updated to the specified
4003 changeset.
3997 changeset.
4004
3998
4005 The following rules apply when the working directory contains
3999 The following rules apply when the working directory contains
4006 uncommitted changes:
4000 uncommitted changes:
4007
4001
4008 1. If neither -c/--check nor -C/--clean is specified, and if
4002 1. If neither -c/--check nor -C/--clean is specified, and if
4009 the requested changeset is an ancestor or descendant of
4003 the requested changeset is an ancestor or descendant of
4010 the working directory's parent, the uncommitted changes
4004 the working directory's parent, the uncommitted changes
4011 are merged into the requested changeset and the merged
4005 are merged into the requested changeset and the merged
4012 result is left uncommitted. If the requested changeset is
4006 result is left uncommitted. If the requested changeset is
4013 not an ancestor or descendant (that is, it is on another
4007 not an ancestor or descendant (that is, it is on another
4014 branch), the update is aborted and the uncommitted changes
4008 branch), the update is aborted and the uncommitted changes
4015 are preserved.
4009 are preserved.
4016
4010
4017 2. With the -c/--check option, the update is aborted and the
4011 2. With the -c/--check option, the update is aborted and the
4018 uncommitted changes are preserved.
4012 uncommitted changes are preserved.
4019
4013
4020 3. With the -C/--clean option, uncommitted changes are discarded and
4014 3. With the -C/--clean option, uncommitted changes are discarded and
4021 the working directory is updated to the requested changeset.
4015 the working directory is updated to the requested changeset.
4022
4016
4023 Use null as the changeset to remove the working directory (like
4017 Use null as the changeset to remove the working directory (like
4024 :hg:`clone -U`).
4018 :hg:`clone -U`).
4025
4019
4026 If you want to update just one file to an older changeset, use
4020 If you want to update just one file to an older changeset, use
4027 :hg:`revert`.
4021 :hg:`revert`.
4028
4022
4029 See :hg:`help dates` for a list of formats valid for -d/--date.
4023 See :hg:`help dates` for a list of formats valid for -d/--date.
4030
4024
4031 Returns 0 on success, 1 if there are unresolved files.
4025 Returns 0 on success, 1 if there are unresolved files.
4032 """
4026 """
4033 if rev and node:
4027 if rev and node:
4034 raise util.Abort(_("please specify just one revision"))
4028 raise util.Abort(_("please specify just one revision"))
4035
4029
4036 if not rev:
4030 if not rev:
4037 rev = node
4031 rev = node
4038
4032
4039 # if we defined a bookmark, we have to remember the original bookmark name
4033 # if we defined a bookmark, we have to remember the original bookmark name
4040 brev = rev
4034 brev = rev
4041 rev = cmdutil.revsingle(repo, rev, rev).rev()
4035 rev = cmdutil.revsingle(repo, rev, rev).rev()
4042
4036
4043 if check and clean:
4037 if check and clean:
4044 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
4038 raise util.Abort(_("cannot specify both -c/--check and -C/--clean"))
4045
4039
4046 if check:
4040 if check:
4047 # we could use dirty() but we can ignore merge and branch trivia
4041 # we could use dirty() but we can ignore merge and branch trivia
4048 c = repo[None]
4042 c = repo[None]
4049 if c.modified() or c.added() or c.removed():
4043 if c.modified() or c.added() or c.removed():
4050 raise util.Abort(_("uncommitted local changes"))
4044 raise util.Abort(_("uncommitted local changes"))
4051
4045
4052 if date:
4046 if date:
4053 if rev:
4047 if rev:
4054 raise util.Abort(_("you can't specify a revision and a date"))
4048 raise util.Abort(_("you can't specify a revision and a date"))
4055 rev = cmdutil.finddate(ui, repo, date)
4049 rev = cmdutil.finddate(ui, repo, date)
4056
4050
4057 if clean or check:
4051 if clean or check:
4058 ret = hg.clean(repo, rev)
4052 ret = hg.clean(repo, rev)
4059 else:
4053 else:
4060 ret = hg.update(repo, rev)
4054 ret = hg.update(repo, rev)
4061
4055
4062 if repo.ui.configbool('bookmarks', 'track.current'):
4056 if brev in repo._bookmarks:
4063 bookmarks.setcurrent(repo, brev)
4057 bookmarks.setcurrent(repo, brev)
4064
4058
4065 return ret
4059 return ret
4066
4060
4067 def verify(ui, repo):
4061 def verify(ui, repo):
4068 """verify the integrity of the repository
4062 """verify the integrity of the repository
4069
4063
4070 Verify the integrity of the current repository.
4064 Verify the integrity of the current repository.
4071
4065
4072 This will perform an extensive check of the repository's
4066 This will perform an extensive check of the repository's
4073 integrity, validating the hashes and checksums of each entry in
4067 integrity, validating the hashes and checksums of each entry in
4074 the changelog, manifest, and tracked files, as well as the
4068 the changelog, manifest, and tracked files, as well as the
4075 integrity of their crosslinks and indices.
4069 integrity of their crosslinks and indices.
4076
4070
4077 Returns 0 on success, 1 if errors are encountered.
4071 Returns 0 on success, 1 if errors are encountered.
4078 """
4072 """
4079 return hg.verify(repo)
4073 return hg.verify(repo)
4080
4074
4081 def version_(ui):
4075 def version_(ui):
4082 """output version and copyright information"""
4076 """output version and copyright information"""
4083 ui.write(_("Mercurial Distributed SCM (version %s)\n")
4077 ui.write(_("Mercurial Distributed SCM (version %s)\n")
4084 % util.version())
4078 % util.version())
4085 ui.status(_(
4079 ui.status(_(
4086 "(see http://mercurial.selenic.com for more information)\n"
4080 "(see http://mercurial.selenic.com for more information)\n"
4087 "\nCopyright (C) 2005-2010 Matt Mackall and others\n"
4081 "\nCopyright (C) 2005-2010 Matt Mackall and others\n"
4088 "This is free software; see the source for copying conditions. "
4082 "This is free software; see the source for copying conditions. "
4089 "There is NO\nwarranty; "
4083 "There is NO\nwarranty; "
4090 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
4084 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
4091 ))
4085 ))
4092
4086
4093 # Command options and aliases are listed here, alphabetically
4087 # Command options and aliases are listed here, alphabetically
4094
4088
4095 globalopts = [
4089 globalopts = [
4096 ('R', 'repository', '',
4090 ('R', 'repository', '',
4097 _('repository root directory or name of overlay bundle file'),
4091 _('repository root directory or name of overlay bundle file'),
4098 _('REPO')),
4092 _('REPO')),
4099 ('', 'cwd', '',
4093 ('', 'cwd', '',
4100 _('change working directory'), _('DIR')),
4094 _('change working directory'), _('DIR')),
4101 ('y', 'noninteractive', None,
4095 ('y', 'noninteractive', None,
4102 _('do not prompt, assume \'yes\' for any required answers')),
4096 _('do not prompt, assume \'yes\' for any required answers')),
4103 ('q', 'quiet', None, _('suppress output')),
4097 ('q', 'quiet', None, _('suppress output')),
4104 ('v', 'verbose', None, _('enable additional output')),
4098 ('v', 'verbose', None, _('enable additional output')),
4105 ('', 'config', [],
4099 ('', 'config', [],
4106 _('set/override config option (use \'section.name=value\')'),
4100 _('set/override config option (use \'section.name=value\')'),
4107 _('CONFIG')),
4101 _('CONFIG')),
4108 ('', 'debug', None, _('enable debugging output')),
4102 ('', 'debug', None, _('enable debugging output')),
4109 ('', 'debugger', None, _('start debugger')),
4103 ('', 'debugger', None, _('start debugger')),
4110 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
4104 ('', 'encoding', encoding.encoding, _('set the charset encoding'),
4111 _('ENCODE')),
4105 _('ENCODE')),
4112 ('', 'encodingmode', encoding.encodingmode,
4106 ('', 'encodingmode', encoding.encodingmode,
4113 _('set the charset encoding mode'), _('MODE')),
4107 _('set the charset encoding mode'), _('MODE')),
4114 ('', 'traceback', None, _('always print a traceback on exception')),
4108 ('', 'traceback', None, _('always print a traceback on exception')),
4115 ('', 'time', None, _('time how long the command takes')),
4109 ('', 'time', None, _('time how long the command takes')),
4116 ('', 'profile', None, _('print command execution profile')),
4110 ('', 'profile', None, _('print command execution profile')),
4117 ('', 'version', None, _('output version information and exit')),
4111 ('', 'version', None, _('output version information and exit')),
4118 ('h', 'help', None, _('display help and exit')),
4112 ('h', 'help', None, _('display help and exit')),
4119 ]
4113 ]
4120
4114
4121 dryrunopts = [('n', 'dry-run', None,
4115 dryrunopts = [('n', 'dry-run', None,
4122 _('do not perform actions, just print output'))]
4116 _('do not perform actions, just print output'))]
4123
4117
4124 remoteopts = [
4118 remoteopts = [
4125 ('e', 'ssh', '',
4119 ('e', 'ssh', '',
4126 _('specify ssh command to use'), _('CMD')),
4120 _('specify ssh command to use'), _('CMD')),
4127 ('', 'remotecmd', '',
4121 ('', 'remotecmd', '',
4128 _('specify hg command to run on the remote side'), _('CMD')),
4122 _('specify hg command to run on the remote side'), _('CMD')),
4129 ('', 'insecure', None,
4123 ('', 'insecure', None,
4130 _('do not verify server certificate (ignoring web.cacerts config)')),
4124 _('do not verify server certificate (ignoring web.cacerts config)')),
4131 ]
4125 ]
4132
4126
4133 walkopts = [
4127 walkopts = [
4134 ('I', 'include', [],
4128 ('I', 'include', [],
4135 _('include names matching the given patterns'), _('PATTERN')),
4129 _('include names matching the given patterns'), _('PATTERN')),
4136 ('X', 'exclude', [],
4130 ('X', 'exclude', [],
4137 _('exclude names matching the given patterns'), _('PATTERN')),
4131 _('exclude names matching the given patterns'), _('PATTERN')),
4138 ]
4132 ]
4139
4133
4140 commitopts = [
4134 commitopts = [
4141 ('m', 'message', '',
4135 ('m', 'message', '',
4142 _('use text as commit message'), _('TEXT')),
4136 _('use text as commit message'), _('TEXT')),
4143 ('l', 'logfile', '',
4137 ('l', 'logfile', '',
4144 _('read commit message from file'), _('FILE')),
4138 _('read commit message from file'), _('FILE')),
4145 ]
4139 ]
4146
4140
4147 commitopts2 = [
4141 commitopts2 = [
4148 ('d', 'date', '',
4142 ('d', 'date', '',
4149 _('record datecode as commit date'), _('DATE')),
4143 _('record datecode as commit date'), _('DATE')),
4150 ('u', 'user', '',
4144 ('u', 'user', '',
4151 _('record the specified user as committer'), _('USER')),
4145 _('record the specified user as committer'), _('USER')),
4152 ]
4146 ]
4153
4147
4154 templateopts = [
4148 templateopts = [
4155 ('', 'style', '',
4149 ('', 'style', '',
4156 _('display using template map file'), _('STYLE')),
4150 _('display using template map file'), _('STYLE')),
4157 ('', 'template', '',
4151 ('', 'template', '',
4158 _('display with template'), _('TEMPLATE')),
4152 _('display with template'), _('TEMPLATE')),
4159 ]
4153 ]
4160
4154
4161 logopts = [
4155 logopts = [
4162 ('p', 'patch', None, _('show patch')),
4156 ('p', 'patch', None, _('show patch')),
4163 ('g', 'git', None, _('use git extended diff format')),
4157 ('g', 'git', None, _('use git extended diff format')),
4164 ('l', 'limit', '',
4158 ('l', 'limit', '',
4165 _('limit number of changes displayed'), _('NUM')),
4159 _('limit number of changes displayed'), _('NUM')),
4166 ('M', 'no-merges', None, _('do not show merges')),
4160 ('M', 'no-merges', None, _('do not show merges')),
4167 ('', 'stat', None, _('output diffstat-style summary of changes')),
4161 ('', 'stat', None, _('output diffstat-style summary of changes')),
4168 ] + templateopts
4162 ] + templateopts
4169
4163
4170 diffopts = [
4164 diffopts = [
4171 ('a', 'text', None, _('treat all files as text')),
4165 ('a', 'text', None, _('treat all files as text')),
4172 ('g', 'git', None, _('use git extended diff format')),
4166 ('g', 'git', None, _('use git extended diff format')),
4173 ('', 'nodates', None, _('omit dates from diff headers'))
4167 ('', 'nodates', None, _('omit dates from diff headers'))
4174 ]
4168 ]
4175
4169
4176 diffopts2 = [
4170 diffopts2 = [
4177 ('p', 'show-function', None, _('show which function each change is in')),
4171 ('p', 'show-function', None, _('show which function each change is in')),
4178 ('', 'reverse', None, _('produce a diff that undoes the changes')),
4172 ('', 'reverse', None, _('produce a diff that undoes the changes')),
4179 ('w', 'ignore-all-space', None,
4173 ('w', 'ignore-all-space', None,
4180 _('ignore white space when comparing lines')),
4174 _('ignore white space when comparing lines')),
4181 ('b', 'ignore-space-change', None,
4175 ('b', 'ignore-space-change', None,
4182 _('ignore changes in the amount of white space')),
4176 _('ignore changes in the amount of white space')),
4183 ('B', 'ignore-blank-lines', None,
4177 ('B', 'ignore-blank-lines', None,
4184 _('ignore changes whose lines are all blank')),
4178 _('ignore changes whose lines are all blank')),
4185 ('U', 'unified', '',
4179 ('U', 'unified', '',
4186 _('number of lines of context to show'), _('NUM')),
4180 _('number of lines of context to show'), _('NUM')),
4187 ('', 'stat', None, _('output diffstat-style summary of changes')),
4181 ('', 'stat', None, _('output diffstat-style summary of changes')),
4188 ]
4182 ]
4189
4183
4190 similarityopts = [
4184 similarityopts = [
4191 ('s', 'similarity', '',
4185 ('s', 'similarity', '',
4192 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
4186 _('guess renamed files by similarity (0<=s<=100)'), _('SIMILARITY'))
4193 ]
4187 ]
4194
4188
4195 subrepoopts = [
4189 subrepoopts = [
4196 ('S', 'subrepos', None,
4190 ('S', 'subrepos', None,
4197 _('recurse into subrepositories'))
4191 _('recurse into subrepositories'))
4198 ]
4192 ]
4199
4193
4200 table = {
4194 table = {
4201 "^add": (add, walkopts + subrepoopts + dryrunopts,
4195 "^add": (add, walkopts + subrepoopts + dryrunopts,
4202 _('[OPTION]... [FILE]...')),
4196 _('[OPTION]... [FILE]...')),
4203 "addremove":
4197 "addremove":
4204 (addremove, similarityopts + walkopts + dryrunopts,
4198 (addremove, similarityopts + walkopts + dryrunopts,
4205 _('[OPTION]... [FILE]...')),
4199 _('[OPTION]... [FILE]...')),
4206 "^annotate|blame":
4200 "^annotate|blame":
4207 (annotate,
4201 (annotate,
4208 [('r', 'rev', '',
4202 [('r', 'rev', '',
4209 _('annotate the specified revision'), _('REV')),
4203 _('annotate the specified revision'), _('REV')),
4210 ('', 'follow', None,
4204 ('', 'follow', None,
4211 _('follow copies/renames and list the filename (DEPRECATED)')),
4205 _('follow copies/renames and list the filename (DEPRECATED)')),
4212 ('', 'no-follow', None, _("don't follow copies and renames")),
4206 ('', 'no-follow', None, _("don't follow copies and renames")),
4213 ('a', 'text', None, _('treat all files as text')),
4207 ('a', 'text', None, _('treat all files as text')),
4214 ('u', 'user', None, _('list the author (long with -v)')),
4208 ('u', 'user', None, _('list the author (long with -v)')),
4215 ('f', 'file', None, _('list the filename')),
4209 ('f', 'file', None, _('list the filename')),
4216 ('d', 'date', None, _('list the date (short with -q)')),
4210 ('d', 'date', None, _('list the date (short with -q)')),
4217 ('n', 'number', None, _('list the revision number (default)')),
4211 ('n', 'number', None, _('list the revision number (default)')),
4218 ('c', 'changeset', None, _('list the changeset')),
4212 ('c', 'changeset', None, _('list the changeset')),
4219 ('l', 'line-number', None,
4213 ('l', 'line-number', None,
4220 _('show line number at the first appearance'))
4214 _('show line number at the first appearance'))
4221 ] + walkopts,
4215 ] + walkopts,
4222 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...')),
4216 _('[-r REV] [-f] [-a] [-u] [-d] [-n] [-c] [-l] FILE...')),
4223 "archive":
4217 "archive":
4224 (archive,
4218 (archive,
4225 [('', 'no-decode', None, _('do not pass files through decoders')),
4219 [('', 'no-decode', None, _('do not pass files through decoders')),
4226 ('p', 'prefix', '',
4220 ('p', 'prefix', '',
4227 _('directory prefix for files in archive'), _('PREFIX')),
4221 _('directory prefix for files in archive'), _('PREFIX')),
4228 ('r', 'rev', '',
4222 ('r', 'rev', '',
4229 _('revision to distribute'), _('REV')),
4223 _('revision to distribute'), _('REV')),
4230 ('t', 'type', '',
4224 ('t', 'type', '',
4231 _('type of distribution to create'), _('TYPE')),
4225 _('type of distribution to create'), _('TYPE')),
4232 ] + subrepoopts + walkopts,
4226 ] + subrepoopts + walkopts,
4233 _('[OPTION]... DEST')),
4227 _('[OPTION]... DEST')),
4234 "backout":
4228 "backout":
4235 (backout,
4229 (backout,
4236 [('', 'merge', None,
4230 [('', 'merge', None,
4237 _('merge with old dirstate parent after backout')),
4231 _('merge with old dirstate parent after backout')),
4238 ('', 'parent', '',
4232 ('', 'parent', '',
4239 _('parent to choose when backing out merge'), _('REV')),
4233 _('parent to choose when backing out merge'), _('REV')),
4240 ('t', 'tool', '',
4234 ('t', 'tool', '',
4241 _('specify merge tool')),
4235 _('specify merge tool')),
4242 ('r', 'rev', '',
4236 ('r', 'rev', '',
4243 _('revision to backout'), _('REV')),
4237 _('revision to backout'), _('REV')),
4244 ] + walkopts + commitopts + commitopts2,
4238 ] + walkopts + commitopts + commitopts2,
4245 _('[OPTION]... [-r] REV')),
4239 _('[OPTION]... [-r] REV')),
4246 "bisect":
4240 "bisect":
4247 (bisect,
4241 (bisect,
4248 [('r', 'reset', False, _('reset bisect state')),
4242 [('r', 'reset', False, _('reset bisect state')),
4249 ('g', 'good', False, _('mark changeset good')),
4243 ('g', 'good', False, _('mark changeset good')),
4250 ('b', 'bad', False, _('mark changeset bad')),
4244 ('b', 'bad', False, _('mark changeset bad')),
4251 ('s', 'skip', False, _('skip testing changeset')),
4245 ('s', 'skip', False, _('skip testing changeset')),
4252 ('c', 'command', '',
4246 ('c', 'command', '',
4253 _('use command to check changeset state'), _('CMD')),
4247 _('use command to check changeset state'), _('CMD')),
4254 ('U', 'noupdate', False, _('do not update to target'))],
4248 ('U', 'noupdate', False, _('do not update to target'))],
4255 _("[-gbsr] [-U] [-c CMD] [REV]")),
4249 _("[-gbsr] [-U] [-c CMD] [REV]")),
4256 "bookmarks":
4250 "bookmarks":
4257 (bookmark,
4251 (bookmark,
4258 [('f', 'force', False, _('force')),
4252 [('f', 'force', False, _('force')),
4259 ('r', 'rev', '', _('revision'), _('REV')),
4253 ('r', 'rev', '', _('revision'), _('REV')),
4260 ('d', 'delete', False, _('delete a given bookmark')),
4254 ('d', 'delete', False, _('delete a given bookmark')),
4261 ('m', 'rename', '', _('rename a given bookmark'), _('NAME'))],
4255 ('m', 'rename', '', _('rename a given bookmark'), _('NAME'))],
4262 _('hg bookmarks [-f] [-d] [-m NAME] [-r REV] [NAME]')),
4256 _('hg bookmarks [-f] [-d] [-m NAME] [-r REV] [NAME]')),
4263 "branch":
4257 "branch":
4264 (branch,
4258 (branch,
4265 [('f', 'force', None,
4259 [('f', 'force', None,
4266 _('set branch name even if it shadows an existing branch')),
4260 _('set branch name even if it shadows an existing branch')),
4267 ('C', 'clean', None, _('reset branch name to parent branch name'))],
4261 ('C', 'clean', None, _('reset branch name to parent branch name'))],
4268 _('[-fC] [NAME]')),
4262 _('[-fC] [NAME]')),
4269 "branches":
4263 "branches":
4270 (branches,
4264 (branches,
4271 [('a', 'active', False,
4265 [('a', 'active', False,
4272 _('show only branches that have unmerged heads')),
4266 _('show only branches that have unmerged heads')),
4273 ('c', 'closed', False,
4267 ('c', 'closed', False,
4274 _('show normal and closed branches'))],
4268 _('show normal and closed branches'))],
4275 _('[-ac]')),
4269 _('[-ac]')),
4276 "bundle":
4270 "bundle":
4277 (bundle,
4271 (bundle,
4278 [('f', 'force', None,
4272 [('f', 'force', None,
4279 _('run even when the destination is unrelated')),
4273 _('run even when the destination is unrelated')),
4280 ('r', 'rev', [],
4274 ('r', 'rev', [],
4281 _('a changeset intended to be added to the destination'),
4275 _('a changeset intended to be added to the destination'),
4282 _('REV')),
4276 _('REV')),
4283 ('b', 'branch', [],
4277 ('b', 'branch', [],
4284 _('a specific branch you would like to bundle'),
4278 _('a specific branch you would like to bundle'),
4285 _('BRANCH')),
4279 _('BRANCH')),
4286 ('', 'base', [],
4280 ('', 'base', [],
4287 _('a base changeset assumed to be available at the destination'),
4281 _('a base changeset assumed to be available at the destination'),
4288 _('REV')),
4282 _('REV')),
4289 ('a', 'all', None, _('bundle all changesets in the repository')),
4283 ('a', 'all', None, _('bundle all changesets in the repository')),
4290 ('t', 'type', 'bzip2',
4284 ('t', 'type', 'bzip2',
4291 _('bundle compression type to use'), _('TYPE')),
4285 _('bundle compression type to use'), _('TYPE')),
4292 ] + remoteopts,
4286 ] + remoteopts,
4293 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]')),
4287 _('[-f] [-t TYPE] [-a] [-r REV]... [--base REV]... FILE [DEST]')),
4294 "cat":
4288 "cat":
4295 (cat,
4289 (cat,
4296 [('o', 'output', '',
4290 [('o', 'output', '',
4297 _('print output to file with formatted name'), _('FORMAT')),
4291 _('print output to file with formatted name'), _('FORMAT')),
4298 ('r', 'rev', '',
4292 ('r', 'rev', '',
4299 _('print the given revision'), _('REV')),
4293 _('print the given revision'), _('REV')),
4300 ('', 'decode', None, _('apply any matching decode filter')),
4294 ('', 'decode', None, _('apply any matching decode filter')),
4301 ] + walkopts,
4295 ] + walkopts,
4302 _('[OPTION]... FILE...')),
4296 _('[OPTION]... FILE...')),
4303 "^clone":
4297 "^clone":
4304 (clone,
4298 (clone,
4305 [('U', 'noupdate', None,
4299 [('U', 'noupdate', None,
4306 _('the clone will include an empty working copy (only a repository)')),
4300 _('the clone will include an empty working copy (only a repository)')),
4307 ('u', 'updaterev', '',
4301 ('u', 'updaterev', '',
4308 _('revision, tag or branch to check out'), _('REV')),
4302 _('revision, tag or branch to check out'), _('REV')),
4309 ('r', 'rev', [],
4303 ('r', 'rev', [],
4310 _('include the specified changeset'), _('REV')),
4304 _('include the specified changeset'), _('REV')),
4311 ('b', 'branch', [],
4305 ('b', 'branch', [],
4312 _('clone only the specified branch'), _('BRANCH')),
4306 _('clone only the specified branch'), _('BRANCH')),
4313 ('', 'pull', None, _('use pull protocol to copy metadata')),
4307 ('', 'pull', None, _('use pull protocol to copy metadata')),
4314 ('', 'uncompressed', None,
4308 ('', 'uncompressed', None,
4315 _('use uncompressed transfer (fast over LAN)')),
4309 _('use uncompressed transfer (fast over LAN)')),
4316 ] + remoteopts,
4310 ] + remoteopts,
4317 _('[OPTION]... SOURCE [DEST]')),
4311 _('[OPTION]... SOURCE [DEST]')),
4318 "^commit|ci":
4312 "^commit|ci":
4319 (commit,
4313 (commit,
4320 [('A', 'addremove', None,
4314 [('A', 'addremove', None,
4321 _('mark new/missing files as added/removed before committing')),
4315 _('mark new/missing files as added/removed before committing')),
4322 ('', 'close-branch', None,
4316 ('', 'close-branch', None,
4323 _('mark a branch as closed, hiding it from the branch list')),
4317 _('mark a branch as closed, hiding it from the branch list')),
4324 ] + walkopts + commitopts + commitopts2,
4318 ] + walkopts + commitopts + commitopts2,
4325 _('[OPTION]... [FILE]...')),
4319 _('[OPTION]... [FILE]...')),
4326 "copy|cp":
4320 "copy|cp":
4327 (copy,
4321 (copy,
4328 [('A', 'after', None, _('record a copy that has already occurred')),
4322 [('A', 'after', None, _('record a copy that has already occurred')),
4329 ('f', 'force', None,
4323 ('f', 'force', None,
4330 _('forcibly copy over an existing managed file')),
4324 _('forcibly copy over an existing managed file')),
4331 ] + walkopts + dryrunopts,
4325 ] + walkopts + dryrunopts,
4332 _('[OPTION]... [SOURCE]... DEST')),
4326 _('[OPTION]... [SOURCE]... DEST')),
4333 "debugancestor": (debugancestor, [], _('[INDEX] REV1 REV2')),
4327 "debugancestor": (debugancestor, [], _('[INDEX] REV1 REV2')),
4334 "debugbuilddag":
4328 "debugbuilddag":
4335 (debugbuilddag,
4329 (debugbuilddag,
4336 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
4330 [('m', 'mergeable-file', None, _('add single file mergeable changes')),
4337 ('a', 'appended-file', None, _('add single file all revs append to')),
4331 ('a', 'appended-file', None, _('add single file all revs append to')),
4338 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
4332 ('o', 'overwritten-file', None, _('add single file all revs overwrite')),
4339 ('n', 'new-file', None, _('add new file at each rev')),
4333 ('n', 'new-file', None, _('add new file at each rev')),
4340 ],
4334 ],
4341 _('[OPTION]... TEXT')),
4335 _('[OPTION]... TEXT')),
4342 "debugcheckstate": (debugcheckstate, [], ''),
4336 "debugcheckstate": (debugcheckstate, [], ''),
4343 "debugcommands": (debugcommands, [], _('[COMMAND]')),
4337 "debugcommands": (debugcommands, [], _('[COMMAND]')),
4344 "debugcomplete":
4338 "debugcomplete":
4345 (debugcomplete,
4339 (debugcomplete,
4346 [('o', 'options', None, _('show the command options'))],
4340 [('o', 'options', None, _('show the command options'))],
4347 _('[-o] CMD')),
4341 _('[-o] CMD')),
4348 "debugdag":
4342 "debugdag":
4349 (debugdag,
4343 (debugdag,
4350 [('t', 'tags', None, _('use tags as labels')),
4344 [('t', 'tags', None, _('use tags as labels')),
4351 ('b', 'branches', None, _('annotate with branch names')),
4345 ('b', 'branches', None, _('annotate with branch names')),
4352 ('', 'dots', None, _('use dots for runs')),
4346 ('', 'dots', None, _('use dots for runs')),
4353 ('s', 'spaces', None, _('separate elements by spaces')),
4347 ('s', 'spaces', None, _('separate elements by spaces')),
4354 ],
4348 ],
4355 _('[OPTION]... [FILE [REV]...]')),
4349 _('[OPTION]... [FILE [REV]...]')),
4356 "debugdate":
4350 "debugdate":
4357 (debugdate,
4351 (debugdate,
4358 [('e', 'extended', None, _('try extended date formats'))],
4352 [('e', 'extended', None, _('try extended date formats'))],
4359 _('[-e] DATE [RANGE]')),
4353 _('[-e] DATE [RANGE]')),
4360 "debugdata": (debugdata, [], _('FILE REV')),
4354 "debugdata": (debugdata, [], _('FILE REV')),
4361 "debugfsinfo": (debugfsinfo, [], _('[PATH]')),
4355 "debugfsinfo": (debugfsinfo, [], _('[PATH]')),
4362 "debugignore": (debugignore, [], ''),
4356 "debugignore": (debugignore, [], ''),
4363 "debugindex": (debugindex,
4357 "debugindex": (debugindex,
4364 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
4358 [('f', 'format', 0, _('revlog format'), _('FORMAT'))],
4365 _('FILE')),
4359 _('FILE')),
4366 "debugindexdot": (debugindexdot, [], _('FILE')),
4360 "debugindexdot": (debugindexdot, [], _('FILE')),
4367 "debuginstall": (debuginstall, [], ''),
4361 "debuginstall": (debuginstall, [], ''),
4368 "debugpushkey": (debugpushkey, [], _('REPO NAMESPACE [KEY OLD NEW]')),
4362 "debugpushkey": (debugpushkey, [], _('REPO NAMESPACE [KEY OLD NEW]')),
4369 "debugrebuildstate":
4363 "debugrebuildstate":
4370 (debugrebuildstate,
4364 (debugrebuildstate,
4371 [('r', 'rev', '',
4365 [('r', 'rev', '',
4372 _('revision to rebuild to'), _('REV'))],
4366 _('revision to rebuild to'), _('REV'))],
4373 _('[-r REV] [REV]')),
4367 _('[-r REV] [REV]')),
4374 "debugrename":
4368 "debugrename":
4375 (debugrename,
4369 (debugrename,
4376 [('r', 'rev', '',
4370 [('r', 'rev', '',
4377 _('revision to debug'), _('REV'))],
4371 _('revision to debug'), _('REV'))],
4378 _('[-r REV] FILE')),
4372 _('[-r REV] FILE')),
4379 "debugrevspec":
4373 "debugrevspec":
4380 (debugrevspec, [], ('REVSPEC')),
4374 (debugrevspec, [], ('REVSPEC')),
4381 "debugsetparents":
4375 "debugsetparents":
4382 (debugsetparents, [], _('REV1 [REV2]')),
4376 (debugsetparents, [], _('REV1 [REV2]')),
4383 "debugstate":
4377 "debugstate":
4384 (debugstate,
4378 (debugstate,
4385 [('', 'nodates', None, _('do not display the saved mtime'))],
4379 [('', 'nodates', None, _('do not display the saved mtime'))],
4386 _('[OPTION]...')),
4380 _('[OPTION]...')),
4387 "debugsub":
4381 "debugsub":
4388 (debugsub,
4382 (debugsub,
4389 [('r', 'rev', '',
4383 [('r', 'rev', '',
4390 _('revision to check'), _('REV'))],
4384 _('revision to check'), _('REV'))],
4391 _('[-r REV] [REV]')),
4385 _('[-r REV] [REV]')),
4392 "debugwalk": (debugwalk, walkopts, _('[OPTION]... [FILE]...')),
4386 "debugwalk": (debugwalk, walkopts, _('[OPTION]... [FILE]...')),
4393 "^diff":
4387 "^diff":
4394 (diff,
4388 (diff,
4395 [('r', 'rev', [],
4389 [('r', 'rev', [],
4396 _('revision'), _('REV')),
4390 _('revision'), _('REV')),
4397 ('c', 'change', '',
4391 ('c', 'change', '',
4398 _('change made by revision'), _('REV'))
4392 _('change made by revision'), _('REV'))
4399 ] + diffopts + diffopts2 + walkopts + subrepoopts,
4393 ] + diffopts + diffopts2 + walkopts + subrepoopts,
4400 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...')),
4394 _('[OPTION]... ([-c REV] | [-r REV1 [-r REV2]]) [FILE]...')),
4401 "^export":
4395 "^export":
4402 (export,
4396 (export,
4403 [('o', 'output', '',
4397 [('o', 'output', '',
4404 _('print output to file with formatted name'), _('FORMAT')),
4398 _('print output to file with formatted name'), _('FORMAT')),
4405 ('', 'switch-parent', None, _('diff against the second parent')),
4399 ('', 'switch-parent', None, _('diff against the second parent')),
4406 ('r', 'rev', [],
4400 ('r', 'rev', [],
4407 _('revisions to export'), _('REV')),
4401 _('revisions to export'), _('REV')),
4408 ] + diffopts,
4402 ] + diffopts,
4409 _('[OPTION]... [-o OUTFILESPEC] REV...')),
4403 _('[OPTION]... [-o OUTFILESPEC] REV...')),
4410 "^forget":
4404 "^forget":
4411 (forget,
4405 (forget,
4412 [] + walkopts,
4406 [] + walkopts,
4413 _('[OPTION]... FILE...')),
4407 _('[OPTION]... FILE...')),
4414 "grep":
4408 "grep":
4415 (grep,
4409 (grep,
4416 [('0', 'print0', None, _('end fields with NUL')),
4410 [('0', 'print0', None, _('end fields with NUL')),
4417 ('', 'all', None, _('print all revisions that match')),
4411 ('', 'all', None, _('print all revisions that match')),
4418 ('f', 'follow', None,
4412 ('f', 'follow', None,
4419 _('follow changeset history,'
4413 _('follow changeset history,'
4420 ' or file history across copies and renames')),
4414 ' or file history across copies and renames')),
4421 ('i', 'ignore-case', None, _('ignore case when matching')),
4415 ('i', 'ignore-case', None, _('ignore case when matching')),
4422 ('l', 'files-with-matches', None,
4416 ('l', 'files-with-matches', None,
4423 _('print only filenames and revisions that match')),
4417 _('print only filenames and revisions that match')),
4424 ('n', 'line-number', None, _('print matching line numbers')),
4418 ('n', 'line-number', None, _('print matching line numbers')),
4425 ('r', 'rev', [],
4419 ('r', 'rev', [],
4426 _('only search files changed within revision range'), _('REV')),
4420 _('only search files changed within revision range'), _('REV')),
4427 ('u', 'user', None, _('list the author (long with -v)')),
4421 ('u', 'user', None, _('list the author (long with -v)')),
4428 ('d', 'date', None, _('list the date (short with -q)')),
4422 ('d', 'date', None, _('list the date (short with -q)')),
4429 ] + walkopts,
4423 ] + walkopts,
4430 _('[OPTION]... PATTERN [FILE]...')),
4424 _('[OPTION]... PATTERN [FILE]...')),
4431 "heads":
4425 "heads":
4432 (heads,
4426 (heads,
4433 [('r', 'rev', '',
4427 [('r', 'rev', '',
4434 _('show only heads which are descendants of STARTREV'),
4428 _('show only heads which are descendants of STARTREV'),
4435 _('STARTREV')),
4429 _('STARTREV')),
4436 ('t', 'topo', False, _('show topological heads only')),
4430 ('t', 'topo', False, _('show topological heads only')),
4437 ('a', 'active', False,
4431 ('a', 'active', False,
4438 _('show active branchheads only (DEPRECATED)')),
4432 _('show active branchheads only (DEPRECATED)')),
4439 ('c', 'closed', False,
4433 ('c', 'closed', False,
4440 _('show normal and closed branch heads')),
4434 _('show normal and closed branch heads')),
4441 ] + templateopts,
4435 ] + templateopts,
4442 _('[-ac] [-r STARTREV] [REV]...')),
4436 _('[-ac] [-r STARTREV] [REV]...')),
4443 "help": (help_, [], _('[TOPIC]')),
4437 "help": (help_, [], _('[TOPIC]')),
4444 "identify|id":
4438 "identify|id":
4445 (identify,
4439 (identify,
4446 [('r', 'rev', '',
4440 [('r', 'rev', '',
4447 _('identify the specified revision'), _('REV')),
4441 _('identify the specified revision'), _('REV')),
4448 ('n', 'num', None, _('show local revision number')),
4442 ('n', 'num', None, _('show local revision number')),
4449 ('i', 'id', None, _('show global revision id')),
4443 ('i', 'id', None, _('show global revision id')),
4450 ('b', 'branch', None, _('show branch')),
4444 ('b', 'branch', None, _('show branch')),
4451 ('t', 'tags', None, _('show tags'))],
4445 ('t', 'tags', None, _('show tags'))],
4452 _('[-nibt] [-r REV] [SOURCE]')),
4446 _('[-nibt] [-r REV] [SOURCE]')),
4453 "import|patch":
4447 "import|patch":
4454 (import_,
4448 (import_,
4455 [('p', 'strip', 1,
4449 [('p', 'strip', 1,
4456 _('directory strip option for patch. This has the same '
4450 _('directory strip option for patch. This has the same '
4457 'meaning as the corresponding patch option'),
4451 'meaning as the corresponding patch option'),
4458 _('NUM')),
4452 _('NUM')),
4459 ('b', 'base', '',
4453 ('b', 'base', '',
4460 _('base path'), _('PATH')),
4454 _('base path'), _('PATH')),
4461 ('f', 'force', None,
4455 ('f', 'force', None,
4462 _('skip check for outstanding uncommitted changes')),
4456 _('skip check for outstanding uncommitted changes')),
4463 ('', 'no-commit', None,
4457 ('', 'no-commit', None,
4464 _("don't commit, just update the working directory")),
4458 _("don't commit, just update the working directory")),
4465 ('', 'exact', None,
4459 ('', 'exact', None,
4466 _('apply patch to the nodes from which it was generated')),
4460 _('apply patch to the nodes from which it was generated')),
4467 ('', 'import-branch', None,
4461 ('', 'import-branch', None,
4468 _('use any branch information in patch (implied by --exact)'))] +
4462 _('use any branch information in patch (implied by --exact)'))] +
4469 commitopts + commitopts2 + similarityopts,
4463 commitopts + commitopts2 + similarityopts,
4470 _('[OPTION]... PATCH...')),
4464 _('[OPTION]... PATCH...')),
4471 "incoming|in":
4465 "incoming|in":
4472 (incoming,
4466 (incoming,
4473 [('f', 'force', None,
4467 [('f', 'force', None,
4474 _('run even if remote repository is unrelated')),
4468 _('run even if remote repository is unrelated')),
4475 ('n', 'newest-first', None, _('show newest record first')),
4469 ('n', 'newest-first', None, _('show newest record first')),
4476 ('', 'bundle', '',
4470 ('', 'bundle', '',
4477 _('file to store the bundles into'), _('FILE')),
4471 _('file to store the bundles into'), _('FILE')),
4478 ('r', 'rev', [],
4472 ('r', 'rev', [],
4479 _('a remote changeset intended to be added'), _('REV')),
4473 _('a remote changeset intended to be added'), _('REV')),
4480 ('B', 'bookmarks', False, _("compare bookmarks")),
4474 ('B', 'bookmarks', False, _("compare bookmarks")),
4481 ('b', 'branch', [],
4475 ('b', 'branch', [],
4482 _('a specific branch you would like to pull'), _('BRANCH')),
4476 _('a specific branch you would like to pull'), _('BRANCH')),
4483 ] + logopts + remoteopts + subrepoopts,
4477 ] + logopts + remoteopts + subrepoopts,
4484 _('[-p] [-n] [-M] [-f] [-r REV]...'
4478 _('[-p] [-n] [-M] [-f] [-r REV]...'
4485 ' [--bundle FILENAME] [SOURCE]')),
4479 ' [--bundle FILENAME] [SOURCE]')),
4486 "^init":
4480 "^init":
4487 (init,
4481 (init,
4488 remoteopts,
4482 remoteopts,
4489 _('[-e CMD] [--remotecmd CMD] [DEST]')),
4483 _('[-e CMD] [--remotecmd CMD] [DEST]')),
4490 "locate":
4484 "locate":
4491 (locate,
4485 (locate,
4492 [('r', 'rev', '',
4486 [('r', 'rev', '',
4493 _('search the repository as it is in REV'), _('REV')),
4487 _('search the repository as it is in REV'), _('REV')),
4494 ('0', 'print0', None,
4488 ('0', 'print0', None,
4495 _('end filenames with NUL, for use with xargs')),
4489 _('end filenames with NUL, for use with xargs')),
4496 ('f', 'fullpath', None,
4490 ('f', 'fullpath', None,
4497 _('print complete paths from the filesystem root')),
4491 _('print complete paths from the filesystem root')),
4498 ] + walkopts,
4492 ] + walkopts,
4499 _('[OPTION]... [PATTERN]...')),
4493 _('[OPTION]... [PATTERN]...')),
4500 "^log|history":
4494 "^log|history":
4501 (log,
4495 (log,
4502 [('f', 'follow', None,
4496 [('f', 'follow', None,
4503 _('follow changeset history,'
4497 _('follow changeset history,'
4504 ' or file history across copies and renames')),
4498 ' or file history across copies and renames')),
4505 ('', 'follow-first', None,
4499 ('', 'follow-first', None,
4506 _('only follow the first parent of merge changesets')),
4500 _('only follow the first parent of merge changesets')),
4507 ('d', 'date', '',
4501 ('d', 'date', '',
4508 _('show revisions matching date spec'), _('DATE')),
4502 _('show revisions matching date spec'), _('DATE')),
4509 ('C', 'copies', None, _('show copied files')),
4503 ('C', 'copies', None, _('show copied files')),
4510 ('k', 'keyword', [],
4504 ('k', 'keyword', [],
4511 _('do case-insensitive search for a given text'), _('TEXT')),
4505 _('do case-insensitive search for a given text'), _('TEXT')),
4512 ('r', 'rev', [],
4506 ('r', 'rev', [],
4513 _('show the specified revision or range'), _('REV')),
4507 _('show the specified revision or range'), _('REV')),
4514 ('', 'removed', None, _('include revisions where files were removed')),
4508 ('', 'removed', None, _('include revisions where files were removed')),
4515 ('m', 'only-merges', None, _('show only merges')),
4509 ('m', 'only-merges', None, _('show only merges')),
4516 ('u', 'user', [],
4510 ('u', 'user', [],
4517 _('revisions committed by user'), _('USER')),
4511 _('revisions committed by user'), _('USER')),
4518 ('', 'only-branch', [],
4512 ('', 'only-branch', [],
4519 _('show only changesets within the given named branch (DEPRECATED)'),
4513 _('show only changesets within the given named branch (DEPRECATED)'),
4520 _('BRANCH')),
4514 _('BRANCH')),
4521 ('b', 'branch', [],
4515 ('b', 'branch', [],
4522 _('show changesets within the given named branch'), _('BRANCH')),
4516 _('show changesets within the given named branch'), _('BRANCH')),
4523 ('P', 'prune', [],
4517 ('P', 'prune', [],
4524 _('do not display revision or any of its ancestors'), _('REV')),
4518 _('do not display revision or any of its ancestors'), _('REV')),
4525 ] + logopts + walkopts,
4519 ] + logopts + walkopts,
4526 _('[OPTION]... [FILE]')),
4520 _('[OPTION]... [FILE]')),
4527 "manifest":
4521 "manifest":
4528 (manifest,
4522 (manifest,
4529 [('r', 'rev', '',
4523 [('r', 'rev', '',
4530 _('revision to display'), _('REV'))],
4524 _('revision to display'), _('REV'))],
4531 _('[-r REV]')),
4525 _('[-r REV]')),
4532 "^merge":
4526 "^merge":
4533 (merge,
4527 (merge,
4534 [('f', 'force', None, _('force a merge with outstanding changes')),
4528 [('f', 'force', None, _('force a merge with outstanding changes')),
4535 ('t', 'tool', '', _('specify merge tool')),
4529 ('t', 'tool', '', _('specify merge tool')),
4536 ('r', 'rev', '',
4530 ('r', 'rev', '',
4537 _('revision to merge'), _('REV')),
4531 _('revision to merge'), _('REV')),
4538 ('P', 'preview', None,
4532 ('P', 'preview', None,
4539 _('review revisions to merge (no merge is performed)'))],
4533 _('review revisions to merge (no merge is performed)'))],
4540 _('[-P] [-f] [[-r] REV]')),
4534 _('[-P] [-f] [[-r] REV]')),
4541 "outgoing|out":
4535 "outgoing|out":
4542 (outgoing,
4536 (outgoing,
4543 [('f', 'force', None,
4537 [('f', 'force', None,
4544 _('run even when the destination is unrelated')),
4538 _('run even when the destination is unrelated')),
4545 ('r', 'rev', [],
4539 ('r', 'rev', [],
4546 _('a changeset intended to be included in the destination'),
4540 _('a changeset intended to be included in the destination'),
4547 _('REV')),
4541 _('REV')),
4548 ('n', 'newest-first', None, _('show newest record first')),
4542 ('n', 'newest-first', None, _('show newest record first')),
4549 ('B', 'bookmarks', False, _("compare bookmarks")),
4543 ('B', 'bookmarks', False, _("compare bookmarks")),
4550 ('b', 'branch', [],
4544 ('b', 'branch', [],
4551 _('a specific branch you would like to push'), _('BRANCH')),
4545 _('a specific branch you would like to push'), _('BRANCH')),
4552 ] + logopts + remoteopts + subrepoopts,
4546 ] + logopts + remoteopts + subrepoopts,
4553 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]')),
4547 _('[-M] [-p] [-n] [-f] [-r REV]... [DEST]')),
4554 "parents":
4548 "parents":
4555 (parents,
4549 (parents,
4556 [('r', 'rev', '',
4550 [('r', 'rev', '',
4557 _('show parents of the specified revision'), _('REV')),
4551 _('show parents of the specified revision'), _('REV')),
4558 ] + templateopts,
4552 ] + templateopts,
4559 _('[-r REV] [FILE]')),
4553 _('[-r REV] [FILE]')),
4560 "paths": (paths, [], _('[NAME]')),
4554 "paths": (paths, [], _('[NAME]')),
4561 "^pull":
4555 "^pull":
4562 (pull,
4556 (pull,
4563 [('u', 'update', None,
4557 [('u', 'update', None,
4564 _('update to new branch head if changesets were pulled')),
4558 _('update to new branch head if changesets were pulled')),
4565 ('f', 'force', None,
4559 ('f', 'force', None,
4566 _('run even when remote repository is unrelated')),
4560 _('run even when remote repository is unrelated')),
4567 ('r', 'rev', [],
4561 ('r', 'rev', [],
4568 _('a remote changeset intended to be added'), _('REV')),
4562 _('a remote changeset intended to be added'), _('REV')),
4569 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4563 ('B', 'bookmark', [], _("bookmark to pull"), _('BOOKMARK')),
4570 ('b', 'branch', [],
4564 ('b', 'branch', [],
4571 _('a specific branch you would like to pull'), _('BRANCH')),
4565 _('a specific branch you would like to pull'), _('BRANCH')),
4572 ] + remoteopts,
4566 ] + remoteopts,
4573 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]')),
4567 _('[-u] [-f] [-r REV]... [-e CMD] [--remotecmd CMD] [SOURCE]')),
4574 "^push":
4568 "^push":
4575 (push,
4569 (push,
4576 [('f', 'force', None, _('force push')),
4570 [('f', 'force', None, _('force push')),
4577 ('r', 'rev', [],
4571 ('r', 'rev', [],
4578 _('a changeset intended to be included in the destination'),
4572 _('a changeset intended to be included in the destination'),
4579 _('REV')),
4573 _('REV')),
4580 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4574 ('B', 'bookmark', [], _("bookmark to push"), _('BOOKMARK')),
4581 ('b', 'branch', [],
4575 ('b', 'branch', [],
4582 _('a specific branch you would like to push'), _('BRANCH')),
4576 _('a specific branch you would like to push'), _('BRANCH')),
4583 ('', 'new-branch', False, _('allow pushing a new branch')),
4577 ('', 'new-branch', False, _('allow pushing a new branch')),
4584 ] + remoteopts,
4578 ] + remoteopts,
4585 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]')),
4579 _('[-f] [-r REV]... [-e CMD] [--remotecmd CMD] [DEST]')),
4586 "recover": (recover, []),
4580 "recover": (recover, []),
4587 "^remove|rm":
4581 "^remove|rm":
4588 (remove,
4582 (remove,
4589 [('A', 'after', None, _('record delete for missing files')),
4583 [('A', 'after', None, _('record delete for missing files')),
4590 ('f', 'force', None,
4584 ('f', 'force', None,
4591 _('remove (and delete) file even if added or modified')),
4585 _('remove (and delete) file even if added or modified')),
4592 ] + walkopts,
4586 ] + walkopts,
4593 _('[OPTION]... FILE...')),
4587 _('[OPTION]... FILE...')),
4594 "rename|move|mv":
4588 "rename|move|mv":
4595 (rename,
4589 (rename,
4596 [('A', 'after', None, _('record a rename that has already occurred')),
4590 [('A', 'after', None, _('record a rename that has already occurred')),
4597 ('f', 'force', None,
4591 ('f', 'force', None,
4598 _('forcibly copy over an existing managed file')),
4592 _('forcibly copy over an existing managed file')),
4599 ] + walkopts + dryrunopts,
4593 ] + walkopts + dryrunopts,
4600 _('[OPTION]... SOURCE... DEST')),
4594 _('[OPTION]... SOURCE... DEST')),
4601 "resolve":
4595 "resolve":
4602 (resolve,
4596 (resolve,
4603 [('a', 'all', None, _('select all unresolved files')),
4597 [('a', 'all', None, _('select all unresolved files')),
4604 ('l', 'list', None, _('list state of files needing merge')),
4598 ('l', 'list', None, _('list state of files needing merge')),
4605 ('m', 'mark', None, _('mark files as resolved')),
4599 ('m', 'mark', None, _('mark files as resolved')),
4606 ('u', 'unmark', None, _('mark files as unresolved')),
4600 ('u', 'unmark', None, _('mark files as unresolved')),
4607 ('t', 'tool', '', _('specify merge tool')),
4601 ('t', 'tool', '', _('specify merge tool')),
4608 ('n', 'no-status', None, _('hide status prefix'))]
4602 ('n', 'no-status', None, _('hide status prefix'))]
4609 + walkopts,
4603 + walkopts,
4610 _('[OPTION]... [FILE]...')),
4604 _('[OPTION]... [FILE]...')),
4611 "revert":
4605 "revert":
4612 (revert,
4606 (revert,
4613 [('a', 'all', None, _('revert all changes when no arguments given')),
4607 [('a', 'all', None, _('revert all changes when no arguments given')),
4614 ('d', 'date', '',
4608 ('d', 'date', '',
4615 _('tipmost revision matching date'), _('DATE')),
4609 _('tipmost revision matching date'), _('DATE')),
4616 ('r', 'rev', '',
4610 ('r', 'rev', '',
4617 _('revert to the specified revision'), _('REV')),
4611 _('revert to the specified revision'), _('REV')),
4618 ('', 'no-backup', None, _('do not save backup copies of files')),
4612 ('', 'no-backup', None, _('do not save backup copies of files')),
4619 ] + walkopts + dryrunopts,
4613 ] + walkopts + dryrunopts,
4620 _('[OPTION]... [-r REV] [NAME]...')),
4614 _('[OPTION]... [-r REV] [NAME]...')),
4621 "rollback": (rollback, dryrunopts),
4615 "rollback": (rollback, dryrunopts),
4622 "root": (root, []),
4616 "root": (root, []),
4623 "^serve":
4617 "^serve":
4624 (serve,
4618 (serve,
4625 [('A', 'accesslog', '',
4619 [('A', 'accesslog', '',
4626 _('name of access log file to write to'), _('FILE')),
4620 _('name of access log file to write to'), _('FILE')),
4627 ('d', 'daemon', None, _('run server in background')),
4621 ('d', 'daemon', None, _('run server in background')),
4628 ('', 'daemon-pipefds', '',
4622 ('', 'daemon-pipefds', '',
4629 _('used internally by daemon mode'), _('NUM')),
4623 _('used internally by daemon mode'), _('NUM')),
4630 ('E', 'errorlog', '',
4624 ('E', 'errorlog', '',
4631 _('name of error log file to write to'), _('FILE')),
4625 _('name of error log file to write to'), _('FILE')),
4632 # use string type, then we can check if something was passed
4626 # use string type, then we can check if something was passed
4633 ('p', 'port', '',
4627 ('p', 'port', '',
4634 _('port to listen on (default: 8000)'), _('PORT')),
4628 _('port to listen on (default: 8000)'), _('PORT')),
4635 ('a', 'address', '',
4629 ('a', 'address', '',
4636 _('address to listen on (default: all interfaces)'), _('ADDR')),
4630 _('address to listen on (default: all interfaces)'), _('ADDR')),
4637 ('', 'prefix', '',
4631 ('', 'prefix', '',
4638 _('prefix path to serve from (default: server root)'), _('PREFIX')),
4632 _('prefix path to serve from (default: server root)'), _('PREFIX')),
4639 ('n', 'name', '',
4633 ('n', 'name', '',
4640 _('name to show in web pages (default: working directory)'),
4634 _('name to show in web pages (default: working directory)'),
4641 _('NAME')),
4635 _('NAME')),
4642 ('', 'web-conf', '',
4636 ('', 'web-conf', '',
4643 _('name of the hgweb config file (see "hg help hgweb")'),
4637 _('name of the hgweb config file (see "hg help hgweb")'),
4644 _('FILE')),
4638 _('FILE')),
4645 ('', 'webdir-conf', '',
4639 ('', 'webdir-conf', '',
4646 _('name of the hgweb config file (DEPRECATED)'), _('FILE')),
4640 _('name of the hgweb config file (DEPRECATED)'), _('FILE')),
4647 ('', 'pid-file', '',
4641 ('', 'pid-file', '',
4648 _('name of file to write process ID to'), _('FILE')),
4642 _('name of file to write process ID to'), _('FILE')),
4649 ('', 'stdio', None, _('for remote clients')),
4643 ('', 'stdio', None, _('for remote clients')),
4650 ('t', 'templates', '',
4644 ('t', 'templates', '',
4651 _('web templates to use'), _('TEMPLATE')),
4645 _('web templates to use'), _('TEMPLATE')),
4652 ('', 'style', '',
4646 ('', 'style', '',
4653 _('template style to use'), _('STYLE')),
4647 _('template style to use'), _('STYLE')),
4654 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4648 ('6', 'ipv6', None, _('use IPv6 in addition to IPv4')),
4655 ('', 'certificate', '',
4649 ('', 'certificate', '',
4656 _('SSL certificate file'), _('FILE'))],
4650 _('SSL certificate file'), _('FILE'))],
4657 _('[OPTION]...')),
4651 _('[OPTION]...')),
4658 "showconfig|debugconfig":
4652 "showconfig|debugconfig":
4659 (showconfig,
4653 (showconfig,
4660 [('u', 'untrusted', None, _('show untrusted configuration options'))],
4654 [('u', 'untrusted', None, _('show untrusted configuration options'))],
4661 _('[-u] [NAME]...')),
4655 _('[-u] [NAME]...')),
4662 "^summary|sum":
4656 "^summary|sum":
4663 (summary,
4657 (summary,
4664 [('', 'remote', None, _('check for push and pull'))], '[--remote]'),
4658 [('', 'remote', None, _('check for push and pull'))], '[--remote]'),
4665 "^status|st":
4659 "^status|st":
4666 (status,
4660 (status,
4667 [('A', 'all', None, _('show status of all files')),
4661 [('A', 'all', None, _('show status of all files')),
4668 ('m', 'modified', None, _('show only modified files')),
4662 ('m', 'modified', None, _('show only modified files')),
4669 ('a', 'added', None, _('show only added files')),
4663 ('a', 'added', None, _('show only added files')),
4670 ('r', 'removed', None, _('show only removed files')),
4664 ('r', 'removed', None, _('show only removed files')),
4671 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4665 ('d', 'deleted', None, _('show only deleted (but tracked) files')),
4672 ('c', 'clean', None, _('show only files without changes')),
4666 ('c', 'clean', None, _('show only files without changes')),
4673 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4667 ('u', 'unknown', None, _('show only unknown (not tracked) files')),
4674 ('i', 'ignored', None, _('show only ignored files')),
4668 ('i', 'ignored', None, _('show only ignored files')),
4675 ('n', 'no-status', None, _('hide status prefix')),
4669 ('n', 'no-status', None, _('hide status prefix')),
4676 ('C', 'copies', None, _('show source of copied files')),
4670 ('C', 'copies', None, _('show source of copied files')),
4677 ('0', 'print0', None,
4671 ('0', 'print0', None,
4678 _('end filenames with NUL, for use with xargs')),
4672 _('end filenames with NUL, for use with xargs')),
4679 ('', 'rev', [],
4673 ('', 'rev', [],
4680 _('show difference from revision'), _('REV')),
4674 _('show difference from revision'), _('REV')),
4681 ('', 'change', '',
4675 ('', 'change', '',
4682 _('list the changed files of a revision'), _('REV')),
4676 _('list the changed files of a revision'), _('REV')),
4683 ] + walkopts + subrepoopts,
4677 ] + walkopts + subrepoopts,
4684 _('[OPTION]... [FILE]...')),
4678 _('[OPTION]... [FILE]...')),
4685 "tag":
4679 "tag":
4686 (tag,
4680 (tag,
4687 [('f', 'force', None, _('force tag')),
4681 [('f', 'force', None, _('force tag')),
4688 ('l', 'local', None, _('make the tag local')),
4682 ('l', 'local', None, _('make the tag local')),
4689 ('r', 'rev', '',
4683 ('r', 'rev', '',
4690 _('revision to tag'), _('REV')),
4684 _('revision to tag'), _('REV')),
4691 ('', 'remove', None, _('remove a tag')),
4685 ('', 'remove', None, _('remove a tag')),
4692 # -l/--local is already there, commitopts cannot be used
4686 # -l/--local is already there, commitopts cannot be used
4693 ('e', 'edit', None, _('edit commit message')),
4687 ('e', 'edit', None, _('edit commit message')),
4694 ('m', 'message', '',
4688 ('m', 'message', '',
4695 _('use <text> as commit message'), _('TEXT')),
4689 _('use <text> as commit message'), _('TEXT')),
4696 ] + commitopts2,
4690 ] + commitopts2,
4697 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...')),
4691 _('[-f] [-l] [-m TEXT] [-d DATE] [-u USER] [-r REV] NAME...')),
4698 "tags": (tags, [], ''),
4692 "tags": (tags, [], ''),
4699 "tip":
4693 "tip":
4700 (tip,
4694 (tip,
4701 [('p', 'patch', None, _('show patch')),
4695 [('p', 'patch', None, _('show patch')),
4702 ('g', 'git', None, _('use git extended diff format')),
4696 ('g', 'git', None, _('use git extended diff format')),
4703 ] + templateopts,
4697 ] + templateopts,
4704 _('[-p] [-g]')),
4698 _('[-p] [-g]')),
4705 "unbundle":
4699 "unbundle":
4706 (unbundle,
4700 (unbundle,
4707 [('u', 'update', None,
4701 [('u', 'update', None,
4708 _('update to new branch head if changesets were unbundled'))],
4702 _('update to new branch head if changesets were unbundled'))],
4709 _('[-u] FILE...')),
4703 _('[-u] FILE...')),
4710 "^update|up|checkout|co":
4704 "^update|up|checkout|co":
4711 (update,
4705 (update,
4712 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
4706 [('C', 'clean', None, _('discard uncommitted changes (no backup)')),
4713 ('c', 'check', None,
4707 ('c', 'check', None,
4714 _('update across branches if no uncommitted changes')),
4708 _('update across branches if no uncommitted changes')),
4715 ('d', 'date', '',
4709 ('d', 'date', '',
4716 _('tipmost revision matching date'), _('DATE')),
4710 _('tipmost revision matching date'), _('DATE')),
4717 ('r', 'rev', '',
4711 ('r', 'rev', '',
4718 _('revision'), _('REV'))],
4712 _('revision'), _('REV'))],
4719 _('[-c] [-C] [-d DATE] [[-r] REV]')),
4713 _('[-c] [-C] [-d DATE] [[-r] REV]')),
4720 "verify": (verify, []),
4714 "verify": (verify, []),
4721 "version": (version_, []),
4715 "version": (version_, []),
4722 }
4716 }
4723
4717
4724 norepo = ("clone init version help debugcommands debugcomplete"
4718 norepo = ("clone init version help debugcommands debugcomplete"
4725 " debugdate debuginstall debugfsinfo debugpushkey")
4719 " debugdate debuginstall debugfsinfo debugpushkey")
4726 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
4720 optionalrepo = ("identify paths serve showconfig debugancestor debugdag"
4727 " debugdata debugindex debugindexdot")
4721 " debugdata debugindex debugindexdot")
@@ -1,92 +1,91 b''
1 $ echo "[extensions]" >> $HGRCPATH
1 $ echo "[extensions]" >> $HGRCPATH
2 $ echo "bookmarks=" >> $HGRCPATH
2 $ echo "bookmarks=" >> $HGRCPATH
3
3
4 $ echo "[bookmarks]" >> $HGRCPATH
4 $ echo "[bookmarks]" >> $HGRCPATH
5 $ echo "track.current = True" >> $HGRCPATH
6
5
7 $ hg init
6 $ hg init
8
7
9 no bookmarks
8 no bookmarks
10
9
11 $ hg bookmarks
10 $ hg bookmarks
12 no bookmarks set
11 no bookmarks set
13
12
14 set bookmark X
13 set bookmark X
15
14
16 $ hg bookmark X
15 $ hg bookmark X
17
16
18 list bookmarks
17 list bookmarks
19
18
20 $ hg bookmark
19 $ hg bookmark
21 * X -1:000000000000
20 * X -1:000000000000
22
21
23 list bookmarks with color
22 list bookmarks with color
24
23
25 $ hg --config extensions.color= --config color.mode=ansi \
24 $ hg --config extensions.color= --config color.mode=ansi \
26 > bookmark --color=always
25 > bookmark --color=always
27 \x1b[0;32m * X -1:000000000000\x1b[0m (esc)
26 \x1b[0;32m * X -1:000000000000\x1b[0m (esc)
28
27
29 update to bookmark X
28 update to bookmark X
30
29
31 $ hg update X
30 $ hg update X
32 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
31 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
33
32
34 list bookmarks
33 list bookmarks
35
34
36 $ hg bookmarks
35 $ hg bookmarks
37 * X -1:000000000000
36 * X -1:000000000000
38
37
39 rename
38 rename
40
39
41 $ hg bookmark -m X Z
40 $ hg bookmark -m X Z
42
41
43 list bookmarks
42 list bookmarks
44
43
45 $ hg bookmarks
44 $ hg bookmarks
46 * Z -1:000000000000
45 * Z -1:000000000000
47
46
48 new bookmark Y
47 new bookmark Y
49
48
50 $ hg bookmark Y
49 $ hg bookmark Y
51
50
52 list bookmarks
51 list bookmarks
53
52
54 $ hg bookmark
53 $ hg bookmark
55 * Y -1:000000000000
54 * Y -1:000000000000
56 Z -1:000000000000
55 Z -1:000000000000
57
56
58 commit
57 commit
59
58
60 $ echo 'b' > b
59 $ echo 'b' > b
61 $ hg add b
60 $ hg add b
62 $ hg commit -m'test'
61 $ hg commit -m'test'
63
62
64 list bookmarks
63 list bookmarks
65
64
66 $ hg bookmark
65 $ hg bookmark
67 * Y 0:719295282060
66 * Y 0:719295282060
68 Z -1:000000000000
67 Z -1:000000000000
69
68
70 delete bookmarks
69 delete bookmarks
71
70
72 $ hg bookmark -d Y
71 $ hg bookmark -d Y
73 $ hg bookmark -d Z
72 $ hg bookmark -d Z
74
73
75 list bookmarks
74 list bookmarks
76
75
77 $ hg bookmark
76 $ hg bookmark
78 no bookmarks set
77 no bookmarks set
79
78
80 update to tip
79 update to tip
81
80
82 $ hg update tip
81 $ hg update tip
83 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
82 0 files updated, 0 files merged, 0 files removed, 0 files unresolved
84
83
85 set bookmark Y using -r .
84 set bookmark Y using -r .
86
85
87 $ hg bookmark -r . Y
86 $ hg bookmark -r . Y
88
87
89 list bookmarks
88 list bookmarks
90
89
91 $ hg bookmark
90 $ hg bookmark
92 * Y 0:719295282060
91 * Y 0:719295282060
@@ -1,186 +1,183 b''
1 $ echo "[extensions]" >> $HGRCPATH
1 $ echo "[extensions]" >> $HGRCPATH
2 $ echo "bookmarks=" >> $HGRCPATH
2 $ echo "bookmarks=" >> $HGRCPATH
3
3
4 $ echo "[bookmarks]" >> $HGRCPATH
5 $ echo "track.current = True" >> $HGRCPATH
6
7 initialize
4 initialize
8
5
9 $ hg init a
6 $ hg init a
10 $ cd a
7 $ cd a
11 $ echo 'test' > test
8 $ echo 'test' > test
12 $ hg commit -Am'test'
9 $ hg commit -Am'test'
13 adding test
10 adding test
14
11
15 set bookmarks
12 set bookmarks
16
13
17 $ hg bookmark X
14 $ hg bookmark X
18 $ hg bookmark Y
15 $ hg bookmark Y
19 $ hg bookmark Z
16 $ hg bookmark Z
20
17
21 import bookmark by name
18 import bookmark by name
22
19
23 $ hg init ../b
20 $ hg init ../b
24 $ cd ../b
21 $ cd ../b
25 $ hg book Y
22 $ hg book Y
26 $ hg book
23 $ hg book
27 * Y -1:000000000000
24 * Y -1:000000000000
28 $ hg pull ../a
25 $ hg pull ../a
29 pulling from ../a
26 pulling from ../a
30 requesting all changes
27 requesting all changes
31 adding changesets
28 adding changesets
32 adding manifests
29 adding manifests
33 adding file changes
30 adding file changes
34 added 1 changesets with 1 changes to 1 files
31 added 1 changesets with 1 changes to 1 files
35 (run 'hg update' to get a working copy)
32 (run 'hg update' to get a working copy)
36 $ hg bookmarks
33 $ hg bookmarks
37 Y 0:4e3505fd9583
34 Y 0:4e3505fd9583
38 $ hg debugpushkey ../a namespaces
35 $ hg debugpushkey ../a namespaces
39 bookmarks
36 bookmarks
40 namespaces
37 namespaces
41 $ hg debugpushkey ../a bookmarks
38 $ hg debugpushkey ../a bookmarks
42 Y 4e3505fd95835d721066b76e75dbb8cc554d7f77
39 Y 4e3505fd95835d721066b76e75dbb8cc554d7f77
43 X 4e3505fd95835d721066b76e75dbb8cc554d7f77
40 X 4e3505fd95835d721066b76e75dbb8cc554d7f77
44 Z 4e3505fd95835d721066b76e75dbb8cc554d7f77
41 Z 4e3505fd95835d721066b76e75dbb8cc554d7f77
45 $ hg pull -B X ../a
42 $ hg pull -B X ../a
46 pulling from ../a
43 pulling from ../a
47 searching for changes
44 searching for changes
48 no changes found
45 no changes found
49 importing bookmark X
46 importing bookmark X
50 $ hg bookmark
47 $ hg bookmark
51 X 0:4e3505fd9583
48 X 0:4e3505fd9583
52 Y 0:4e3505fd9583
49 Y 0:4e3505fd9583
53
50
54 export bookmark by name
51 export bookmark by name
55
52
56 $ hg bookmark W
53 $ hg bookmark W
57 $ hg bookmark foo
54 $ hg bookmark foo
58 $ hg bookmark foobar
55 $ hg bookmark foobar
59 $ hg push -B W ../a
56 $ hg push -B W ../a
60 pushing to ../a
57 pushing to ../a
61 searching for changes
58 searching for changes
62 no changes found
59 no changes found
63 exporting bookmark W
60 exporting bookmark W
64 $ hg -R ../a bookmarks
61 $ hg -R ../a bookmarks
65 W -1:000000000000
62 W -1:000000000000
66 X 0:4e3505fd9583
63 X 0:4e3505fd9583
67 Y 0:4e3505fd9583
64 Y 0:4e3505fd9583
68 * Z 0:4e3505fd9583
65 * Z 0:4e3505fd9583
69
66
70 delete a remote bookmark
67 delete a remote bookmark
71
68
72 $ hg book -d W
69 $ hg book -d W
73 $ hg push -B W ../a
70 $ hg push -B W ../a
74 pushing to ../a
71 pushing to ../a
75 searching for changes
72 searching for changes
76 no changes found
73 no changes found
77 deleting remote bookmark W
74 deleting remote bookmark W
78
75
79 push/pull name that doesn't exist
76 push/pull name that doesn't exist
80
77
81 $ hg push -B badname ../a
78 $ hg push -B badname ../a
82 pushing to ../a
79 pushing to ../a
83 searching for changes
80 searching for changes
84 no changes found
81 no changes found
85 bookmark badname does not exist on the local or remote repository!
82 bookmark badname does not exist on the local or remote repository!
86 [2]
83 [2]
87 $ hg pull -B anotherbadname ../a
84 $ hg pull -B anotherbadname ../a
88 pulling from ../a
85 pulling from ../a
89 abort: remote bookmark anotherbadname not found!
86 abort: remote bookmark anotherbadname not found!
90 [255]
87 [255]
91
88
92 divergent bookmarks
89 divergent bookmarks
93
90
94 $ cd ../a
91 $ cd ../a
95 $ echo c1 > f1
92 $ echo c1 > f1
96 $ hg ci -Am1
93 $ hg ci -Am1
97 adding f1
94 adding f1
98 $ hg book -f X
95 $ hg book -f X
99 $ hg book
96 $ hg book
100 * X 1:0d2164f0ce0d
97 * X 1:0d2164f0ce0d
101 Y 0:4e3505fd9583
98 Y 0:4e3505fd9583
102 Z 1:0d2164f0ce0d
99 Z 1:0d2164f0ce0d
103
100
104 $ cd ../b
101 $ cd ../b
105 $ hg up
102 $ hg up
106 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
103 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
107 $ echo c2 > f2
104 $ echo c2 > f2
108 $ hg ci -Am2
105 $ hg ci -Am2
109 adding f2
106 adding f2
110 $ hg book -f X
107 $ hg book -f X
111 $ hg book
108 $ hg book
112 * X 1:9b140be10808
109 * X 1:9b140be10808
113 Y 0:4e3505fd9583
110 Y 0:4e3505fd9583
114 foo -1:000000000000
111 foo -1:000000000000
115 foobar -1:000000000000
112 foobar -1:000000000000
116
113
117 $ hg pull ../a
114 $ hg pull ../a
118 pulling from ../a
115 pulling from ../a
119 searching for changes
116 searching for changes
120 adding changesets
117 adding changesets
121 adding manifests
118 adding manifests
122 adding file changes
119 adding file changes
123 added 1 changesets with 1 changes to 1 files (+1 heads)
120 added 1 changesets with 1 changes to 1 files (+1 heads)
124 not updating divergent bookmark X
121 not updating divergent bookmark X
125 (run 'hg heads' to see heads, 'hg merge' to merge)
122 (run 'hg heads' to see heads, 'hg merge' to merge)
126 $ hg book
123 $ hg book
127 * X 1:9b140be10808
124 * X 1:9b140be10808
128 Y 0:4e3505fd9583
125 Y 0:4e3505fd9583
129 foo -1:000000000000
126 foo -1:000000000000
130 foobar -1:000000000000
127 foobar -1:000000000000
131 $ hg push -f ../a
128 $ hg push -f ../a
132 pushing to ../a
129 pushing to ../a
133 searching for changes
130 searching for changes
134 adding changesets
131 adding changesets
135 adding manifests
132 adding manifests
136 adding file changes
133 adding file changes
137 added 1 changesets with 1 changes to 1 files (+1 heads)
134 added 1 changesets with 1 changes to 1 files (+1 heads)
138 $ hg -R ../a book
135 $ hg -R ../a book
139 * X 1:0d2164f0ce0d
136 * X 1:0d2164f0ce0d
140 Y 0:4e3505fd9583
137 Y 0:4e3505fd9583
141 Z 1:0d2164f0ce0d
138 Z 1:0d2164f0ce0d
142
139
143 hgweb
140 hgweb
144
141
145 $ cat <<EOF > .hg/hgrc
142 $ cat <<EOF > .hg/hgrc
146 > [web]
143 > [web]
147 > push_ssl = false
144 > push_ssl = false
148 > allow_push = *
145 > allow_push = *
149 > EOF
146 > EOF
150
147
151 $ hg serve -p $HGPORT -d --pid-file=../hg.pid -E errors.log
148 $ hg serve -p $HGPORT -d --pid-file=../hg.pid -E errors.log
152 $ cat ../hg.pid >> $DAEMON_PIDS
149 $ cat ../hg.pid >> $DAEMON_PIDS
153 $ cd ../a
150 $ cd ../a
154
151
155 $ hg debugpushkey http://localhost:$HGPORT/ namespaces
152 $ hg debugpushkey http://localhost:$HGPORT/ namespaces
156 bookmarks
153 bookmarks
157 namespaces
154 namespaces
158 $ hg debugpushkey http://localhost:$HGPORT/ bookmarks
155 $ hg debugpushkey http://localhost:$HGPORT/ bookmarks
159 Y 4e3505fd95835d721066b76e75dbb8cc554d7f77
156 Y 4e3505fd95835d721066b76e75dbb8cc554d7f77
160 X 9b140be1080824d768c5a4691a564088eede71f9
157 X 9b140be1080824d768c5a4691a564088eede71f9
161 foo 0000000000000000000000000000000000000000
158 foo 0000000000000000000000000000000000000000
162 foobar 0000000000000000000000000000000000000000
159 foobar 0000000000000000000000000000000000000000
163 $ hg out -B http://localhost:$HGPORT/
160 $ hg out -B http://localhost:$HGPORT/
164 comparing with http://localhost:$HGPORT/
161 comparing with http://localhost:$HGPORT/
165 searching for changed bookmarks
162 searching for changed bookmarks
166 Z 0d2164f0ce0d
163 Z 0d2164f0ce0d
167 $ hg push -B Z http://localhost:$HGPORT/
164 $ hg push -B Z http://localhost:$HGPORT/
168 pushing to http://localhost:$HGPORT/
165 pushing to http://localhost:$HGPORT/
169 searching for changes
166 searching for changes
170 no changes found
167 no changes found
171 exporting bookmark Z
168 exporting bookmark Z
172 $ hg book -d Z
169 $ hg book -d Z
173 $ hg in -B http://localhost:$HGPORT/
170 $ hg in -B http://localhost:$HGPORT/
174 comparing with http://localhost:$HGPORT/
171 comparing with http://localhost:$HGPORT/
175 searching for changed bookmarks
172 searching for changed bookmarks
176 Z 0d2164f0ce0d
173 Z 0d2164f0ce0d
177 foo 000000000000
174 foo 000000000000
178 foobar 000000000000
175 foobar 000000000000
179 $ hg pull -B Z http://localhost:$HGPORT/
176 $ hg pull -B Z http://localhost:$HGPORT/
180 pulling from http://localhost:$HGPORT/
177 pulling from http://localhost:$HGPORT/
181 searching for changes
178 searching for changes
182 no changes found
179 no changes found
183 not updating divergent bookmark X
180 not updating divergent bookmark X
184 importing bookmark Z
181 importing bookmark Z
185
182
186 $ kill `cat ../hg.pid`
183 $ kill `cat ../hg.pid`
@@ -1,68 +1,68 b''
1 $ echo "[extensions]" >> $HGRCPATH
1 $ echo "[extensions]" >> $HGRCPATH
2 $ echo "rebase=" >> $HGRCPATH
2 $ echo "rebase=" >> $HGRCPATH
3 $ echo "bookmarks=" >> $HGRCPATH
3 $ echo "bookmarks=" >> $HGRCPATH
4
4
5 initialize repository
5 initialize repository
6
6
7 $ hg init
7 $ hg init
8
8
9 $ echo 'a' > a
9 $ echo 'a' > a
10 $ hg ci -A -m "0"
10 $ hg ci -A -m "0"
11 adding a
11 adding a
12
12
13 $ echo 'b' > b
13 $ echo 'b' > b
14 $ hg ci -A -m "1"
14 $ hg ci -A -m "1"
15 adding b
15 adding b
16
16
17 $ hg up 0
17 $ hg up 0
18 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
18 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
19 $ echo 'c' > c
19 $ echo 'c' > c
20 $ hg ci -A -m "2"
20 $ hg ci -A -m "2"
21 adding c
21 adding c
22 created new head
22 created new head
23
23
24 $ echo 'd' > d
24 $ echo 'd' > d
25 $ hg ci -A -m "3"
25 $ hg ci -A -m "3"
26 adding d
26 adding d
27
27
28 $ hg bookmark -r 1 one
28 $ hg bookmark -r 1 one
29 $ hg bookmark -r 3 two
29 $ hg bookmark -r 3 two
30
30
31 bookmark list
31 bookmark list
32
32
33 $ hg bookmark
33 $ hg bookmark
34 one 1:925d80f479bb
34 one 1:925d80f479bb
35 * two 3:2ae46b1d99a7
35 * two 3:2ae46b1d99a7
36
36
37 rebase
37 rebase
38
38
39 $ hg rebase -s two -d one
39 $ hg rebase -s two -d one
40 saved backup bundle to $TESTTMP/.hg/strip-backup/*-backup.hg (glob)
40 saved backup bundle to $TESTTMP/.hg/strip-backup/*-backup.hg (glob)
41
41
42 $ hg log
42 $ hg log
43 changeset: 3:9163974d1cb5
43 changeset: 3:9163974d1cb5
44 bookmark: one
45 bookmark: two
44 bookmark: two
46 tag: tip
45 tag: tip
47 parent: 1:925d80f479bb
46 parent: 1:925d80f479bb
48 parent: 2:db815d6d32e6
47 parent: 2:db815d6d32e6
49 user: test
48 user: test
50 date: Thu Jan 01 00:00:00 1970 +0000
49 date: Thu Jan 01 00:00:00 1970 +0000
51 summary: 3
50 summary: 3
52
51
53 changeset: 2:db815d6d32e6
52 changeset: 2:db815d6d32e6
54 parent: 0:f7b1eb17ad24
53 parent: 0:f7b1eb17ad24
55 user: test
54 user: test
56 date: Thu Jan 01 00:00:00 1970 +0000
55 date: Thu Jan 01 00:00:00 1970 +0000
57 summary: 2
56 summary: 2
58
57
59 changeset: 1:925d80f479bb
58 changeset: 1:925d80f479bb
59 bookmark: one
60 user: test
60 user: test
61 date: Thu Jan 01 00:00:00 1970 +0000
61 date: Thu Jan 01 00:00:00 1970 +0000
62 summary: 1
62 summary: 1
63
63
64 changeset: 0:f7b1eb17ad24
64 changeset: 0:f7b1eb17ad24
65 user: test
65 user: test
66 date: Thu Jan 01 00:00:00 1970 +0000
66 date: Thu Jan 01 00:00:00 1970 +0000
67 summary: 0
67 summary: 0
68
68
@@ -1,102 +1,102 b''
1 $ echo "[extensions]" >> $HGRCPATH
1 $ echo "[extensions]" >> $HGRCPATH
2 $ echo "bookmarks=" >> $HGRCPATH
2 $ echo "bookmarks=" >> $HGRCPATH
3 $ echo "mq=" >> $HGRCPATH
3 $ echo "mq=" >> $HGRCPATH
4
4
5 $ hg init
5 $ hg init
6
6
7 $ echo qqq>qqq.txt
7 $ echo qqq>qqq.txt
8
8
9 rollback dry run without rollback information
9 rollback dry run without rollback information
10
10
11 $ hg rollback
11 $ hg rollback
12 no rollback information available
12 no rollback information available
13 [1]
13 [1]
14
14
15 add file
15 add file
16
16
17 $ hg add
17 $ hg add
18 adding qqq.txt
18 adding qqq.txt
19
19
20 commit first revision
20 commit first revision
21
21
22 $ hg ci -m 1
22 $ hg ci -m 1
23
23
24 set bookmark
24 set bookmark
25
25
26 $ hg book test
26 $ hg book test
27
27
28 $ echo www>>qqq.txt
28 $ echo www>>qqq.txt
29
29
30 commit second revision
30 commit second revision
31
31
32 $ hg ci -m 2
32 $ hg ci -m 2
33
33
34 set bookmark
34 set bookmark
35
35
36 $ hg book test2
36 $ hg book test2
37
37
38 update to -2
38 update to -2
39
39
40 $ hg update -r -2
40 $ hg update -r -2
41 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
41 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
42
42
43 $ echo eee>>qqq.txt
43 $ echo eee>>qqq.txt
44
44
45 commit new head
45 commit new head
46
46
47 $ hg ci -m 3
47 $ hg ci -m 3
48 created new head
48 created new head
49
49
50 bookmarks updated?
50 bookmarks updated?
51
51
52 $ hg book
52 $ hg book
53 test 1:25e1ee7a0081
53 test 1:25e1ee7a0081
54 test2 1:25e1ee7a0081
54 test2 1:25e1ee7a0081
55
55
56 strip to revision 1
56 strip to revision 1
57
57
58 $ hg strip 1
58 $ hg strip 1
59 saved backup bundle to $TESTTMP/.hg/strip-backup/*-backup.hg (glob)
59 saved backup bundle to $TESTTMP/.hg/strip-backup/*-backup.hg (glob)
60
60
61 list bookmarks
61 list bookmarks
62
62
63 $ hg book
63 $ hg book
64 * test 1:8cf31af87a2b
64 test 1:8cf31af87a2b
65 * test2 1:8cf31af87a2b
65 * test2 1:8cf31af87a2b
66
66
67 immediate rollback and reentrancy issue
67 immediate rollback and reentrancy issue
68
68
69 $ echo "mq=!" >> $HGRCPATH
69 $ echo "mq=!" >> $HGRCPATH
70 $ hg init repo
70 $ hg init repo
71 $ cd repo
71 $ cd repo
72 $ echo a > a
72 $ echo a > a
73 $ hg ci -Am adda
73 $ hg ci -Am adda
74 adding a
74 adding a
75 $ echo b > b
75 $ echo b > b
76 $ hg ci -Am addb
76 $ hg ci -Am addb
77 adding b
77 adding b
78 $ hg bookmarks markb
78 $ hg bookmarks markb
79 $ hg rollback
79 $ hg rollback
80 rolling back to revision 0 (undo commit)
80 rolling back to revision 0 (undo commit)
81
81
82 are you there?
82 are you there?
83
83
84 $ hg bookmarks
84 $ hg bookmarks
85 no bookmarks set
85 no bookmarks set
86
86
87 can you be added again?
87 can you be added again?
88
88
89 $ hg bookmarks markb
89 $ hg bookmarks markb
90 $ hg bookmarks
90 $ hg bookmarks
91 * markb 0:07f494440405
91 * markb 0:07f494440405
92
92
93 rollback dry run with rollback information
93 rollback dry run with rollback information
94
94
95 $ hg rollback -n
95 $ hg rollback -n
96 no rollback information available
96 no rollback information available
97 [1]
97 [1]
98 $ hg bookmarks
98 $ hg bookmarks
99 * markb 0:07f494440405
99 * markb 0:07f494440405
100
100
101 $ cd ..
101 $ cd ..
102
102
@@ -1,213 +1,214 b''
1 $ echo "[extensions]" >> $HGRCPATH
1 $ echo "[extensions]" >> $HGRCPATH
2 $ echo "bookmarks=" >> $HGRCPATH
2 $ echo "bookmarks=" >> $HGRCPATH
3
3
4 $ hg init
4 $ hg init
5
5
6 no bookmarks
6 no bookmarks
7
7
8 $ hg bookmarks
8 $ hg bookmarks
9 no bookmarks set
9 no bookmarks set
10
10
11 bookmark rev -1
11 bookmark rev -1
12
12
13 $ hg bookmark X
13 $ hg bookmark X
14
14
15 list bookmarks
15 list bookmarks
16
16
17 $ hg bookmarks
17 $ hg bookmarks
18 * X -1:000000000000
18 * X -1:000000000000
19
19
20 list bookmarks with color
20 list bookmarks with color
21
21
22 $ hg --config extensions.color= --config color.mode=ansi \
22 $ hg --config extensions.color= --config color.mode=ansi \
23 > bookmarks --color=always
23 > bookmarks --color=always
24 \x1b[0;32m * X -1:000000000000\x1b[0m (esc)
24 \x1b[0;32m * X -1:000000000000\x1b[0m (esc)
25
25
26 $ echo a > a
26 $ echo a > a
27 $ hg add a
27 $ hg add a
28 $ hg commit -m 0
28 $ hg commit -m 0
29
29
30 bookmark X moved to rev 0
30 bookmark X moved to rev 0
31
31
32 $ hg bookmarks
32 $ hg bookmarks
33 * X 0:f7b1eb17ad24
33 * X 0:f7b1eb17ad24
34
34
35 look up bookmark
35 look up bookmark
36
36
37 $ hg log -r X
37 $ hg log -r X
38 changeset: 0:f7b1eb17ad24
38 changeset: 0:f7b1eb17ad24
39 bookmark: X
39 bookmark: X
40 tag: tip
40 tag: tip
41 user: test
41 user: test
42 date: Thu Jan 01 00:00:00 1970 +0000
42 date: Thu Jan 01 00:00:00 1970 +0000
43 summary: 0
43 summary: 0
44
44
45
45
46 second bookmark for rev 0
46 second bookmark for rev 0
47
47
48 $ hg bookmark X2
48 $ hg bookmark X2
49
49
50 bookmark rev -1 again
50 bookmark rev -1 again
51
51
52 $ hg bookmark -r null Y
52 $ hg bookmark -r null Y
53
53
54 list bookmarks
54 list bookmarks
55
55
56 $ hg bookmarks
56 $ hg bookmarks
57 * X 0:f7b1eb17ad24
57 X 0:f7b1eb17ad24
58 * X2 0:f7b1eb17ad24
58 X2 0:f7b1eb17ad24
59 Y -1:000000000000
59 Y -1:000000000000
60
60
61 $ echo b > b
61 $ echo b > b
62 $ hg add b
62 $ hg add b
63 $ hg commit -m 1
63 $ hg commit -m 1
64
64
65 bookmarks revset
65 bookmarks revset
66
66
67 $ hg log -r 'bookmark()'
67 $ hg log -r 'bookmark()'
68 changeset: 1:925d80f479bb
68 changeset: 0:f7b1eb17ad24
69 bookmark: X
69 bookmark: X
70 bookmark: X2
70 bookmark: X2
71 tag: tip
72 user: test
71 user: test
73 date: Thu Jan 01 00:00:00 1970 +0000
72 date: Thu Jan 01 00:00:00 1970 +0000
74 summary: 1
73 summary: 0
75
74
76 $ hg log -r 'bookmark(Y)'
75 $ hg log -r 'bookmark(Y)'
77 $ hg log -r 'bookmark(X2)'
76 $ hg log -r 'bookmark(X2)'
78 changeset: 1:925d80f479bb
77 changeset: 0:f7b1eb17ad24
79 bookmark: X
78 bookmark: X
80 bookmark: X2
79 bookmark: X2
81 tag: tip
82 user: test
80 user: test
83 date: Thu Jan 01 00:00:00 1970 +0000
81 date: Thu Jan 01 00:00:00 1970 +0000
84 summary: 1
82 summary: 0
85
83
86 $ hg help revsets | grep 'bookmark('
84 $ hg help revsets | grep 'bookmark('
87 "bookmark([name])"
85 "bookmark([name])"
88
86
89 bookmarks X and X2 moved to rev 1, Y at rev -1
87 bookmarks X and X2 moved to rev 1, Y at rev -1
90
88
91 $ hg bookmarks
89 $ hg bookmarks
92 * X 1:925d80f479bb
90 X 0:f7b1eb17ad24
93 * X2 1:925d80f479bb
91 X2 0:f7b1eb17ad24
94 Y -1:000000000000
92 Y -1:000000000000
95
93
96 bookmark rev 0 again
94 bookmark rev 0 again
97
95
98 $ hg bookmark -r 0 Z
96 $ hg bookmark -r 0 Z
99
97
98 $ hg update X
99 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
100 $ echo c > c
100 $ echo c > c
101 $ hg add c
101 $ hg add c
102 $ hg commit -m 2
102 $ hg commit -m 2
103 created new head
103
104
104 bookmarks X and X2 moved to rev 2, Y at rev -1, Z at rev 0
105 bookmarks X moved to rev 2, Y at rev -1, Z at rev 0
105
106
106 $ hg bookmarks
107 $ hg bookmarks
107 * X 2:0316ce92851d
108 * X 2:db815d6d32e6
108 * X2 2:0316ce92851d
109 X2 0:f7b1eb17ad24
109 Y -1:000000000000
110 Y -1:000000000000
110 Z 0:f7b1eb17ad24
111 Z 0:f7b1eb17ad24
111
112
112 rename nonexistent bookmark
113 rename nonexistent bookmark
113
114
114 $ hg bookmark -m A B
115 $ hg bookmark -m A B
115 abort: a bookmark of this name does not exist
116 abort: a bookmark of this name does not exist
116 [255]
117 [255]
117
118
118 rename to existent bookmark
119 rename to existent bookmark
119
120
120 $ hg bookmark -m X Y
121 $ hg bookmark -m X Y
121 abort: a bookmark of the same name already exists
122 abort: a bookmark of the same name already exists
122 [255]
123 [255]
123
124
124 force rename to existent bookmark
125 force rename to existent bookmark
125
126
126 $ hg bookmark -f -m X Y
127 $ hg bookmark -f -m X Y
127
128
128 list bookmarks
129 list bookmarks
129
130
130 $ hg bookmark
131 $ hg bookmark
131 * X2 2:0316ce92851d
132 X2 0:f7b1eb17ad24
132 * Y 2:0316ce92851d
133 * Y 2:db815d6d32e6
133 Z 0:f7b1eb17ad24
134 Z 0:f7b1eb17ad24
134
135
135 rename without new name
136 rename without new name
136
137
137 $ hg bookmark -m Y
138 $ hg bookmark -m Y
138 abort: new bookmark name required
139 abort: new bookmark name required
139 [255]
140 [255]
140
141
141 delete without name
142 delete without name
142
143
143 $ hg bookmark -d
144 $ hg bookmark -d
144 abort: bookmark name required
145 abort: bookmark name required
145 [255]
146 [255]
146
147
147 delete nonexistent bookmark
148 delete nonexistent bookmark
148
149
149 $ hg bookmark -d A
150 $ hg bookmark -d A
150 abort: a bookmark of this name does not exist
151 abort: a bookmark of this name does not exist
151 [255]
152 [255]
152
153
153 bookmark name with spaces should be stripped
154 bookmark name with spaces should be stripped
154
155
155 $ hg bookmark ' x y '
156 $ hg bookmark ' x y '
156
157
157 list bookmarks
158 list bookmarks
158
159
159 $ hg bookmarks
160 $ hg bookmarks
160 * X2 2:0316ce92851d
161 X2 0:f7b1eb17ad24
161 * Y 2:0316ce92851d
162 Y 2:db815d6d32e6
162 Z 0:f7b1eb17ad24
163 Z 0:f7b1eb17ad24
163 * x y 2:0316ce92851d
164 * x y 2:db815d6d32e6
164
165
165 look up stripped bookmark name
166 look up stripped bookmark name
166
167
167 $ hg log -r '"x y"'
168 $ hg log -r '"x y"'
168 changeset: 2:0316ce92851d
169 changeset: 2:db815d6d32e6
169 bookmark: X2
170 bookmark: Y
170 bookmark: Y
171 bookmark: x y
171 bookmark: x y
172 tag: tip
172 tag: tip
173 parent: 0:f7b1eb17ad24
173 user: test
174 user: test
174 date: Thu Jan 01 00:00:00 1970 +0000
175 date: Thu Jan 01 00:00:00 1970 +0000
175 summary: 2
176 summary: 2
176
177
177
178
178 reject bookmark name with newline
179 reject bookmark name with newline
179
180
180 $ hg bookmark '
181 $ hg bookmark '
181 > '
182 > '
182 abort: bookmark name cannot contain newlines
183 abort: bookmark name cannot contain newlines
183 [255]
184 [255]
184
185
185 bookmark with existing name
186 bookmark with existing name
186
187
187 $ hg bookmark Z
188 $ hg bookmark Z
188 abort: a bookmark of the same name already exists
189 abort: a bookmark of the same name already exists
189 [255]
190 [255]
190
191
191 force bookmark with existing name
192 force bookmark with existing name
192
193
193 $ hg bookmark -f Z
194 $ hg bookmark -f Z
194
195
195 list bookmarks
196 list bookmarks
196
197
197 $ hg bookmark
198 $ hg bookmark
198 * X2 2:0316ce92851d
199 X2 0:f7b1eb17ad24
199 * Y 2:0316ce92851d
200 Y 2:db815d6d32e6
200 * Z 2:0316ce92851d
201 * Z 2:db815d6d32e6
201 * x y 2:0316ce92851d
202 x y 2:db815d6d32e6
202
203
203 revision but no bookmark name
204 revision but no bookmark name
204
205
205 $ hg bookmark -r .
206 $ hg bookmark -r .
206 abort: bookmark name required
207 abort: bookmark name required
207 [255]
208 [255]
208
209
209 bookmark name with whitespace only
210 bookmark name with whitespace only
210
211
211 $ hg bookmark ' '
212 $ hg bookmark ' '
212 abort: bookmark names cannot consist entirely of whitespace
213 abort: bookmark names cannot consist entirely of whitespace
213 [255]
214 [255]
General Comments 0
You need to be logged in to leave comments. Login now