Show More
@@ -33,7 +33,8 b' COMMAND ELEMENTS' | |||
|
33 | 33 | ---------------- |
|
34 | 34 | |
|
35 | 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 | 39 | path:: |
|
39 | 40 | indicates a path on the local machine |
@@ -51,11 +52,14 b' repository path::' | |||
|
51 | 52 | COMMANDS |
|
52 | 53 | -------- |
|
53 | 54 | |
|
54 | add [files ...]:: | |
|
55 | add [options] [files ...]:: | |
|
55 | 56 | Schedule files to be version controlled and added to the repository. |
|
56 | 57 | |
|
57 | 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 | 63 | addremove:: |
|
60 | 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 | 187 | init:: |
|
184 | 188 | Initialize a new repository in the current directory. |
|
185 | 189 | |
|
186 |
locate [options] [ |
|
|
187 |
Print all files under Mercurial control whose |
|
|
190 | locate [options] [files]:: | |
|
191 | Print all files under Mercurial control whose names match the | |
|
188 | 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 | 194 | This command searches the current directory and its |
|
195 | 195 | subdirectories. To search an entire repository, move to the root |
|
196 | 196 | of the repository. |
@@ -207,9 +207,9 b' locate [options] [patterns]::' | |||
|
207 | 207 | |
|
208 | 208 | -0, --print0 end filenames with NUL, for use with xargs |
|
209 | 209 | -f, --fullpath print complete paths from the filesystem root |
|
210 |
- |
|
|
210 | -I, --include <pat> include directories matching the given patterns | |
|
211 | 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 | 214 | log [-r revision ...] [-p] [file]:: |
|
215 | 215 | Print the revision history of the specified file or the entire project. |
@@ -398,6 +398,52 b' verify::' | |||
|
398 | 398 | the changelog, manifest, and tracked files, as well as the |
|
399 | 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 | 447 | SPECIFYING SINGLE REVISIONS |
|
402 | 448 | --------------------------- |
|
403 | 449 |
@@ -36,6 +36,39 b' def relpath(repo, args):' | |||
|
36 | 36 | for x in args] |
|
37 | 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 | 72 | revrangesep = ':' |
|
40 | 73 | |
|
41 | 74 | def revrange(ui, repo, revs, revlog=None): |
@@ -288,9 +321,17 b' def help_(ui, cmd=None):' | |||
|
288 | 321 | |
|
289 | 322 | # Commands start here, listed alphabetically |
|
290 | 323 | |
|
291 |
def add(ui, repo, |
|
|
324 | def add(ui, repo, *pats, **opts): | |
|
292 | 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 | 336 | def addremove(ui, repo, *files): |
|
296 | 337 | """add all new files, delete all missing files""" |
@@ -669,46 +710,15 b' def init(ui, source=None):' | |||
|
669 | 710 | |
|
670 | 711 | def locate(ui, repo, *pats, **opts): |
|
671 | 712 | """locate files matching specific patterns""" |
|
672 | if [p for p in pats if os.sep in p]: | |
|
673 | ui.warn("error: patterns may not contain '%s'\n" % os.sep) | |
|
674 | ui.warn("use '-i <dir>' instead\n") | |
|
675 | sys.exit(1) | |
|
676 | def compile(pats, head='^', tail=os.sep, on_empty=True): | |
|
677 | if not pats: | |
|
678 | class c: | |
|
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: | |
|
693 | node = repo.manifest.tip() | |
|
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 | |
|
713 | if opts['print0']: end = '\0' | |
|
714 | else: end = '\n' | |
|
715 | opts['rootless'] = True | |
|
716 | for abs, rel in walk(repo, pats, opts): | |
|
717 | if repo.dirstate.state(abs) == '?': continue | |
|
704 | 718 | if opts['fullpath']: |
|
705 |
|
|
|
706 |
el |
|
|
707 | f = f[len(cwd_plus):] | |
|
708 | found.append(f) | |
|
709 | found.sort() | |
|
710 | for f in found: | |
|
711 | ui.write(f, end) | |
|
719 | ui.write(os.path.join(repo.root, abs), end) | |
|
720 | else: | |
|
721 | ui.write(rel, end) | |
|
712 | 722 | |
|
713 | 723 | def log(ui, repo, f=None, **opts): |
|
714 | 724 | """show the revision history of the repository or a single file""" |
@@ -1087,7 +1097,10 b' def verify(ui, repo):' | |||
|
1087 | 1097 | # Command options and aliases are listed here, alphabetically |
|
1088 | 1098 | |
|
1089 | 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 | 1104 | "addremove": (addremove, [], "hg addremove [files]"), |
|
1092 | 1105 | "^annotate": |
|
1093 | 1106 | (annotate, |
@@ -1139,9 +1152,9 b' table = {' | |||
|
1139 | 1152 | (locate, |
|
1140 | 1153 | [('0', 'print0', None, 'end records with NUL'), |
|
1141 | 1154 | ('f', 'fullpath', None, 'print complete paths'), |
|
1142 |
(' |
|
|
1155 | ('I', 'include', [], 'include path in search'), | |
|
1143 | 1156 | ('r', 'rev', '', 'revision'), |
|
1144 |
(' |
|
|
1157 | ('X', 'exclude', [], 'exclude path from search')], | |
|
1145 | 1158 | 'hg locate [options] [files]'), |
|
1146 | 1159 | "^log|history": |
|
1147 | 1160 | (log, |
@@ -13,9 +13,6 b' demandload(globals(), "re lock urllib ur' | |||
|
13 | 13 | demandload(globals(), "tempfile httprangereader bdiff") |
|
14 | 14 | demandload(globals(), "bisect select") |
|
15 | 15 | |
|
16 | def always(fn): | |
|
17 | return True | |
|
18 | ||
|
19 | 16 | class filelog(revlog): |
|
20 | 17 | def __init__(self, opener, path): |
|
21 | 18 | revlog.__init__(self, opener, |
@@ -416,7 +413,7 b' class dirstate:' | |||
|
416 | 413 | st.write(e + f) |
|
417 | 414 | self.dirty = 0 |
|
418 | 415 | |
|
419 | def walk(self, files = None, match = always): | |
|
416 | def walk(self, files = None, match = util.always): | |
|
420 | 417 | self.read() |
|
421 | 418 | dc = self.map.copy() |
|
422 | 419 | # walk all files by default |
@@ -454,7 +451,7 b' class dirstate:' | |||
|
454 | 451 | if match(fn): |
|
455 | 452 | yield fn |
|
456 | 453 | |
|
457 | def changes(self, files = None, match = always): | |
|
454 | def changes(self, files = None, match = util.always): | |
|
458 | 455 | self.read() |
|
459 | 456 | dc = self.map.copy() |
|
460 | 457 | lookup, changed, added, unknown = [], [], [], [] |
@@ -840,12 +837,16 b' class localrepository:' | |||
|
840 | 837 | if not self.hook("commit", node=hex(n)): |
|
841 | 838 | return 1 |
|
842 | 839 | |
|
843 |
def walk(self, |
|
|
844 | if rev is None: fns = self.dirstate.walk(files, match) | |
|
845 | else: fns = filter(match, self.manifest.read(rev)) | |
|
840 | def walk(self, node = None, files = [], match = util.always): | |
|
841 | if node: | |
|
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 | 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 | 850 | mf2, u = None, [] |
|
850 | 851 | |
|
851 | 852 | def fcmp(fn, mf): |
@@ -922,7 +923,7 b' class localrepository:' | |||
|
922 | 923 | self.ui.warn("%s does not exist!\n" % f) |
|
923 | 924 | elif not os.path.isfile(p): |
|
924 | 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 | 927 | self.ui.warn("%s already tracked!\n" % f) |
|
927 | 928 | else: |
|
928 | 929 | self.dirstate.update([f], "a") |
@@ -6,6 +6,8 b'' | |||
|
6 | 6 | # of the GNU General Public License, incorporated herein by reference. |
|
7 | 7 | |
|
8 | 8 | import os, errno |
|
9 | from demandload import * | |
|
10 | demandload(globals(), "re") | |
|
9 | 11 | |
|
10 | 12 | def unique(g): |
|
11 | 13 | seen = {} |
@@ -29,6 +31,54 b' def explain_exit(code):' | |||
|
29 | 31 | return "stopped by signal %d" % val, val |
|
30 | 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 | 82 | def system(cmd, errprefix=None): |
|
33 | 83 | """execute a shell command that must succeed""" |
|
34 | 84 | rc = os.system(cmd) |
General Comments 0
You need to be logged in to leave comments.
Login now