comparison mercurial/dirstate.py @ 1270:fc3b41570082

Switch to new syntax for .hgignore files. Here is the new syntax, in summary. Trailing white space is dropped. The escape character is "\". Comments start with #. Empty lines are skipped. Lines can be of the following formats: syntax: regexp # defaults following lines to non-rooted regexps syntax: glob # defaults following lines to non-rooted globs re:pattern # non-rooted regular expression glob:pattern # non-rooted glob pattern # pattern of the current default type The default pattern type is regexp, which is completely backwards compatible with the old hgignore syntax. In the dirstate class, the ignore method has been reworked to be based on the util.matcher function, by way of a new dirstate.hgignore method.
author Bryan O'Sullivan <bos@serpentine.com>
date Sat, 17 Sep 2005 00:27:27 -0700
parents c631f26346ca
children 9ab14ca22e37
comparison
equal deleted inserted replaced
1269:5e9816decbb7 1270:fc3b41570082
30 def getcwd(self): 30 def getcwd(self):
31 cwd = os.getcwd() 31 cwd = os.getcwd()
32 if cwd == self.root: return '' 32 if cwd == self.root: return ''
33 return cwd[len(self.root) + 1:] 33 return cwd[len(self.root) + 1:]
34 34
35 def ignore(self, f): 35 def hgignore(self):
36 '''return the contents of .hgignore as a list of patterns.
37
38 trailing white space is dropped.
39 the escape character is backslash.
40 comments start with #.
41 empty lines are skipped.
42
43 lines can be of the following formats:
44
45 syntax: regexp # defaults following lines to non-rooted regexps
46 syntax: glob # defaults following lines to non-rooted globs
47 re:pattern # non-rooted regular expression
48 glob:pattern # non-rooted glob
49 pattern # pattern of the current default type'''
50 syntaxes = {'re': 'relre:', 'regexp': 'relre:', 'glob': 'relglob:'}
51 def parselines(fp):
52 for line in fp:
53 escape = False
54 for i in xrange(len(line)):
55 if escape: escape = False
56 elif line[i] == '\\': escape = True
57 elif line[i] == '#': break
58 line = line[:i].rstrip()
59 if line: yield line
60 pats = []
61 try:
62 fp = open(self.wjoin('.hgignore'))
63 syntax = 'relre:'
64 for line in parselines(fp):
65 if line.startswith('syntax:'):
66 s = line[7:].strip()
67 try:
68 syntax = syntaxes[s]
69 except KeyError:
70 self.ui.warn("ignoring invalid syntax '%s'\n" % s)
71 continue
72 pat = syntax + line
73 for s in syntaxes.values():
74 if line.startswith(s):
75 pat = line
76 break
77 pats.append(pat)
78 except IOError: pass
79 return pats
80
81 def ignore(self, fn):
82 '''default match function used by dirstate and localrepository.
83 this honours the .hgignore file, and nothing more.'''
36 if self.blockignore: 84 if self.blockignore:
37 return False 85 return False
38 if not self.ignorefunc: 86 if not self.ignorefunc:
39 bigpat = [] 87 files, self.ignorefunc, anypats = util.matcher(self.root,
40 try: 88 inc=self.hgignore())
41 l = file(self.wjoin(".hgignore")) 89 return self.ignorefunc(fn)
42 for pat in l:
43 p = pat.rstrip()
44 if p:
45 try:
46 re.compile(p)
47 except:
48 self.ui.warn("ignoring invalid ignore"
49 + " regular expression '%s'\n" % p)
50 else:
51 bigpat.append(p)
52 except IOError: pass
53
54 if bigpat:
55 s = "(?:%s)" % (")|(?:".join(bigpat))
56 r = re.compile(s)
57 self.ignorefunc = r.search
58 else:
59 self.ignorefunc = util.never
60
61 return self.ignorefunc(f)
62 90
63 def __del__(self): 91 def __del__(self):
64 if self.dirty: 92 if self.dirty:
65 self.write() 93 self.write()
66 94
351 checkappend(modified, fn) 379 checkappend(modified, fn)
352 elif type == 'a': 380 elif type == 'a':
353 checkappend(added, fn) 381 checkappend(added, fn)
354 elif type == 'r': 382 elif type == 'r':
355 checkappend(unknown, fn) 383 checkappend(unknown, fn)
356 else: 384 elif not self.ignore(fn) and match(fn):
357 if not self.ignore(fn) and match(fn): 385 unknown.append(fn)
358 unknown.append(fn)
359 # return false because we've already handled all cases above. 386 # return false because we've already handled all cases above.
360 # there's no need for the walking code to process the file 387 # there's no need for the walking code to process the file
361 # any further. 388 # any further.
362 return False 389 return False
363 390