comparison mercurial/commands.py @ 724:1c0c413cccdd

Get add and locate to use new repo and dirstate walk code. They use a walk function that abstracts out the irritating details, so that there's a higher likelihood of commands behaving uniformly.
author Bryan O'Sullivan <bos@serpentine.com>
date Mon, 18 Jul 2005 06:54:21 -0800
parents 9e0f3ba4a9c2
children c6b912f8b5b2
comparison
equal deleted inserted replaced
723:9e0f3ba4a9c2 724:1c0c413cccdd
33 cwd = repo.getcwd() 33 cwd = repo.getcwd()
34 if cwd: 34 if cwd:
35 return [util.pconvert(os.path.normpath(os.path.join(cwd, x))) 35 return [util.pconvert(os.path.normpath(os.path.join(cwd, x)))
36 for x in args] 36 for x in args]
37 return args 37 return args
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
38 71
39 revrangesep = ':' 72 revrangesep = ':'
40 73
41 def revrange(ui, repo, revs, revlog=None): 74 def revrange(ui, repo, revs, revlog=None):
42 if revlog is None: 75 if revlog is None:
286 for f in fns: 319 for f in fns:
287 ui.write(' %-*s %s\n' % (m, f, h[f])) 320 ui.write(' %-*s %s\n' % (m, f, h[f]))
288 321
289 # Commands start here, listed alphabetically 322 # Commands start here, listed alphabetically
290 323
291 def add(ui, repo, file1, *files): 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"""
297 if files: 338 if files:
298 files = relpath(repo, files) 339 files = relpath(repo, files)
667 sys.exit(1) 708 sys.exit(1)
668 hg.repository(ui, ".", create=1) 709 hg.repository(ui, ".", create=1)
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 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
704 if opts['fullpath']: 718 if opts['fullpath']:
705 f = os.path.join(repo.root, f) 719 ui.write(os.path.join(repo.root, abs), end)
706 elif cwd: 720 else:
707 f = f[len(cwd_plus):] 721 ui.write(rel, end)
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"""
715 if f: 725 if f:
716 files = relpath(repo, [f]) 726 files = relpath(repo, [f])
1085 return repo.verify() 1095 return repo.verify()
1086 1096
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,
1094 [('r', 'revision', '', 'revision'), 1107 [('r', 'revision', '', 'revision'),
1095 ('u', 'user', None, 'show user'), 1108 ('u', 'user', None, 'show user'),
1137 "^init": (init, [], 'hg init'), 1150 "^init": (init, [], 'hg init'),
1138 "locate": 1151 "locate":
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 ('i', 'include', [], 'include path in search'), 1155 ('I', 'include', [], 'include path in search'),
1143 ('r', 'rev', '', 'revision'), 1156 ('r', 'rev', '', 'revision'),
1144 ('x', 'exclude', [], 'exclude path from search')], 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,
1148 [('r', 'rev', [], 'revision'), 1161 [('r', 'rev', [], 'revision'),
1149 ('p', 'patch', None, 'show patch')], 1162 ('p', 'patch', None, 'show patch')],