7 of the GNU General Public License, incorporated herein by reference. |
7 of the GNU General Public License, incorporated herein by reference. |
8 """ |
8 """ |
9 |
9 |
10 from node import * |
10 from node import * |
11 from i18n import _ |
11 from i18n import _ |
12 import struct, os, time, bisect, stat, strutil, util, re, errno |
12 import struct, os, time, bisect, stat, strutil, util, re, errno, ignore |
13 import cStringIO |
13 import cStringIO |
14 |
14 |
15 class dirstate(object): |
15 class dirstate(object): |
16 format = ">cllll" |
16 format = ">cllll" |
17 |
17 |
18 def __init__(self, opener, ui, root): |
18 def __init__(self, opener, ui, root): |
19 self.opener = opener |
19 self.opener = opener |
20 self.root = root |
20 self.root = root |
21 self.dirty = 0 |
21 self.dirty = 0 |
22 self.ui = ui |
22 self.ui = ui |
23 self.ignorefunc = None |
|
24 self._slash = None |
23 self._slash = None |
25 |
24 |
26 def __getattr__(self, name): |
25 def __getattr__(self, name): |
27 if name == 'map': |
26 if name == 'map': |
28 self.read() |
27 self.read() |
78 self._slash = self.ui.configbool('ui', 'slash') and os.sep != '/' |
81 self._slash = self.ui.configbool('ui', 'slash') and os.sep != '/' |
79 if self._slash: |
82 if self._slash: |
80 path = path.replace(os.sep, '/') |
83 path = path.replace(os.sep, '/') |
81 return path |
84 return path |
82 |
85 |
83 def hgignore(self): |
|
84 '''return the contents of .hgignore files as a list of patterns. |
|
85 |
|
86 the files parsed for patterns include: |
|
87 .hgignore in the repository root |
|
88 any additional files specified in the [ui] section of ~/.hgrc |
|
89 |
|
90 trailing white space is dropped. |
|
91 the escape character is backslash. |
|
92 comments start with #. |
|
93 empty lines are skipped. |
|
94 |
|
95 lines can be of the following formats: |
|
96 |
|
97 syntax: regexp # defaults following lines to non-rooted regexps |
|
98 syntax: glob # defaults following lines to non-rooted globs |
|
99 re:pattern # non-rooted regular expression |
|
100 glob:pattern # non-rooted glob |
|
101 pattern # pattern of the current default type''' |
|
102 syntaxes = {'re': 'relre:', 'regexp': 'relre:', 'glob': 'relglob:'} |
|
103 def parselines(fp): |
|
104 for line in fp: |
|
105 if not line.endswith('\n'): |
|
106 line += '\n' |
|
107 escape = False |
|
108 for i in xrange(len(line)): |
|
109 if escape: escape = False |
|
110 elif line[i] == '\\': escape = True |
|
111 elif line[i] == '#': break |
|
112 line = line[:i].rstrip() |
|
113 if line: yield line |
|
114 repoignore = self.wjoin('.hgignore') |
|
115 files = [repoignore] |
|
116 files.extend(self.ui.hgignorefiles()) |
|
117 pats = {} |
|
118 for f in files: |
|
119 try: |
|
120 pats[f] = [] |
|
121 fp = open(f) |
|
122 syntax = 'relre:' |
|
123 for line in parselines(fp): |
|
124 if line.startswith('syntax:'): |
|
125 s = line[7:].strip() |
|
126 try: |
|
127 syntax = syntaxes[s] |
|
128 except KeyError: |
|
129 self.ui.warn(_("%s: ignoring invalid " |
|
130 "syntax '%s'\n") % (f, s)) |
|
131 continue |
|
132 pat = syntax + line |
|
133 for s in syntaxes.values(): |
|
134 if line.startswith(s): |
|
135 pat = line |
|
136 break |
|
137 pats[f].append(pat) |
|
138 except IOError, inst: |
|
139 if f != repoignore: |
|
140 self.ui.warn(_("skipping unreadable ignore file" |
|
141 " '%s': %s\n") % (f, inst.strerror)) |
|
142 return pats |
|
143 |
|
144 def ignore(self, fn): |
|
145 '''default match function used by dirstate and |
|
146 localrepository. this honours the repository .hgignore file |
|
147 and any other files specified in the [ui] section of .hgrc.''' |
|
148 if not self.ignorefunc: |
|
149 ignore = self.hgignore() |
|
150 allpats = [] |
|
151 [allpats.extend(patlist) for patlist in ignore.values()] |
|
152 if allpats: |
|
153 try: |
|
154 files, self.ignorefunc, anypats = ( |
|
155 util.matcher(self.root, inc=allpats, src='.hgignore')) |
|
156 except util.Abort: |
|
157 # Re-raise an exception where the src is the right file |
|
158 for f, patlist in ignore.items(): |
|
159 files, self.ignorefunc, anypats = ( |
|
160 util.matcher(self.root, inc=patlist, src=f)) |
|
161 else: |
|
162 self.ignorefunc = util.never |
|
163 return self.ignorefunc(fn) |
|
164 |
|
165 def __del__(self): |
86 def __del__(self): |
166 if self.dirty: |
87 if self.dirty: |
167 self.write() |
88 self.write() |
168 |
89 |
169 def __getitem__(self, key): |
90 def __getitem__(self, key): |