##// END OF EJS Templates
Get add and locate to use new repo and dirstate walk code....
Bryan O'Sullivan -
r724:1c0c413c default
parent child Browse files
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] [patterns]::
187 Print all files under Mercurial control whose basenames match the
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 -i, --include <pat> include directories matching the given globs
210 -I, --include <pat> include directories matching the given patterns
211 211 -r, --rev <rev> search the repository as it stood at rev
212 -x, --exclude <pat> exclude directories matching the given globs
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, file1, *files):
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'])
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
718 if opts['fullpath']:
719 ui.write(os.path.join(repo.root, abs), end)
692 720 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
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)
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 ('i', 'include', [], 'include path in search'),
1155 ('I', 'include', [], 'include path in search'),
1143 1156 ('r', 'rev', '', 'revision'),
1144 ('x', 'exclude', [], 'exclude path from search')],
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, rev = None, files = [], match = always):
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 = [], match = always):
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) == 'n':
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