##// END OF EJS Templates
Support for 'hg --version'. setup.py stores version from hg repository....
Thomas Arendsen Hein -
r423:25afb21d default
parent child Browse files
Show More
@@ -0,0 +1,62
1 # Copyright (C) 2005 by Intevation GmbH
2 # Author(s):
3 # Thomas Arendsen Hein <thomas@intevation.de>
4 #
5 # This program is free software under the GNU GPL (>=v2)
6 # Read the file COPYING coming with the software for details.
7
8 """
9 Mercurial version
10 """
11
12 import os
13 import os.path
14 import re
15 import time
16
17 unknown_version = 'unknown'
18
19 def get_version():
20 """Return version information if available."""
21 try:
22 from mercurial.__version__ import version
23 except ImportError:
24 version = unknown_version
25 return version
26
27 def write_version(version):
28 """Overwrite version file."""
29 filename = os.path.join(os.path.dirname(__file__), '__version__.py')
30 f = open(filename, 'w')
31 f.write("# This file is auto-generated.\n")
32 f.write("version = %r\n" % version)
33 f.close()
34
35 def remember_version():
36 """Store version information."""
37 f = os.popen("hg identify 2>/dev/null") # use real hg installation
38 ident = f.read()[:-1]
39 if not f.close() and ident:
40 ids = ident.split(' ', 1)
41 version = ids.pop(0)
42 if version[-1] == '+':
43 version = version[:-1]
44 modified = True
45 else:
46 modified = False
47 if version.isalnum() and ids:
48 for tag in ids[0].split('/'):
49 # is a tag is suitable as a version number?
50 if re.match(r'^(\d+\.)+[\w.-]+$', tag):
51 version = tag
52 break
53 if modified:
54 version += time.strftime('+%Y%m%d')
55 else:
56 version = unknown_version
57 write_version(version)
58
59 def forget_version():
60 """Remove version information."""
61 write_version(unknown_version)
62
@@ -1,10 +1,11
1 .*\.orig
1 .*\.orig
2 .*\.rej
2 .*\.rej
3 .*~
3 .*~
4 .*\.so
4 .*\.so
5 .*pyc
5 .*pyc
6 build/.*
6 build/.*
7 dist/
7 dist/
8 MANIFEST$
8 MANIFEST$
9 .pc/
9 .pc/
10 patches/ No newline at end of file
10 patches/
11 mercurial/__version__.py$
@@ -1,52 +1,51
1 General:
1 General:
2 - Better documentation
2 - Better documentation
3 - More regression tests
3 - More regression tests
4 - More specific try/except.
4 - More specific try/except.
5 - less code duplication, more code in the right places
5 - less code duplication, more code in the right places
6 - python 2.2 support
6 - python 2.2 support
7 - better import support
7 - better import support
8 - export to git
8 - export to git
9 - Add standard files: AUTHORS, CREDITS, COPYING. ChangeLog? What else?
9 - Add standard files: AUTHORS, CREDITS, ChangeLog? What else?
10 - Code cleanup: apply http://python.org/peps/pep-0008.html
10 - Code cleanup: apply http://python.org/peps/pep-0008.html
11
11
12 Core:
12 Core:
13 - difflib creating/removing files (fixed except dates: should be epoch)
13 - difflib creating/removing files (fixed except dates: should be epoch)
14 - directory foo.d or foo.i with existing file foo (use some quoting?)
14 - directory foo.d or foo.i with existing file foo (use some quoting?)
15 - get various options from hgrc (e.g. history always -v, tip always -q)
15 - get various options from hgrc (e.g. history always -v, tip always -q)
16 - allow full decimal (part of) hash
16 - allow full decimal (part of) hash
17 hg export 5005048662 -> OverflowError: long int too large to convert
17 hg export 5005048662 -> OverflowError: long int too large to convert
18 to int
18 to int
19 - push support (hack exists)
19 - push support (hack exists)
20 - hg over ssh://
20 - hg over ssh://
21 - commit mailinglist/trigger/hooks
21 - commit mailinglist/trigger/hooks
22 - fast diff extension
22 - fast diff extension
23
23
24 Commands:
24 Commands:
25 - hg status <filename>: file rev, changeset rev, changed, added,
25 - hg status <filename>: file rev, changeset rev, changed, added,
26 deleted, sha-1
26 deleted, sha-1
27 - select to pull a subset of the heads
27 - select to pull a subset of the heads
28 - commands.py: number of args too much magic (e.g. in patch())
28 - commands.py: number of args too much magic (e.g. in patch())
29 - adding a tag with "hg tag foobar"
29 - adding a tag with "hg tag foobar"
30 - automatic pull fallback to old-http://
30 - automatic pull fallback to old-http://
31 - hg init|pull http://example.com doesn't say that no repo was found
31 - hg init|pull http://example.com doesn't say that no repo was found
32 - hg annotate -u and hgweb annotate with long $EMAIL
32 - hg annotate -u and hgweb annotate with long $EMAIL
33 - hg -v history doesn't show tkmerge as modified (removed).
33 - hg -v history doesn't show tkmerge as modified (removed).
34 - hg import vs. hg patch in help etc., import is a reserved python
34 - hg import vs. hg patch in help etc., import is a reserved python
35 word, PEP8 mentions trailing underscore as a convention for this.
35 word, PEP8 mentions trailing underscore as a convention for this.
36 - version reporting (hg --version / version.py / setup.py etc.)
37 - hg pull default in a subdir doesn't work, if it is a relative path
36 - hg pull default in a subdir doesn't work, if it is a relative path
38 - optionally only show merges (two parents or parent != changeset-1, etc.)
37 - optionally only show merges (two parents or parent != changeset-1, etc.)
39
38
40 Web:
39 Web:
41 - show tags in hgweb
40 - show tags in hgweb
42 - show parent changeset number in hgweb
41 - show parent changeset number in hgweb
43 - optionally only show merges (two parents or parent != changeset-1, etc.)
42 - optionally only show merges (two parents or parent != changeset-1, etc.)
44 - one hgweb with many repos (another script)
43 - one hgweb with many repos (another script)
45 - hgweb tip link too verbose
44 - hgweb tip link too verbose
46 - hgweb: deliver static files (e.g. favicon, stylesheets)
45 - hgweb: deliver static files (e.g. favicon, stylesheets)
47 - hgweb personalization: timezone (display/change), display of
46 - hgweb personalization: timezone (display/change), display of
48 features
47 features
49 - hg export 240 shows -tkmerge (good), hgweb does not (bad).
48 - hg export 240 shows -tkmerge (good), hgweb does not (bad).
50 - some web servers think hgweb.cgi.[di] is a CGI script with old-http://
49 - some web servers think hgweb.cgi.[di] is a CGI script with old-http://
51 (use quoting (see foo.d in Core) or document server configurations?)
50 (use quoting (see foo.d in Core) or document server configurations?)
52 - link children in hgweb
51 - link children in hgweb
@@ -1,778 +1,796
1 # commands.py - command processing for mercurial
1 # commands.py - command processing for mercurial
2 #
2 #
3 # Copyright 2005 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms
5 # This software may be used and distributed according to the terms
6 # of the GNU General Public License, incorporated herein by reference.
6 # of the GNU General Public License, incorporated herein by reference.
7
7
8 import os, re, sys, signal
8 import os, re, sys, signal
9 import fancyopts, ui, hg
9 import fancyopts, ui, hg
10 from demandload import *
10 from demandload import *
11 demandload(globals(), "mdiff time hgweb traceback random signal errno")
11 demandload(globals(), "mdiff time hgweb traceback random signal errno version")
12
12
13 class UnknownCommand(Exception): pass
13 class UnknownCommand(Exception): pass
14
14
15 def filterfiles(filters, files):
15 def filterfiles(filters, files):
16 l = [ x for x in files if x in filters ]
16 l = [ x for x in files if x in filters ]
17
17
18 for t in filters:
18 for t in filters:
19 if t and t[-1] != os.sep: t += os.sep
19 if t and t[-1] != os.sep: t += os.sep
20 l += [ x for x in files if x.startswith(t) ]
20 l += [ x for x in files if x.startswith(t) ]
21 return l
21 return l
22
22
23 def relfilter(repo, files):
23 def relfilter(repo, files):
24 if os.getcwd() != repo.root:
24 if os.getcwd() != repo.root:
25 p = os.getcwd()[len(repo.root) + 1: ]
25 p = os.getcwd()[len(repo.root) + 1: ]
26 return filterfiles([p], files)
26 return filterfiles([p], files)
27 return files
27 return files
28
28
29 def relpath(repo, args):
29 def relpath(repo, args):
30 if os.getcwd() != repo.root:
30 if os.getcwd() != repo.root:
31 p = os.getcwd()[len(repo.root) + 1: ]
31 p = os.getcwd()[len(repo.root) + 1: ]
32 return [ os.path.normpath(os.path.join(p, x)) for x in args ]
32 return [ os.path.normpath(os.path.join(p, x)) for x in args ]
33 return args
33 return args
34
34
35 def dodiff(ui, repo, path, files = None, node1 = None, node2 = None):
35 def dodiff(ui, repo, path, files = None, node1 = None, node2 = None):
36 def date(c):
36 def date(c):
37 return time.asctime(time.gmtime(float(c[2].split(' ')[0])))
37 return time.asctime(time.gmtime(float(c[2].split(' ')[0])))
38
38
39 if node2:
39 if node2:
40 change = repo.changelog.read(node2)
40 change = repo.changelog.read(node2)
41 mmap2 = repo.manifest.read(change[0])
41 mmap2 = repo.manifest.read(change[0])
42 (c, a, d) = repo.diffrevs(node1, node2)
42 (c, a, d) = repo.diffrevs(node1, node2)
43 def read(f): return repo.file(f).read(mmap2[f])
43 def read(f): return repo.file(f).read(mmap2[f])
44 date2 = date(change)
44 date2 = date(change)
45 else:
45 else:
46 date2 = time.asctime()
46 date2 = time.asctime()
47 (c, a, d, u) = repo.diffdir(path, node1)
47 (c, a, d, u) = repo.diffdir(path, node1)
48 if not node1:
48 if not node1:
49 node1 = repo.dirstate.parents()[0]
49 node1 = repo.dirstate.parents()[0]
50 def read(f): return file(os.path.join(repo.root, f)).read()
50 def read(f): return file(os.path.join(repo.root, f)).read()
51
51
52 if ui.quiet:
52 if ui.quiet:
53 r = None
53 r = None
54 else:
54 else:
55 hexfunc = ui.verbose and hg.hex or hg.short
55 hexfunc = ui.verbose and hg.hex or hg.short
56 r = [hexfunc(node) for node in [node1, node2] if node]
56 r = [hexfunc(node) for node in [node1, node2] if node]
57
57
58 change = repo.changelog.read(node1)
58 change = repo.changelog.read(node1)
59 mmap = repo.manifest.read(change[0])
59 mmap = repo.manifest.read(change[0])
60 date1 = date(change)
60 date1 = date(change)
61
61
62 if files:
62 if files:
63 c, a, d = map(lambda x: filterfiles(files, x), (c, a, d))
63 c, a, d = map(lambda x: filterfiles(files, x), (c, a, d))
64
64
65 for f in c:
65 for f in c:
66 to = None
66 to = None
67 if f in mmap:
67 if f in mmap:
68 to = repo.file(f).read(mmap[f])
68 to = repo.file(f).read(mmap[f])
69 tn = read(f)
69 tn = read(f)
70 sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f, r))
70 sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f, r))
71 for f in a:
71 for f in a:
72 to = None
72 to = None
73 tn = read(f)
73 tn = read(f)
74 sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f, r))
74 sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f, r))
75 for f in d:
75 for f in d:
76 to = repo.file(f).read(mmap[f])
76 to = repo.file(f).read(mmap[f])
77 tn = None
77 tn = None
78 sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f, r))
78 sys.stdout.write(mdiff.unidiff(to, date1, tn, date2, f, r))
79
79
80 def show_changeset(ui, repo, rev=0, changenode=None, filelog=None):
80 def show_changeset(ui, repo, rev=0, changenode=None, filelog=None):
81 """show a single changeset or file revision"""
81 """show a single changeset or file revision"""
82 changelog = repo.changelog
82 changelog = repo.changelog
83 if filelog:
83 if filelog:
84 log = filelog
84 log = filelog
85 filerev = rev
85 filerev = rev
86 node = filenode = filelog.node(filerev)
86 node = filenode = filelog.node(filerev)
87 changerev = filelog.linkrev(filenode)
87 changerev = filelog.linkrev(filenode)
88 changenode = changenode or changelog.node(changerev)
88 changenode = changenode or changelog.node(changerev)
89 else:
89 else:
90 log = changelog
90 log = changelog
91 changerev = rev
91 changerev = rev
92 if changenode is None:
92 if changenode is None:
93 changenode = changelog.node(changerev)
93 changenode = changelog.node(changerev)
94 elif not changerev:
94 elif not changerev:
95 rev = changerev = changelog.rev(changenode)
95 rev = changerev = changelog.rev(changenode)
96 node = changenode
96 node = changenode
97
97
98 if ui.quiet:
98 if ui.quiet:
99 ui.write("%d:%s\n" % (rev, hg.hex(node)))
99 ui.write("%d:%s\n" % (rev, hg.hex(node)))
100 return
100 return
101
101
102 changes = changelog.read(changenode)
102 changes = changelog.read(changenode)
103
103
104 parents = [(log.rev(parent), hg.hex(parent))
104 parents = [(log.rev(parent), hg.hex(parent))
105 for parent in log.parents(node)
105 for parent in log.parents(node)
106 if ui.debugflag or parent != hg.nullid]
106 if ui.debugflag or parent != hg.nullid]
107 if not ui.debugflag and len(parents) == 1 and parents[0][0] == rev-1:
107 if not ui.debugflag and len(parents) == 1 and parents[0][0] == rev-1:
108 parents = []
108 parents = []
109
109
110 if filelog:
110 if filelog:
111 ui.write("revision: %d:%s\n" % (filerev, hg.hex(filenode)))
111 ui.write("revision: %d:%s\n" % (filerev, hg.hex(filenode)))
112 for parent in parents:
112 for parent in parents:
113 ui.write("parent: %d:%s\n" % parent)
113 ui.write("parent: %d:%s\n" % parent)
114 ui.status("changeset: %d:%s\n" % (changerev, hg.hex(changenode)))
114 ui.status("changeset: %d:%s\n" % (changerev, hg.hex(changenode)))
115 else:
115 else:
116 ui.write("changeset: %d:%s\n" % (changerev, hg.hex(changenode)))
116 ui.write("changeset: %d:%s\n" % (changerev, hg.hex(changenode)))
117 for tag in repo.nodetags(changenode):
117 for tag in repo.nodetags(changenode):
118 ui.status("tag: %s\n" % tag)
118 ui.status("tag: %s\n" % tag)
119 for parent in parents:
119 for parent in parents:
120 ui.write("parent: %d:%s\n" % parent)
120 ui.write("parent: %d:%s\n" % parent)
121 ui.note("manifest: %d:%s\n" % (repo.manifest.rev(changes[0]),
121 ui.note("manifest: %d:%s\n" % (repo.manifest.rev(changes[0]),
122 hg.hex(changes[0])))
122 hg.hex(changes[0])))
123 ui.status("user: %s\n" % changes[1])
123 ui.status("user: %s\n" % changes[1])
124 ui.status("date: %s\n" % time.asctime(
124 ui.status("date: %s\n" % time.asctime(
125 time.localtime(float(changes[2].split(' ')[0]))))
125 time.localtime(float(changes[2].split(' ')[0]))))
126 ui.note("files: %s\n" % " ".join(changes[3]))
126 ui.note("files: %s\n" % " ".join(changes[3]))
127 description = changes[4].strip()
127 description = changes[4].strip()
128 if description:
128 if description:
129 if ui.verbose:
129 if ui.verbose:
130 ui.status("description:\n")
130 ui.status("description:\n")
131 ui.status(description)
131 ui.status(description)
132 ui.status("\n")
132 ui.status("\n")
133 else:
133 else:
134 ui.status("summary: %s\n" % description.splitlines()[0])
134 ui.status("summary: %s\n" % description.splitlines()[0])
135 ui.status("\n")
135 ui.status("\n")
136
136
137 def show_version(ui):
138 """output version and copyright information"""
139 ui.write("Mercurial version %s\n" % version.get_version())
140 ui.status(
141 "\nCopyright (C) 2005 Matt Mackall <mpm@selenic.com>\n"
142 "This is free software; see the source for copying conditions. "
143 "There is NO\nwarranty; "
144 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
145 )
146
137 def help(ui, cmd=None):
147 def help(ui, cmd=None):
138 '''show help for a given command or all commands'''
148 '''show help for a given command or all commands'''
139 if cmd:
149 if cmd:
140 try:
150 try:
141 i = find(cmd)
151 i = find(cmd)
142 ui.write("%s\n\n" % i[2])
152 ui.write("%s\n\n" % i[2])
143
153
144 if i[1]:
154 if i[1]:
145 for s, l, d, c in i[1]:
155 for s, l, d, c in i[1]:
146 opt=' '
156 opt=' '
147 if s: opt = opt + '-' + s + ' '
157 if s: opt = opt + '-' + s + ' '
148 if l: opt = opt + '--' + l + ' '
158 if l: opt = opt + '--' + l + ' '
149 if d: opt = opt + '(' + str(d) + ')'
159 if d: opt = opt + '(' + str(d) + ')'
150 ui.write(opt, "\n")
160 ui.write(opt, "\n")
151 if c: ui.write(' %s\n' % c)
161 if c: ui.write(' %s\n' % c)
152 ui.write("\n")
162 ui.write("\n")
153
163
154 ui.write(i[0].__doc__, "\n")
164 ui.write(i[0].__doc__, "\n")
155 except UnknownCommand:
165 except UnknownCommand:
156 ui.warn("hg: unknown command %s\n" % cmd)
166 ui.warn("hg: unknown command %s\n" % cmd)
157 sys.exit(0)
167 sys.exit(0)
158 else:
168 else:
159 ui.status('hg commands:\n\n')
169 if not ui.quiet:
170 show_version(ui)
171 ui.write('\n')
172 ui.write('hg commands:\n\n')
160
173
161 h = {}
174 h = {}
162 for e in table.values():
175 for e in table.values():
163 f = e[0]
176 f = e[0]
164 if f.__name__.startswith("debug"): continue
177 if f.__name__.startswith("debug"): continue
165 d = ""
178 d = ""
166 if f.__doc__:
179 if f.__doc__:
167 d = f.__doc__.splitlines(0)[0].rstrip()
180 d = f.__doc__.splitlines(0)[0].rstrip()
168 h[f.__name__] = d
181 h[f.__name__] = d
169
182
170 fns = h.keys()
183 fns = h.keys()
171 fns.sort()
184 fns.sort()
172 m = max(map(len, fns))
185 m = max(map(len, fns))
173 for f in fns:
186 for f in fns:
174 ui.status(' %-*s %s\n' % (m, f, h[f]))
187 ui.write(' %-*s %s\n' % (m, f, h[f]))
175
188
176 # Commands start here, listed alphabetically
189 # Commands start here, listed alphabetically
177
190
178 def add(ui, repo, file, *files):
191 def add(ui, repo, file, *files):
179 '''add the specified files on the next commit'''
192 '''add the specified files on the next commit'''
180 repo.add(relpath(repo, (file,) + files))
193 repo.add(relpath(repo, (file,) + files))
181
194
182 def addremove(ui, repo, *files):
195 def addremove(ui, repo, *files):
183 """add all new files, delete all missing files"""
196 """add all new files, delete all missing files"""
184 if files:
197 if files:
185 files = relpath(repo, files)
198 files = relpath(repo, files)
186 d = []
199 d = []
187 u = []
200 u = []
188 for f in files:
201 for f in files:
189 p = repo.wjoin(f)
202 p = repo.wjoin(f)
190 s = repo.dirstate.state(f)
203 s = repo.dirstate.state(f)
191 isfile = os.path.isfile(p)
204 isfile = os.path.isfile(p)
192 if s != 'r' and not isfile:
205 if s != 'r' and not isfile:
193 d.append(f)
206 d.append(f)
194 elif s not in 'nmai' and isfile:
207 elif s not in 'nmai' and isfile:
195 u.append(f)
208 u.append(f)
196 else:
209 else:
197 (c, a, d, u) = repo.diffdir(repo.root)
210 (c, a, d, u) = repo.diffdir(repo.root)
198 repo.add(u)
211 repo.add(u)
199 repo.remove(d)
212 repo.remove(d)
200
213
201 def annotate(u, repo, file, *files, **ops):
214 def annotate(u, repo, file, *files, **ops):
202 """show changeset information per file line"""
215 """show changeset information per file line"""
203 def getnode(rev):
216 def getnode(rev):
204 return hg.short(repo.changelog.node(rev))
217 return hg.short(repo.changelog.node(rev))
205
218
206 def getname(rev):
219 def getname(rev):
207 try:
220 try:
208 return bcache[rev]
221 return bcache[rev]
209 except KeyError:
222 except KeyError:
210 cl = repo.changelog.read(repo.changelog.node(rev))
223 cl = repo.changelog.read(repo.changelog.node(rev))
211 name = cl[1]
224 name = cl[1]
212 f = name.find('@')
225 f = name.find('@')
213 if f >= 0:
226 if f >= 0:
214 name = name[:f]
227 name = name[:f]
215 bcache[rev] = name
228 bcache[rev] = name
216 return name
229 return name
217
230
218 bcache = {}
231 bcache = {}
219 opmap = [['user', getname], ['number', str], ['changeset', getnode]]
232 opmap = [['user', getname], ['number', str], ['changeset', getnode]]
220 if not ops['user'] and not ops['changeset']:
233 if not ops['user'] and not ops['changeset']:
221 ops['number'] = 1
234 ops['number'] = 1
222
235
223 node = repo.dirstate.parents()[0]
236 node = repo.dirstate.parents()[0]
224 if ops['revision']:
237 if ops['revision']:
225 node = repo.changelog.lookup(ops['revision'])
238 node = repo.changelog.lookup(ops['revision'])
226 change = repo.changelog.read(node)
239 change = repo.changelog.read(node)
227 mmap = repo.manifest.read(change[0])
240 mmap = repo.manifest.read(change[0])
228 maxuserlen = 0
241 maxuserlen = 0
229 maxchangelen = 0
242 maxchangelen = 0
230 for f in relpath(repo, (file,) + files):
243 for f in relpath(repo, (file,) + files):
231 lines = repo.file(f).annotate(mmap[f])
244 lines = repo.file(f).annotate(mmap[f])
232 pieces = []
245 pieces = []
233
246
234 for o, f in opmap:
247 for o, f in opmap:
235 if ops[o]:
248 if ops[o]:
236 l = [ f(n) for n,t in lines ]
249 l = [ f(n) for n,t in lines ]
237 m = max(map(len, l))
250 m = max(map(len, l))
238 pieces.append([ "%*s" % (m, x) for x in l])
251 pieces.append([ "%*s" % (m, x) for x in l])
239
252
240 for p,l in zip(zip(*pieces), lines):
253 for p,l in zip(zip(*pieces), lines):
241 u.write(" ".join(p) + ": " + l[1])
254 u.write(" ".join(p) + ": " + l[1])
242
255
243 def cat(ui, repo, file, rev = []):
256 def cat(ui, repo, file, rev = []):
244 """output the latest or given revision of a file"""
257 """output the latest or given revision of a file"""
245 r = repo.file(relpath(repo, [file])[0])
258 r = repo.file(relpath(repo, [file])[0])
246 n = r.tip()
259 n = r.tip()
247 if rev: n = r.lookup(rev)
260 if rev: n = r.lookup(rev)
248 sys.stdout.write(r.read(n))
261 sys.stdout.write(r.read(n))
249
262
250 def commit(ui, repo, *files, **opts):
263 def commit(ui, repo, *files, **opts):
251 """commit the specified files or all outstanding changes"""
264 """commit the specified files or all outstanding changes"""
252 text = opts['text']
265 text = opts['text']
253 if not text and opts['logfile']:
266 if not text and opts['logfile']:
254 try: text = open(opts['logfile']).read()
267 try: text = open(opts['logfile']).read()
255 except IOError: pass
268 except IOError: pass
256
269
257 if opts['addremove']:
270 if opts['addremove']:
258 addremove(ui, repo, *files)
271 addremove(ui, repo, *files)
259 repo.commit(relpath(repo, files), text, opts['user'], opts['date'])
272 repo.commit(relpath(repo, files), text, opts['user'], opts['date'])
260
273
261 def copy(ui, repo, source, dest):
274 def copy(ui, repo, source, dest):
262 """mark a file as copied or renamed for the next commit"""
275 """mark a file as copied or renamed for the next commit"""
263 return repo.copy(*relpath(repo, (source, dest)))
276 return repo.copy(*relpath(repo, (source, dest)))
264
277
265 def debugaddchangegroup(ui, repo):
278 def debugaddchangegroup(ui, repo):
266 data = sys.stdin.read()
279 data = sys.stdin.read()
267 repo.addchangegroup(data)
280 repo.addchangegroup(data)
268
281
269 def debugchangegroup(ui, repo, roots):
282 def debugchangegroup(ui, repo, roots):
270 newer = repo.newer(map(repo.lookup, roots))
283 newer = repo.newer(map(repo.lookup, roots))
271 for chunk in repo.changegroup(newer):
284 for chunk in repo.changegroup(newer):
272 sys.stdout.write(chunk)
285 sys.stdout.write(chunk)
273
286
274 def debugindex(ui, file):
287 def debugindex(ui, file):
275 r = hg.revlog(open, file, "")
288 r = hg.revlog(open, file, "")
276 print " rev offset length base linkrev"+\
289 print " rev offset length base linkrev"+\
277 " p1 p2 nodeid"
290 " p1 p2 nodeid"
278 for i in range(r.count()):
291 for i in range(r.count()):
279 e = r.index[i]
292 e = r.index[i]
280 print "% 6d % 9d % 7d % 6d % 7d %s.. %s.. %s.." % (
293 print "% 6d % 9d % 7d % 6d % 7d %s.. %s.. %s.." % (
281 i, e[0], e[1], e[2], e[3],
294 i, e[0], e[1], e[2], e[3],
282 hg.hex(e[4][:5]), hg.hex(e[5][:5]), hg.hex(e[6][:5]))
295 hg.hex(e[4][:5]), hg.hex(e[5][:5]), hg.hex(e[6][:5]))
283
296
284 def debugindexdot(ui, file):
297 def debugindexdot(ui, file):
285 r = hg.revlog(open, file, "")
298 r = hg.revlog(open, file, "")
286 print "digraph G {"
299 print "digraph G {"
287 for i in range(r.count()):
300 for i in range(r.count()):
288 e = r.index[i]
301 e = r.index[i]
289 print "\t%d -> %d" % (r.rev(e[4]), i)
302 print "\t%d -> %d" % (r.rev(e[4]), i)
290 if e[5] != hg.nullid:
303 if e[5] != hg.nullid:
291 print "\t%d -> %d" % (r.rev(e[5]), i)
304 print "\t%d -> %d" % (r.rev(e[5]), i)
292 print "}"
305 print "}"
293
306
294 def diff(ui, repo, *files, **opts):
307 def diff(ui, repo, *files, **opts):
295 """diff working directory (or selected files)"""
308 """diff working directory (or selected files)"""
296 revs = []
309 revs = []
297 if opts['rev']:
310 if opts['rev']:
298 revs = map(lambda x: repo.lookup(x), opts['rev'])
311 revs = map(lambda x: repo.lookup(x), opts['rev'])
299
312
300 if len(revs) > 2:
313 if len(revs) > 2:
301 self.ui.warn("too many revisions to diff\n")
314 self.ui.warn("too many revisions to diff\n")
302 sys.exit(1)
315 sys.exit(1)
303
316
304 if files:
317 if files:
305 files = relpath(repo, files)
318 files = relpath(repo, files)
306 else:
319 else:
307 files = relpath(repo, [""])
320 files = relpath(repo, [""])
308
321
309 dodiff(ui, repo, os.getcwd(), files, *revs)
322 dodiff(ui, repo, os.getcwd(), files, *revs)
310
323
311 def export(ui, repo, changeset):
324 def export(ui, repo, changeset):
312 """dump the changeset header and diffs for a revision"""
325 """dump the changeset header and diffs for a revision"""
313 node = repo.lookup(changeset)
326 node = repo.lookup(changeset)
314 prev, other = repo.changelog.parents(node)
327 prev, other = repo.changelog.parents(node)
315 change = repo.changelog.read(node)
328 change = repo.changelog.read(node)
316 print "# HG changeset patch"
329 print "# HG changeset patch"
317 print "# User %s" % change[1]
330 print "# User %s" % change[1]
318 print "# Node ID %s" % hg.hex(node)
331 print "# Node ID %s" % hg.hex(node)
319 print "# Parent %s" % hg.hex(prev)
332 print "# Parent %s" % hg.hex(prev)
320 print
333 print
321 if other != hg.nullid:
334 if other != hg.nullid:
322 print "# Parent %s" % hg.hex(other)
335 print "# Parent %s" % hg.hex(other)
323 print change[4].rstrip()
336 print change[4].rstrip()
324 print
337 print
325
338
326 dodiff(ui, repo, "", None, prev, node)
339 dodiff(ui, repo, "", None, prev, node)
327
340
328 def forget(ui, repo, file, *files):
341 def forget(ui, repo, file, *files):
329 """don't add the specified files on the next commit"""
342 """don't add the specified files on the next commit"""
330 repo.forget(relpath(repo, (file,) + files))
343 repo.forget(relpath(repo, (file,) + files))
331
344
332 def heads(ui, repo):
345 def heads(ui, repo):
333 """show current repository heads"""
346 """show current repository heads"""
334 for n in repo.changelog.heads():
347 for n in repo.changelog.heads():
335 show_changeset(ui, repo, changenode=n)
348 show_changeset(ui, repo, changenode=n)
336
349
337 def history(ui, repo):
350 def history(ui, repo):
338 """show the changelog history"""
351 """show the changelog history"""
339 for i in range(repo.changelog.count() - 1, -1, -1):
352 for i in range(repo.changelog.count() - 1, -1, -1):
340 show_changeset(ui, repo, rev=i)
353 show_changeset(ui, repo, rev=i)
341
354
342 def identify(ui, repo):
355 def identify(ui, repo):
343 """print information about the working copy"""
356 """print information about the working copy"""
344 parents = [p for p in repo.dirstate.parents() if p != hg.nullid]
357 parents = [p for p in repo.dirstate.parents() if p != hg.nullid]
345 if not parents:
358 if not parents:
346 ui.write("unknown\n")
359 ui.write("unknown\n")
347 return
360 return
348
361
349 hexfunc = ui.verbose and hg.hex or hg.short
362 hexfunc = ui.verbose and hg.hex or hg.short
350 (c, a, d, u) = repo.diffdir(repo.root)
363 (c, a, d, u) = repo.diffdir(repo.root)
351 output = ["%s%s" % ('+'.join([hexfunc(parent) for parent in parents]),
364 output = ["%s%s" % ('+'.join([hexfunc(parent) for parent in parents]),
352 (c or a or d) and "+" or "")]
365 (c or a or d) and "+" or "")]
353
366
354 if not ui.quiet:
367 if not ui.quiet:
355 # multiple tags for a single parent separated by '/'
368 # multiple tags for a single parent separated by '/'
356 parenttags = ['/'.join(tags)
369 parenttags = ['/'.join(tags)
357 for tags in map(repo.nodetags, parents) if tags]
370 for tags in map(repo.nodetags, parents) if tags]
358 # tags for multiple parents separated by ' + '
371 # tags for multiple parents separated by ' + '
359 output.append(' + '.join(parenttags))
372 output.append(' + '.join(parenttags))
360
373
361 ui.write("%s\n" % ' '.join(output))
374 ui.write("%s\n" % ' '.join(output))
362
375
363 def init(ui, source=None, **opts):
376 def init(ui, source=None, **opts):
364 """create a new repository or copy an existing one"""
377 """create a new repository or copy an existing one"""
365
378
366 if source:
379 if source:
367 paths = {}
380 paths = {}
368 for name, path in ui.configitems("paths"):
381 for name, path in ui.configitems("paths"):
369 paths[name] = path
382 paths[name] = path
370
383
371 if source in paths: source = paths[source]
384 if source in paths: source = paths[source]
372
385
373 link = 0
386 link = 0
374 if not source.startswith("http://"):
387 if not source.startswith("http://"):
375 d1 = os.stat(os.getcwd()).st_dev
388 d1 = os.stat(os.getcwd()).st_dev
376 d2 = os.stat(source).st_dev
389 d2 = os.stat(source).st_dev
377 if d1 == d2: link = 1
390 if d1 == d2: link = 1
378
391
379 if link:
392 if link:
380 ui.debug("copying by hardlink\n")
393 ui.debug("copying by hardlink\n")
381 os.system("cp -al %s/.hg .hg" % source)
394 os.system("cp -al %s/.hg .hg" % source)
382 try:
395 try:
383 os.remove(".hg/dirstate")
396 os.remove(".hg/dirstate")
384 except: pass
397 except: pass
385
398
386 repo = hg.repository(ui, ".")
399 repo = hg.repository(ui, ".")
387
400
388 else:
401 else:
389 repo = hg.repository(ui, ".", create=1)
402 repo = hg.repository(ui, ".", create=1)
390 other = hg.repository(ui, source)
403 other = hg.repository(ui, source)
391 cg = repo.getchangegroup(other)
404 cg = repo.getchangegroup(other)
392 repo.addchangegroup(cg)
405 repo.addchangegroup(cg)
393
406
394 f = repo.opener("hgrc", "w")
407 f = repo.opener("hgrc", "w")
395 f.write("[paths]\n")
408 f.write("[paths]\n")
396 f.write("default = %s\n" % source)
409 f.write("default = %s\n" % source)
397
410
398 if opts['update']:
411 if opts['update']:
399 update(ui, repo)
412 update(ui, repo)
400 else:
413 else:
401 repo = hg.repository(ui, ".", create=1)
414 repo = hg.repository(ui, ".", create=1)
402
415
403 def log(ui, repo, f):
416 def log(ui, repo, f):
404 """show the revision history of a single file"""
417 """show the revision history of a single file"""
405 f = relpath(repo, [f])[0]
418 f = relpath(repo, [f])[0]
406
419
407 r = repo.file(f)
420 r = repo.file(f)
408 for i in range(r.count() - 1, -1, -1):
421 for i in range(r.count() - 1, -1, -1):
409 show_changeset(ui, repo, filelog=r, rev=i)
422 show_changeset(ui, repo, filelog=r, rev=i)
410
423
411 def manifest(ui, repo, rev = []):
424 def manifest(ui, repo, rev = []):
412 """output the latest or given revision of the project manifest"""
425 """output the latest or given revision of the project manifest"""
413 n = repo.manifest.tip()
426 n = repo.manifest.tip()
414 if rev:
427 if rev:
415 n = repo.manifest.lookup(rev)
428 n = repo.manifest.lookup(rev)
416 m = repo.manifest.read(n)
429 m = repo.manifest.read(n)
417 mf = repo.manifest.readflags(n)
430 mf = repo.manifest.readflags(n)
418 files = m.keys()
431 files = m.keys()
419 files.sort()
432 files.sort()
420
433
421 for f in files:
434 for f in files:
422 ui.write("%40s %3s %s\n" % (hg.hex(m[f]), mf[f] and "755" or "644", f))
435 ui.write("%40s %3s %s\n" % (hg.hex(m[f]), mf[f] and "755" or "644", f))
423
436
424 def parents(ui, repo, node = None):
437 def parents(ui, repo, node = None):
425 '''show the parents of the current working dir'''
438 '''show the parents of the current working dir'''
426 if node:
439 if node:
427 p = repo.changelog.parents(repo.lookup(hg.bin(node)))
440 p = repo.changelog.parents(repo.lookup(hg.bin(node)))
428 else:
441 else:
429 p = repo.dirstate.parents()
442 p = repo.dirstate.parents()
430
443
431 for n in p:
444 for n in p:
432 if n != hg.nullid:
445 if n != hg.nullid:
433 show_changeset(ui, repo, changenode=n)
446 show_changeset(ui, repo, changenode=n)
434
447
435 def patch(ui, repo, patch1, *patches, **opts):
448 def patch(ui, repo, patch1, *patches, **opts):
436 """import an ordered set of patches"""
449 """import an ordered set of patches"""
437 try:
450 try:
438 import psyco
451 import psyco
439 psyco.full()
452 psyco.full()
440 except:
453 except:
441 pass
454 pass
442
455
443 patches = (patch1,) + patches
456 patches = (patch1,) + patches
444
457
445 d = opts["base"]
458 d = opts["base"]
446 strip = opts["strip"]
459 strip = opts["strip"]
447 quiet = opts["quiet"] and "> /dev/null" or ""
460 quiet = opts["quiet"] and "> /dev/null" or ""
448
461
449 for patch in patches:
462 for patch in patches:
450 ui.status("applying %s\n" % patch)
463 ui.status("applying %s\n" % patch)
451 pf = os.path.join(d, patch)
464 pf = os.path.join(d, patch)
452
465
453 text = ""
466 text = ""
454 for l in file(pf):
467 for l in file(pf):
455 if l[:4] == "--- ": break
468 if l[:4] == "--- ": break
456 text += l
469 text += l
457
470
458 # make sure text isn't empty
471 # make sure text isn't empty
459 if not text: text = "imported patch %s\n" % patch
472 if not text: text = "imported patch %s\n" % patch
460
473
461 f = os.popen("patch -p%d < %s" % (strip, pf))
474 f = os.popen("patch -p%d < %s" % (strip, pf))
462 files = []
475 files = []
463 for l in f.read().splitlines():
476 for l in f.read().splitlines():
464 l.rstrip('\r\n');
477 l.rstrip('\r\n');
465 if not quiet:
478 if not quiet:
466 print l
479 print l
467 if l[:14] == 'patching file ':
480 if l[:14] == 'patching file ':
468 files.append(l[14:])
481 files.append(l[14:])
469 f.close()
482 f.close()
470
483
471 if len(files) > 0:
484 if len(files) > 0:
472 addremove(ui, repo, *files)
485 addremove(ui, repo, *files)
473 repo.commit(files, text)
486 repo.commit(files, text)
474
487
475 def pull(ui, repo, source="default"):
488 def pull(ui, repo, source="default"):
476 """pull changes from the specified source"""
489 """pull changes from the specified source"""
477 paths = {}
490 paths = {}
478 for name, path in ui.configitems("paths"):
491 for name, path in ui.configitems("paths"):
479 paths[name] = path
492 paths[name] = path
480
493
481 if source in paths: source = paths[source]
494 if source in paths: source = paths[source]
482
495
483 other = hg.repository(ui, source)
496 other = hg.repository(ui, source)
484 cg = repo.getchangegroup(other)
497 cg = repo.getchangegroup(other)
485 repo.addchangegroup(cg)
498 repo.addchangegroup(cg)
486
499
487 def push(ui, repo, dest="default-push"):
500 def push(ui, repo, dest="default-push"):
488 """push changes to the specified destination"""
501 """push changes to the specified destination"""
489 paths = {}
502 paths = {}
490 for name, path in ui.configitems("paths"):
503 for name, path in ui.configitems("paths"):
491 paths[name] = path
504 paths[name] = path
492
505
493 if dest in paths: dest = paths[dest]
506 if dest in paths: dest = paths[dest]
494
507
495 if not dest.startswith("ssh://"):
508 if not dest.startswith("ssh://"):
496 ui.warn("abort: can only push to ssh:// destinations currently\n")
509 ui.warn("abort: can only push to ssh:// destinations currently\n")
497 return 1
510 return 1
498
511
499 m = re.match(r'ssh://(([^@]+)@)?([^:/]+)(:(\d+))?(/(.*))?', dest)
512 m = re.match(r'ssh://(([^@]+)@)?([^:/]+)(:(\d+))?(/(.*))?', dest)
500 if not m:
513 if not m:
501 ui.warn("abort: couldn't parse destination %s\n" % dest)
514 ui.warn("abort: couldn't parse destination %s\n" % dest)
502 return 1
515 return 1
503
516
504 user, host, port, path = map(m.group, (2, 3, 5, 7))
517 user, host, port, path = map(m.group, (2, 3, 5, 7))
505 host = user and ("%s@%s" % (user, host)) or host
518 host = user and ("%s@%s" % (user, host)) or host
506 port = port and (" -p %s") % port or ""
519 port = port and (" -p %s") % port or ""
507 path = path or ""
520 path = path or ""
508
521
509 sport = random.randrange(30000, 60000)
522 sport = random.randrange(30000, 60000)
510 cmd = "ssh %s%s -R %d:localhost:%d 'cd %s; hg pull http://localhost:%d/'"
523 cmd = "ssh %s%s -R %d:localhost:%d 'cd %s; hg pull http://localhost:%d/'"
511 cmd = cmd % (host, port, sport+1, sport, path, sport+1)
524 cmd = cmd % (host, port, sport+1, sport, path, sport+1)
512
525
513 child = os.fork()
526 child = os.fork()
514 if not child:
527 if not child:
515 sys.stdout = file("/dev/null", "w")
528 sys.stdout = file("/dev/null", "w")
516 sys.stderr = sys.stdout
529 sys.stderr = sys.stdout
517 hgweb.server(repo.root, "pull", "", "localhost", sport)
530 hgweb.server(repo.root, "pull", "", "localhost", sport)
518 else:
531 else:
519 r = os.system(cmd)
532 r = os.system(cmd)
520 os.kill(child, signal.SIGTERM)
533 os.kill(child, signal.SIGTERM)
521 return r
534 return r
522
535
523 def rawcommit(ui, repo, flist, **rc):
536 def rawcommit(ui, repo, flist, **rc):
524 "raw commit interface"
537 "raw commit interface"
525
538
526 text = rc['text']
539 text = rc['text']
527 if not text and rc['logfile']:
540 if not text and rc['logfile']:
528 try: text = open(rc['logfile']).read()
541 try: text = open(rc['logfile']).read()
529 except IOError: pass
542 except IOError: pass
530 if not text and not rc['logfile']:
543 if not text and not rc['logfile']:
531 print "missing commit text"
544 print "missing commit text"
532 return 1
545 return 1
533
546
534 files = relpath(repo, flist)
547 files = relpath(repo, flist)
535 if rc['files']:
548 if rc['files']:
536 files += open(rc['files']).read().splitlines()
549 files += open(rc['files']).read().splitlines()
537
550
538 repo.rawcommit(files, text, rc['user'], rc['date'], *rc['parent'])
551 repo.rawcommit(files, text, rc['user'], rc['date'], *rc['parent'])
539
552
540 def recover(ui, repo):
553 def recover(ui, repo):
541 """roll back an interrupted transaction"""
554 """roll back an interrupted transaction"""
542 repo.recover()
555 repo.recover()
543
556
544 def remove(ui, repo, file, *files):
557 def remove(ui, repo, file, *files):
545 """remove the specified files on the next commit"""
558 """remove the specified files on the next commit"""
546 repo.remove(relpath(repo, (file,) + files))
559 repo.remove(relpath(repo, (file,) + files))
547
560
548 def serve(ui, repo, **opts):
561 def serve(ui, repo, **opts):
549 """export the repository via HTTP"""
562 """export the repository via HTTP"""
550 hgweb.server(repo.root, opts["name"], opts["templates"],
563 hgweb.server(repo.root, opts["name"], opts["templates"],
551 opts["address"], opts["port"])
564 opts["address"], opts["port"])
552
565
553 def status(ui, repo):
566 def status(ui, repo):
554 '''show changed files in the working directory
567 '''show changed files in the working directory
555
568
556 C = changed
569 C = changed
557 A = added
570 A = added
558 R = removed
571 R = removed
559 ? = not tracked'''
572 ? = not tracked'''
560
573
561 (c, a, d, u) = repo.diffdir(os.getcwd())
574 (c, a, d, u) = repo.diffdir(os.getcwd())
562 (c, a, d, u) = map(lambda x: relfilter(repo, x), (c, a, d, u))
575 (c, a, d, u) = map(lambda x: relfilter(repo, x), (c, a, d, u))
563
576
564 for f in c: print "C", f
577 for f in c: print "C", f
565 for f in a: print "A", f
578 for f in a: print "A", f
566 for f in d: print "R", f
579 for f in d: print "R", f
567 for f in u: print "?", f
580 for f in u: print "?", f
568
581
569 def tags(ui, repo):
582 def tags(ui, repo):
570 """list repository tags"""
583 """list repository tags"""
571
584
572 l = repo.tagslist()
585 l = repo.tagslist()
573 l.reverse()
586 l.reverse()
574 for t,n in l:
587 for t,n in l:
575 try:
588 try:
576 r = repo.changelog.rev(n)
589 r = repo.changelog.rev(n)
577 except KeyError:
590 except KeyError:
578 r = "?"
591 r = "?"
579 print "%-30s %5d:%s" % (t, repo.changelog.rev(n), hg.hex(n))
592 print "%-30s %5d:%s" % (t, repo.changelog.rev(n), hg.hex(n))
580
593
581 def tip(ui, repo):
594 def tip(ui, repo):
582 """show the tip revision"""
595 """show the tip revision"""
583 n = repo.changelog.tip()
596 n = repo.changelog.tip()
584 show_changeset(ui, repo, changenode=n)
597 show_changeset(ui, repo, changenode=n)
585
598
586 def undo(ui, repo):
599 def undo(ui, repo):
587 """undo the last transaction"""
600 """undo the last transaction"""
588 repo.undo()
601 repo.undo()
589
602
590 def update(ui, repo, node=None, merge=False, clean=False):
603 def update(ui, repo, node=None, merge=False, clean=False):
591 '''update or merge working directory
604 '''update or merge working directory
592
605
593 If there are no outstanding changes in the working directory and
606 If there are no outstanding changes in the working directory and
594 there is a linear relationship between the current version and the
607 there is a linear relationship between the current version and the
595 requested version, the result is the requested version.
608 requested version, the result is the requested version.
596
609
597 Otherwise the result is a merge between the contents of the
610 Otherwise the result is a merge between the contents of the
598 current working directory and the requested version. Files that
611 current working directory and the requested version. Files that
599 changed between either parent are marked as changed for the next
612 changed between either parent are marked as changed for the next
600 commit and a commit must be performed before any further updates
613 commit and a commit must be performed before any further updates
601 are allowed.
614 are allowed.
602 '''
615 '''
603 node = node and repo.lookup(node) or repo.changelog.tip()
616 node = node and repo.lookup(node) or repo.changelog.tip()
604 return repo.update(node, allow=merge, force=clean)
617 return repo.update(node, allow=merge, force=clean)
605
618
606 def verify(ui, repo):
619 def verify(ui, repo):
607 """verify the integrity of the repository"""
620 """verify the integrity of the repository"""
608 return repo.verify()
621 return repo.verify()
609
622
610 # Command options and aliases are listed here, alphabetically
623 # Command options and aliases are listed here, alphabetically
611
624
612 table = {
625 table = {
613 "add": (add, [], "hg add [files]"),
626 "add": (add, [], "hg add [files]"),
614 "addremove": (addremove, [], "hg addremove [files]"),
627 "addremove": (addremove, [], "hg addremove [files]"),
615 "ann|annotate": (annotate,
628 "ann|annotate": (annotate,
616 [('r', 'revision', '', 'revision'),
629 [('r', 'revision', '', 'revision'),
617 ('u', 'user', None, 'show user'),
630 ('u', 'user', None, 'show user'),
618 ('n', 'number', None, 'show revision number'),
631 ('n', 'number', None, 'show revision number'),
619 ('c', 'changeset', None, 'show changeset')],
632 ('c', 'changeset', None, 'show changeset')],
620 'hg annotate [-u] [-c] [-n] [-r id] [files]'),
633 'hg annotate [-u] [-c] [-n] [-r id] [files]'),
621 "cat|dump": (cat, [], 'hg cat <file> [rev]'),
634 "cat|dump": (cat, [], 'hg cat <file> [rev]'),
622 "commit|ci": (commit,
635 "commit|ci": (commit,
623 [('t', 'text', "", 'commit text'),
636 [('t', 'text', "", 'commit text'),
624 ('A', 'addremove', None, 'run add/remove during commit'),
637 ('A', 'addremove', None, 'run add/remove during commit'),
625 ('l', 'logfile', "", 'commit text file'),
638 ('l', 'logfile', "", 'commit text file'),
626 ('d', 'date', "", 'data'),
639 ('d', 'date', "", 'data'),
627 ('u', 'user', "", 'user')],
640 ('u', 'user', "", 'user')],
628 'hg commit [files]'),
641 'hg commit [files]'),
629 "copy": (copy, [], 'hg copy <source> <dest>'),
642 "copy": (copy, [], 'hg copy <source> <dest>'),
630 "debugaddchangegroup": (debugaddchangegroup, [], 'debugaddchangegroup'),
643 "debugaddchangegroup": (debugaddchangegroup, [], 'debugaddchangegroup'),
631 "debugchangegroup": (debugchangegroup, [], 'debugchangegroup [roots]'),
644 "debugchangegroup": (debugchangegroup, [], 'debugchangegroup [roots]'),
632 "debugindex": (debugindex, [], 'debugindex <file>'),
645 "debugindex": (debugindex, [], 'debugindex <file>'),
633 "debugindexdot": (debugindexdot, [], 'debugindexdot <file>'),
646 "debugindexdot": (debugindexdot, [], 'debugindexdot <file>'),
634 "diff": (diff, [('r', 'rev', [], 'revision')],
647 "diff": (diff, [('r', 'rev', [], 'revision')],
635 'hg diff [-r A] [-r B] [files]'),
648 'hg diff [-r A] [-r B] [files]'),
636 "export": (export, [], "hg export <changeset>"),
649 "export": (export, [], "hg export <changeset>"),
637 "forget": (forget, [], "hg forget [files]"),
650 "forget": (forget, [], "hg forget [files]"),
638 "heads": (heads, [], 'hg heads'),
651 "heads": (heads, [], 'hg heads'),
639 "history": (history, [], 'hg history'),
652 "history": (history, [], 'hg history'),
640 "help": (help, [], 'hg help [command]'),
653 "help": (help, [], 'hg help [command]'),
641 "identify|id": (identify, [], 'hg identify'),
654 "identify|id": (identify, [], 'hg identify'),
642 "init": (init, [('u', 'update', None, 'update after init')],
655 "init": (init, [('u', 'update', None, 'update after init')],
643 'hg init [options] [url]'),
656 'hg init [options] [url]'),
644 "log": (log, [], 'hg log <file>'),
657 "log": (log, [], 'hg log <file>'),
645 "manifest|dumpmanifest": (manifest, [], 'hg manifest [rev]'),
658 "manifest|dumpmanifest": (manifest, [], 'hg manifest [rev]'),
646 "parents": (parents, [], 'hg parents [node]'),
659 "parents": (parents, [], 'hg parents [node]'),
647 "patch|import": (patch,
660 "patch|import": (patch,
648 [('p', 'strip', 1, 'path strip'),
661 [('p', 'strip', 1, 'path strip'),
649 ('b', 'base', "", 'base path'),
662 ('b', 'base', "", 'base path'),
650 ('q', 'quiet', "", 'silence diff')],
663 ('q', 'quiet', "", 'silence diff')],
651 "hg import [options] patches"),
664 "hg import [options] patches"),
652 "pull|merge": (pull, [], 'hg pull [source]'),
665 "pull|merge": (pull, [], 'hg pull [source]'),
653 "push": (push, [], 'hg push <destination>'),
666 "push": (push, [], 'hg push <destination>'),
654 "rawcommit": (rawcommit,
667 "rawcommit": (rawcommit,
655 [('p', 'parent', [], 'parent'),
668 [('p', 'parent', [], 'parent'),
656 ('d', 'date', "", 'data'),
669 ('d', 'date', "", 'data'),
657 ('u', 'user', "", 'user'),
670 ('u', 'user', "", 'user'),
658 ('F', 'files', "", 'file list'),
671 ('F', 'files', "", 'file list'),
659 ('t', 'text', "", 'commit text'),
672 ('t', 'text', "", 'commit text'),
660 ('l', 'logfile', "", 'commit text file')],
673 ('l', 'logfile', "", 'commit text file')],
661 'hg rawcommit [options] [files]'),
674 'hg rawcommit [options] [files]'),
662 "recover": (recover, [], "hg recover"),
675 "recover": (recover, [], "hg recover"),
663 "remove": (remove, [], "hg remove [files]"),
676 "remove": (remove, [], "hg remove [files]"),
664 "serve": (serve, [('p', 'port', 8000, 'listen port'),
677 "serve": (serve, [('p', 'port', 8000, 'listen port'),
665 ('a', 'address', '', 'interface address'),
678 ('a', 'address', '', 'interface address'),
666 ('n', 'name', os.getcwd(), 'repository name'),
679 ('n', 'name', os.getcwd(), 'repository name'),
667 ('t', 'templates', "", 'template map')],
680 ('t', 'templates', "", 'template map')],
668 "hg serve [options]"),
681 "hg serve [options]"),
669 "status": (status, [], 'hg status'),
682 "status": (status, [], 'hg status'),
670 "tags": (tags, [], 'hg tags'),
683 "tags": (tags, [], 'hg tags'),
671 "tip": (tip, [], 'hg tip'),
684 "tip": (tip, [], 'hg tip'),
672 "undo": (undo, [], 'hg undo'),
685 "undo": (undo, [], 'hg undo'),
673 "update|up|checkout|co|resolve": (update,
686 "update|up|checkout|co|resolve": (update,
674 [('m', 'merge', None,
687 [('m', 'merge', None,
675 'allow merging of conflicts'),
688 'allow merging of conflicts'),
676 ('C', 'clean', None,
689 ('C', 'clean', None,
677 'overwrite locally modified files')],
690 'overwrite locally modified files')],
678 'hg update [options] [node]'),
691 'hg update [options] [node]'),
679 "verify": (verify, [], 'hg verify'),
692 "verify": (verify, [], 'hg verify'),
680 }
693 }
681
694
682 norepo = "init branch help debugindex debugindexdot"
695 norepo = "init version help debugindex debugindexdot"
683
696
684 def find(cmd):
697 def find(cmd):
685 i = None
698 i = None
686 for e in table.keys():
699 for e in table.keys():
687 if re.match("(%s)$" % e, cmd):
700 if re.match("(%s)$" % e, cmd):
688 return table[e]
701 return table[e]
689
702
690 raise UnknownCommand(cmd)
703 raise UnknownCommand(cmd)
691
704
692 class SignalInterrupt(Exception): pass
705 class SignalInterrupt(Exception): pass
693
706
694 def catchterm(*args):
707 def catchterm(*args):
695 raise SignalInterrupt
708 raise SignalInterrupt
696
709
697 def run():
710 def run():
698 sys.exit(dispatch(sys.argv[1:]))
711 sys.exit(dispatch(sys.argv[1:]))
699
712
700 def dispatch(args):
713 def dispatch(args):
701 options = {}
714 options = {}
702 opts = [('v', 'verbose', None, 'verbose'),
715 opts = [('v', 'verbose', None, 'verbose'),
703 ('d', 'debug', None, 'debug'),
716 ('d', 'debug', None, 'debug'),
704 ('q', 'quiet', None, 'quiet'),
717 ('q', 'quiet', None, 'quiet'),
705 ('p', 'profile', None, 'profile'),
718 ('p', 'profile', None, 'profile'),
706 ('y', 'noninteractive', None, 'run non-interactively'),
719 ('y', 'noninteractive', None, 'run non-interactively'),
720 ('', 'version', None, 'output version information and exit'),
707 ]
721 ]
708
722
709 args = fancyopts.fancyopts(args, opts, options,
723 args = fancyopts.fancyopts(args, opts, options,
710 'hg [options] <command> [options] [files]')
724 'hg [options] <command> [options] [files]')
711
725
712 if not args:
726 if not args:
713 cmd = "help"
727 cmd = "help"
714 else:
728 else:
715 cmd, args = args[0], args[1:]
729 cmd, args = args[0], args[1:]
716
730
717 u = ui.ui(options["verbose"], options["debug"], options["quiet"],
731 u = ui.ui(options["verbose"], options["debug"], options["quiet"],
718 not options["noninteractive"])
732 not options["noninteractive"])
719
733
734 if options["version"]:
735 show_version(u)
736 sys.exit(0)
737
720 try:
738 try:
721 i = find(cmd)
739 i = find(cmd)
722 except UnknownCommand:
740 except UnknownCommand:
723 u.warn("hg: unknown command '%s'\n" % cmd)
741 u.warn("hg: unknown command '%s'\n" % cmd)
724 help(u)
742 help(u)
725 sys.exit(1)
743 sys.exit(1)
726
744
727 signal.signal(signal.SIGTERM, catchterm)
745 signal.signal(signal.SIGTERM, catchterm)
728
746
729 cmdoptions = {}
747 cmdoptions = {}
730 try:
748 try:
731 args = fancyopts.fancyopts(args, i[1], cmdoptions, i[2])
749 args = fancyopts.fancyopts(args, i[1], cmdoptions, i[2])
732 except fancyopts.getopt.GetoptError, inst:
750 except fancyopts.getopt.GetoptError, inst:
733 u.warn("hg %s: %s\n" % (cmd, inst))
751 u.warn("hg %s: %s\n" % (cmd, inst))
734 help(u, cmd)
752 help(u, cmd)
735 sys.exit(-1)
753 sys.exit(-1)
736
754
737 if cmd not in norepo.split():
755 if cmd not in norepo.split():
738 repo = hg.repository(ui = u)
756 repo = hg.repository(ui = u)
739 d = lambda: i[0](u, repo, *args, **cmdoptions)
757 d = lambda: i[0](u, repo, *args, **cmdoptions)
740 else:
758 else:
741 d = lambda: i[0](u, *args, **cmdoptions)
759 d = lambda: i[0](u, *args, **cmdoptions)
742
760
743 try:
761 try:
744 if options['profile']:
762 if options['profile']:
745 import hotshot, hotshot.stats
763 import hotshot, hotshot.stats
746 prof = hotshot.Profile("hg.prof")
764 prof = hotshot.Profile("hg.prof")
747 r = prof.runcall(d)
765 r = prof.runcall(d)
748 prof.close()
766 prof.close()
749 stats = hotshot.stats.load("hg.prof")
767 stats = hotshot.stats.load("hg.prof")
750 stats.strip_dirs()
768 stats.strip_dirs()
751 stats.sort_stats('time', 'calls')
769 stats.sort_stats('time', 'calls')
752 stats.print_stats(40)
770 stats.print_stats(40)
753 return r
771 return r
754 else:
772 else:
755 return d()
773 return d()
756 except SignalInterrupt:
774 except SignalInterrupt:
757 u.warn("killed!\n")
775 u.warn("killed!\n")
758 except KeyboardInterrupt:
776 except KeyboardInterrupt:
759 u.warn("interrupted!\n")
777 u.warn("interrupted!\n")
760 except IOError, inst:
778 except IOError, inst:
761 if hasattr(inst, "code"):
779 if hasattr(inst, "code"):
762 u.warn("abort: %s\n" % inst)
780 u.warn("abort: %s\n" % inst)
763 elif hasattr(inst, "reason"):
781 elif hasattr(inst, "reason"):
764 u.warn("abort: error %d: %s\n" % (inst.reason[0], inst.reason[1]))
782 u.warn("abort: error %d: %s\n" % (inst.reason[0], inst.reason[1]))
765 elif hasattr(inst, "args") and inst[0] == errno.EPIPE:
783 elif hasattr(inst, "args") and inst[0] == errno.EPIPE:
766 u.warn("broken pipe\n")
784 u.warn("broken pipe\n")
767 else:
785 else:
768 raise
786 raise
769 except TypeError, inst:
787 except TypeError, inst:
770 # was this an argument error?
788 # was this an argument error?
771 tb = traceback.extract_tb(sys.exc_info()[2])
789 tb = traceback.extract_tb(sys.exc_info()[2])
772 if len(tb) > 2: # no
790 if len(tb) > 2: # no
773 raise
791 raise
774 u.debug(inst, "\n")
792 u.debug(inst, "\n")
775 u.warn("%s: invalid arguments\n" % i[0].__name__)
793 u.warn("%s: invalid arguments\n" % i[0].__name__)
776 help(u, cmd)
794 help(u, cmd)
777 sys.exit(-1)
795 sys.exit(-1)
778
796
@@ -1,32 +1,38
1 #!/usr/bin/env python
1 #!/usr/bin/env python
2
2
3 # This is the mercurial setup script.
3 # This is the mercurial setup script.
4 #
4 #
5 # './setup.py install', or
5 # './setup.py install', or
6 # './setup.py --help' for more options
6 # './setup.py --help' for more options
7
7
8 import glob
8 import glob
9 from distutils.core import setup, Extension
9 from distutils.core import setup, Extension
10 from distutils.command.install_data import install_data
10 from distutils.command.install_data import install_data
11
11
12 import mercurial.version
13
12 class install_package_data(install_data):
14 class install_package_data(install_data):
13 def finalize_options(self):
15 def finalize_options(self):
14 self.set_undefined_options('install',
16 self.set_undefined_options('install',
15 ('install_lib', 'install_dir'))
17 ('install_lib', 'install_dir'))
16 install_data.finalize_options(self)
18 install_data.finalize_options(self)
17
19
18 setup(name='mercurial',
20 try:
19 version='0.5b',
21 mercurial.version.remember_version()
20 author='Matt Mackall',
22 setup(name='mercurial',
21 author_email='mpm@selenic.com',
23 version=mercurial.version.get_version(),
22 url='http://selenic.com/mercurial',
24 author='Matt Mackall',
23 description='scalable distributed SCM',
25 author_email='mpm@selenic.com',
24 license='GNU GPL',
26 url='http://selenic.com/mercurial',
25 packages=['mercurial'],
27 description='scalable distributed SCM',
26 ext_modules=[Extension('mercurial.mpatch', ['mercurial/mpatch.c'])],
28 license='GNU GPL',
27 data_files=[('mercurial/templates',
29 packages=['mercurial'],
28 ['templates/map'] +
30 ext_modules=[Extension('mercurial.mpatch', ['mercurial/mpatch.c'])],
29 glob.glob('templates/map-*') +
31 data_files=[('mercurial/templates',
30 glob.glob('templates/*.tmpl'))],
32 ['templates/map'] +
31 cmdclass = { 'install_data' : install_package_data },
33 glob.glob('templates/map-*') +
32 scripts=['hg', 'hgmerge'])
34 glob.glob('templates/*.tmpl'))],
35 cmdclass = { 'install_data' : install_package_data },
36 scripts=['hg', 'hgmerge'])
37 finally:
38 mercurial.version.forget_version()
@@ -1,11 +1,11
1 #!/bin/bash
1 #!/bin/bash
2
2
3 set -x
3 set -x
4
4
5 hg help
5 hg -q help
6 hg add -h
6 hg add -h
7 hg help diff
7 hg help diff
8 hg help foo
8 hg help foo
9 hg commands
9 hg -q commands
10
10
11 exit 0 No newline at end of file
11 exit 0
@@ -1,82 +1,82
1 + hg help
1 + hg -q help
2 hg commands:
2 hg commands:
3
3
4 add add the specified files on the next commit
4 add add the specified files on the next commit
5 addremove add all new files, delete all missing files
5 addremove add all new files, delete all missing files
6 annotate show changeset information per file line
6 annotate show changeset information per file line
7 cat output the latest or given revision of a file
7 cat output the latest or given revision of a file
8 commit commit the specified files or all outstanding changes
8 commit commit the specified files or all outstanding changes
9 copy mark a file as copied or renamed for the next commit
9 copy mark a file as copied or renamed for the next commit
10 diff diff working directory (or selected files)
10 diff diff working directory (or selected files)
11 export dump the changeset header and diffs for a revision
11 export dump the changeset header and diffs for a revision
12 forget don't add the specified files on the next commit
12 forget don't add the specified files on the next commit
13 heads show current repository heads
13 heads show current repository heads
14 help show help for a given command or all commands
14 help show help for a given command or all commands
15 history show the changelog history
15 history show the changelog history
16 identify print information about the working copy
16 identify print information about the working copy
17 init create a new repository or copy an existing one
17 init create a new repository or copy an existing one
18 log show the revision history of a single file
18 log show the revision history of a single file
19 manifest output the latest or given revision of the project manifest
19 manifest output the latest or given revision of the project manifest
20 parents show the parents of the current working dir
20 parents show the parents of the current working dir
21 patch import an ordered set of patches
21 patch import an ordered set of patches
22 pull pull changes from the specified source
22 pull pull changes from the specified source
23 push push changes to the specified destination
23 push push changes to the specified destination
24 rawcommit raw commit interface
24 rawcommit raw commit interface
25 recover roll back an interrupted transaction
25 recover roll back an interrupted transaction
26 remove remove the specified files on the next commit
26 remove remove the specified files on the next commit
27 serve export the repository via HTTP
27 serve export the repository via HTTP
28 status show changed files in the working directory
28 status show changed files in the working directory
29 tags list repository tags
29 tags list repository tags
30 tip show the tip revision
30 tip show the tip revision
31 undo undo the last transaction
31 undo undo the last transaction
32 update update or merge working directory
32 update update or merge working directory
33 verify verify the integrity of the repository
33 verify verify the integrity of the repository
34 + hg add -h
34 + hg add -h
35 hg add: option -h not recognized
35 hg add: option -h not recognized
36 hg add [files]
36 hg add [files]
37
37
38 add the specified files on the next commit
38 add the specified files on the next commit
39 + hg help diff
39 + hg help diff
40 hg diff [-r A] [-r B] [files]
40 hg diff [-r A] [-r B] [files]
41
41
42 -r --rev
42 -r --rev
43 revision
43 revision
44
44
45 diff working directory (or selected files)
45 diff working directory (or selected files)
46 + hg help foo
46 + hg help foo
47 hg: unknown command foo
47 hg: unknown command foo
48 + hg commands
48 + hg -q commands
49 hg: unknown command 'commands'
49 hg: unknown command 'commands'
50 hg commands:
50 hg commands:
51
51
52 add add the specified files on the next commit
52 add add the specified files on the next commit
53 addremove add all new files, delete all missing files
53 addremove add all new files, delete all missing files
54 annotate show changeset information per file line
54 annotate show changeset information per file line
55 cat output the latest or given revision of a file
55 cat output the latest or given revision of a file
56 commit commit the specified files or all outstanding changes
56 commit commit the specified files or all outstanding changes
57 copy mark a file as copied or renamed for the next commit
57 copy mark a file as copied or renamed for the next commit
58 diff diff working directory (or selected files)
58 diff diff working directory (or selected files)
59 export dump the changeset header and diffs for a revision
59 export dump the changeset header and diffs for a revision
60 forget don't add the specified files on the next commit
60 forget don't add the specified files on the next commit
61 heads show current repository heads
61 heads show current repository heads
62 help show help for a given command or all commands
62 help show help for a given command or all commands
63 history show the changelog history
63 history show the changelog history
64 identify print information about the working copy
64 identify print information about the working copy
65 init create a new repository or copy an existing one
65 init create a new repository or copy an existing one
66 log show the revision history of a single file
66 log show the revision history of a single file
67 manifest output the latest or given revision of the project manifest
67 manifest output the latest or given revision of the project manifest
68 parents show the parents of the current working dir
68 parents show the parents of the current working dir
69 patch import an ordered set of patches
69 patch import an ordered set of patches
70 pull pull changes from the specified source
70 pull pull changes from the specified source
71 push push changes to the specified destination
71 push push changes to the specified destination
72 rawcommit raw commit interface
72 rawcommit raw commit interface
73 recover roll back an interrupted transaction
73 recover roll back an interrupted transaction
74 remove remove the specified files on the next commit
74 remove remove the specified files on the next commit
75 serve export the repository via HTTP
75 serve export the repository via HTTP
76 status show changed files in the working directory
76 status show changed files in the working directory
77 tags list repository tags
77 tags list repository tags
78 tip show the tip revision
78 tip show the tip revision
79 undo undo the last transaction
79 undo undo the last transaction
80 update update or merge working directory
80 update update or merge working directory
81 verify verify the integrity of the repository
81 verify verify the integrity of the repository
82 + exit 0
82 + exit 0
General Comments 0
You need to be logged in to leave comments. Login now