##// END OF EJS Templates
[PATCH] simplify init...
mpm@selenic.com -
r496:6ce95a04 default
parent child Browse files
Show More
@@ -1,395 +1,381 b''
1 HG(1)
1 HG(1)
2 =====
2 =====
3 Matt Mackall <mpm@selenic.com>
3 Matt Mackall <mpm@selenic.com>
4 v0.6, 24 Jun 2005
4 v0.6, 24 Jun 2005
5
5
6 NAME
6 NAME
7 ----
7 ----
8 hg - Mercurial source code management system
8 hg - Mercurial source code management system
9
9
10 SYNOPSIS
10 SYNOPSIS
11 --------
11 --------
12 'hg' [-v -d -q -y] <command> [command options] [files]
12 'hg' [-v -d -q -y] <command> [command options] [files]
13
13
14 DESCRIPTION
14 DESCRIPTION
15 -----------
15 -----------
16 The hg(1) command provides a command line interface to the Mercurial system.
16 The hg(1) command provides a command line interface to the Mercurial system.
17
17
18 OPTIONS
18 OPTIONS
19 -------
19 -------
20
20
21 --debug, -d::
21 --debug, -d::
22 enable debugging output
22 enable debugging output
23
23
24 --quiet, -q::
24 --quiet, -q::
25 suppress output
25 suppress output
26
26
27 --verbose, -v::
27 --verbose, -v::
28 enable additional output
28 enable additional output
29
29
30 --noninteractive, -y::
30 --noninteractive, -y::
31 do not prompt, assume 'yes' for any required answers
31 do not prompt, assume 'yes' for any required answers
32
32
33 COMMAND ELEMENTS
33 COMMAND ELEMENTS
34 ----------------
34 ----------------
35
35
36 files ...::
36 files ...::
37 indicates one or more filename or relative path filenames
37 indicates one or more filename or relative path filenames
38
38
39 path::
39 path::
40 indicates a path on the local machine
40 indicates a path on the local machine
41
41
42 revision::
42 revision::
43 indicates a changeset which can be specified as a changeset revision
43 indicates a changeset which can be specified as a changeset revision
44 number, a tag, or a unique substring of the changeset hash value
44 number, a tag, or a unique substring of the changeset hash value
45
45
46 repository path::
46 repository path::
47 is either the pathname of a local repository of the URI of a remote
47 is either the pathname of a local repository of the URI of a remote
48 repository. There are two available URI protocols, http:// which is
48 repository. There are two available URI protocols, http:// which is
49 fast and the old-http:// protocol which is much slower but does not
49 fast and the old-http:// protocol which is much slower but does not
50 require a special server on the web host.
50 require a special server on the web host.
51
51
52 COMMANDS
52 COMMANDS
53 --------
53 --------
54
54
55 add [files ...]::
55 add [files ...]::
56 Add the given files to the repository. Note that this just schedules the
56 Add the given files to the repository. Note that this just schedules the
57 files for addition at the next hg commit time.
57 files for addition at the next hg commit time.
58
58
59 addremove::
59 addremove::
60 Add all new files and remove all missing files from the repository. New
60 Add all new files and remove all missing files from the repository. New
61 files are ignored if they match any of the patterns in .hgignore
61 files are ignored if they match any of the patterns in .hgignore
62
62
63 annotate [-r <rev> -u -n -c] [files ...]::
63 annotate [-r <rev> -u -n -c] [files ...]::
64 List the files with each line showing the revision id responsible
64 List the files with each line showing the revision id responsible
65 for that line.
65 for that line.
66
66
67 options:
67 options:
68 -r, --revision <rev> annotate the specified revision
68 -r, --revision <rev> annotate the specified revision
69 -u, --user list the author
69 -u, --user list the author
70 -c, --changeset list the changeset
70 -c, --changeset list the changeset
71 -n, --number list the revision number (default)
71 -n, --number list the revision number (default)
72
72
73 cat <file> [revision]::
73 cat <file> [revision]::
74 Output the given revision or tip of the specified file to stdout.
74 Output the given revision or tip of the specified file to stdout.
75
75
76 clone [-U] <source> [dest]::
76 clone [-U] <source> [dest]::
77 Create a new copy of an existing repository.
77 Create a new copy of an existing repository.
78
78
79 If the specified source is on the same filesystem, the repository
79 If the specified source is on the same filesystem, the repository
80 will be copied via hardlinks. This is the fastest and most
80 will be copied via hardlinks. This is the fastest and most
81 space-efficient mode of operation.
81 space-efficient mode of operation.
82
82
83 If the destination directory is not specified, it defaults to the
83 If the destination directory is not specified, it defaults to the
84 current directory.
84 current directory.
85
85
86 If the destination is specified, but does not exist, it is created.
86 If the destination is specified, but does not exist, it is created.
87
87
88 The source is added to .hg/hgrc in the new copy as the default for
88 The source is added to .hg/hgrc in the new copy as the default for
89 future pulls.
89 future pulls.
90
90
91 options:
91 options:
92 -U, --no-update do not update the new working directory
92 -U, --no-update do not update the new working directory
93
93
94 commit [-A -t -l <file> -t <text> -u <user> -d <datecode>] [files...]::
94 commit [-A -t -l <file> -t <text> -u <user> -d <datecode>] [files...]::
95 Commit all changed files in the working dir to the repository. This uses
95 Commit all changed files in the working dir to the repository. This uses
96 the EDITOR environment variable to bring up an editor to add a commit
96 the EDITOR environment variable to bring up an editor to add a commit
97 comment.
97 comment.
98
98
99 Options:
99 Options:
100
100
101 -A, --addremove run addremove during commit
101 -A, --addremove run addremove during commit
102 -t, --text <text> use <text> as commit message
102 -t, --text <text> use <text> as commit message
103 -l, --logfile <file> read the commit message from the specified
103 -l, --logfile <file> read the commit message from the specified
104 file
104 file
105 -d, --date <datecode> use the specified date code
105 -d, --date <datecode> use the specified date code
106 -u, --user <user> record commit as the specified user
106 -u, --user <user> record commit as the specified user
107
107
108 aliases: ci
108 aliases: ci
109
109
110 copy <source> <dest>::
110 copy <source> <dest>::
111 Mark a file as copied or renamed for the next commit.
111 Mark a file as copied or renamed for the next commit.
112
112
113 diff [-r revision] [-r revision] [files ...]::
113 diff [-r revision] [-r revision] [files ...]::
114 Generate a unified diff of the indicated files. If there are no
114 Generate a unified diff of the indicated files. If there are no
115 revisions specified, the working directory file is compared to
115 revisions specified, the working directory file is compared to
116 the tip, one revision specified indicates a comparison between the
116 the tip, one revision specified indicates a comparison between the
117 working directory file and the specified revision, and two revisions
117 working directory file and the specified revision, and two revisions
118 compares the two versions specified.
118 compares the two versions specified.
119
119
120 export [revision]::
120 export [revision]::
121 Print the changeset header (author, changeset hash, parent, and commit
121 Print the changeset header (author, changeset hash, parent, and commit
122 comment) and the diffs for a particular revision.
122 comment) and the diffs for a particular revision.
123
123
124 forget [files]::
124 forget [files]::
125 Undo an 'hg add' scheduled for the next commit.
125 Undo an 'hg add' scheduled for the next commit.
126
126
127 heads::
127 heads::
128 Show all changesets with no children. These are the "heads" of
128 Show all changesets with no children. These are the "heads" of
129 development branches and are the usual targets for updates and merges.
129 development branches and are the usual targets for updates and merges.
130
130
131 history::
131 history::
132 Print the revision history of the repository. Use the -v switch
132 Print the revision history of the repository. Use the -v switch
133 for more detail.
133 for more detail.
134
134
135 identify::
135 identify::
136 Print a short identifier of the current state of the repo. This
136 Print a short identifier of the current state of the repo. This
137 includes one or two parent hash identifiers, followed by
137 includes one or two parent hash identifiers, followed by
138 a "+" if there are uncommitted changes in the working directory,
138 a "+" if there are uncommitted changes in the working directory,
139 followed by a list of tags for this revision.
139 followed by a list of tags for this revision.
140
140
141 aliases: id
141 aliases: id
142
142
143 import [-p <n> -b <base> -q] <patches>::
143 import [-p <n> -b <base> -q] <patches>::
144 Import the listed patches and commit them individually.
144 Import the listed patches and commit them individually.
145
145
146 options:
146 options:
147 -p, --strip <n> directory strip option for patch
147 -p, --strip <n> directory strip option for patch
148 -b <path> base directory to read patches from
148 -b <path> base directory to read patches from
149
149
150 aliases: patch
150 aliases: patch
151
151
152 init [-u] [source]::
152 init::
153 Initialize a repository in the current directory.
153 Initialize a new repository in the current directory.
154
155 NOTE: The following use is deprecated, and will be removed soon;
156 use the "hg clone" command instead.
157
158 If a source is specified, pull that source into the repository.
159 This source is added to .hg/hgrc as the default for future pulls
160 in this repository.
161
162 If the specified source is on the same filesystem, the repository
163 will be copied via hardlinks. This is the fastest and most
164 space-efficient mode of operation.
165
166 options:
167 -u, --update update the working directory to match the tip
168
154
169 log <file>::
155 log <file>::
170 Print the revision history of the specified file.
156 Print the revision history of the specified file.
171
157
172 manifest [revision]::
158 manifest [revision]::
173 Print the indicated revision of the manifest (list of version controlled
159 Print the indicated revision of the manifest (list of version controlled
174 files).
160 files).
175
161
176 parents::
162 parents::
177 Print the working directory's parent revisions.
163 Print the working directory's parent revisions.
178
164
179 pull <repository path>::
165 pull <repository path>::
180 Pull any changes from the specified repository to the repository in the
166 Pull any changes from the specified repository to the repository in the
181 current directory.
167 current directory.
182
168
183 options:
169 options:
184 -u, --update update the working directory to tip after pull
170 -u, --update update the working directory to tip after pull
185
171
186 push <destination>::
172 push <destination>::
187 Push changes from the local repository to the specified
173 Push changes from the local repository to the specified
188 destination. If the destination is local, this is identical to a
174 destination. If the destination is local, this is identical to a
189 a pull in that directory from the current directory.
175 a pull in that directory from the current directory.
190
176
191 The other currently available push method is SSH. This requires an
177 The other currently available push method is SSH. This requires an
192 accessible shell account on the destination machine and a copy of
178 accessible shell account on the destination machine and a copy of
193 hg in the remote path. Destinations are specified in the following
179 hg in the remote path. Destinations are specified in the following
194 form:
180 form:
195
181
196 ssh://[user@]host[:port]/path
182 ssh://[user@]host[:port]/path
197
183
198 rawcommit [-p -d -u -F -t -l]::
184 rawcommit [-p -d -u -F -t -l]::
199 Primarily useful for importing from other SCMs.
185 Primarily useful for importing from other SCMs.
200
186
201 recover::
187 recover::
202 Recover from an interrupted commit or pull. This should only be
188 Recover from an interrupted commit or pull. This should only be
203 necessary when Mercurial suggests it.
189 necessary when Mercurial suggests it.
204
190
205 remove [files ...]::
191 remove [files ...]::
206 Schedule the indicated files for removal from the repository at the next
192 Schedule the indicated files for removal from the repository at the next
207 commit.
193 commit.
208
194
209 aliases: rm
195 aliases: rm
210
196
211 root::
197 root::
212 Print the root directory of the current repository.
198 Print the root directory of the current repository.
213
199
214 serve [-a addr -n name -p port -t templatedir]::
200 serve [-a addr -n name -p port -t templatedir]::
215 Start a local HTTP repository browser and pull server.
201 Start a local HTTP repository browser and pull server.
216
202
217 options:
203 options:
218 -a, --address <addr> address to use
204 -a, --address <addr> address to use
219 -p, --port <n> port to use (default: 8000)
205 -p, --port <n> port to use (default: 8000)
220 -n, --name <name> name to show in web pages (default: working dir)
206 -n, --name <name> name to show in web pages (default: working dir)
221 -t, --templatedir <path> web templates to use
207 -t, --templatedir <path> web templates to use
222
208
223 status::
209 status::
224 Show changed files in the working directory.
210 Show changed files in the working directory.
225
211
226 C = changed
212 C = changed
227 A = added
213 A = added
228 R = removed
214 R = removed
229 ? = not tracked
215 ? = not tracked
230
216
231 tag [-t <text> -d <datecode> -u <user>] <name> [revision]::
217 tag [-t <text> -d <datecode> -u <user>] <name> [revision]::
232 Add a tag <name> to the specified revision or the tip.
218 Add a tag <name> to the specified revision or the tip.
233
219
234 options:
220 options:
235 -t, --text <text> message for tag commit log entry
221 -t, --text <text> message for tag commit log entry
236 -d, --date <datecode> datecode for commit
222 -d, --date <datecode> datecode for commit
237 -u, --user <user> user for commit
223 -u, --user <user> user for commit
238
224
239 tags::
225 tags::
240 List the repository tags.
226 List the repository tags.
241
227
242 tip::
228 tip::
243 Show the tip revision.
229 Show the tip revision.
244
230
245 undo::
231 undo::
246 Undo the last commit or pull transaction.
232 Undo the last commit or pull transaction.
247
233
248 update [-m -C] [revision]::
234 update [-m -C] [revision]::
249 Update or merge the working directory to a specified revision.
235 Update or merge the working directory to a specified revision.
250
236
251 If there are no outstanding changes in the working directory and
237 If there are no outstanding changes in the working directory and
252 there is a linear relationship between the current version and the
238 there is a linear relationship between the current version and the
253 requested version, the result is the requested version.
239 requested version, the result is the requested version.
254
240
255 Otherwise the result is a merge between the contents of the
241 Otherwise the result is a merge between the contents of the
256 current working directory and the requested version. Files that
242 current working directory and the requested version. Files that
257 changed between either parent are marked as changed for the next
243 changed between either parent are marked as changed for the next
258 commit and a commit must be performed before any further updates
244 commit and a commit must be performed before any further updates
259 are allowed. Merging will not be performed without the -m flag.
245 are allowed. Merging will not be performed without the -m flag.
260
246
261 The -C switch will tell Mercurial to forcibly update to the
247 The -C switch will tell Mercurial to forcibly update to the
262 specified version, adding, removing, and overwriting locally
248 specified version, adding, removing, and overwriting locally
263 changed fils as necessary.
249 changed fils as necessary.
264
250
265 options:
251 options:
266 -m, --merge allow merging of branches
252 -m, --merge allow merging of branches
267 -C, --clean overwrite locally modified files
253 -C, --clean overwrite locally modified files
268
254
269 aliases: up checkout co
255 aliases: up checkout co
270
256
271 verify::
257 verify::
272 Verify the integrity of the current repository.
258 Verify the integrity of the current repository.
273
259
274 This will perform an extensive check of the repository's
260 This will perform an extensive check of the repository's
275 integrity, validating the hashes and checksums of each entry in
261 integrity, validating the hashes and checksums of each entry in
276 the changelog, manifest, and tracked files, as well as the
262 the changelog, manifest, and tracked files, as well as the
277 integrity of their crosslinks and indices.
263 integrity of their crosslinks and indices.
278
264
279
265
280 ENVIRONMENT VARIABLES
266 ENVIRONMENT VARIABLES
281 ---------------------
267 ---------------------
282
268
283 HGEDITOR::
269 HGEDITOR::
284 This is the name of the editor to use when committing. Defaults to the
270 This is the name of the editor to use when committing. Defaults to the
285 value of EDITOR.
271 value of EDITOR.
286
272
287 HGMERGE::
273 HGMERGE::
288 An executable to use for resolving merge conflicts. The program ,
274 An executable to use for resolving merge conflicts. The program ,
289 will be executed with three arguments: local file, remote file,
275 will be executed with three arguments: local file, remote file,
290 ancestor file.
276 ancestor file.
291
277
292 The default program is "hgmerge", which is a shell script provided
278 The default program is "hgmerge", which is a shell script provided
293 by Mercurial with some sensible defaults.
279 by Mercurial with some sensible defaults.
294
280
295 HGUSER::
281 HGUSER::
296 This is the string used for the author of a commit.
282 This is the string used for the author of a commit.
297
283
298 EMAIL::
284 EMAIL::
299 If HGUSER is not set, this will be used as the author for a commit.
285 If HGUSER is not set, this will be used as the author for a commit.
300
286
301 LOGNAME::
287 LOGNAME::
302 If neither HGUSER nor EMAIL is set, LOGNAME will be used (with
288 If neither HGUSER nor EMAIL is set, LOGNAME will be used (with
303 '@hostname' appended) as the author value for a commit.
289 '@hostname' appended) as the author value for a commit.
304
290
305 EDITOR::
291 EDITOR::
306 This is the name of the editor used in the hgmerge script. It will be
292 This is the name of the editor used in the hgmerge script. It will be
307 used for commit messages, too, if HGEDITOR isn't set. Defaults to 'vi'.
293 used for commit messages, too, if HGEDITOR isn't set. Defaults to 'vi'.
308
294
309 PYTHONPATH::
295 PYTHONPATH::
310 This is used by Python to find imported modules and may need to be set
296 This is used by Python to find imported modules and may need to be set
311 appropriately if Mercurial is not installed system-wide.
297 appropriately if Mercurial is not installed system-wide.
312
298
313 FILES
299 FILES
314 -----
300 -----
315 .hgignore::
301 .hgignore::
316 This file contains regular expressions (one per line) that describe file
302 This file contains regular expressions (one per line) that describe file
317 names that should be ignored by hg.
303 names that should be ignored by hg.
318
304
319 .hgtags::
305 .hgtags::
320 This file contains changeset hash values and text tag names (one of each
306 This file contains changeset hash values and text tag names (one of each
321 seperated by spaces) that correspond to tagged versions of the repository
307 seperated by spaces) that correspond to tagged versions of the repository
322 contents.
308 contents.
323
309
324 $HOME/.hgrc, .hg/hgrc::
310 $HOME/.hgrc, .hg/hgrc::
325 This file contains defaults and configuration. Values in .hg/hgrc
311 This file contains defaults and configuration. Values in .hg/hgrc
326 override those in .hgrc.
312 override those in .hgrc.
327
313
328 NAMED REPOSITORIES
314 NAMED REPOSITORIES
329 ------------------
315 ------------------
330
316
331 To give symbolic names to a repository, create a section in .hgrc
317 To give symbolic names to a repository, create a section in .hgrc
332 or .hg/hgrc containing assignments of names to paths. Example:
318 or .hg/hgrc containing assignments of names to paths. Example:
333
319
334 -----------------
320 -----------------
335 [paths]
321 [paths]
336 hg = http://selenic.com/hg
322 hg = http://selenic.com/hg
337 tah = http://hg.intevation.org/mercurial-tah/
323 tah = http://hg.intevation.org/mercurial-tah/
338 -----------------
324 -----------------
339
325
340
326
341 HOOKS
327 HOOKS
342 -----
328 -----
343
329
344 Mercurial supports a set of 'hook', commands that get automatically
330 Mercurial supports a set of 'hook', commands that get automatically
345 executed by various actions such as starting or finishing a commit. To
331 executed by various actions such as starting or finishing a commit. To
346 specify a hook, simply create an hgrc section like the following:
332 specify a hook, simply create an hgrc section like the following:
347
333
348 -----------------
334 -----------------
349 [hooks]
335 [hooks]
350 precommit = echo "this hook gets executed immediately before a commit"
336 precommit = echo "this hook gets executed immediately before a commit"
351 commit = hg export $NODE | mail -s "new commit $NODE" commit-list
337 commit = hg export $NODE | mail -s "new commit $NODE" commit-list
352 -----------------
338 -----------------
353
339
354
340
355 NON_TRANSPARENT PROXY SUPPORT
341 NON_TRANSPARENT PROXY SUPPORT
356 -----------------------------
342 -----------------------------
357
343
358 To access a Mercurial repository through a proxy, create a file
344 To access a Mercurial repository through a proxy, create a file
359 $HOME/.hgrc in the following format:
345 $HOME/.hgrc in the following format:
360
346
361 --------------
347 --------------
362 [http_proxy]
348 [http_proxy]
363 host=myproxy:8080
349 host=myproxy:8080
364 user=<username>
350 user=<username>
365 passwd=<password>
351 passwd=<password>
366 no=<localhost1>,<localhost2>,<localhost3>,...
352 no=<localhost1>,<localhost2>,<localhost3>,...
367 --------------
353 --------------
368
354
369 "user","passwd" fields are used for authenticating proxies, "no" is a
355 "user","passwd" fields are used for authenticating proxies, "no" is a
370 comma-separated list of local host names for which proxy must be
356 comma-separated list of local host names for which proxy must be
371 bypassed.
357 bypassed.
372
358
373
359
374 BUGS
360 BUGS
375 ----
361 ----
376 Probably lots, please post them to the mailing list (See Resources below)
362 Probably lots, please post them to the mailing list (See Resources below)
377 when you find them.
363 when you find them.
378
364
379 AUTHOR
365 AUTHOR
380 ------
366 ------
381 Written by Matt Mackall <mpm@selenic.com>
367 Written by Matt Mackall <mpm@selenic.com>
382
368
383 RESOURCES
369 RESOURCES
384 ---------
370 ---------
385 http://selenic.com/mercurial[Main Web Site]
371 http://selenic.com/mercurial[Main Web Site]
386
372
387 http://selenic.com/hg[Source code repository]
373 http://selenic.com/hg[Source code repository]
388
374
389 http://selenic.com/mailman/listinfo/mercurial[Mailing list]
375 http://selenic.com/mailman/listinfo/mercurial[Mailing list]
390
376
391 COPYING
377 COPYING
392 -------
378 -------
393 Copyright (C) 2005 Matt Mackall.
379 Copyright (C) 2005 Matt Mackall.
394 Free use of this software is granted under the terms of the GNU General
380 Free use of this software is granted under the terms of the GNU General
395 Public License (GPL).
381 Public License (GPL).
@@ -1,898 +1,895 b''
1 # commands.py - command processing for mercurial
1 # commands.py - command processing for mercurial
2 #
2 #
3 # Copyright 2005 Matt Mackall <mpm@selenic.com>
3 # Copyright 2005 Matt Mackall <mpm@selenic.com>
4 #
4 #
5 # This software may be used and distributed according to the terms
5 # This software may be used and distributed according to the terms
6 # of the GNU General Public License, incorporated herein by reference.
6 # of the GNU General Public License, incorporated herein by reference.
7
7
8 import os, re, sys, signal
8 import os, re, sys, signal
9 import fancyopts, ui, hg, util
9 import fancyopts, ui, hg, util
10 from demandload import *
10 from demandload import *
11 demandload(globals(), "mdiff time hgweb traceback random signal errno version")
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] != "/": t += "/"
19 if t and t[-1] != "/": t += "/"
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([util.pconvert(p)], files)
26 return filterfiles([util.pconvert(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 [ util.pconvert(os.path.normpath(os.path.join(p, x))) for x in args ]
32 return [ util.pconvert(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 repo.wfile(f).read()
50 def read(f): return repo.wfile(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 if ui.debugflag:
126 if ui.debugflag:
127 files = repo.diffrevs(changelog.parents(changenode)[0], changenode)
127 files = repo.diffrevs(changelog.parents(changenode)[0], changenode)
128 for key, value in zip(["files:", "files+:", "files-:"], files):
128 for key, value in zip(["files:", "files+:", "files-:"], files):
129 if value:
129 if value:
130 ui.note("%-12s %s\n" % (key, " ".join(value)))
130 ui.note("%-12s %s\n" % (key, " ".join(value)))
131 else:
131 else:
132 ui.note("files: %s\n" % " ".join(changes[3]))
132 ui.note("files: %s\n" % " ".join(changes[3]))
133 description = changes[4].strip()
133 description = changes[4].strip()
134 if description:
134 if description:
135 if ui.verbose:
135 if ui.verbose:
136 ui.status("description:\n")
136 ui.status("description:\n")
137 ui.status(description)
137 ui.status(description)
138 ui.status("\n")
138 ui.status("\n")
139 else:
139 else:
140 ui.status("summary: %s\n" % description.splitlines()[0])
140 ui.status("summary: %s\n" % description.splitlines()[0])
141 ui.status("\n")
141 ui.status("\n")
142
142
143 def show_version(ui):
143 def show_version(ui):
144 """output version and copyright information"""
144 """output version and copyright information"""
145 ui.write("Mercurial version %s\n" % version.get_version())
145 ui.write("Mercurial version %s\n" % version.get_version())
146 ui.status(
146 ui.status(
147 "\nCopyright (C) 2005 Matt Mackall <mpm@selenic.com>\n"
147 "\nCopyright (C) 2005 Matt Mackall <mpm@selenic.com>\n"
148 "This is free software; see the source for copying conditions. "
148 "This is free software; see the source for copying conditions. "
149 "There is NO\nwarranty; "
149 "There is NO\nwarranty; "
150 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
150 "not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
151 )
151 )
152
152
153 def help(ui, cmd=None):
153 def help(ui, cmd=None):
154 '''show help for a given command or all commands'''
154 '''show help for a given command or all commands'''
155 if cmd:
155 if cmd:
156 try:
156 try:
157 i = find(cmd)
157 i = find(cmd)
158 ui.write("%s\n\n" % i[2])
158 ui.write("%s\n\n" % i[2])
159
159
160 if i[1]:
160 if i[1]:
161 for s, l, d, c in i[1]:
161 for s, l, d, c in i[1]:
162 opt=' '
162 opt=' '
163 if s: opt = opt + '-' + s + ' '
163 if s: opt = opt + '-' + s + ' '
164 if l: opt = opt + '--' + l + ' '
164 if l: opt = opt + '--' + l + ' '
165 if d: opt = opt + '(' + str(d) + ')'
165 if d: opt = opt + '(' + str(d) + ')'
166 ui.write(opt, "\n")
166 ui.write(opt, "\n")
167 if c: ui.write(' %s\n' % c)
167 if c: ui.write(' %s\n' % c)
168 ui.write("\n")
168 ui.write("\n")
169
169
170 ui.write(i[0].__doc__, "\n")
170 ui.write(i[0].__doc__, "\n")
171 except UnknownCommand:
171 except UnknownCommand:
172 ui.warn("hg: unknown command %s\n" % cmd)
172 ui.warn("hg: unknown command %s\n" % cmd)
173 sys.exit(0)
173 sys.exit(0)
174 else:
174 else:
175 if not ui.quiet:
175 if not ui.quiet:
176 show_version(ui)
176 show_version(ui)
177 ui.write('\n')
177 ui.write('\n')
178 ui.write('hg commands:\n\n')
178 ui.write('hg commands:\n\n')
179
179
180 h = {}
180 h = {}
181 for c, e in table.items():
181 for c, e in table.items():
182 f = c.split("|")[0]
182 f = c.split("|")[0]
183 if f.startswith("debug"):
183 if f.startswith("debug"):
184 continue
184 continue
185 d = ""
185 d = ""
186 if e[0].__doc__:
186 if e[0].__doc__:
187 d = e[0].__doc__.splitlines(0)[0].rstrip()
187 d = e[0].__doc__.splitlines(0)[0].rstrip()
188 h[f] = d
188 h[f] = d
189
189
190 fns = h.keys()
190 fns = h.keys()
191 fns.sort()
191 fns.sort()
192 m = max(map(len, fns))
192 m = max(map(len, fns))
193 for f in fns:
193 for f in fns:
194 ui.write(' %-*s %s\n' % (m, f, h[f]))
194 ui.write(' %-*s %s\n' % (m, f, h[f]))
195
195
196 # Commands start here, listed alphabetically
196 # Commands start here, listed alphabetically
197
197
198 def add(ui, repo, file, *files):
198 def add(ui, repo, file, *files):
199 '''add the specified files on the next commit'''
199 '''add the specified files on the next commit'''
200 repo.add(relpath(repo, (file,) + files))
200 repo.add(relpath(repo, (file,) + files))
201
201
202 def addremove(ui, repo, *files):
202 def addremove(ui, repo, *files):
203 """add all new files, delete all missing files"""
203 """add all new files, delete all missing files"""
204 if files:
204 if files:
205 files = relpath(repo, files)
205 files = relpath(repo, files)
206 d = []
206 d = []
207 u = []
207 u = []
208 for f in files:
208 for f in files:
209 p = repo.wjoin(f)
209 p = repo.wjoin(f)
210 s = repo.dirstate.state(f)
210 s = repo.dirstate.state(f)
211 isfile = os.path.isfile(p)
211 isfile = os.path.isfile(p)
212 if s != 'r' and not isfile:
212 if s != 'r' and not isfile:
213 d.append(f)
213 d.append(f)
214 elif s not in 'nmai' and isfile:
214 elif s not in 'nmai' and isfile:
215 u.append(f)
215 u.append(f)
216 else:
216 else:
217 (c, a, d, u) = repo.diffdir(repo.root)
217 (c, a, d, u) = repo.diffdir(repo.root)
218 repo.add(u)
218 repo.add(u)
219 repo.remove(d)
219 repo.remove(d)
220
220
221 def annotate(u, repo, file, *files, **ops):
221 def annotate(u, repo, file, *files, **ops):
222 """show changeset information per file line"""
222 """show changeset information per file line"""
223 def getnode(rev):
223 def getnode(rev):
224 return hg.short(repo.changelog.node(rev))
224 return hg.short(repo.changelog.node(rev))
225
225
226 def getname(rev):
226 def getname(rev):
227 try:
227 try:
228 return bcache[rev]
228 return bcache[rev]
229 except KeyError:
229 except KeyError:
230 cl = repo.changelog.read(repo.changelog.node(rev))
230 cl = repo.changelog.read(repo.changelog.node(rev))
231 name = cl[1]
231 name = cl[1]
232 f = name.find('@')
232 f = name.find('@')
233 if f >= 0:
233 if f >= 0:
234 name = name[:f]
234 name = name[:f]
235 bcache[rev] = name
235 bcache[rev] = name
236 return name
236 return name
237
237
238 bcache = {}
238 bcache = {}
239 opmap = [['user', getname], ['number', str], ['changeset', getnode]]
239 opmap = [['user', getname], ['number', str], ['changeset', getnode]]
240 if not ops['user'] and not ops['changeset']:
240 if not ops['user'] and not ops['changeset']:
241 ops['number'] = 1
241 ops['number'] = 1
242
242
243 node = repo.dirstate.parents()[0]
243 node = repo.dirstate.parents()[0]
244 if ops['revision']:
244 if ops['revision']:
245 node = repo.changelog.lookup(ops['revision'])
245 node = repo.changelog.lookup(ops['revision'])
246 change = repo.changelog.read(node)
246 change = repo.changelog.read(node)
247 mmap = repo.manifest.read(change[0])
247 mmap = repo.manifest.read(change[0])
248 for f in relpath(repo, (file,) + files):
248 for f in relpath(repo, (file,) + files):
249 lines = repo.file(f).annotate(mmap[f])
249 lines = repo.file(f).annotate(mmap[f])
250 pieces = []
250 pieces = []
251
251
252 for o, f in opmap:
252 for o, f in opmap:
253 if ops[o]:
253 if ops[o]:
254 l = [ f(n) for n,t in lines ]
254 l = [ f(n) for n,t in lines ]
255 m = max(map(len, l))
255 m = max(map(len, l))
256 pieces.append([ "%*s" % (m, x) for x in l])
256 pieces.append([ "%*s" % (m, x) for x in l])
257
257
258 for p,l in zip(zip(*pieces), lines):
258 for p,l in zip(zip(*pieces), lines):
259 u.write(" ".join(p) + ": " + l[1])
259 u.write(" ".join(p) + ": " + l[1])
260
260
261 def cat(ui, repo, file, rev = []):
261 def cat(ui, repo, file, rev = []):
262 """output the latest or given revision of a file"""
262 """output the latest or given revision of a file"""
263 r = repo.file(relpath(repo, [file])[0])
263 r = repo.file(relpath(repo, [file])[0])
264 n = r.tip()
264 n = r.tip()
265 if rev: n = r.lookup(rev)
265 if rev: n = r.lookup(rev)
266 sys.stdout.write(r.read(n))
266 sys.stdout.write(r.read(n))
267
267
268 def clone(ui, source, dest = None, **opts):
268 def clone(ui, source, dest = None, **opts):
269 """make a copy of an existing repository"""
269 """make a copy of an existing repository"""
270 paths = {}
270 paths = {}
271 for name, path in ui.configitems("paths"):
271 for name, path in ui.configitems("paths"):
272 paths[name] = path
272 paths[name] = path
273
273
274 if source in paths: source = paths[source]
274 if source in paths: source = paths[source]
275
275
276 if dest is None:
276 if dest is None:
277 dest = os.getcwd()
277 dest = os.getcwd()
278 elif not os.path.exists(dest):
278 elif not os.path.exists(dest):
279 os.makedirs(dest)
279 os.makedirs(dest)
280
280
281 link = 0
281 link = 0
282 if not source.startswith("http://"):
282 if not source.startswith("http://"):
283 source = os.path.realpath(source)
283 source = os.path.realpath(source)
284 d1 = os.stat(dest).st_dev
284 d1 = os.stat(dest).st_dev
285 d2 = os.stat(source).st_dev
285 d2 = os.stat(source).st_dev
286 if d1 == d2: link = 1
286 if d1 == d2: link = 1
287
287
288 os.chdir(dest)
288 os.chdir(dest)
289
289
290 if link:
290 if link:
291 ui.debug("copying by hardlink\n")
291 ui.debug("copying by hardlink\n")
292 os.system("cp -al %s/.hg .hg" % source)
292 os.system("cp -al %s/.hg .hg" % source)
293 try:
293 try:
294 os.remove(".hg/dirstate")
294 os.remove(".hg/dirstate")
295 except: pass
295 except: pass
296
296
297 repo = hg.repository(ui, ".")
297 repo = hg.repository(ui, ".")
298
298
299 else:
299 else:
300 repo = hg.repository(ui, ".", create=1)
300 repo = hg.repository(ui, ".", create=1)
301 other = hg.repository(ui, source)
301 other = hg.repository(ui, source)
302 cg = repo.getchangegroup(other)
302 cg = repo.getchangegroup(other)
303 repo.addchangegroup(cg)
303 repo.addchangegroup(cg)
304
304
305 f = repo.opener("hgrc", "w")
305 f = repo.opener("hgrc", "w")
306 f.write("[paths]\n")
306 f.write("[paths]\n")
307 f.write("default = %s\n" % source)
307 f.write("default = %s\n" % source)
308
308
309 if not opts['no-update']:
309 if not opts['no-update']:
310 update(ui, repo)
310 update(ui, repo)
311
311
312 def commit(ui, repo, *files, **opts):
312 def commit(ui, repo, *files, **opts):
313 """commit the specified files or all outstanding changes"""
313 """commit the specified files or all outstanding changes"""
314 text = opts['text']
314 text = opts['text']
315 if not text and opts['logfile']:
315 if not text and opts['logfile']:
316 try: text = open(opts['logfile']).read()
316 try: text = open(opts['logfile']).read()
317 except IOError: pass
317 except IOError: pass
318
318
319 if opts['addremove']:
319 if opts['addremove']:
320 addremove(ui, repo, *files)
320 addremove(ui, repo, *files)
321 repo.commit(relpath(repo, files), text, opts['user'], opts['date'])
321 repo.commit(relpath(repo, files), text, opts['user'], opts['date'])
322
322
323 def copy(ui, repo, source, dest):
323 def copy(ui, repo, source, dest):
324 """mark a file as copied or renamed for the next commit"""
324 """mark a file as copied or renamed for the next commit"""
325 return repo.copy(*relpath(repo, (source, dest)))
325 return repo.copy(*relpath(repo, (source, dest)))
326
326
327 def debugcheckdirstate(ui, repo):
327 def debugcheckdirstate(ui, repo):
328 parent1, parent2 = repo.dirstate.parents()
328 parent1, parent2 = repo.dirstate.parents()
329 dc = repo.dirstate.dup()
329 dc = repo.dirstate.dup()
330 keys = dc.keys()
330 keys = dc.keys()
331 keys.sort()
331 keys.sort()
332 m1n = repo.changelog.read(parent1)[0]
332 m1n = repo.changelog.read(parent1)[0]
333 m2n = repo.changelog.read(parent2)[0]
333 m2n = repo.changelog.read(parent2)[0]
334 m1 = repo.manifest.read(m1n)
334 m1 = repo.manifest.read(m1n)
335 m2 = repo.manifest.read(m2n)
335 m2 = repo.manifest.read(m2n)
336 errors = 0
336 errors = 0
337 for f in dc:
337 for f in dc:
338 state = repo.dirstate.state(f)
338 state = repo.dirstate.state(f)
339 if state in "nr" and f not in m1:
339 if state in "nr" and f not in m1:
340 print "%s in state %s, but not listed in manifest1" % (f, state)
340 print "%s in state %s, but not listed in manifest1" % (f, state)
341 errors += 1
341 errors += 1
342 if state in "a" and f in m1:
342 if state in "a" and f in m1:
343 print "%s in state %s, but also listed in manifest1" % (f, state)
343 print "%s in state %s, but also listed in manifest1" % (f, state)
344 errors += 1
344 errors += 1
345 if state in "m" and f not in m1 and f not in m2:
345 if state in "m" and f not in m1 and f not in m2:
346 print "%s in state %s, but not listed in either manifest" % (f, state)
346 print "%s in state %s, but not listed in either manifest" % (f, state)
347 errors += 1
347 errors += 1
348 for f in m1:
348 for f in m1:
349 state = repo.dirstate.state(f)
349 state = repo.dirstate.state(f)
350 if state not in "nrm":
350 if state not in "nrm":
351 print "%s in manifest1, but listed as state %s" % (f, state)
351 print "%s in manifest1, but listed as state %s" % (f, state)
352 errors += 1
352 errors += 1
353 if errors:
353 if errors:
354 print ".hg/dirstate inconsistent with current parent's manifest, aborting"
354 print ".hg/dirstate inconsistent with current parent's manifest, aborting"
355 sys.exit(1)
355 sys.exit(1)
356
356
357 def debugdumpdirstate(ui, repo):
357 def debugdumpdirstate(ui, repo):
358 dc = repo.dirstate.dup()
358 dc = repo.dirstate.dup()
359 keys = dc.keys()
359 keys = dc.keys()
360 keys.sort()
360 keys.sort()
361 for file in keys:
361 for file in keys:
362 print "%s => %c" % (file, dc[file][0])
362 print "%s => %c" % (file, dc[file][0])
363
363
364 def debugindex(ui, file):
364 def debugindex(ui, file):
365 r = hg.revlog(hg.opener(""), file, "")
365 r = hg.revlog(hg.opener(""), file, "")
366 print " rev offset length base linkrev"+\
366 print " rev offset length base linkrev"+\
367 " p1 p2 nodeid"
367 " p1 p2 nodeid"
368 for i in range(r.count()):
368 for i in range(r.count()):
369 e = r.index[i]
369 e = r.index[i]
370 print "% 6d % 9d % 7d % 6d % 7d %s.. %s.. %s.." % (
370 print "% 6d % 9d % 7d % 6d % 7d %s.. %s.. %s.." % (
371 i, e[0], e[1], e[2], e[3],
371 i, e[0], e[1], e[2], e[3],
372 hg.hex(e[4][:5]), hg.hex(e[5][:5]), hg.hex(e[6][:5]))
372 hg.hex(e[4][:5]), hg.hex(e[5][:5]), hg.hex(e[6][:5]))
373
373
374 def debugindexdot(ui, file):
374 def debugindexdot(ui, file):
375 r = hg.revlog(hg.opener(""), file, "")
375 r = hg.revlog(hg.opener(""), file, "")
376 print "digraph G {"
376 print "digraph G {"
377 for i in range(r.count()):
377 for i in range(r.count()):
378 e = r.index[i]
378 e = r.index[i]
379 print "\t%d -> %d" % (r.rev(e[4]), i)
379 print "\t%d -> %d" % (r.rev(e[4]), i)
380 if e[5] != hg.nullid:
380 if e[5] != hg.nullid:
381 print "\t%d -> %d" % (r.rev(e[5]), i)
381 print "\t%d -> %d" % (r.rev(e[5]), i)
382 print "}"
382 print "}"
383
383
384 def diff(ui, repo, *files, **opts):
384 def diff(ui, repo, *files, **opts):
385 """diff working directory (or selected files)"""
385 """diff working directory (or selected files)"""
386 revs = []
386 revs = []
387 if opts['rev']:
387 if opts['rev']:
388 revs = map(lambda x: repo.lookup(x), opts['rev'])
388 revs = map(lambda x: repo.lookup(x), opts['rev'])
389
389
390 if len(revs) > 2:
390 if len(revs) > 2:
391 ui.warn("too many revisions to diff\n")
391 ui.warn("too many revisions to diff\n")
392 sys.exit(1)
392 sys.exit(1)
393
393
394 if files:
394 if files:
395 files = relpath(repo, files)
395 files = relpath(repo, files)
396 else:
396 else:
397 files = relpath(repo, [""])
397 files = relpath(repo, [""])
398
398
399 dodiff(ui, repo, os.getcwd(), files, *revs)
399 dodiff(ui, repo, os.getcwd(), files, *revs)
400
400
401 def export(ui, repo, changeset):
401 def export(ui, repo, changeset):
402 """dump the changeset header and diffs for a revision"""
402 """dump the changeset header and diffs for a revision"""
403 node = repo.lookup(changeset)
403 node = repo.lookup(changeset)
404 prev, other = repo.changelog.parents(node)
404 prev, other = repo.changelog.parents(node)
405 change = repo.changelog.read(node)
405 change = repo.changelog.read(node)
406 print "# HG changeset patch"
406 print "# HG changeset patch"
407 print "# User %s" % change[1]
407 print "# User %s" % change[1]
408 print "# Node ID %s" % hg.hex(node)
408 print "# Node ID %s" % hg.hex(node)
409 print "# Parent %s" % hg.hex(prev)
409 print "# Parent %s" % hg.hex(prev)
410 print
410 print
411 if other != hg.nullid:
411 if other != hg.nullid:
412 print "# Parent %s" % hg.hex(other)
412 print "# Parent %s" % hg.hex(other)
413 print change[4].rstrip()
413 print change[4].rstrip()
414 print
414 print
415
415
416 dodiff(ui, repo, "", None, prev, node)
416 dodiff(ui, repo, "", None, prev, node)
417
417
418 def forget(ui, repo, file, *files):
418 def forget(ui, repo, file, *files):
419 """don't add the specified files on the next commit"""
419 """don't add the specified files on the next commit"""
420 repo.forget(relpath(repo, (file,) + files))
420 repo.forget(relpath(repo, (file,) + files))
421
421
422 def heads(ui, repo):
422 def heads(ui, repo):
423 """show current repository heads"""
423 """show current repository heads"""
424 for n in repo.changelog.heads():
424 for n in repo.changelog.heads():
425 show_changeset(ui, repo, changenode=n)
425 show_changeset(ui, repo, changenode=n)
426
426
427 def history(ui, repo):
427 def history(ui, repo):
428 """show the changelog history"""
428 """show the changelog history"""
429 for i in range(repo.changelog.count() - 1, -1, -1):
429 for i in range(repo.changelog.count() - 1, -1, -1):
430 show_changeset(ui, repo, rev=i)
430 show_changeset(ui, repo, rev=i)
431
431
432 def identify(ui, repo):
432 def identify(ui, repo):
433 """print information about the working copy"""
433 """print information about the working copy"""
434 parents = [p for p in repo.dirstate.parents() if p != hg.nullid]
434 parents = [p for p in repo.dirstate.parents() if p != hg.nullid]
435 if not parents:
435 if not parents:
436 ui.write("unknown\n")
436 ui.write("unknown\n")
437 return
437 return
438
438
439 hexfunc = ui.verbose and hg.hex or hg.short
439 hexfunc = ui.verbose and hg.hex or hg.short
440 (c, a, d, u) = repo.diffdir(repo.root)
440 (c, a, d, u) = repo.diffdir(repo.root)
441 output = ["%s%s" % ('+'.join([hexfunc(parent) for parent in parents]),
441 output = ["%s%s" % ('+'.join([hexfunc(parent) for parent in parents]),
442 (c or a or d) and "+" or "")]
442 (c or a or d) and "+" or "")]
443
443
444 if not ui.quiet:
444 if not ui.quiet:
445 # multiple tags for a single parent separated by '/'
445 # multiple tags for a single parent separated by '/'
446 parenttags = ['/'.join(tags)
446 parenttags = ['/'.join(tags)
447 for tags in map(repo.nodetags, parents) if tags]
447 for tags in map(repo.nodetags, parents) if tags]
448 # tags for multiple parents separated by ' + '
448 # tags for multiple parents separated by ' + '
449 output.append(' + '.join(parenttags))
449 output.append(' + '.join(parenttags))
450
450
451 ui.write("%s\n" % ' '.join(output))
451 ui.write("%s\n" % ' '.join(output))
452
452
453 def import_(ui, repo, patch1, *patches, **opts):
453 def import_(ui, repo, patch1, *patches, **opts):
454 """import an ordered set of patches"""
454 """import an ordered set of patches"""
455 try:
455 try:
456 import psyco
456 import psyco
457 psyco.full()
457 psyco.full()
458 except:
458 except:
459 pass
459 pass
460
460
461 patches = (patch1,) + patches
461 patches = (patch1,) + patches
462
462
463 d = opts["base"]
463 d = opts["base"]
464 strip = opts["strip"]
464 strip = opts["strip"]
465
465
466 for patch in patches:
466 for patch in patches:
467 ui.status("applying %s\n" % patch)
467 ui.status("applying %s\n" % patch)
468 pf = os.path.join(d, patch)
468 pf = os.path.join(d, patch)
469
469
470 text = ""
470 text = ""
471 for l in file(pf):
471 for l in file(pf):
472 if l[:4] == "--- ": break
472 if l[:4] == "--- ": break
473 text += l
473 text += l
474
474
475 # make sure text isn't empty
475 # make sure text isn't empty
476 if not text: text = "imported patch %s\n" % patch
476 if not text: text = "imported patch %s\n" % patch
477
477
478 f = os.popen("patch -p%d < %s" % (strip, pf))
478 f = os.popen("patch -p%d < %s" % (strip, pf))
479 files = []
479 files = []
480 for l in f.read().splitlines():
480 for l in f.read().splitlines():
481 l.rstrip('\r\n');
481 l.rstrip('\r\n');
482 ui.status("%s\n" % l)
482 ui.status("%s\n" % l)
483 if l[:14] == 'patching file ':
483 if l[:14] == 'patching file ':
484 pf = l[14:]
484 pf = l[14:]
485 if pf not in files:
485 if pf not in files:
486 files.append(pf)
486 files.append(pf)
487 patcherr = f.close()
487 patcherr = f.close()
488 if patcherr:
488 if patcherr:
489 sys.stderr.write("patch failed")
489 sys.stderr.write("patch failed")
490 sys.exit(1)
490 sys.exit(1)
491
491
492 if len(files) > 0:
492 if len(files) > 0:
493 addremove(ui, repo, *files)
493 addremove(ui, repo, *files)
494 repo.commit(files, text)
494 repo.commit(files, text)
495
495
496 def init(ui, source=None, **opts):
496 def init(ui, source=None):
497 """create a new repository or (deprecated, use clone) copy an existing one"""
497 """create a new repository in the current directory"""
498
498
499 if source:
499 if source:
500 ui.warn("this use of init is deprecated: use \"hg clone\" instead\n")
500 ui.warn("no longer supported: use \"hg clone\" instead\n")
501 opts['no-update'] = not opts['update']
501 sys.exit(1)
502 clone(ui, source, None, **opts)
502 repo = hg.repository(ui, ".", create=1)
503 else:
504 repo = hg.repository(ui, ".", create=1)
505
503
506 def log(ui, repo, f):
504 def log(ui, repo, f):
507 """show the revision history of a single file"""
505 """show the revision history of a single file"""
508 f = relpath(repo, [f])[0]
506 f = relpath(repo, [f])[0]
509
507
510 r = repo.file(f)
508 r = repo.file(f)
511 for i in range(r.count() - 1, -1, -1):
509 for i in range(r.count() - 1, -1, -1):
512 show_changeset(ui, repo, filelog=r, rev=i)
510 show_changeset(ui, repo, filelog=r, rev=i)
513
511
514 def manifest(ui, repo, rev = []):
512 def manifest(ui, repo, rev = []):
515 """output the latest or given revision of the project manifest"""
513 """output the latest or given revision of the project manifest"""
516 n = repo.manifest.tip()
514 n = repo.manifest.tip()
517 if rev:
515 if rev:
518 n = repo.manifest.lookup(rev)
516 n = repo.manifest.lookup(rev)
519 m = repo.manifest.read(n)
517 m = repo.manifest.read(n)
520 mf = repo.manifest.readflags(n)
518 mf = repo.manifest.readflags(n)
521 files = m.keys()
519 files = m.keys()
522 files.sort()
520 files.sort()
523
521
524 for f in files:
522 for f in files:
525 ui.write("%40s %3s %s\n" % (hg.hex(m[f]), mf[f] and "755" or "644", f))
523 ui.write("%40s %3s %s\n" % (hg.hex(m[f]), mf[f] and "755" or "644", f))
526
524
527 def parents(ui, repo, node = None):
525 def parents(ui, repo, node = None):
528 '''show the parents of the current working dir'''
526 '''show the parents of the current working dir'''
529 if node:
527 if node:
530 p = repo.changelog.parents(repo.lookup(hg.bin(node)))
528 p = repo.changelog.parents(repo.lookup(hg.bin(node)))
531 else:
529 else:
532 p = repo.dirstate.parents()
530 p = repo.dirstate.parents()
533
531
534 for n in p:
532 for n in p:
535 if n != hg.nullid:
533 if n != hg.nullid:
536 show_changeset(ui, repo, changenode=n)
534 show_changeset(ui, repo, changenode=n)
537
535
538 def pull(ui, repo, source="default", **opts):
536 def pull(ui, repo, source="default", **opts):
539 """pull changes from the specified source"""
537 """pull changes from the specified source"""
540 paths = {}
538 paths = {}
541 for name, path in ui.configitems("paths"):
539 for name, path in ui.configitems("paths"):
542 paths[name] = path
540 paths[name] = path
543
541
544 if source in paths:
542 if source in paths:
545 source = paths[source]
543 source = paths[source]
546
544
547 ui.status('pulling from %s\n' % (source))
545 ui.status('pulling from %s\n' % (source))
548
546
549 other = hg.repository(ui, source)
547 other = hg.repository(ui, source)
550 cg = repo.getchangegroup(other)
548 cg = repo.getchangegroup(other)
551 r = repo.addchangegroup(cg)
549 r = repo.addchangegroup(cg)
552 if cg and not r:
550 if cg and not r:
553 if opts['update']:
551 if opts['update']:
554 return update(ui, repo)
552 return update(ui, repo)
555 else:
553 else:
556 ui.status("(run 'hg update' to get a working copy)\n")
554 ui.status("(run 'hg update' to get a working copy)\n")
557
555
558 return r
556 return r
559
557
560 def push(ui, repo, dest="default-push"):
558 def push(ui, repo, dest="default-push"):
561 """push changes to the specified destination"""
559 """push changes to the specified destination"""
562 paths = {}
560 paths = {}
563 for name, path in ui.configitems("paths"):
561 for name, path in ui.configitems("paths"):
564 paths[name] = path
562 paths[name] = path
565
563
566 if dest in paths: dest = paths[dest]
564 if dest in paths: dest = paths[dest]
567
565
568 if not dest.startswith("ssh://"):
566 if not dest.startswith("ssh://"):
569 ui.warn("abort: can only push to ssh:// destinations currently\n")
567 ui.warn("abort: can only push to ssh:// destinations currently\n")
570 return 1
568 return 1
571
569
572 m = re.match(r'ssh://(([^@]+)@)?([^:/]+)(:(\d+))?(/(.*))?', dest)
570 m = re.match(r'ssh://(([^@]+)@)?([^:/]+)(:(\d+))?(/(.*))?', dest)
573 if not m:
571 if not m:
574 ui.warn("abort: couldn't parse destination %s\n" % dest)
572 ui.warn("abort: couldn't parse destination %s\n" % dest)
575 return 1
573 return 1
576
574
577 user, host, port, path = map(m.group, (2, 3, 5, 7))
575 user, host, port, path = map(m.group, (2, 3, 5, 7))
578 host = user and ("%s@%s" % (user, host)) or host
576 host = user and ("%s@%s" % (user, host)) or host
579 port = port and (" -p %s") % port or ""
577 port = port and (" -p %s") % port or ""
580 path = path or ""
578 path = path or ""
581
579
582 sport = random.randrange(30000, 60000)
580 sport = random.randrange(30000, 60000)
583 cmd = "ssh %s%s -R %d:localhost:%d 'cd %s; hg pull http://localhost:%d/'"
581 cmd = "ssh %s%s -R %d:localhost:%d 'cd %s; hg pull http://localhost:%d/'"
584 cmd = cmd % (host, port, sport+1, sport, path, sport+1)
582 cmd = cmd % (host, port, sport+1, sport, path, sport+1)
585
583
586 child = os.fork()
584 child = os.fork()
587 if not child:
585 if not child:
588 sys.stdout = file("/dev/null", "w")
586 sys.stdout = file("/dev/null", "w")
589 sys.stderr = sys.stdout
587 sys.stderr = sys.stdout
590 hgweb.server(repo.root, "pull", "", "localhost", sport)
588 hgweb.server(repo.root, "pull", "", "localhost", sport)
591 else:
589 else:
592 r = os.system(cmd)
590 r = os.system(cmd)
593 os.kill(child, signal.SIGTERM)
591 os.kill(child, signal.SIGTERM)
594 return r
592 return r
595
593
596 def rawcommit(ui, repo, *flist, **rc):
594 def rawcommit(ui, repo, *flist, **rc):
597 "raw commit interface"
595 "raw commit interface"
598
596
599 text = rc['text']
597 text = rc['text']
600 if not text and rc['logfile']:
598 if not text and rc['logfile']:
601 try: text = open(rc['logfile']).read()
599 try: text = open(rc['logfile']).read()
602 except IOError: pass
600 except IOError: pass
603 if not text and not rc['logfile']:
601 if not text and not rc['logfile']:
604 print "missing commit text"
602 print "missing commit text"
605 return 1
603 return 1
606
604
607 files = relpath(repo, list(flist))
605 files = relpath(repo, list(flist))
608 if rc['files']:
606 if rc['files']:
609 files += open(rc['files']).read().splitlines()
607 files += open(rc['files']).read().splitlines()
610
608
611 rc['parent'] = map(repo.lookup, rc['parent'])
609 rc['parent'] = map(repo.lookup, rc['parent'])
612
610
613 repo.rawcommit(files, text, rc['user'], rc['date'], *rc['parent'])
611 repo.rawcommit(files, text, rc['user'], rc['date'], *rc['parent'])
614
612
615 def recover(ui, repo):
613 def recover(ui, repo):
616 """roll back an interrupted transaction"""
614 """roll back an interrupted transaction"""
617 repo.recover()
615 repo.recover()
618
616
619 def remove(ui, repo, file, *files):
617 def remove(ui, repo, file, *files):
620 """remove the specified files on the next commit"""
618 """remove the specified files on the next commit"""
621 repo.remove(relpath(repo, (file,) + files))
619 repo.remove(relpath(repo, (file,) + files))
622
620
623 def root(ui, repo):
621 def root(ui, repo):
624 """print the root (top) of the current working dir"""
622 """print the root (top) of the current working dir"""
625 ui.write(repo.root + "\n")
623 ui.write(repo.root + "\n")
626
624
627 def serve(ui, repo, **opts):
625 def serve(ui, repo, **opts):
628 """export the repository via HTTP"""
626 """export the repository via HTTP"""
629 hgweb.server(repo.root, opts["name"], opts["templates"],
627 hgweb.server(repo.root, opts["name"], opts["templates"],
630 opts["address"], opts["port"])
628 opts["address"], opts["port"])
631
629
632 def status(ui, repo):
630 def status(ui, repo):
633 '''show changed files in the working directory
631 '''show changed files in the working directory
634
632
635 C = changed
633 C = changed
636 A = added
634 A = added
637 R = removed
635 R = removed
638 ? = not tracked'''
636 ? = not tracked'''
639
637
640 (c, a, d, u) = repo.diffdir(os.getcwd())
638 (c, a, d, u) = repo.diffdir(os.getcwd())
641 (c, a, d, u) = map(lambda x: relfilter(repo, x), (c, a, d, u))
639 (c, a, d, u) = map(lambda x: relfilter(repo, x), (c, a, d, u))
642
640
643 for f in c: print "C", f
641 for f in c: print "C", f
644 for f in a: print "A", f
642 for f in a: print "A", f
645 for f in d: print "R", f
643 for f in d: print "R", f
646 for f in u: print "?", f
644 for f in u: print "?", f
647
645
648 def tag(ui, repo, name, rev = None, **opts):
646 def tag(ui, repo, name, rev = None, **opts):
649 """add a tag for the current tip or a given revision"""
647 """add a tag for the current tip or a given revision"""
650
648
651 if name == "tip":
649 if name == "tip":
652 ui.warn("abort: 'tip' is a reserved name!\n")
650 ui.warn("abort: 'tip' is a reserved name!\n")
653 return -1
651 return -1
654
652
655 (c, a, d, u) = repo.diffdir(repo.root)
653 (c, a, d, u) = repo.diffdir(repo.root)
656 for x in (c, a, d, u):
654 for x in (c, a, d, u):
657 if ".hgtags" in x:
655 if ".hgtags" in x:
658 ui.warn("abort: working copy of .hgtags is changed!\n")
656 ui.warn("abort: working copy of .hgtags is changed!\n")
659 ui.status("(please commit .hgtags manually)\n")
657 ui.status("(please commit .hgtags manually)\n")
660 return -1
658 return -1
661
659
662 if rev:
660 if rev:
663 r = hg.hex(repo.lookup(rev))
661 r = hg.hex(repo.lookup(rev))
664 else:
662 else:
665 r = hg.hex(repo.changelog.tip())
663 r = hg.hex(repo.changelog.tip())
666
664
667 add = 0
665 add = 0
668 if not os.path.exists(repo.wjoin(".hgtags")): add = 1
666 if not os.path.exists(repo.wjoin(".hgtags")): add = 1
669 repo.wfile(".hgtags", "a").write("%s %s\n" % (r, name))
667 repo.wfile(".hgtags", "a").write("%s %s\n" % (r, name))
670 if add: repo.add([".hgtags"])
668 if add: repo.add([".hgtags"])
671
669
672 if not opts['text']:
670 if not opts['text']:
673 opts['text'] = "Added tag %s for changeset %s" % (name, r)
671 opts['text'] = "Added tag %s for changeset %s" % (name, r)
674
672
675 repo.commit([".hgtags"], opts['text'], opts['user'], opts['date'])
673 repo.commit([".hgtags"], opts['text'], opts['user'], opts['date'])
676
674
677 def tags(ui, repo):
675 def tags(ui, repo):
678 """list repository tags"""
676 """list repository tags"""
679
677
680 l = repo.tagslist()
678 l = repo.tagslist()
681 l.reverse()
679 l.reverse()
682 for t, n in l:
680 for t, n in l:
683 try:
681 try:
684 r = "%5d:%s" % (repo.changelog.rev(n), hg.hex(n))
682 r = "%5d:%s" % (repo.changelog.rev(n), hg.hex(n))
685 except KeyError:
683 except KeyError:
686 r = " ?:?"
684 r = " ?:?"
687 ui.write("%-30s %s\n" % (t, r))
685 ui.write("%-30s %s\n" % (t, r))
688
686
689 def tip(ui, repo):
687 def tip(ui, repo):
690 """show the tip revision"""
688 """show the tip revision"""
691 n = repo.changelog.tip()
689 n = repo.changelog.tip()
692 show_changeset(ui, repo, changenode=n)
690 show_changeset(ui, repo, changenode=n)
693
691
694 def undo(ui, repo):
692 def undo(ui, repo):
695 """undo the last transaction"""
693 """undo the last transaction"""
696 repo.undo()
694 repo.undo()
697
695
698 def update(ui, repo, node=None, merge=False, clean=False):
696 def update(ui, repo, node=None, merge=False, clean=False):
699 '''update or merge working directory
697 '''update or merge working directory
700
698
701 If there are no outstanding changes in the working directory and
699 If there are no outstanding changes in the working directory and
702 there is a linear relationship between the current version and the
700 there is a linear relationship between the current version and the
703 requested version, the result is the requested version.
701 requested version, the result is the requested version.
704
702
705 Otherwise the result is a merge between the contents of the
703 Otherwise the result is a merge between the contents of the
706 current working directory and the requested version. Files that
704 current working directory and the requested version. Files that
707 changed between either parent are marked as changed for the next
705 changed between either parent are marked as changed for the next
708 commit and a commit must be performed before any further updates
706 commit and a commit must be performed before any further updates
709 are allowed.
707 are allowed.
710 '''
708 '''
711 node = node and repo.lookup(node) or repo.changelog.tip()
709 node = node and repo.lookup(node) or repo.changelog.tip()
712 return repo.update(node, allow=merge, force=clean)
710 return repo.update(node, allow=merge, force=clean)
713
711
714 def verify(ui, repo):
712 def verify(ui, repo):
715 """verify the integrity of the repository"""
713 """verify the integrity of the repository"""
716 return repo.verify()
714 return repo.verify()
717
715
718 # Command options and aliases are listed here, alphabetically
716 # Command options and aliases are listed here, alphabetically
719
717
720 table = {
718 table = {
721 "add": (add, [], "hg add [files]"),
719 "add": (add, [], "hg add [files]"),
722 "addremove": (addremove, [], "hg addremove [files]"),
720 "addremove": (addremove, [], "hg addremove [files]"),
723 "annotate": (annotate,
721 "annotate": (annotate,
724 [('r', 'revision', '', 'revision'),
722 [('r', 'revision', '', 'revision'),
725 ('u', 'user', None, 'show user'),
723 ('u', 'user', None, 'show user'),
726 ('n', 'number', None, 'show revision number'),
724 ('n', 'number', None, 'show revision number'),
727 ('c', 'changeset', None, 'show changeset')],
725 ('c', 'changeset', None, 'show changeset')],
728 'hg annotate [-u] [-c] [-n] [-r id] [files]'),
726 'hg annotate [-u] [-c] [-n] [-r id] [files]'),
729 "cat": (cat, [], 'hg cat <file> [rev]'),
727 "cat": (cat, [], 'hg cat <file> [rev]'),
730 "clone": (clone, [('U', 'no-update', None, 'skip update after cloning')],
728 "clone": (clone, [('U', 'no-update', None, 'skip update after cloning')],
731 'hg clone [options] <source> [dest]'),
729 'hg clone [options] <source> [dest]'),
732 "commit|ci": (commit,
730 "commit|ci": (commit,
733 [('t', 'text', "", 'commit text'),
731 [('t', 'text', "", 'commit text'),
734 ('A', 'addremove', None, 'run add/remove during commit'),
732 ('A', 'addremove', None, 'run add/remove during commit'),
735 ('l', 'logfile', "", 'commit text file'),
733 ('l', 'logfile', "", 'commit text file'),
736 ('d', 'date', "", 'data'),
734 ('d', 'date', "", 'data'),
737 ('u', 'user', "", 'user')],
735 ('u', 'user', "", 'user')],
738 'hg commit [files]'),
736 'hg commit [files]'),
739 "copy": (copy, [], 'hg copy <source> <dest>'),
737 "copy": (copy, [], 'hg copy <source> <dest>'),
740 "debugcheckdirstate": (debugcheckdirstate, [], 'debugcheckdirstate'),
738 "debugcheckdirstate": (debugcheckdirstate, [], 'debugcheckdirstate'),
741 "debugdumpdirstate": (debugdumpdirstate, [], 'debugdumpdirstate'),
739 "debugdumpdirstate": (debugdumpdirstate, [], 'debugdumpdirstate'),
742 "debugindex": (debugindex, [], 'debugindex <file>'),
740 "debugindex": (debugindex, [], 'debugindex <file>'),
743 "debugindexdot": (debugindexdot, [], 'debugindexdot <file>'),
741 "debugindexdot": (debugindexdot, [], 'debugindexdot <file>'),
744 "diff": (diff, [('r', 'rev', [], 'revision')],
742 "diff": (diff, [('r', 'rev', [], 'revision')],
745 'hg diff [-r A] [-r B] [files]'),
743 'hg diff [-r A] [-r B] [files]'),
746 "export": (export, [], "hg export <changeset>"),
744 "export": (export, [], "hg export <changeset>"),
747 "forget": (forget, [], "hg forget [files]"),
745 "forget": (forget, [], "hg forget [files]"),
748 "heads": (heads, [], 'hg heads'),
746 "heads": (heads, [], 'hg heads'),
749 "history": (history, [], 'hg history'),
747 "history": (history, [], 'hg history'),
750 "help": (help, [], 'hg help [command]'),
748 "help": (help, [], 'hg help [command]'),
751 "identify|id": (identify, [], 'hg identify'),
749 "identify|id": (identify, [], 'hg identify'),
752 "import|patch": (import_,
750 "import|patch": (import_,
753 [('p', 'strip', 1, 'path strip'),
751 [('p', 'strip', 1, 'path strip'),
754 ('b', 'base', "", 'base path')],
752 ('b', 'base', "", 'base path')],
755 "hg import [options] <patches>"),
753 "hg import [options] <patches>"),
756 "init": (init, [('u', 'update', None, 'update after init')],
754 "init": (init, [], 'hg init'),
757 'hg init [options] [url]'),
758 "log": (log, [], 'hg log <file>'),
755 "log": (log, [], 'hg log <file>'),
759 "manifest": (manifest, [], 'hg manifest [rev]'),
756 "manifest": (manifest, [], 'hg manifest [rev]'),
760 "parents": (parents, [], 'hg parents [node]'),
757 "parents": (parents, [], 'hg parents [node]'),
761 "pull": (pull,
758 "pull": (pull,
762 [('u', 'update', None, 'update working directory')],
759 [('u', 'update', None, 'update working directory')],
763 'hg pull [options] [source]'),
760 'hg pull [options] [source]'),
764 "push": (push, [], 'hg push <destination>'),
761 "push": (push, [], 'hg push <destination>'),
765 "rawcommit": (rawcommit,
762 "rawcommit": (rawcommit,
766 [('p', 'parent', [], 'parent'),
763 [('p', 'parent', [], 'parent'),
767 ('d', 'date', "", 'data'),
764 ('d', 'date', "", 'data'),
768 ('u', 'user', "", 'user'),
765 ('u', 'user', "", 'user'),
769 ('F', 'files', "", 'file list'),
766 ('F', 'files', "", 'file list'),
770 ('t', 'text', "", 'commit text'),
767 ('t', 'text', "", 'commit text'),
771 ('l', 'logfile', "", 'commit text file')],
768 ('l', 'logfile', "", 'commit text file')],
772 'hg rawcommit [options] [files]'),
769 'hg rawcommit [options] [files]'),
773 "recover": (recover, [], "hg recover"),
770 "recover": (recover, [], "hg recover"),
774 "remove|rm": (remove, [], "hg remove [files]"),
771 "remove|rm": (remove, [], "hg remove [files]"),
775 "root": (root, [], "hg root"),
772 "root": (root, [], "hg root"),
776 "serve": (serve, [('p', 'port', 8000, 'listen port'),
773 "serve": (serve, [('p', 'port', 8000, 'listen port'),
777 ('a', 'address', '', 'interface address'),
774 ('a', 'address', '', 'interface address'),
778 ('n', 'name', os.getcwd(), 'repository name'),
775 ('n', 'name', os.getcwd(), 'repository name'),
779 ('t', 'templates', "", 'template map')],
776 ('t', 'templates', "", 'template map')],
780 "hg serve [options]"),
777 "hg serve [options]"),
781 "status": (status, [], 'hg status'),
778 "status": (status, [], 'hg status'),
782 "tag": (tag, [('t', 'text', "", 'commit text'),
779 "tag": (tag, [('t', 'text', "", 'commit text'),
783 ('d', 'date', "", 'date'),
780 ('d', 'date', "", 'date'),
784 ('u', 'user', "", 'user')],
781 ('u', 'user', "", 'user')],
785 'hg tag [options] <name> [rev]'),
782 'hg tag [options] <name> [rev]'),
786 "tags": (tags, [], 'hg tags'),
783 "tags": (tags, [], 'hg tags'),
787 "tip": (tip, [], 'hg tip'),
784 "tip": (tip, [], 'hg tip'),
788 "undo": (undo, [], 'hg undo'),
785 "undo": (undo, [], 'hg undo'),
789 "update|up|checkout|co":
786 "update|up|checkout|co":
790 (update,
787 (update,
791 [('m', 'merge', None, 'allow merging of conflicts'),
788 [('m', 'merge', None, 'allow merging of conflicts'),
792 ('C', 'clean', None, 'overwrite locally modified files')],
789 ('C', 'clean', None, 'overwrite locally modified files')],
793 'hg update [options] [node]'),
790 'hg update [options] [node]'),
794 "verify": (verify, [], 'hg verify'),
791 "verify": (verify, [], 'hg verify'),
795 "version": (show_version, [], 'hg version'),
792 "version": (show_version, [], 'hg version'),
796 }
793 }
797
794
798 norepo = "clone init version help debugindex debugindexdot"
795 norepo = "clone init version help debugindex debugindexdot"
799
796
800 def find(cmd):
797 def find(cmd):
801 for e in table.keys():
798 for e in table.keys():
802 if re.match("(%s)$" % e, cmd):
799 if re.match("(%s)$" % e, cmd):
803 return table[e]
800 return table[e]
804
801
805 raise UnknownCommand(cmd)
802 raise UnknownCommand(cmd)
806
803
807 class SignalInterrupt(Exception): pass
804 class SignalInterrupt(Exception): pass
808
805
809 def catchterm(*args):
806 def catchterm(*args):
810 raise SignalInterrupt
807 raise SignalInterrupt
811
808
812 def run():
809 def run():
813 sys.exit(dispatch(sys.argv[1:]))
810 sys.exit(dispatch(sys.argv[1:]))
814
811
815 def dispatch(args):
812 def dispatch(args):
816 options = {}
813 options = {}
817 opts = [('v', 'verbose', None, 'verbose'),
814 opts = [('v', 'verbose', None, 'verbose'),
818 ('d', 'debug', None, 'debug'),
815 ('d', 'debug', None, 'debug'),
819 ('q', 'quiet', None, 'quiet'),
816 ('q', 'quiet', None, 'quiet'),
820 ('p', 'profile', None, 'profile'),
817 ('p', 'profile', None, 'profile'),
821 ('y', 'noninteractive', None, 'run non-interactively'),
818 ('y', 'noninteractive', None, 'run non-interactively'),
822 ('', 'version', None, 'output version information and exit'),
819 ('', 'version', None, 'output version information and exit'),
823 ]
820 ]
824
821
825 args = fancyopts.fancyopts(args, opts, options,
822 args = fancyopts.fancyopts(args, opts, options,
826 'hg [options] <command> [options] [files]')
823 'hg [options] <command> [options] [files]')
827
824
828 if not args:
825 if not args:
829 cmd = "help"
826 cmd = "help"
830 else:
827 else:
831 cmd, args = args[0], args[1:]
828 cmd, args = args[0], args[1:]
832
829
833 u = ui.ui(options["verbose"], options["debug"], options["quiet"],
830 u = ui.ui(options["verbose"], options["debug"], options["quiet"],
834 not options["noninteractive"])
831 not options["noninteractive"])
835
832
836 if options["version"]:
833 if options["version"]:
837 show_version(u)
834 show_version(u)
838 sys.exit(0)
835 sys.exit(0)
839
836
840 try:
837 try:
841 i = find(cmd)
838 i = find(cmd)
842 except UnknownCommand:
839 except UnknownCommand:
843 u.warn("hg: unknown command '%s'\n" % cmd)
840 u.warn("hg: unknown command '%s'\n" % cmd)
844 help(u)
841 help(u)
845 sys.exit(1)
842 sys.exit(1)
846
843
847 signal.signal(signal.SIGTERM, catchterm)
844 signal.signal(signal.SIGTERM, catchterm)
848
845
849 cmdoptions = {}
846 cmdoptions = {}
850 try:
847 try:
851 args = fancyopts.fancyopts(args, i[1], cmdoptions, i[2])
848 args = fancyopts.fancyopts(args, i[1], cmdoptions, i[2])
852 except fancyopts.getopt.GetoptError, inst:
849 except fancyopts.getopt.GetoptError, inst:
853 u.warn("hg %s: %s\n" % (cmd, inst))
850 u.warn("hg %s: %s\n" % (cmd, inst))
854 help(u, cmd)
851 help(u, cmd)
855 sys.exit(-1)
852 sys.exit(-1)
856
853
857 if cmd not in norepo.split():
854 if cmd not in norepo.split():
858 repo = hg.repository(ui = u)
855 repo = hg.repository(ui = u)
859 d = lambda: i[0](u, repo, *args, **cmdoptions)
856 d = lambda: i[0](u, repo, *args, **cmdoptions)
860 else:
857 else:
861 d = lambda: i[0](u, *args, **cmdoptions)
858 d = lambda: i[0](u, *args, **cmdoptions)
862
859
863 try:
860 try:
864 if options['profile']:
861 if options['profile']:
865 import hotshot, hotshot.stats
862 import hotshot, hotshot.stats
866 prof = hotshot.Profile("hg.prof")
863 prof = hotshot.Profile("hg.prof")
867 r = prof.runcall(d)
864 r = prof.runcall(d)
868 prof.close()
865 prof.close()
869 stats = hotshot.stats.load("hg.prof")
866 stats = hotshot.stats.load("hg.prof")
870 stats.strip_dirs()
867 stats.strip_dirs()
871 stats.sort_stats('time', 'calls')
868 stats.sort_stats('time', 'calls')
872 stats.print_stats(40)
869 stats.print_stats(40)
873 return r
870 return r
874 else:
871 else:
875 return d()
872 return d()
876 except SignalInterrupt:
873 except SignalInterrupt:
877 u.warn("killed!\n")
874 u.warn("killed!\n")
878 except KeyboardInterrupt:
875 except KeyboardInterrupt:
879 u.warn("interrupted!\n")
876 u.warn("interrupted!\n")
880 except IOError, inst:
877 except IOError, inst:
881 if hasattr(inst, "code"):
878 if hasattr(inst, "code"):
882 u.warn("abort: %s\n" % inst)
879 u.warn("abort: %s\n" % inst)
883 elif hasattr(inst, "reason"):
880 elif hasattr(inst, "reason"):
884 u.warn("abort: error %d: %s\n" % (inst.reason[0], inst.reason[1]))
881 u.warn("abort: error %d: %s\n" % (inst.reason[0], inst.reason[1]))
885 elif hasattr(inst, "args") and inst[0] == errno.EPIPE:
882 elif hasattr(inst, "args") and inst[0] == errno.EPIPE:
886 u.warn("broken pipe\n")
883 u.warn("broken pipe\n")
887 else:
884 else:
888 raise
885 raise
889 except TypeError, inst:
886 except TypeError, inst:
890 # was this an argument error?
887 # was this an argument error?
891 tb = traceback.extract_tb(sys.exc_info()[2])
888 tb = traceback.extract_tb(sys.exc_info()[2])
892 if len(tb) > 2: # no
889 if len(tb) > 2: # no
893 raise
890 raise
894 u.debug(inst, "\n")
891 u.debug(inst, "\n")
895 u.warn("%s: invalid arguments\n" % i[0].__name__)
892 u.warn("%s: invalid arguments\n" % i[0].__name__)
896 help(u, cmd)
893 help(u, cmd)
897 sys.exit(-1)
894 sys.exit(-1)
898
895
@@ -1,90 +1,90 b''
1 + hg -q 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 clone make a copy of an existing repository
8 clone make a copy of an existing repository
9 commit commit the specified files or all outstanding changes
9 commit commit the specified files or all outstanding changes
10 copy mark a file as copied or renamed for the next commit
10 copy mark a file as copied or renamed for the next commit
11 diff diff working directory (or selected files)
11 diff diff working directory (or selected files)
12 export dump the changeset header and diffs for a revision
12 export dump the changeset header and diffs for a revision
13 forget don't add the specified files on the next commit
13 forget don't add the specified files on the next commit
14 heads show current repository heads
14 heads show current repository heads
15 help show help for a given command or all commands
15 help show help for a given command or all commands
16 history show the changelog history
16 history show the changelog history
17 identify print information about the working copy
17 identify print information about the working copy
18 import import an ordered set of patches
18 import import an ordered set of patches
19 init create a new repository or (deprecated, use clone) copy an existing one
19 init create a new repository in the current directory
20 log show the revision history of a single file
20 log show the revision history of a single file
21 manifest output the latest or given revision of the project manifest
21 manifest output the latest or given revision of the project manifest
22 parents show the parents of the current working dir
22 parents show the parents of the current working dir
23 pull pull changes from the specified source
23 pull pull changes from the specified source
24 push push changes to the specified destination
24 push push changes to the specified destination
25 rawcommit raw commit interface
25 rawcommit raw commit interface
26 recover roll back an interrupted transaction
26 recover roll back an interrupted transaction
27 remove remove the specified files on the next commit
27 remove remove the specified files on the next commit
28 root print the root (top) of the current working dir
28 root print the root (top) of the current working dir
29 serve export the repository via HTTP
29 serve export the repository via HTTP
30 status show changed files in the working directory
30 status show changed files in the working directory
31 tag add a tag for the current tip or a given revision
31 tag add a tag for the current tip or a given revision
32 tags list repository tags
32 tags list repository tags
33 tip show the tip revision
33 tip show the tip revision
34 undo undo the last transaction
34 undo undo the last transaction
35 update update or merge working directory
35 update update or merge working directory
36 verify verify the integrity of the repository
36 verify verify the integrity of the repository
37 version output version and copyright information
37 version output version and copyright information
38 + hg add -h
38 + hg add -h
39 hg add: option -h not recognized
39 hg add: option -h not recognized
40 hg add [files]
40 hg add [files]
41
41
42 add the specified files on the next commit
42 add the specified files on the next commit
43 + hg help diff
43 + hg help diff
44 hg diff [-r A] [-r B] [files]
44 hg diff [-r A] [-r B] [files]
45
45
46 -r --rev
46 -r --rev
47 revision
47 revision
48
48
49 diff working directory (or selected files)
49 diff working directory (or selected files)
50 + hg help foo
50 + hg help foo
51 hg: unknown command foo
51 hg: unknown command foo
52 + hg -q commands
52 + hg -q commands
53 hg: unknown command 'commands'
53 hg: unknown command 'commands'
54 hg commands:
54 hg commands:
55
55
56 add add the specified files on the next commit
56 add add the specified files on the next commit
57 addremove add all new files, delete all missing files
57 addremove add all new files, delete all missing files
58 annotate show changeset information per file line
58 annotate show changeset information per file line
59 cat output the latest or given revision of a file
59 cat output the latest or given revision of a file
60 clone make a copy of an existing repository
60 clone make a copy of an existing repository
61 commit commit the specified files or all outstanding changes
61 commit commit the specified files or all outstanding changes
62 copy mark a file as copied or renamed for the next commit
62 copy mark a file as copied or renamed for the next commit
63 diff diff working directory (or selected files)
63 diff diff working directory (or selected files)
64 export dump the changeset header and diffs for a revision
64 export dump the changeset header and diffs for a revision
65 forget don't add the specified files on the next commit
65 forget don't add the specified files on the next commit
66 heads show current repository heads
66 heads show current repository heads
67 help show help for a given command or all commands
67 help show help for a given command or all commands
68 history show the changelog history
68 history show the changelog history
69 identify print information about the working copy
69 identify print information about the working copy
70 import import an ordered set of patches
70 import import an ordered set of patches
71 init create a new repository or (deprecated, use clone) copy an existing one
71 init create a new repository in the current directory
72 log show the revision history of a single file
72 log show the revision history of a single file
73 manifest output the latest or given revision of the project manifest
73 manifest output the latest or given revision of the project manifest
74 parents show the parents of the current working dir
74 parents show the parents of the current working dir
75 pull pull changes from the specified source
75 pull pull changes from the specified source
76 push push changes to the specified destination
76 push push changes to the specified destination
77 rawcommit raw commit interface
77 rawcommit raw commit interface
78 recover roll back an interrupted transaction
78 recover roll back an interrupted transaction
79 remove remove the specified files on the next commit
79 remove remove the specified files on the next commit
80 root print the root (top) of the current working dir
80 root print the root (top) of the current working dir
81 serve export the repository via HTTP
81 serve export the repository via HTTP
82 status show changed files in the working directory
82 status show changed files in the working directory
83 tag add a tag for the current tip or a given revision
83 tag add a tag for the current tip or a given revision
84 tags list repository tags
84 tags list repository tags
85 tip show the tip revision
85 tip show the tip revision
86 undo undo the last transaction
86 undo undo the last transaction
87 update update or merge working directory
87 update update or merge working directory
88 verify verify the integrity of the repository
88 verify verify the integrity of the repository
89 version output version and copyright information
89 version output version and copyright information
90 + exit 0
90 + exit 0
General Comments 0
You need to be logged in to leave comments. Login now