comparison mercurial/dirstate.py @ 1471:f56f38a1a85f

rewrote changes function in dirstate to use generic walk code now, file with unsupported type will not show up in status anymore
author Benoit Boissinot <benoit.boissinot@ens-lyon.org>
date Thu, 27 Oct 2005 13:29:35 -0700
parents 9d2c2e6b32b5
children 17e8c70fb670
comparison
equal deleted inserted replaced
1470:fb9b84c91222 1471:f56f38a1a85f
239 else: 239 else:
240 break 240 break
241 bs += 1 241 bs += 1
242 return ret 242 return ret
243 243
244 def walk(self, files=None, match=util.always, dc=None): 244 def statwalk(self, files=None, match=util.always, dc=None):
245 self.read() 245 self.read()
246 246
247 # walk all files by default 247 # walk all files by default
248 if not files: 248 if not files:
249 files = [self.root] 249 files = [self.root]
258 return False 258 return False
259 return match(file) 259 return match(file)
260 260
261 return self.walkhelper(files=files, statmatch=statmatch, dc=dc) 261 return self.walkhelper(files=files, statmatch=statmatch, dc=dc)
262 262
263 def walk(self, files=None, match=util.always, dc=None):
264 # filter out the stat
265 for src, f, st in self.statwalk(files, match, dc):
266 yield src, f
267
263 # walk recursively through the directory tree, finding all files 268 # walk recursively through the directory tree, finding all files
264 # matched by the statmatch function 269 # matched by the statmatch function
265 # 270 #
266 # results are yielded in a tuple (src, filename), where src is one of: 271 # results are yielded in a tuple (src, filename, st), where src
272 # is one of:
267 # 'f' the file was found in the directory tree 273 # 'f' the file was found in the directory tree
268 # 'm' the file was only in the dirstate and not in the tree 274 # 'm' the file was only in the dirstate and not in the tree
275 # and st is the stat result if the file was found in the directory.
269 # 276 #
270 # dc is an optional arg for the current dirstate. dc is not modified 277 # dc is an optional arg for the current dirstate. dc is not modified
271 # directly by this function, but might be modified by your statmatch call. 278 # directly by this function, but might be modified by your statmatch call.
272 # 279 #
273 def walkhelper(self, files, statmatch, dc): 280 def walkhelper(self, files, statmatch, dc):
308 if stat.S_ISDIR(st.st_mode): 315 if stat.S_ISDIR(st.st_mode):
309 ds = os.path.join(nd, f +'/') 316 ds = os.path.join(nd, f +'/')
310 if statmatch(ds, st): 317 if statmatch(ds, st):
311 work.append(p) 318 work.append(p)
312 elif statmatch(np, st) and supported_type(np, st): 319 elif statmatch(np, st) and supported_type(np, st):
313 yield util.pconvert(np) 320 yield util.pconvert(np), st
314 321
315 322
316 known = {'.hg': 1} 323 known = {'.hg': 1}
317 def seen(fn): 324 def seen(fn):
318 if fn in known: return True 325 if fn in known: return True
328 if ff not in dc: self.ui.warn('%s: %s\n' % ( 335 if ff not in dc: self.ui.warn('%s: %s\n' % (
329 util.pathto(self.getcwd(), ff), 336 util.pathto(self.getcwd(), ff),
330 inst.strerror)) 337 inst.strerror))
331 continue 338 continue
332 if stat.S_ISDIR(st.st_mode): 339 if stat.S_ISDIR(st.st_mode):
340 cmp0 = (lambda x, y: cmp(x[0], y[0]))
333 sorted = [ x for x in findfiles(f) ] 341 sorted = [ x for x in findfiles(f) ]
334 sorted.sort() 342 sorted.sort(cmp0)
335 for fl in sorted: 343 for fl, stl in sorted:
336 yield 'f', fl 344 yield 'f', fl, stl
337 else: 345 else:
338 ff = util.normpath(ff) 346 ff = util.normpath(ff)
339 if seen(ff): 347 if seen(ff):
340 continue 348 continue
341 found = False 349 found = False
342 self.blockignore = True 350 self.blockignore = True
343 if statmatch(ff, st) and supported_type(ff, st): 351 if statmatch(ff, st) and supported_type(ff, st):
344 found = True 352 found = True
345 self.blockignore = False 353 self.blockignore = False
346 if found: 354 if found:
347 yield 'f', ff 355 yield 'f', ff, st
348 356
349 # step two run through anything left in the dc hash and yield 357 # step two run through anything left in the dc hash and yield
350 # if we haven't already seen it 358 # if we haven't already seen it
351 ks = dc.keys() 359 ks = dc.keys()
352 ks.sort() 360 ks.sort()
353 for k in ks: 361 for k in ks:
354 if not seen(k) and (statmatch(k, None)): 362 if not seen(k) and (statmatch(k, None)):
355 yield 'm', k 363 yield 'm', k, None
356 364
357 def changes(self, files=None, match=util.always): 365 def changes(self, files=None, match=util.always):
358 self.read()
359 if not files:
360 files = [self.root]
361 dc = self.map.copy()
362 else:
363 dc = self.filterfiles(files)
364 lookup, modified, added, unknown = [], [], [], [] 366 lookup, modified, added, unknown = [], [], [], []
365 removed, deleted = [], [] 367 removed, deleted = [], []
366 368
367 # statmatch function to eliminate entries from the dirstate copy 369 for src, fn, st in self.statwalk(files, match):
368 # and put files into the appropriate array. This gets passed 370 try:
369 # to the walking code 371 type, mode, size, time = self[fn]
370 def statmatch(fn, s): 372 except KeyError:
371 fn = util.pconvert(fn)
372 def checkappend(l, fn):
373 if match is util.always or match(fn):
374 l.append(fn)
375
376 if not s or stat.S_ISDIR(s.st_mode):
377 if self.ignore(fn): return False
378 return match(fn)
379
380 c = dc.pop(fn, None)
381 if c:
382 type, mode, size, time = c
383 # check the common case first
384 if type == 'n':
385 if size != s.st_size or (mode ^ s.st_mode) & 0100:
386 checkappend(modified, fn)
387 elif time != s.st_mtime:
388 checkappend(lookup, fn)
389 elif type == 'm':
390 checkappend(modified, fn)
391 elif type == 'a':
392 checkappend(added, fn)
393 elif type == 'r':
394 checkappend(unknown, fn)
395 elif not self.ignore(fn) and match(fn):
396 unknown.append(fn) 373 unknown.append(fn)
397 # return false because we've already handled all cases above. 374 continue
398 # there's no need for the walking code to process the file 375 # XXX: what to do with file no longer present in the fs
399 # any further. 376 # who are not removed in the dirstate ?
400 return False 377 if src == 'm' and not type == 'r':
401 378 deleted.append(fn)
402 # because our statmatch always returns false, self.walk will only 379 continue
403 # return files in the dirstate map that are not present in the FS. 380 # check the common case first
404 # But, we still need to iterate through the results to force the 381 if type == 'n':
405 # walk to complete 382 if not st:
406 for src, fn in self.walkhelper(files, statmatch, dc): 383 st = os.stat(fn)
407 pass 384 if size != st.st_size or (mode ^ st.st_mode) & 0100:
408 385 modified.append(fn)
409 # there may be patterns in the .hgignore file that prevent us 386 elif time != st.st_mtime:
410 # from examining entire directories in the dirstate map, so we 387 lookup.append(fn)
411 # go back and explicitly examine any matching files we've 388 elif type == 'm':
412 # ignored 389 modified.append(fn)
413 unexamined = [fn for fn in dc.iterkeys() 390 elif type == 'a':
414 if self.ignore(fn) and match(fn)] 391 added.append(fn)
415 392 elif type == 'r':
416 for src, fn in self.walkhelper(unexamined, statmatch, dc):
417 pass
418
419 # anything left in dc didn't exist in the filesystem
420 for fn, c in dc.iteritems():
421 if not match(fn): continue
422 if c[0] == 'r':
423 removed.append(fn) 393 removed.append(fn)
424 else: 394
425 deleted.append(fn)
426 return (lookup, modified, added, removed + deleted, unknown) 395 return (lookup, modified, added, removed + deleted, unknown)