469 supported = self._supported |
469 supported = self._supported |
470 _join = self._join |
470 _join = self._join |
471 work = [] |
471 work = [] |
472 wadd = work.append |
472 wadd = work.append |
473 |
473 |
474 seen = {'.hg': 1} |
474 results = {} |
475 |
475 |
476 # step 1: find all explicit files |
476 # step 1: find all explicit files |
477 for ff in util.sort(files): |
477 for ff in util.sort(files): |
478 nf = normalize(normpath(ff)) |
478 nf = normalize(normpath(ff)) |
479 if nf in seen: |
479 if nf in results: |
480 continue |
480 continue |
481 |
481 |
482 try: |
482 try: |
483 st = lstat(_join(nf)) |
483 st = lstat(_join(nf)) |
484 if isdir(st.st_mode): |
484 if isdir(st.st_mode): |
485 if not dirignore(nf): |
485 if not dirignore(nf): |
486 wadd(nf) |
486 wadd(nf) |
487 else: |
487 else: |
488 seen[nf] = 1 |
|
489 if supported(ff, st.st_mode, verbose=True): |
488 if supported(ff, st.st_mode, verbose=True): |
490 yield nf, st |
489 results[nf] = st |
491 elif nf in dmap: |
490 elif nf in dmap: |
492 yield nf, None |
491 results[nf] = None |
493 except OSError, inst: |
492 except OSError, inst: |
494 keep = False |
493 keep = False |
495 prefix = nf + "/" |
494 prefix = nf + "/" |
496 for fn in dmap: |
495 for fn in dmap: |
497 if nf == fn or fn.startswith(prefix): |
496 if nf == fn or fn.startswith(prefix): |
499 break |
498 break |
500 if not keep: |
499 if not keep: |
501 if inst.errno != errno.ENOENT: |
500 if inst.errno != errno.ENOENT: |
502 fwarn(ff, inst.strerror) |
501 fwarn(ff, inst.strerror) |
503 elif badfn(ff, inst.strerror) and imatch(nf): |
502 elif badfn(ff, inst.strerror) and imatch(nf): |
504 yield nf, None |
503 results[nf] = None |
505 |
504 |
506 # step 2: visit subdirectories |
505 # step 2: visit subdirectories |
507 while work: |
506 while work: |
508 nd = work.pop() |
507 nd = work.pop() |
509 if hasattr(match, 'dir'): |
508 if hasattr(match, 'dir'): |
510 match.dir(nd) |
509 match.dir(nd) |
511 entries = listdir(_join(nd), stat=True) |
510 entries = listdir(_join(nd), stat=True) |
512 if nd == '.': |
511 if nd == '.': |
513 nd = '' |
512 nd = '' |
|
513 elif nd == '.hg': |
|
514 continue |
514 else: |
515 else: |
515 # do not recurse into a repo contained in this |
516 # do not recurse into a repo contained in this |
516 # one. use bisect to find .hg directory so speed |
517 # one. use bisect to find .hg directory so speed |
517 # is good on big directory. |
518 # is good on big directory. |
518 hg = bisect_left(entries, ('.hg')) |
519 hg = bisect_left(entries, ('.hg')) |
519 if hg < len(entries) and entries[hg][0] == '.hg' \ |
520 if hg < len(entries) and entries[hg][0] == '.hg' \ |
520 and entries[hg][1] == dirkind: |
521 and entries[hg][1] == dirkind: |
521 continue |
522 continue |
522 for f, kind, st in entries: |
523 for f, kind, st in entries: |
523 nf = normalize(nd and (nd + "/" + f) or f) |
524 nf = normalize(nd and (nd + "/" + f) or f) |
524 if nf not in seen: |
525 if nf not in results: |
525 seen[nf] = 1 |
|
526 if kind == dirkind: |
526 if kind == dirkind: |
527 if not ignore(nf): |
527 if not ignore(nf): |
528 wadd(nf) |
528 wadd(nf) |
529 if nf in dmap and match(nf): |
529 if nf in dmap and match(nf): |
530 yield nf, None |
530 results[nf] = None |
531 elif imatch(nf): |
531 elif imatch(nf): |
532 if supported(nf, st.st_mode): |
532 if supported(nf, st.st_mode): |
533 yield nf, st |
533 results[nf] = st |
534 elif nf in dmap: |
534 elif nf in dmap: |
535 yield nf, None |
535 results[nf] = None |
536 |
536 |
537 # step 3: report unseen items in the dmap hash |
537 # step 3: report unseen items in the dmap hash |
538 for f in util.sort(dmap): |
538 for f in util.sort(dmap): |
539 if f not in seen and match(f): |
539 if f not in results and match(f): |
|
540 results[f] = None |
540 try: |
541 try: |
541 st = lstat(_join(f)) |
542 st = lstat(_join(f)) |
542 if supported(f, st.st_mode): |
543 if supported(f, st.st_mode): |
543 yield f, st |
544 results[f] = st |
544 continue |
|
545 except OSError, inst: |
545 except OSError, inst: |
546 if inst.errno not in (errno.ENOENT, errno.ENOTDIR): |
546 if inst.errno not in (errno.ENOENT, errno.ENOTDIR): |
547 raise |
547 raise |
548 yield f, None |
548 |
|
549 return results |
549 |
550 |
550 def status(self, match, ignored, clean, unknown): |
551 def status(self, match, ignored, clean, unknown): |
551 listignored, listclean, listunknown = ignored, clean, unknown |
552 listignored, listclean, listunknown = ignored, clean, unknown |
552 lookup, modified, added, unknown, ignored = [], [], [], [], [] |
553 lookup, modified, added, unknown, ignored = [], [], [], [], [] |
553 removed, deleted, clean = [], [], [] |
554 removed, deleted, clean = [], [], [] |