Show More
@@ -33,7 +33,8 b' COMMAND ELEMENTS' | |||||
33 | ---------------- |
|
33 | ---------------- | |
34 |
|
34 | |||
35 | files ...:: |
|
35 | files ...:: | |
36 | indicates one or more filename or relative path filenames |
|
36 | indicates one or more filename or relative path filenames; see | |
|
37 | "FILE NAME PATTERNS" for information on pattern matching | |||
37 |
|
38 | |||
38 | path:: |
|
39 | path:: | |
39 | indicates a path on the local machine |
|
40 | indicates a path on the local machine | |
@@ -51,11 +52,14 b' repository path::' | |||||
51 | COMMANDS |
|
52 | COMMANDS | |
52 | -------- |
|
53 | -------- | |
53 |
|
54 | |||
54 | add [files ...]:: |
|
55 | add [options] [files ...]:: | |
55 | Schedule files to be version controlled and added to the repository. |
|
56 | Schedule files to be version controlled and added to the repository. | |
56 |
|
57 | |||
57 | The files will be added to the repository at the next commit. |
|
58 | The files will be added to the repository at the next commit. | |
58 |
|
59 | |||
|
60 | If no names are given, add all files in the current directory and | |||
|
61 | its subdirectory. | |||
|
62 | ||||
59 | addremove:: |
|
63 | addremove:: | |
60 | Add all new files and remove all missing files from the repository. |
|
64 | Add all new files and remove all missing files from the repository. | |
61 |
|
65 | |||
@@ -183,14 +187,10 b' import [-p <n> -b <base> -q] <patches>::' | |||||
183 | init:: |
|
187 | init:: | |
184 | Initialize a new repository in the current directory. |
|
188 | Initialize a new repository in the current directory. | |
185 |
|
189 | |||
186 |
locate [options] [ |
|
190 | locate [options] [files]:: | |
187 |
Print all files under Mercurial control whose |
|
191 | Print all files under Mercurial control whose names match the | |
188 | given patterns. |
|
192 | given patterns. | |
189 |
|
193 | |||
190 | Patterns are shell-style globs. To restrict searches to specific |
|
|||
191 | directories, use the "-i <pat>" option. To eliminate particular |
|
|||
192 | directories from searching, use the "-x <pat>" option. |
|
|||
193 |
|
||||
194 | This command searches the current directory and its |
|
194 | This command searches the current directory and its | |
195 | subdirectories. To search an entire repository, move to the root |
|
195 | subdirectories. To search an entire repository, move to the root | |
196 | of the repository. |
|
196 | of the repository. | |
@@ -207,9 +207,9 b' locate [options] [patterns]::' | |||||
207 |
|
207 | |||
208 | -0, --print0 end filenames with NUL, for use with xargs |
|
208 | -0, --print0 end filenames with NUL, for use with xargs | |
209 | -f, --fullpath print complete paths from the filesystem root |
|
209 | -f, --fullpath print complete paths from the filesystem root | |
210 |
- |
|
210 | -I, --include <pat> include directories matching the given patterns | |
211 | -r, --rev <rev> search the repository as it stood at rev |
|
211 | -r, --rev <rev> search the repository as it stood at rev | |
212 |
- |
|
212 | -X, --exclude <pat> exclude directories matching the given patterns | |
213 |
|
213 | |||
214 | log [-r revision ...] [-p] [file]:: |
|
214 | log [-r revision ...] [-p] [file]:: | |
215 | Print the revision history of the specified file or the entire project. |
|
215 | Print the revision history of the specified file or the entire project. | |
@@ -398,6 +398,52 b' verify::' | |||||
398 | the changelog, manifest, and tracked files, as well as the |
|
398 | the changelog, manifest, and tracked files, as well as the | |
399 | integrity of their crosslinks and indices. |
|
399 | integrity of their crosslinks and indices. | |
400 |
|
400 | |||
|
401 | FILE NAME PATTERNS | |||
|
402 | ------------------ | |||
|
403 | ||||
|
404 | Mercurial accepts several notations for identifying one or more | |||
|
405 | file at a time. | |||
|
406 | ||||
|
407 | By default, Mercurial treats file names as shell-style extended | |||
|
408 | glob patterns. | |||
|
409 | ||||
|
410 | Alternate pattern notations must be specified explicitly. | |||
|
411 | ||||
|
412 | To use a plain path name without any pattern matching, start a | |||
|
413 | name with "path:". These path names must match completely, from | |||
|
414 | the root of the current repository. | |||
|
415 | ||||
|
416 | To use an extended glob, start a name with "glob:". Globs are | |||
|
417 | rooted at the current directory; a glob such as "*.c" will match | |||
|
418 | files ending in ".c" in the current directory only. | |||
|
419 | ||||
|
420 | The supported glob syntax extensions are "**" to match any string | |||
|
421 | across path separators, and "{a,b}" to mean "a or b". | |||
|
422 | ||||
|
423 | To use a Perl/Python regular expression, start a name with "re:". | |||
|
424 | Regexp pattern matching is anchored at the root of the repository. | |||
|
425 | ||||
|
426 | Plain examples: | |||
|
427 | ||||
|
428 | path:foo/bar a name bar in a directory named foo in the root of | |||
|
429 | the repository | |||
|
430 | path:path:name a file or directory named "path:name" | |||
|
431 | ||||
|
432 | Glob examples: | |||
|
433 | ||||
|
434 | glob:*.c any name ending in ".c" in the current directory | |||
|
435 | *.c any name ending in ".c" in the current directory | |||
|
436 | **.c any name ending in ".c" in the current directory, or | |||
|
437 | any subdirectory | |||
|
438 | foo/*.c any name ending in ".c" in the directory foo | |||
|
439 | foo/**.c any name ending in ".c" in the directory foo, or any | |||
|
440 | subdirectory | |||
|
441 | ||||
|
442 | Regexp examples: | |||
|
443 | ||||
|
444 | re:.*\.c$ any name ending in ".c", anywhere in the repsitory | |||
|
445 | ||||
|
446 | ||||
401 | SPECIFYING SINGLE REVISIONS |
|
447 | SPECIFYING SINGLE REVISIONS | |
402 | --------------------------- |
|
448 | --------------------------- | |
403 |
|
449 |
@@ -36,6 +36,39 b' def relpath(repo, args):' | |||||
36 | for x in args] |
|
36 | for x in args] | |
37 | return args |
|
37 | return args | |
38 |
|
38 | |||
|
39 | def matchpats(ui, cwd, pats = [], opts = {}): | |||
|
40 | head = '' | |||
|
41 | if opts.get('rootless'): head = '(?:.*/|)' | |||
|
42 | def reify(name, tail): | |||
|
43 | if name.startswith('re:'): | |||
|
44 | return name[3:] | |||
|
45 | elif name.startswith('glob:'): | |||
|
46 | return head + util.globre(name[5:], '', tail) | |||
|
47 | elif name.startswith('path:'): | |||
|
48 | return '^' + re.escape(name[5:]) + '$' | |||
|
49 | return head + util.globre(name, '', tail) | |||
|
50 | cwdsep = cwd + os.sep | |||
|
51 | def under(fn): | |||
|
52 | if not cwd or fn.startswith(cwdsep): return True | |||
|
53 | def matchfn(pats, tail, ifempty = util.always): | |||
|
54 | if not pats: return ifempty | |||
|
55 | pat = '(?:%s)' % '|'.join([reify(p, tail) for p in pats]) | |||
|
56 | if cwd: pat = re.escape(cwd + os.sep) + pat | |||
|
57 | ui.debug('regexp: %s\n' % pat) | |||
|
58 | return re.compile(pat).match | |||
|
59 | patmatch = matchfn(pats, '$') | |||
|
60 | incmatch = matchfn(opts.get('include'), '(?:/|$)', under) | |||
|
61 | excmatch = matchfn(opts.get('exclude'), '(?:/|$)', util.never) | |||
|
62 | return lambda fn: (incmatch(fn) and not excmatch(fn) and | |||
|
63 | (fn.endswith('/') or patmatch(fn))) | |||
|
64 | ||||
|
65 | def walk(repo, pats, opts): | |||
|
66 | cwd = repo.getcwd() | |||
|
67 | if cwd: c = len(cwd) + 1 | |||
|
68 | for fn in repo.walk(match = matchpats(repo.ui, cwd, pats, opts)): | |||
|
69 | if cwd: yield fn, fn[c:] | |||
|
70 | else: yield fn, fn | |||
|
71 | ||||
39 | revrangesep = ':' |
|
72 | revrangesep = ':' | |
40 |
|
73 | |||
41 | def revrange(ui, repo, revs, revlog=None): |
|
74 | def revrange(ui, repo, revs, revlog=None): | |
@@ -288,9 +321,17 b' def help_(ui, cmd=None):' | |||||
288 |
|
321 | |||
289 | # Commands start here, listed alphabetically |
|
322 | # Commands start here, listed alphabetically | |
290 |
|
323 | |||
291 |
def add(ui, repo, |
|
324 | def add(ui, repo, *pats, **opts): | |
292 | '''add the specified files on the next commit''' |
|
325 | '''add the specified files on the next commit''' | |
293 | repo.add(relpath(repo, (file1,) + files)) |
|
326 | names = [] | |
|
327 | q = dict(zip(pats, pats)) | |||
|
328 | for abs, rel in walk(repo, pats, opts): | |||
|
329 | if rel in q or abs in q: | |||
|
330 | names.append(abs) | |||
|
331 | elif repo.dirstate.state(abs) == '?': | |||
|
332 | ui.status('adding %s\n' % rel) | |||
|
333 | names.append(abs) | |||
|
334 | repo.add(names) | |||
294 |
|
335 | |||
295 | def addremove(ui, repo, *files): |
|
336 | def addremove(ui, repo, *files): | |
296 | """add all new files, delete all missing files""" |
|
337 | """add all new files, delete all missing files""" | |
@@ -669,46 +710,15 b' def init(ui, source=None):' | |||||
669 |
|
710 | |||
670 | def locate(ui, repo, *pats, **opts): |
|
711 | def locate(ui, repo, *pats, **opts): | |
671 | """locate files matching specific patterns""" |
|
712 | """locate files matching specific patterns""" | |
672 | if [p for p in pats if os.sep in p]: |
|
713 | if opts['print0']: end = '\0' | |
673 | ui.warn("error: patterns may not contain '%s'\n" % os.sep) |
|
714 | else: end = '\n' | |
674 | ui.warn("use '-i <dir>' instead\n") |
|
715 | opts['rootless'] = True | |
675 | sys.exit(1) |
|
716 | for abs, rel in walk(repo, pats, opts): | |
676 | def compile(pats, head='^', tail=os.sep, on_empty=True): |
|
717 | if repo.dirstate.state(abs) == '?': continue | |
677 |
if |
|
718 | if opts['fullpath']: | |
678 | class c: |
|
719 | ui.write(os.path.join(repo.root, abs), end) | |
679 | def match(self, x): |
|
|||
680 | return on_empty |
|
|||
681 | return c() |
|
|||
682 | fnpats = [fnmatch.translate(os.path.normpath(os.path.normcase(p)))[:-1] |
|
|||
683 | for p in pats] |
|
|||
684 | regexp = r'%s(?:%s)%s' % (head, '|'.join(fnpats), tail) |
|
|||
685 | return re.compile(regexp) |
|
|||
686 | exclude = compile(opts['exclude'], on_empty=False) |
|
|||
687 | include = compile(opts['include']) |
|
|||
688 | pat = compile(pats, head='', tail='$') |
|
|||
689 | end = opts['print0'] and '\0' or '\n' |
|
|||
690 | if opts['rev']: |
|
|||
691 | node = repo.manifest.lookup(opts['rev']) |
|
|||
692 | else: |
|
720 | else: | |
693 | node = repo.manifest.tip() |
|
721 | ui.write(rel, end) | |
694 | manifest = repo.manifest.read(node) |
|
|||
695 | cwd = repo.getcwd() |
|
|||
696 | cwd_plus = cwd and (cwd + os.sep) |
|
|||
697 | found = [] |
|
|||
698 | for f in manifest: |
|
|||
699 | f = os.path.normcase(f) |
|
|||
700 | if exclude.match(f) or not(include.match(f) and |
|
|||
701 | f.startswith(cwd_plus) and |
|
|||
702 | pat.match(os.path.basename(f))): |
|
|||
703 | continue |
|
|||
704 | if opts['fullpath']: |
|
|||
705 | f = os.path.join(repo.root, f) |
|
|||
706 | elif cwd: |
|
|||
707 | f = f[len(cwd_plus):] |
|
|||
708 | found.append(f) |
|
|||
709 | found.sort() |
|
|||
710 | for f in found: |
|
|||
711 | ui.write(f, end) |
|
|||
712 |
|
722 | |||
713 | def log(ui, repo, f=None, **opts): |
|
723 | def log(ui, repo, f=None, **opts): | |
714 | """show the revision history of the repository or a single file""" |
|
724 | """show the revision history of the repository or a single file""" | |
@@ -1087,7 +1097,10 b' def verify(ui, repo):' | |||||
1087 | # Command options and aliases are listed here, alphabetically |
|
1097 | # Command options and aliases are listed here, alphabetically | |
1088 |
|
1098 | |||
1089 | table = { |
|
1099 | table = { | |
1090 | "^add": (add, [], "hg add [files]"), |
|
1100 | "^add": (add, | |
|
1101 | [('I', 'include', [], 'include path in search'), | |||
|
1102 | ('X', 'exclude', [], 'exclude path from search')], | |||
|
1103 | "hg add [options] [files]"), | |||
1091 | "addremove": (addremove, [], "hg addremove [files]"), |
|
1104 | "addremove": (addremove, [], "hg addremove [files]"), | |
1092 | "^annotate": |
|
1105 | "^annotate": | |
1093 | (annotate, |
|
1106 | (annotate, | |
@@ -1139,9 +1152,9 b' table = {' | |||||
1139 | (locate, |
|
1152 | (locate, | |
1140 | [('0', 'print0', None, 'end records with NUL'), |
|
1153 | [('0', 'print0', None, 'end records with NUL'), | |
1141 | ('f', 'fullpath', None, 'print complete paths'), |
|
1154 | ('f', 'fullpath', None, 'print complete paths'), | |
1142 |
(' |
|
1155 | ('I', 'include', [], 'include path in search'), | |
1143 | ('r', 'rev', '', 'revision'), |
|
1156 | ('r', 'rev', '', 'revision'), | |
1144 |
(' |
|
1157 | ('X', 'exclude', [], 'exclude path from search')], | |
1145 | 'hg locate [options] [files]'), |
|
1158 | 'hg locate [options] [files]'), | |
1146 | "^log|history": |
|
1159 | "^log|history": | |
1147 | (log, |
|
1160 | (log, |
@@ -13,9 +13,6 b' demandload(globals(), "re lock urllib ur' | |||||
13 | demandload(globals(), "tempfile httprangereader bdiff") |
|
13 | demandload(globals(), "tempfile httprangereader bdiff") | |
14 | demandload(globals(), "bisect select") |
|
14 | demandload(globals(), "bisect select") | |
15 |
|
15 | |||
16 | def always(fn): |
|
|||
17 | return True |
|
|||
18 |
|
||||
19 | class filelog(revlog): |
|
16 | class filelog(revlog): | |
20 | def __init__(self, opener, path): |
|
17 | def __init__(self, opener, path): | |
21 | revlog.__init__(self, opener, |
|
18 | revlog.__init__(self, opener, | |
@@ -416,7 +413,7 b' class dirstate:' | |||||
416 | st.write(e + f) |
|
413 | st.write(e + f) | |
417 | self.dirty = 0 |
|
414 | self.dirty = 0 | |
418 |
|
415 | |||
419 | def walk(self, files = None, match = always): |
|
416 | def walk(self, files = None, match = util.always): | |
420 | self.read() |
|
417 | self.read() | |
421 | dc = self.map.copy() |
|
418 | dc = self.map.copy() | |
422 | # walk all files by default |
|
419 | # walk all files by default | |
@@ -454,7 +451,7 b' class dirstate:' | |||||
454 | if match(fn): |
|
451 | if match(fn): | |
455 | yield fn |
|
452 | yield fn | |
456 |
|
453 | |||
457 | def changes(self, files = None, match = always): |
|
454 | def changes(self, files = None, match = util.always): | |
458 | self.read() |
|
455 | self.read() | |
459 | dc = self.map.copy() |
|
456 | dc = self.map.copy() | |
460 | lookup, changed, added, unknown = [], [], [], [] |
|
457 | lookup, changed, added, unknown = [], [], [], [] | |
@@ -840,12 +837,16 b' class localrepository:' | |||||
840 | if not self.hook("commit", node=hex(n)): |
|
837 | if not self.hook("commit", node=hex(n)): | |
841 | return 1 |
|
838 | return 1 | |
842 |
|
839 | |||
843 |
def walk(self, |
|
840 | def walk(self, node = None, files = [], match = util.always): | |
844 | if rev is None: fns = self.dirstate.walk(files, match) |
|
841 | if node: | |
845 | else: fns = filter(match, self.manifest.read(rev)) |
|
842 | change = self.changelog.read(node) | |
|
843 | fns = filter(match, self.manifest.read(change[0])) | |||
|
844 | else: | |||
|
845 | fns = self.dirstate.walk(files, match) | |||
846 | for fn in fns: yield fn |
|
846 | for fn in fns: yield fn | |
847 |
|
847 | |||
848 |
def changes(self, node1 = None, node2 = None, files = [], |
|
848 | def changes(self, node1 = None, node2 = None, files = [], | |
|
849 | match = util.always): | |||
849 | mf2, u = None, [] |
|
850 | mf2, u = None, [] | |
850 |
|
851 | |||
851 | def fcmp(fn, mf): |
|
852 | def fcmp(fn, mf): | |
@@ -922,7 +923,7 b' class localrepository:' | |||||
922 | self.ui.warn("%s does not exist!\n" % f) |
|
923 | self.ui.warn("%s does not exist!\n" % f) | |
923 | elif not os.path.isfile(p): |
|
924 | elif not os.path.isfile(p): | |
924 | self.ui.warn("%s not added: mercurial only supports files currently\n" % f) |
|
925 | self.ui.warn("%s not added: mercurial only supports files currently\n" % f) | |
925 |
elif self.dirstate.state(f) |
|
926 | elif self.dirstate.state(f) in 'an': | |
926 | self.ui.warn("%s already tracked!\n" % f) |
|
927 | self.ui.warn("%s already tracked!\n" % f) | |
927 | else: |
|
928 | else: | |
928 | self.dirstate.update([f], "a") |
|
929 | self.dirstate.update([f], "a") |
@@ -6,6 +6,8 b'' | |||||
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, errno |
|
8 | import os, errno | |
|
9 | from demandload import * | |||
|
10 | demandload(globals(), "re") | |||
9 |
|
11 | |||
10 | def unique(g): |
|
12 | def unique(g): | |
11 | seen = {} |
|
13 | seen = {} | |
@@ -29,6 +31,54 b' def explain_exit(code):' | |||||
29 | return "stopped by signal %d" % val, val |
|
31 | return "stopped by signal %d" % val, val | |
30 | raise ValueError("invalid exit code") |
|
32 | raise ValueError("invalid exit code") | |
31 |
|
33 | |||
|
34 | def always(fn): return True | |||
|
35 | def never(fn): return False | |||
|
36 | ||||
|
37 | def globre(pat, head = '^', tail = '$'): | |||
|
38 | "convert a glob pattern into a regexp" | |||
|
39 | i, n = 0, len(pat) | |||
|
40 | res = '' | |||
|
41 | group = False | |||
|
42 | def peek(): return i < n and pat[i] | |||
|
43 | while i < n: | |||
|
44 | c = pat[i] | |||
|
45 | i = i+1 | |||
|
46 | if c == '*': | |||
|
47 | if peek() == '*': | |||
|
48 | i += 1 | |||
|
49 | res += '.*' | |||
|
50 | else: | |||
|
51 | res += '[^/]*' | |||
|
52 | elif c == '?': | |||
|
53 | res += '.' | |||
|
54 | elif c == '[': | |||
|
55 | j = i | |||
|
56 | if j < n and pat[j] in '!]': | |||
|
57 | j += 1 | |||
|
58 | while j < n and pat[j] != ']': | |||
|
59 | j += 1 | |||
|
60 | if j >= n: | |||
|
61 | res += '\\[' | |||
|
62 | else: | |||
|
63 | stuff = pat[i:j].replace('\\','\\\\') | |||
|
64 | i = j + 1 | |||
|
65 | if stuff[0] == '!': | |||
|
66 | stuff = '^' + stuff[1:] | |||
|
67 | elif stuff[0] == '^': | |||
|
68 | stuff = '\\' + stuff | |||
|
69 | res = '%s[%s]' % (res, stuff) | |||
|
70 | elif c == '{': | |||
|
71 | group = True | |||
|
72 | res += '(?:' | |||
|
73 | elif c == '}' and group: | |||
|
74 | res += ')' | |||
|
75 | group = False | |||
|
76 | elif c == ',' and group: | |||
|
77 | res += '|' | |||
|
78 | else: | |||
|
79 | res += re.escape(c) | |||
|
80 | return head + res + tail | |||
|
81 | ||||
32 | def system(cmd, errprefix=None): |
|
82 | def system(cmd, errprefix=None): | |
33 | """execute a shell command that must succeed""" |
|
83 | """execute a shell command that must succeed""" | |
34 | rc = os.system(cmd) |
|
84 | rc = os.system(cmd) |
General Comments 0
You need to be logged in to leave comments.
Login now