Mercurial > hg > mercurial-crew-with-dirclash
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 |