Mercurial > public > mercurial-scm > hg
annotate 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 |
rev | line source |
---|---|
1089 | 1 """ |
2 dirstate.py - working directory tracking for mercurial | |
3 | |
4 Copyright 2005 Matt Mackall <mpm@selenic.com> | |
5 | |
6 This software may be used and distributed according to the terms | |
7 of the GNU General Public License, incorporated herein by reference. | |
8 """ | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
9 |
1094 | 10 import struct, os |
11 from node import * | |
262 | 12 from demandload import * |
1104 | 13 demandload(globals(), "time bisect stat util re") |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
14 |
220 | 15 class dirstate: |
244 | 16 def __init__(self, opener, ui, root): |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
17 self.opener = opener |
244 | 18 self.root = root |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
19 self.dirty = 0 |
20 | 20 self.ui = ui |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
21 self.map = None |
227 | 22 self.pl = None |
363 | 23 self.copies = {} |
723 | 24 self.ignorefunc = None |
1183 | 25 self.blockignore = False |
723 | 26 |
27 def wjoin(self, f): | |
28 return os.path.join(self.root, f) | |
29 | |
870
a82eae840447
Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents:
839
diff
changeset
|
30 def getcwd(self): |
a82eae840447
Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents:
839
diff
changeset
|
31 cwd = os.getcwd() |
a82eae840447
Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents:
839
diff
changeset
|
32 if cwd == self.root: return '' |
a82eae840447
Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents:
839
diff
changeset
|
33 return cwd[len(self.root) + 1:] |
a82eae840447
Teach walk code about absolute paths.
Bryan O'Sullivan <bos@serpentine.com>
parents:
839
diff
changeset
|
34 |
1270
fc3b41570082
Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents:
1268
diff
changeset
|
35 def hgignore(self): |
fc3b41570082
Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents:
1268
diff
changeset
|
36 '''return the contents of .hgignore as a list of patterns. |
fc3b41570082
Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents:
1268
diff
changeset
|
37 |
fc3b41570082
Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents:
1268
diff
changeset
|
38 trailing white space is dropped. |
fc3b41570082
Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents:
1268
diff
changeset
|
39 the escape character is backslash. |
fc3b41570082
Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents:
1268
diff
changeset
|
40 comments start with #. |
fc3b41570082
Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents:
1268
diff
changeset
|
41 empty lines are skipped. |
fc3b41570082
Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents:
1268
diff
changeset
|
42 |
fc3b41570082
Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents:
1268
diff
changeset
|
43 lines can be of the following formats: |
fc3b41570082
Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents:
1268
diff
changeset
|
44 |
fc3b41570082
Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents:
1268
diff
changeset
|
45 syntax: regexp # defaults following lines to non-rooted regexps |
fc3b41570082
Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents:
1268
diff
changeset
|
46 syntax: glob # defaults following lines to non-rooted globs |
fc3b41570082
Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents:
1268
diff
changeset
|
47 re:pattern # non-rooted regular expression |
fc3b41570082
Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents:
1268
diff
changeset
|
48 glob:pattern # non-rooted glob |
fc3b41570082
Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents:
1268
diff
changeset
|
49 pattern # pattern of the current default type''' |
fc3b41570082
Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents:
1268
diff
changeset
|
50 syntaxes = {'re': 'relre:', 'regexp': 'relre:', 'glob': 'relglob:'} |
fc3b41570082
Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents:
1268
diff
changeset
|
51 def parselines(fp): |
fc3b41570082
Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents:
1268
diff
changeset
|
52 for line in fp: |
fc3b41570082
Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents:
1268
diff
changeset
|
53 escape = False |
fc3b41570082
Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents:
1268
diff
changeset
|
54 for i in xrange(len(line)): |
fc3b41570082
Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents:
1268
diff
changeset
|
55 if escape: escape = False |
fc3b41570082
Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents:
1268
diff
changeset
|
56 elif line[i] == '\\': escape = True |
fc3b41570082
Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents:
1268
diff
changeset
|
57 elif line[i] == '#': break |
fc3b41570082
Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents:
1268
diff
changeset
|
58 line = line[:i].rstrip() |
fc3b41570082
Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents:
1268
diff
changeset
|
59 if line: yield line |
fc3b41570082
Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents:
1268
diff
changeset
|
60 pats = [] |
fc3b41570082
Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents:
1268
diff
changeset
|
61 try: |
fc3b41570082
Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents:
1268
diff
changeset
|
62 fp = open(self.wjoin('.hgignore')) |
fc3b41570082
Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents:
1268
diff
changeset
|
63 syntax = 'relre:' |
fc3b41570082
Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents:
1268
diff
changeset
|
64 for line in parselines(fp): |
fc3b41570082
Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents:
1268
diff
changeset
|
65 if line.startswith('syntax:'): |
fc3b41570082
Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents:
1268
diff
changeset
|
66 s = line[7:].strip() |
fc3b41570082
Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents:
1268
diff
changeset
|
67 try: |
fc3b41570082
Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents:
1268
diff
changeset
|
68 syntax = syntaxes[s] |
fc3b41570082
Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents:
1268
diff
changeset
|
69 except KeyError: |
fc3b41570082
Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents:
1268
diff
changeset
|
70 self.ui.warn("ignoring invalid syntax '%s'\n" % s) |
fc3b41570082
Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents:
1268
diff
changeset
|
71 continue |
fc3b41570082
Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents:
1268
diff
changeset
|
72 pat = syntax + line |
fc3b41570082
Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents:
1268
diff
changeset
|
73 for s in syntaxes.values(): |
fc3b41570082
Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents:
1268
diff
changeset
|
74 if line.startswith(s): |
fc3b41570082
Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents:
1268
diff
changeset
|
75 pat = line |
fc3b41570082
Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents:
1268
diff
changeset
|
76 break |
fc3b41570082
Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents:
1268
diff
changeset
|
77 pats.append(pat) |
fc3b41570082
Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents:
1268
diff
changeset
|
78 except IOError: pass |
fc3b41570082
Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents:
1268
diff
changeset
|
79 return pats |
fc3b41570082
Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents:
1268
diff
changeset
|
80 |
fc3b41570082
Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents:
1268
diff
changeset
|
81 def ignore(self, fn): |
fc3b41570082
Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents:
1268
diff
changeset
|
82 '''default match function used by dirstate and localrepository. |
fc3b41570082
Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents:
1268
diff
changeset
|
83 this honours the .hgignore file, and nothing more.''' |
1183 | 84 if self.blockignore: |
85 return False | |
723 | 86 if not self.ignorefunc: |
1270
fc3b41570082
Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents:
1268
diff
changeset
|
87 files, self.ignorefunc, anypats = util.matcher(self.root, |
fc3b41570082
Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents:
1268
diff
changeset
|
88 inc=self.hgignore()) |
fc3b41570082
Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents:
1268
diff
changeset
|
89 return self.ignorefunc(fn) |
220 | 90 |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
91 def __del__(self): |
220 | 92 if self.dirty: |
93 self.write() | |
94 | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
95 def __getitem__(self, key): |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
96 try: |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
97 return self.map[key] |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
98 except TypeError: |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
99 self.read() |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
100 return self[key] |
220 | 101 |
102 def __contains__(self, key): | |
103 if not self.map: self.read() | |
104 return key in self.map | |
105 | |
227 | 106 def parents(self): |
107 if not self.pl: | |
108 self.read() | |
109 return self.pl | |
110 | |
723 | 111 def markdirty(self): |
112 if not self.dirty: | |
113 self.dirty = 1 | |
114 | |
1062 | 115 def setparents(self, p1, p2=nullid): |
723 | 116 self.markdirty() |
227 | 117 self.pl = p1, p2 |
118 | |
220 | 119 def state(self, key): |
120 try: | |
121 return self[key][0] | |
122 except KeyError: | |
123 return "?" | |
124 | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
125 def read(self): |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
126 if self.map is not None: return self.map |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
127 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
128 self.map = {} |
227 | 129 self.pl = [nullid, nullid] |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
130 try: |
220 | 131 st = self.opener("dirstate").read() |
311 | 132 if not st: return |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
133 except: return |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
134 |
227 | 135 self.pl = [st[:20], st[20: 40]] |
136 | |
137 pos = 40 | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
138 while pos < len(st): |
220 | 139 e = struct.unpack(">cllll", st[pos:pos+17]) |
140 l = e[4] | |
141 pos += 17 | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
142 f = st[pos:pos + l] |
515 | 143 if '\0' in f: |
363 | 144 f, c = f.split('\0') |
145 self.copies[f] = c | |
220 | 146 self.map[f] = e[:4] |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
147 pos += l |
363 | 148 |
149 def copy(self, source, dest): | |
150 self.read() | |
723 | 151 self.markdirty() |
363 | 152 self.copies[dest] = source |
153 | |
154 def copied(self, file): | |
155 return self.copies.get(file, None) | |
515 | 156 |
862
d70c1c31fd45
Fix 3-way-merge of original parent, workdir and new parent.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
861
diff
changeset
|
157 def update(self, files, state, **kw): |
220 | 158 ''' current states: |
159 n normal | |
231 | 160 m needs merging |
220 | 161 r marked for removal |
162 a marked for addition''' | |
163 | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
164 if not files: return |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
165 self.read() |
723 | 166 self.markdirty() |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
167 for f in files: |
220 | 168 if state == "r": |
169 self.map[f] = ('r', 0, 0, 0) | |
170 else: | |
1230 | 171 s = os.lstat(os.path.join(self.root, f)) |
862
d70c1c31fd45
Fix 3-way-merge of original parent, workdir and new parent.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
861
diff
changeset
|
172 st_size = kw.get('st_size', s.st_size) |
d70c1c31fd45
Fix 3-way-merge of original parent, workdir and new parent.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
861
diff
changeset
|
173 st_mtime = kw.get('st_mtime', s.st_mtime) |
865
2d2fee33ec68
Cleanup after previous changes:
Thomas Arendsen Hein <thomas@intevation.de>
parents:
863
diff
changeset
|
174 self.map[f] = (state, s.st_mode, st_size, st_mtime) |
1117 | 175 if self.copies.has_key(f): |
176 del self.copies[f] | |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
177 |
220 | 178 def forget(self, files): |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
179 if not files: return |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
180 self.read() |
723 | 181 self.markdirty() |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
182 for f in files: |
20 | 183 try: |
184 del self.map[f] | |
185 except KeyError: | |
220 | 186 self.ui.warn("not in dirstate: %s!\n" % f) |
20 | 187 pass |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
188 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
189 def clear(self): |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
190 self.map = {} |
723 | 191 self.markdirty() |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
192 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
193 def write(self): |
220 | 194 st = self.opener("dirstate", "w") |
227 | 195 st.write("".join(self.pl)) |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
196 for f, e in self.map.items(): |
363 | 197 c = self.copied(f) |
198 if c: | |
199 f = f + "\0" + c | |
220 | 200 e = struct.pack(">cllll", e[0], e[1], e[2], e[3], len(f)) |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
201 st.write(e + f) |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
202 self.dirty = 0 |
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
203 |
879 | 204 def filterfiles(self, files): |
205 ret = {} | |
206 unknown = [] | |
207 | |
208 for x in files: | |
209 if x is '.': | |
210 return self.map.copy() | |
211 if x not in self.map: | |
212 unknown.append(x) | |
213 else: | |
214 ret[x] = self.map[x] | |
919 | 215 |
879 | 216 if not unknown: |
217 return ret | |
218 | |
219 b = self.map.keys() | |
220 b.sort() | |
221 blen = len(b) | |
222 | |
223 for x in unknown: | |
224 bs = bisect.bisect(b, x) | |
919 | 225 if bs != 0 and b[bs-1] == x: |
879 | 226 ret[x] = self.map[x] |
227 continue | |
228 while bs < blen: | |
229 s = b[bs] | |
230 if len(s) > len(x) and s.startswith(x) and s[len(x)] == '/': | |
231 ret[s] = self.map[s] | |
232 else: | |
233 break | |
234 bs += 1 | |
235 return ret | |
236 | |
1062 | 237 def walk(self, files=None, match=util.always, dc=None): |
0
9117c6561b0b
Add back links from file revisions to changeset revisions
mpm@selenic.com
parents:
diff
changeset
|
238 self.read() |
879 | 239 |
723 | 240 # walk all files by default |
879 | 241 if not files: |
242 files = [self.root] | |
243 if not dc: | |
244 dc = self.map.copy() | |
245 elif not dc: | |
246 dc = self.filterfiles(files) | |
919 | 247 |
1183 | 248 def statmatch(file, stat): |
1224
cc61d366bc3b
Fix Windows status problem from new dirstate walk code
mpm@selenic.com
parents:
1183
diff
changeset
|
249 file = util.pconvert(file) |
1183 | 250 if file not in dc and self.ignore(file): |
251 return False | |
252 return match(file) | |
1224
cc61d366bc3b
Fix Windows status problem from new dirstate walk code
mpm@selenic.com
parents:
1183
diff
changeset
|
253 |
1183 | 254 return self.walkhelper(files=files, statmatch=statmatch, dc=dc) |
255 | |
256 # walk recursively through the directory tree, finding all files | |
257 # matched by the statmatch function | |
1224
cc61d366bc3b
Fix Windows status problem from new dirstate walk code
mpm@selenic.com
parents:
1183
diff
changeset
|
258 # |
1183 | 259 # results are yielded in a tuple (src, filename), where src is one of: |
260 # 'f' the file was found in the directory tree | |
261 # 'm' the file was only in the dirstate and not in the tree | |
262 # | |
263 # dc is an optional arg for the current dirstate. dc is not modified | |
264 # directly by this function, but might be modified by your statmatch call. | |
265 # | |
266 def walkhelper(self, files, statmatch, dc): | |
267 # recursion free walker, faster than os.walk. | |
268 def findfiles(s): | |
269 retfiles = [] | |
270 work = [s] | |
271 while work: | |
272 top = work.pop() | |
273 names = os.listdir(top) | |
274 names.sort() | |
275 # nd is the top of the repository dir tree | |
276 nd = util.normpath(top[len(self.root) + 1:]) | |
277 if nd == '.': nd = '' | |
278 for f in names: | |
279 np = os.path.join(nd, f) | |
280 if seen(np): | |
281 continue | |
282 p = os.path.join(top, f) | |
1228
db950da49539
Fix dangling symlink bug in dirstate walk code
mpm@selenic.com
parents:
1224
diff
changeset
|
283 # don't trip over symlinks |
db950da49539
Fix dangling symlink bug in dirstate walk code
mpm@selenic.com
parents:
1224
diff
changeset
|
284 st = os.lstat(p) |
1183 | 285 if stat.S_ISDIR(st.st_mode): |
286 ds = os.path.join(nd, f +'/') | |
287 if statmatch(ds, st): | |
288 work.append(p) | |
289 else: | |
290 if statmatch(np, st): | |
1245
d0a960b437a8
Files not getting added appropiately
Chris Mason <mason@suse.com>
parents:
1230
diff
changeset
|
291 yield util.pconvert(np) |
1183 | 292 |
821
72d9bd4841f3
Ensure that dirstate.walk only yields names once.
Bryan O'Sullivan <bos@serpentine.com>
parents:
820
diff
changeset
|
293 known = {'.hg': 1} |
72d9bd4841f3
Ensure that dirstate.walk only yields names once.
Bryan O'Sullivan <bos@serpentine.com>
parents:
820
diff
changeset
|
294 def seen(fn): |
72d9bd4841f3
Ensure that dirstate.walk only yields names once.
Bryan O'Sullivan <bos@serpentine.com>
parents:
820
diff
changeset
|
295 if fn in known: return True |
72d9bd4841f3
Ensure that dirstate.walk only yields names once.
Bryan O'Sullivan <bos@serpentine.com>
parents:
820
diff
changeset
|
296 known[fn] = 1 |
1183 | 297 |
298 # step one, find all files that match our criteria | |
299 files.sort() | |
300 for ff in util.unique(files): | |
301 f = os.path.join(self.root, ff) | |
302 try: | |
1230 | 303 st = os.lstat(f) |
1183 | 304 except OSError, inst: |
305 if ff not in dc: self.ui.warn('%s: %s\n' % ( | |
306 util.pathto(self.getcwd(), ff), | |
307 inst.strerror)) | |
308 continue | |
309 if stat.S_ISDIR(st.st_mode): | |
310 sorted = [ x for x in findfiles(f) ] | |
311 sorted.sort() | |
312 for fl in sorted: | |
313 yield 'f', fl | |
314 elif stat.S_ISREG(st.st_mode): | |
315 ff = util.normpath(ff) | |
316 if seen(ff): | |
884
087771ebe2e6
Fix walk code for files that do not exist anywhere, and unhandled types.
Bryan O'Sullivan <bos@serpentine.com>
parents:
883
diff
changeset
|
317 continue |
1183 | 318 found = False |
319 self.blockignore = True | |
320 if statmatch(ff, st): | |
321 found = True | |
322 self.blockignore = False | |
323 if found: | |
884
087771ebe2e6
Fix walk code for files that do not exist anywhere, and unhandled types.
Bryan O'Sullivan <bos@serpentine.com>
parents:
883
diff
changeset
|
324 yield 'f', ff |
1183 | 325 else: |
326 kind = 'unknown' | |
327 if stat.S_ISCHR(st.st_mode): kind = 'character device' | |
328 elif stat.S_ISBLK(st.st_mode): kind = 'block device' | |
329 elif stat.S_ISFIFO(st.st_mode): kind = 'fifo' | |
330 elif stat.S_ISLNK(st.st_mode): kind = 'symbolic link' | |
331 elif stat.S_ISSOCK(st.st_mode): kind = 'socket' | |
332 self.ui.warn('%s: unsupported file type (type is %s)\n' % ( | |
333 util.pathto(self.getcwd(), ff), | |
334 kind)) | |
536 | 335 |
1183 | 336 # step two run through anything left in the dc hash and yield |
337 # if we haven't already seen it | |
338 ks = dc.keys() | |
339 ks.sort() | |
340 for k in ks: | |
341 if not seen(k) and (statmatch(k, None)): | |
726
809a870a0e73
Add a source designator to the walk methods.
Bryan O'Sullivan <bos@serpentine.com>
parents:
725
diff
changeset
|
342 yield 'm', k |
669
8aa2a282eda4
.hgignore speedups patch incorporating Matt's feedback.
mwilli2@localhost.localdomain
parents:
667
diff
changeset
|
343 |
861
cbe5c4d016b7
dirstate.changes() now distinguishes 'hg remove'd or just deleted files.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
856
diff
changeset
|
344 def changes(self, files=None, match=util.always): |
723 | 345 self.read() |
879 | 346 if not files: |
1183 | 347 files = [self.root] |
879 | 348 dc = self.map.copy() |
349 else: | |
350 dc = self.filterfiles(files) | |
861
cbe5c4d016b7
dirstate.changes() now distinguishes 'hg remove'd or just deleted files.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
856
diff
changeset
|
351 lookup, modified, added, unknown = [], [], [], [] |
cbe5c4d016b7
dirstate.changes() now distinguishes 'hg remove'd or just deleted files.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
856
diff
changeset
|
352 removed, deleted = [], [] |
723 | 353 |
1183 | 354 # statmatch function to eliminate entries from the dirstate copy |
355 # and put files into the appropriate array. This gets passed | |
356 # to the walking code | |
357 def statmatch(fn, s): | |
1224
cc61d366bc3b
Fix Windows status problem from new dirstate walk code
mpm@selenic.com
parents:
1183
diff
changeset
|
358 fn = util.pconvert(fn) |
1183 | 359 def checkappend(l, fn): |
360 if match is util.always or match(fn): | |
361 l.append(fn) | |
1224
cc61d366bc3b
Fix Windows status problem from new dirstate walk code
mpm@selenic.com
parents:
1183
diff
changeset
|
362 |
1183 | 363 if not s or stat.S_ISDIR(s.st_mode): |
1268
c631f26346ca
Fix performance of dirstate.changes with ignored directories.
Bryan O'Sullivan <bos@serpentine.com>
parents:
1245
diff
changeset
|
364 if self.ignore(fn): return False |
c631f26346ca
Fix performance of dirstate.changes with ignored directories.
Bryan O'Sullivan <bos@serpentine.com>
parents:
1245
diff
changeset
|
365 return match(fn) |
1183 | 366 |
861
cbe5c4d016b7
dirstate.changes() now distinguishes 'hg remove'd or just deleted files.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
856
diff
changeset
|
367 if not stat.S_ISREG(s.st_mode): |
1183 | 368 return False |
369 c = dc.pop(fn, None) | |
861
cbe5c4d016b7
dirstate.changes() now distinguishes 'hg remove'd or just deleted files.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
856
diff
changeset
|
370 if c: |
1183 | 371 type, mode, size, time = c |
372 # check the common case first | |
373 if type == 'n': | |
374 if size != s.st_size or (mode ^ s.st_mode) & 0100: | |
375 checkappend(modified, fn) | |
376 elif time != s.st_mtime: | |
377 checkappend(lookup, fn) | |
378 elif type == 'm': | |
379 checkappend(modified, fn) | |
380 elif type == 'a': | |
381 checkappend(added, fn) | |
382 elif type == 'r': | |
383 checkappend(unknown, fn) | |
1270
fc3b41570082
Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents:
1268
diff
changeset
|
384 elif not self.ignore(fn) and match(fn): |
fc3b41570082
Switch to new syntax for .hgignore files.
Bryan O'Sullivan <bos@serpentine.com>
parents:
1268
diff
changeset
|
385 unknown.append(fn) |
1183 | 386 # return false because we've already handled all cases above. |
387 # there's no need for the walking code to process the file | |
388 # any further. | |
389 return False | |
536 | 390 |
1183 | 391 # because our statmatch always returns false, self.walk will only |
392 # return files in the dirstate map that are not present in the FS. | |
393 # But, we still need to iterate through the results to force the | |
394 # walk to complete | |
395 for src, fn in self.walkhelper(files, statmatch, dc): | |
396 pass | |
397 | |
398 # anything left in dc didn't exist in the filesystem | |
861
cbe5c4d016b7
dirstate.changes() now distinguishes 'hg remove'd or just deleted files.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
856
diff
changeset
|
399 for fn, c in [(fn, c) for fn, c in dc.items() if match(fn)]: |
cbe5c4d016b7
dirstate.changes() now distinguishes 'hg remove'd or just deleted files.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
856
diff
changeset
|
400 if c[0] == 'r': |
cbe5c4d016b7
dirstate.changes() now distinguishes 'hg remove'd or just deleted files.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
856
diff
changeset
|
401 removed.append(fn) |
cbe5c4d016b7
dirstate.changes() now distinguishes 'hg remove'd or just deleted files.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
856
diff
changeset
|
402 else: |
cbe5c4d016b7
dirstate.changes() now distinguishes 'hg remove'd or just deleted files.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
856
diff
changeset
|
403 deleted.append(fn) |
cbe5c4d016b7
dirstate.changes() now distinguishes 'hg remove'd or just deleted files.
Thomas Arendsen Hein <thomas@intevation.de>
parents:
856
diff
changeset
|
404 return (lookup, modified, added, removed + deleted, unknown) |