Show More
@@ -40,16 +40,24 b' def relpath(repo, args):' | |||
|
40 | 40 | return args |
|
41 | 41 | |
|
42 | 42 | def matchpats(cwd, pats = [], opts = {}, head = ''): |
|
43 | return util.matcher(cwd, pats, opts.get('include'), | |
|
43 | return util.matcher(cwd, pats or ['.'], opts.get('include'), | |
|
44 | 44 | opts.get('exclude'), head) |
|
45 | 45 | |
|
46 | def pathto(n1, n2): | |
|
47 | '''return the relative path from one place to another''' | |
|
48 | if not n1: return n2 | |
|
49 | a, b = n1.split(os.sep), n2.split(os.sep) | |
|
50 | a.reverse(), b.reverse() | |
|
51 | while a and b and a[-1] == b[-1]: | |
|
52 | a.pop(), b.pop() | |
|
53 | b.reverse() | |
|
54 | return os.sep.join((['..'] * len(a)) + b) | |
|
55 | ||
|
46 | 56 | def walk(repo, pats, opts, head = ''): |
|
47 | 57 | cwd = repo.getcwd() |
|
48 | c = 0 | |
|
49 | if cwd: c = len(cwd) + 1 | |
|
50 | 58 | files, matchfn = matchpats(cwd, pats, opts, head) |
|
51 | 59 | for src, fn in repo.walk(files = files, match = matchfn): |
|
52 |
yield src, fn, fn |
|
|
60 | yield src, fn, pathto(cwd, fn) | |
|
53 | 61 | |
|
54 | 62 | revrangesep = ':' |
|
55 | 63 | |
@@ -565,6 +573,11 b' def debugindexdot(ui, file_):' | |||
|
565 | 573 | ui.write("\t%d -> %d\n" % (r.rev(e[5]), i)) |
|
566 | 574 | ui.write("}\n") |
|
567 | 575 | |
|
576 | def debugwalk(ui, repo, *pats, **opts): | |
|
577 | items = list(walk(repo, pats, opts)) | |
|
578 | fmt = '%%s %%-%ds %%s' % max([len(abs) for (src, abs, rel) in items]) | |
|
579 | for i in items: print fmt % i | |
|
580 | ||
|
568 | 581 | def diff(ui, repo, *pats, **opts): |
|
569 | 582 | """diff working directory (or selected files)""" |
|
570 | 583 | revs = [] |
@@ -1015,9 +1028,10 b' def status(ui, repo, *pats, **opts):' | |||
|
1015 | 1028 | R = removed |
|
1016 | 1029 | ? = not tracked''' |
|
1017 | 1030 | |
|
1018 | files, matchfn = matchpats(repo.getcwd(), pats, opts) | |
|
1019 | (c, a, d, u) = repo.changes(files = files, match = matchfn) | |
|
1020 | (c, a, d, u) = map(lambda x: relfilter(repo, x), (c, a, d, u)) | |
|
1031 | cwd = repo.getcwd() | |
|
1032 | files, matchfn = matchpats(cwd, pats, opts) | |
|
1033 | (c, a, d, u) = [[pathto(cwd, x) for x in n] | |
|
1034 | for n in repo.changes(files=files, match=matchfn)] | |
|
1021 | 1035 | |
|
1022 | 1036 | for f in c: |
|
1023 | 1037 | ui.write("M ", f, "\n") |
@@ -1160,6 +1174,10 b' table = {' | |||
|
1160 | 1174 | "debugstate": (debugstate, [], 'debugstate'), |
|
1161 | 1175 | "debugindex": (debugindex, [], 'debugindex FILE'), |
|
1162 | 1176 | "debugindexdot": (debugindexdot, [], 'debugindexdot FILE'), |
|
1177 | "debugwalk": (debugwalk, | |
|
1178 | [('I', 'include', [], 'include path in search'), | |
|
1179 | ('X', 'exclude', [], 'exclude path from search')], | |
|
1180 | 'debugwalk [OPTIONS]... [FILE]...'), | |
|
1163 | 1181 | "^diff": |
|
1164 | 1182 | (diff, |
|
1165 | 1183 | [('r', 'rev', [], 'revision'), |
@@ -440,32 +440,43 b' class dirstate:' | |||
|
440 | 440 | dc = self.map.copy() |
|
441 | 441 | # walk all files by default |
|
442 | 442 | if not files: files = [self.root] |
|
443 | known = {'.hg': 1} | |
|
444 | def seen(fn): | |
|
445 | if fn in known: return True | |
|
446 | known[fn] = 1 | |
|
443 | 447 | def traverse(): |
|
444 | 448 | for f in util.unique(files): |
|
445 | 449 | f = os.path.join(self.root, f) |
|
446 | 450 | if os.path.isdir(f): |
|
447 | 451 | for dir, subdirs, fl in os.walk(f): |
|
448 | 452 | d = dir[len(self.root) + 1:] |
|
449 |
|
|
|
453 | nd = os.path.normpath(d) | |
|
454 | if seen(nd): | |
|
450 | 455 | subdirs[:] = [] |
|
451 | 456 | continue |
|
452 | 457 | for sd in subdirs: |
|
453 | ds = os.path.join(d, sd +'/') | |
|
458 | ds = os.path.join(nd, sd +'/') | |
|
454 | 459 | if self.ignore(ds) or not match(ds): |
|
455 | 460 | subdirs.remove(sd) |
|
461 | subdirs.sort() | |
|
462 | fl.sort() | |
|
456 | 463 | for fn in fl: |
|
457 | 464 | fn = util.pconvert(os.path.join(d, fn)) |
|
458 | 465 | yield 'f', fn |
|
459 | 466 | else: |
|
460 | 467 | yield 'f', f[len(self.root) + 1:] |
|
461 | 468 | |
|
462 |
|
|
|
469 | ks = dc.keys() | |
|
470 | ks.sort() | |
|
471 | for k in ks: | |
|
463 | 472 | yield 'm', k |
|
464 | 473 | |
|
465 | 474 | # yield only files that match: all in dirstate, others only if |
|
466 | 475 | # not in .hgignore |
|
467 | 476 | |
|
468 | 477 | for src, fn in util.unique(traverse()): |
|
478 | fn = os.path.normpath(fn) | |
|
479 | if seen(fn): continue | |
|
469 | 480 | if fn in dc: |
|
470 | 481 | del dc[fn] |
|
471 | 482 | elif self.ignore(fn): |
@@ -868,7 +879,7 b' class localrepository:' | |||
|
868 | 879 | def walk(self, node = None, files = [], match = util.always): |
|
869 | 880 | if node: |
|
870 | 881 | for fn in self.manifest.read(self.changelog.read(node)[0]): |
|
871 | yield 'm', fn | |
|
882 | if match(fn): yield 'm', fn | |
|
872 | 883 | else: |
|
873 | 884 | for src, fn in self.dirstate.walk(files, match): |
|
874 | 885 | yield src, fn |
@@ -69,24 +69,27 b" def globre(pat, head = '^', tail = '$'):" | |||
|
69 | 69 | _globchars = {'[': 1, '{': 1, '*': 1, '?': 1} |
|
70 | 70 | |
|
71 | 71 | def matcher(cwd, names, inc, exc, head = ''): |
|
72 |
def pat |
|
|
72 | def patkind(name): | |
|
73 | 73 | for prefix in 're:', 'glob:', 'path:': |
|
74 |
if name.startswith(prefix): return |
|
|
74 | if name.startswith(prefix): return name.split(':', 1) | |
|
75 | 75 | for c in name: |
|
76 |
if c in _globchars: return |
|
|
76 | if c in _globchars: return 'glob', name | |
|
77 | return 'relpath', name | |
|
78 | ||
|
79 | cwdsep = cwd + os.sep | |
|
77 | 80 | |
|
78 | 81 | def regex(name, tail): |
|
79 | 82 | '''convert a pattern into a regular expression''' |
|
80 | if name.startswith('re:'): | |
|
81 | return name[3:] | |
|
82 | elif name.startswith('path:'): | |
|
83 | return '^' + re.escape(name[5:]) + '$' | |
|
84 | elif name.startswith('glob:'): | |
|
85 | return head + globre(name[5:], '', tail) | |
|
83 | kind, name = patkind(name) | |
|
84 | if kind == 're': | |
|
85 | return name | |
|
86 | elif kind == 'path': | |
|
87 | return '^' + re.escape(name) + '$' | |
|
88 | if cwd: name = os.path.join(cwdsep, name) | |
|
89 | name = os.path.normpath(name) | |
|
90 | if name == '.': name = '**' | |
|
86 | 91 | return head + globre(name, '', tail) |
|
87 | 92 | |
|
88 | cwdsep = cwd + os.sep | |
|
89 | ||
|
90 | 93 | def under(fn): |
|
91 | 94 | """check if fn is under our cwd""" |
|
92 | 95 | return not cwd or fn.startswith(cwdsep) |
@@ -95,22 +98,28 b' def matcher(cwd, names, inc, exc, head =' | |||
|
95 | 98 | """build a matching function from a set of patterns""" |
|
96 | 99 | if pats: |
|
97 | 100 | pat = '(?:%s)' % '|'.join([regex(p, tail) for p in pats]) |
|
98 | if cwd: | |
|
99 | pat = re.escape(cwdsep) + pat | |
|
100 | 101 | return re.compile(pat).match |
|
101 | 102 | |
|
102 | pats = filter(patlike, names) | |
|
103 | files = [n for n in names if not patlike(n)] | |
|
104 | if pats: plain = [] | |
|
105 | elif cwd: plain = [cwdsep + f for f in files] | |
|
106 | else: plain = files | |
|
103 | def globprefix(pat): | |
|
104 | '''return the non-glob prefix of a path, e.g. foo/* -> foo''' | |
|
105 | root = [] | |
|
106 | for p in pat.split(os.sep): | |
|
107 | if patkind(p)[0] == 'glob': break | |
|
108 | root.append(p) | |
|
109 | return os.sep.join(root) | |
|
110 | ||
|
111 | patkinds = map(patkind, names) | |
|
112 | pats = [name for (kind, name) in patkinds if kind != 'relpath'] | |
|
113 | files = [name for (kind, name) in patkinds if kind == 'relpath'] | |
|
114 | roots = filter(None, map(globprefix, pats)) + files | |
|
115 | if cwd: roots = [cwdsep + r for r in roots] | |
|
107 | 116 | |
|
108 | patmatch = matchfn(pats, '$') | |
|
109 | filematch = matchfn(files, '(?:/|$)') | |
|
110 |
incmatch = matchfn(inc, '(?:/|$)') or |
|
|
117 | patmatch = matchfn(pats, '$') or always | |
|
118 | filematch = matchfn(files, '(?:/|$)') or always | |
|
119 | incmatch = matchfn(inc, '(?:/|$)') or always | |
|
111 | 120 | excmatch = matchfn(exc, '(?:/|$)') or (lambda fn: False) |
|
112 | 121 | |
|
113 |
return |
|
|
122 | return roots, lambda fn: (incmatch(fn) and not excmatch(fn) and | |
|
114 | 123 | (fn.endswith('/') or |
|
115 | 124 | (not pats and not files) or |
|
116 | 125 | (pats and patmatch(fn)) or |
General Comments 0
You need to be logged in to leave comments.
Login now