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