##// END OF EJS Templates
Add warning if user-configured hgignore file isn't found
mcmillen@cs.cmu.edu -
r2004:7dd6317a default
parent child Browse files
Show More
@@ -1,448 +1,451
1 """
1 """
2 dirstate.py - working directory tracking for mercurial
2 dirstate.py - working directory tracking for mercurial
3
3
4 Copyright 2005 Matt Mackall <mpm@selenic.com>
4 Copyright 2005 Matt Mackall <mpm@selenic.com>
5
5
6 This software may be used and distributed according to the terms
6 This software may be used and distributed according to the terms
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 import struct, os
10 import struct, os
11 from node import *
11 from node import *
12 from i18n import gettext as _
12 from i18n import gettext as _
13 from demandload import *
13 from demandload import *
14 demandload(globals(), "time bisect stat util re errno")
14 demandload(globals(), "time bisect stat util re errno")
15
15
16 class dirstate(object):
16 class dirstate(object):
17 def __init__(self, opener, ui, root):
17 def __init__(self, opener, ui, root):
18 self.opener = opener
18 self.opener = opener
19 self.root = root
19 self.root = root
20 self.dirty = 0
20 self.dirty = 0
21 self.ui = ui
21 self.ui = ui
22 self.map = None
22 self.map = None
23 self.pl = None
23 self.pl = None
24 self.copies = {}
24 self.copies = {}
25 self.ignorefunc = None
25 self.ignorefunc = None
26 self.blockignore = False
26 self.blockignore = False
27
27
28 def wjoin(self, f):
28 def wjoin(self, f):
29 return os.path.join(self.root, f)
29 return os.path.join(self.root, f)
30
30
31 def getcwd(self):
31 def getcwd(self):
32 cwd = os.getcwd()
32 cwd = os.getcwd()
33 if cwd == self.root: return ''
33 if cwd == self.root: return ''
34 return cwd[len(self.root) + 1:]
34 return cwd[len(self.root) + 1:]
35
35
36 def hgignore(self):
36 def hgignore(self):
37 '''return the contents of .hgignore files as a list of patterns.
37 '''return the contents of .hgignore files as a list of patterns.
38
38
39 the files parsed for patterns include:
39 the files parsed for patterns include:
40 .hgignore in the repository root
40 .hgignore in the repository root
41 any additional files specified in the [ui] section of ~/.hgrc
41 any additional files specified in the [ui] section of ~/.hgrc
42
42
43 trailing white space is dropped.
43 trailing white space is dropped.
44 the escape character is backslash.
44 the escape character is backslash.
45 comments start with #.
45 comments start with #.
46 empty lines are skipped.
46 empty lines are skipped.
47
47
48 lines can be of the following formats:
48 lines can be of the following formats:
49
49
50 syntax: regexp # defaults following lines to non-rooted regexps
50 syntax: regexp # defaults following lines to non-rooted regexps
51 syntax: glob # defaults following lines to non-rooted globs
51 syntax: glob # defaults following lines to non-rooted globs
52 re:pattern # non-rooted regular expression
52 re:pattern # non-rooted regular expression
53 glob:pattern # non-rooted glob
53 glob:pattern # non-rooted glob
54 pattern # pattern of the current default type'''
54 pattern # pattern of the current default type'''
55 syntaxes = {'re': 'relre:', 'regexp': 'relre:', 'glob': 'relglob:'}
55 syntaxes = {'re': 'relre:', 'regexp': 'relre:', 'glob': 'relglob:'}
56 def parselines(fp):
56 def parselines(fp):
57 for line in fp:
57 for line in fp:
58 escape = False
58 escape = False
59 for i in xrange(len(line)):
59 for i in xrange(len(line)):
60 if escape: escape = False
60 if escape: escape = False
61 elif line[i] == '\\': escape = True
61 elif line[i] == '\\': escape = True
62 elif line[i] == '#': break
62 elif line[i] == '#': break
63 line = line[:i].rstrip()
63 line = line[:i].rstrip()
64 if line: yield line
64 if line: yield line
65 files = [self.wjoin('.hgignore')]
65 repoignore = self.wjoin('.hgignore')
66 files = [repoignore]
66 files.extend(self.ui.hgignorefiles())
67 files.extend(self.ui.hgignorefiles())
67 pats = []
68 pats = []
68 for f in files:
69 for f in files:
69 try:
70 try:
70 fp = open(f)
71 fp = open(f)
71 syntax = 'relre:'
72 syntax = 'relre:'
72 for line in parselines(fp):
73 for line in parselines(fp):
73 if line.startswith('syntax:'):
74 if line.startswith('syntax:'):
74 s = line[7:].strip()
75 s = line[7:].strip()
75 try:
76 try:
76 syntax = syntaxes[s]
77 syntax = syntaxes[s]
77 except KeyError:
78 except KeyError:
78 self.ui.warn(_("%s: ignoring invalid "
79 self.ui.warn(_("%s: ignoring invalid "
79 "syntax '%s'\n") % (f, s))
80 "syntax '%s'\n") % (f, s))
80 continue
81 continue
81 pat = syntax + line
82 pat = syntax + line
82 for s in syntaxes.values():
83 for s in syntaxes.values():
83 if line.startswith(s):
84 if line.startswith(s):
84 pat = line
85 pat = line
85 break
86 break
86 pats.append(pat)
87 pats.append(pat)
87 except IOError: pass
88 except IOError:
89 if f != repoignore:
90 self.ui.warn(_("ignore file %s not found\n") % f)
88 return pats
91 return pats
89
92
90 def ignore(self, fn):
93 def ignore(self, fn):
91 '''default match function used by dirstate and
94 '''default match function used by dirstate and
92 localrepository. this honours the repository .hgignore file
95 localrepository. this honours the repository .hgignore file
93 and any other files specified in the [ui] section of .hgrc.'''
96 and any other files specified in the [ui] section of .hgrc.'''
94 if self.blockignore:
97 if self.blockignore:
95 return False
98 return False
96 if not self.ignorefunc:
99 if not self.ignorefunc:
97 ignore = self.hgignore()
100 ignore = self.hgignore()
98 if ignore:
101 if ignore:
99 # FIXME: if there are errors in patterns, matcher will
102 # FIXME: if there are errors in patterns, matcher will
100 # print out an error containing src ('.hgignore');
103 # print out an error containing src ('.hgignore');
101 # really, we want the original source file to be
104 # really, we want the original source file to be
102 # printed instead.
105 # printed instead.
103 files, self.ignorefunc, anypats = util.matcher(self.root,
106 files, self.ignorefunc, anypats = util.matcher(self.root,
104 inc=ignore,
107 inc=ignore,
105 src='.hgignore')
108 src='.hgignore')
106 else:
109 else:
107 self.ignorefunc = util.never
110 self.ignorefunc = util.never
108 return self.ignorefunc(fn)
111 return self.ignorefunc(fn)
109
112
110 def __del__(self):
113 def __del__(self):
111 if self.dirty:
114 if self.dirty:
112 self.write()
115 self.write()
113
116
114 def __getitem__(self, key):
117 def __getitem__(self, key):
115 try:
118 try:
116 return self.map[key]
119 return self.map[key]
117 except TypeError:
120 except TypeError:
118 self.lazyread()
121 self.lazyread()
119 return self[key]
122 return self[key]
120
123
121 def __contains__(self, key):
124 def __contains__(self, key):
122 self.lazyread()
125 self.lazyread()
123 return key in self.map
126 return key in self.map
124
127
125 def parents(self):
128 def parents(self):
126 self.lazyread()
129 self.lazyread()
127 return self.pl
130 return self.pl
128
131
129 def markdirty(self):
132 def markdirty(self):
130 if not self.dirty:
133 if not self.dirty:
131 self.dirty = 1
134 self.dirty = 1
132
135
133 def setparents(self, p1, p2=nullid):
136 def setparents(self, p1, p2=nullid):
134 self.lazyread()
137 self.lazyread()
135 self.markdirty()
138 self.markdirty()
136 self.pl = p1, p2
139 self.pl = p1, p2
137
140
138 def state(self, key):
141 def state(self, key):
139 try:
142 try:
140 return self[key][0]
143 return self[key][0]
141 except KeyError:
144 except KeyError:
142 return "?"
145 return "?"
143
146
144 def lazyread(self):
147 def lazyread(self):
145 if self.map is None:
148 if self.map is None:
146 self.read()
149 self.read()
147
150
148 def read(self):
151 def read(self):
149 self.map = {}
152 self.map = {}
150 self.pl = [nullid, nullid]
153 self.pl = [nullid, nullid]
151 try:
154 try:
152 st = self.opener("dirstate").read()
155 st = self.opener("dirstate").read()
153 if not st: return
156 if not st: return
154 except: return
157 except: return
155
158
156 self.pl = [st[:20], st[20: 40]]
159 self.pl = [st[:20], st[20: 40]]
157
160
158 pos = 40
161 pos = 40
159 while pos < len(st):
162 while pos < len(st):
160 e = struct.unpack(">cllll", st[pos:pos+17])
163 e = struct.unpack(">cllll", st[pos:pos+17])
161 l = e[4]
164 l = e[4]
162 pos += 17
165 pos += 17
163 f = st[pos:pos + l]
166 f = st[pos:pos + l]
164 if '\0' in f:
167 if '\0' in f:
165 f, c = f.split('\0')
168 f, c = f.split('\0')
166 self.copies[f] = c
169 self.copies[f] = c
167 self.map[f] = e[:4]
170 self.map[f] = e[:4]
168 pos += l
171 pos += l
169
172
170 def copy(self, source, dest):
173 def copy(self, source, dest):
171 self.lazyread()
174 self.lazyread()
172 self.markdirty()
175 self.markdirty()
173 self.copies[dest] = source
176 self.copies[dest] = source
174
177
175 def copied(self, file):
178 def copied(self, file):
176 return self.copies.get(file, None)
179 return self.copies.get(file, None)
177
180
178 def update(self, files, state, **kw):
181 def update(self, files, state, **kw):
179 ''' current states:
182 ''' current states:
180 n normal
183 n normal
181 m needs merging
184 m needs merging
182 r marked for removal
185 r marked for removal
183 a marked for addition'''
186 a marked for addition'''
184
187
185 if not files: return
188 if not files: return
186 self.lazyread()
189 self.lazyread()
187 self.markdirty()
190 self.markdirty()
188 for f in files:
191 for f in files:
189 if state == "r":
192 if state == "r":
190 self.map[f] = ('r', 0, 0, 0)
193 self.map[f] = ('r', 0, 0, 0)
191 else:
194 else:
192 s = os.lstat(self.wjoin(f))
195 s = os.lstat(self.wjoin(f))
193 st_size = kw.get('st_size', s.st_size)
196 st_size = kw.get('st_size', s.st_size)
194 st_mtime = kw.get('st_mtime', s.st_mtime)
197 st_mtime = kw.get('st_mtime', s.st_mtime)
195 self.map[f] = (state, s.st_mode, st_size, st_mtime)
198 self.map[f] = (state, s.st_mode, st_size, st_mtime)
196 if self.copies.has_key(f):
199 if self.copies.has_key(f):
197 del self.copies[f]
200 del self.copies[f]
198
201
199 def forget(self, files):
202 def forget(self, files):
200 if not files: return
203 if not files: return
201 self.lazyread()
204 self.lazyread()
202 self.markdirty()
205 self.markdirty()
203 for f in files:
206 for f in files:
204 try:
207 try:
205 del self.map[f]
208 del self.map[f]
206 except KeyError:
209 except KeyError:
207 self.ui.warn(_("not in dirstate: %s!\n") % f)
210 self.ui.warn(_("not in dirstate: %s!\n") % f)
208 pass
211 pass
209
212
210 def clear(self):
213 def clear(self):
211 self.map = {}
214 self.map = {}
212 self.copies = {}
215 self.copies = {}
213 self.markdirty()
216 self.markdirty()
214
217
215 def rebuild(self, parent, files):
218 def rebuild(self, parent, files):
216 self.clear()
219 self.clear()
217 umask = os.umask(0)
220 umask = os.umask(0)
218 os.umask(umask)
221 os.umask(umask)
219 for f, mode in files:
222 for f, mode in files:
220 if mode:
223 if mode:
221 self.map[f] = ('n', ~umask, -1, 0)
224 self.map[f] = ('n', ~umask, -1, 0)
222 else:
225 else:
223 self.map[f] = ('n', ~umask & 0666, -1, 0)
226 self.map[f] = ('n', ~umask & 0666, -1, 0)
224 self.pl = (parent, nullid)
227 self.pl = (parent, nullid)
225 self.markdirty()
228 self.markdirty()
226
229
227 def write(self):
230 def write(self):
228 if not self.dirty:
231 if not self.dirty:
229 return
232 return
230 st = self.opener("dirstate", "w", atomic=True)
233 st = self.opener("dirstate", "w", atomic=True)
231 st.write("".join(self.pl))
234 st.write("".join(self.pl))
232 for f, e in self.map.items():
235 for f, e in self.map.items():
233 c = self.copied(f)
236 c = self.copied(f)
234 if c:
237 if c:
235 f = f + "\0" + c
238 f = f + "\0" + c
236 e = struct.pack(">cllll", e[0], e[1], e[2], e[3], len(f))
239 e = struct.pack(">cllll", e[0], e[1], e[2], e[3], len(f))
237 st.write(e + f)
240 st.write(e + f)
238 self.dirty = 0
241 self.dirty = 0
239
242
240 def filterfiles(self, files):
243 def filterfiles(self, files):
241 ret = {}
244 ret = {}
242 unknown = []
245 unknown = []
243
246
244 for x in files:
247 for x in files:
245 if x == '.':
248 if x == '.':
246 return self.map.copy()
249 return self.map.copy()
247 if x not in self.map:
250 if x not in self.map:
248 unknown.append(x)
251 unknown.append(x)
249 else:
252 else:
250 ret[x] = self.map[x]
253 ret[x] = self.map[x]
251
254
252 if not unknown:
255 if not unknown:
253 return ret
256 return ret
254
257
255 b = self.map.keys()
258 b = self.map.keys()
256 b.sort()
259 b.sort()
257 blen = len(b)
260 blen = len(b)
258
261
259 for x in unknown:
262 for x in unknown:
260 bs = bisect.bisect(b, x)
263 bs = bisect.bisect(b, x)
261 if bs != 0 and b[bs-1] == x:
264 if bs != 0 and b[bs-1] == x:
262 ret[x] = self.map[x]
265 ret[x] = self.map[x]
263 continue
266 continue
264 while bs < blen:
267 while bs < blen:
265 s = b[bs]
268 s = b[bs]
266 if len(s) > len(x) and s.startswith(x) and s[len(x)] == '/':
269 if len(s) > len(x) and s.startswith(x) and s[len(x)] == '/':
267 ret[s] = self.map[s]
270 ret[s] = self.map[s]
268 else:
271 else:
269 break
272 break
270 bs += 1
273 bs += 1
271 return ret
274 return ret
272
275
273 def supported_type(self, f, st, verbose=False):
276 def supported_type(self, f, st, verbose=False):
274 if stat.S_ISREG(st.st_mode):
277 if stat.S_ISREG(st.st_mode):
275 return True
278 return True
276 if verbose:
279 if verbose:
277 kind = 'unknown'
280 kind = 'unknown'
278 if stat.S_ISCHR(st.st_mode): kind = _('character device')
281 if stat.S_ISCHR(st.st_mode): kind = _('character device')
279 elif stat.S_ISBLK(st.st_mode): kind = _('block device')
282 elif stat.S_ISBLK(st.st_mode): kind = _('block device')
280 elif stat.S_ISFIFO(st.st_mode): kind = _('fifo')
283 elif stat.S_ISFIFO(st.st_mode): kind = _('fifo')
281 elif stat.S_ISLNK(st.st_mode): kind = _('symbolic link')
284 elif stat.S_ISLNK(st.st_mode): kind = _('symbolic link')
282 elif stat.S_ISSOCK(st.st_mode): kind = _('socket')
285 elif stat.S_ISSOCK(st.st_mode): kind = _('socket')
283 elif stat.S_ISDIR(st.st_mode): kind = _('directory')
286 elif stat.S_ISDIR(st.st_mode): kind = _('directory')
284 self.ui.warn(_('%s: unsupported file type (type is %s)\n') % (
287 self.ui.warn(_('%s: unsupported file type (type is %s)\n') % (
285 util.pathto(self.getcwd(), f),
288 util.pathto(self.getcwd(), f),
286 kind))
289 kind))
287 return False
290 return False
288
291
289 def statwalk(self, files=None, match=util.always, dc=None):
292 def statwalk(self, files=None, match=util.always, dc=None):
290 self.lazyread()
293 self.lazyread()
291
294
292 # walk all files by default
295 # walk all files by default
293 if not files:
296 if not files:
294 files = [self.root]
297 files = [self.root]
295 if not dc:
298 if not dc:
296 dc = self.map.copy()
299 dc = self.map.copy()
297 elif not dc:
300 elif not dc:
298 dc = self.filterfiles(files)
301 dc = self.filterfiles(files)
299
302
300 def statmatch(file_, stat):
303 def statmatch(file_, stat):
301 file_ = util.pconvert(file_)
304 file_ = util.pconvert(file_)
302 if file_ not in dc and self.ignore(file_):
305 if file_ not in dc and self.ignore(file_):
303 return False
306 return False
304 return match(file_)
307 return match(file_)
305
308
306 return self.walkhelper(files=files, statmatch=statmatch, dc=dc)
309 return self.walkhelper(files=files, statmatch=statmatch, dc=dc)
307
310
308 def walk(self, files=None, match=util.always, dc=None):
311 def walk(self, files=None, match=util.always, dc=None):
309 # filter out the stat
312 # filter out the stat
310 for src, f, st in self.statwalk(files, match, dc):
313 for src, f, st in self.statwalk(files, match, dc):
311 yield src, f
314 yield src, f
312
315
313 # walk recursively through the directory tree, finding all files
316 # walk recursively through the directory tree, finding all files
314 # matched by the statmatch function
317 # matched by the statmatch function
315 #
318 #
316 # results are yielded in a tuple (src, filename, st), where src
319 # results are yielded in a tuple (src, filename, st), where src
317 # is one of:
320 # is one of:
318 # 'f' the file was found in the directory tree
321 # 'f' the file was found in the directory tree
319 # 'm' the file was only in the dirstate and not in the tree
322 # 'm' the file was only in the dirstate and not in the tree
320 # and st is the stat result if the file was found in the directory.
323 # and st is the stat result if the file was found in the directory.
321 #
324 #
322 # dc is an optional arg for the current dirstate. dc is not modified
325 # dc is an optional arg for the current dirstate. dc is not modified
323 # directly by this function, but might be modified by your statmatch call.
326 # directly by this function, but might be modified by your statmatch call.
324 #
327 #
325 def walkhelper(self, files, statmatch, dc):
328 def walkhelper(self, files, statmatch, dc):
326 # recursion free walker, faster than os.walk.
329 # recursion free walker, faster than os.walk.
327 def findfiles(s):
330 def findfiles(s):
328 work = [s]
331 work = [s]
329 while work:
332 while work:
330 top = work.pop()
333 top = work.pop()
331 names = os.listdir(top)
334 names = os.listdir(top)
332 names.sort()
335 names.sort()
333 # nd is the top of the repository dir tree
336 # nd is the top of the repository dir tree
334 nd = util.normpath(top[len(self.root) + 1:])
337 nd = util.normpath(top[len(self.root) + 1:])
335 if nd == '.': nd = ''
338 if nd == '.': nd = ''
336 for f in names:
339 for f in names:
337 np = util.pconvert(os.path.join(nd, f))
340 np = util.pconvert(os.path.join(nd, f))
338 if seen(np):
341 if seen(np):
339 continue
342 continue
340 p = os.path.join(top, f)
343 p = os.path.join(top, f)
341 # don't trip over symlinks
344 # don't trip over symlinks
342 st = os.lstat(p)
345 st = os.lstat(p)
343 if stat.S_ISDIR(st.st_mode):
346 if stat.S_ISDIR(st.st_mode):
344 ds = os.path.join(nd, f +'/')
347 ds = os.path.join(nd, f +'/')
345 if statmatch(ds, st):
348 if statmatch(ds, st):
346 work.append(p)
349 work.append(p)
347 if statmatch(np, st) and np in dc:
350 if statmatch(np, st) and np in dc:
348 yield 'm', np, st
351 yield 'm', np, st
349 elif statmatch(np, st):
352 elif statmatch(np, st):
350 if self.supported_type(np, st):
353 if self.supported_type(np, st):
351 yield 'f', np, st
354 yield 'f', np, st
352 elif np in dc:
355 elif np in dc:
353 yield 'm', np, st
356 yield 'm', np, st
354
357
355 known = {'.hg': 1}
358 known = {'.hg': 1}
356 def seen(fn):
359 def seen(fn):
357 if fn in known: return True
360 if fn in known: return True
358 known[fn] = 1
361 known[fn] = 1
359
362
360 # step one, find all files that match our criteria
363 # step one, find all files that match our criteria
361 files.sort()
364 files.sort()
362 for ff in util.unique(files):
365 for ff in util.unique(files):
363 f = self.wjoin(ff)
366 f = self.wjoin(ff)
364 try:
367 try:
365 st = os.lstat(f)
368 st = os.lstat(f)
366 except OSError, inst:
369 except OSError, inst:
367 nf = util.normpath(ff)
370 nf = util.normpath(ff)
368 found = False
371 found = False
369 for fn in dc:
372 for fn in dc:
370 if nf == fn or (fn.startswith(nf) and fn[len(nf)] == '/'):
373 if nf == fn or (fn.startswith(nf) and fn[len(nf)] == '/'):
371 found = True
374 found = True
372 break
375 break
373 if not found:
376 if not found:
374 self.ui.warn('%s: %s\n' % (
377 self.ui.warn('%s: %s\n' % (
375 util.pathto(self.getcwd(), ff),
378 util.pathto(self.getcwd(), ff),
376 inst.strerror))
379 inst.strerror))
377 continue
380 continue
378 if stat.S_ISDIR(st.st_mode):
381 if stat.S_ISDIR(st.st_mode):
379 cmp1 = (lambda x, y: cmp(x[1], y[1]))
382 cmp1 = (lambda x, y: cmp(x[1], y[1]))
380 sorted_ = [ x for x in findfiles(f) ]
383 sorted_ = [ x for x in findfiles(f) ]
381 sorted_.sort(cmp1)
384 sorted_.sort(cmp1)
382 for e in sorted_:
385 for e in sorted_:
383 yield e
386 yield e
384 else:
387 else:
385 ff = util.normpath(ff)
388 ff = util.normpath(ff)
386 if seen(ff):
389 if seen(ff):
387 continue
390 continue
388 self.blockignore = True
391 self.blockignore = True
389 if statmatch(ff, st):
392 if statmatch(ff, st):
390 if self.supported_type(ff, st, verbose=True):
393 if self.supported_type(ff, st, verbose=True):
391 yield 'f', ff, st
394 yield 'f', ff, st
392 elif ff in dc:
395 elif ff in dc:
393 yield 'm', ff, st
396 yield 'm', ff, st
394 self.blockignore = False
397 self.blockignore = False
395
398
396 # step two run through anything left in the dc hash and yield
399 # step two run through anything left in the dc hash and yield
397 # if we haven't already seen it
400 # if we haven't already seen it
398 ks = dc.keys()
401 ks = dc.keys()
399 ks.sort()
402 ks.sort()
400 for k in ks:
403 for k in ks:
401 if not seen(k) and (statmatch(k, None)):
404 if not seen(k) and (statmatch(k, None)):
402 yield 'm', k, None
405 yield 'm', k, None
403
406
404 def changes(self, files=None, match=util.always):
407 def changes(self, files=None, match=util.always):
405 lookup, modified, added, unknown = [], [], [], []
408 lookup, modified, added, unknown = [], [], [], []
406 removed, deleted = [], []
409 removed, deleted = [], []
407
410
408 for src, fn, st in self.statwalk(files, match):
411 for src, fn, st in self.statwalk(files, match):
409 try:
412 try:
410 type_, mode, size, time = self[fn]
413 type_, mode, size, time = self[fn]
411 except KeyError:
414 except KeyError:
412 unknown.append(fn)
415 unknown.append(fn)
413 continue
416 continue
414 if src == 'm':
417 if src == 'm':
415 nonexistent = True
418 nonexistent = True
416 if not st:
419 if not st:
417 try:
420 try:
418 f = self.wjoin(fn)
421 f = self.wjoin(fn)
419 st = os.lstat(f)
422 st = os.lstat(f)
420 except OSError, inst:
423 except OSError, inst:
421 if inst.errno != errno.ENOENT:
424 if inst.errno != errno.ENOENT:
422 raise
425 raise
423 st = None
426 st = None
424 # We need to re-check that it is a valid file
427 # We need to re-check that it is a valid file
425 if st and self.supported_type(fn, st):
428 if st and self.supported_type(fn, st):
426 nonexistent = False
429 nonexistent = False
427 # XXX: what to do with file no longer present in the fs
430 # XXX: what to do with file no longer present in the fs
428 # who are not removed in the dirstate ?
431 # who are not removed in the dirstate ?
429 if nonexistent and type_ in "nm":
432 if nonexistent and type_ in "nm":
430 deleted.append(fn)
433 deleted.append(fn)
431 continue
434 continue
432 # check the common case first
435 # check the common case first
433 if type_ == 'n':
436 if type_ == 'n':
434 if not st:
437 if not st:
435 st = os.stat(fn)
438 st = os.stat(fn)
436 if size >= 0 and (size != st.st_size
439 if size >= 0 and (size != st.st_size
437 or (mode ^ st.st_mode) & 0100):
440 or (mode ^ st.st_mode) & 0100):
438 modified.append(fn)
441 modified.append(fn)
439 elif time != st.st_mtime:
442 elif time != st.st_mtime:
440 lookup.append(fn)
443 lookup.append(fn)
441 elif type_ == 'm':
444 elif type_ == 'm':
442 modified.append(fn)
445 modified.append(fn)
443 elif type_ == 'a':
446 elif type_ == 'a':
444 added.append(fn)
447 added.append(fn)
445 elif type_ == 'r':
448 elif type_ == 'r':
446 removed.append(fn)
449 removed.append(fn)
447
450
448 return (lookup, modified, added, removed, deleted, unknown)
451 return (lookup, modified, added, removed, deleted, unknown)
General Comments 0
You need to be logged in to leave comments. Login now