235 d = directory(join(ret.path, next)) |
235 d = directory(join(ret.path, next)) |
236 ret.dirs[next] = d |
236 ret.dirs[next] = d |
237 ret = d |
237 ret = d |
238 return ret |
238 return ret |
239 |
239 |
240 def walk(self, states): |
240 def walk(self, states, visited=None): |
241 """ |
241 """ |
242 yield (filename, status) pairs for items in the trees |
242 yield (filename, status) pairs for items in the trees |
243 that have status in states. |
243 that have status in states. |
244 filenames are relative to the repo root |
244 filenames are relative to the repo root |
245 """ |
245 """ |
246 for file, st in self.files.iteritems(): |
246 for file, st in self.files.iteritems(): |
247 if st in states: |
247 if st in states: |
248 yield join(self.path, file), st |
248 yield join(self.path, file), st |
249 for dir in self.dirs.itervalues(): |
249 for dir in self.dirs.itervalues(): |
|
250 if visited is not None: |
|
251 visited.add(dir.path) |
250 for e in dir.walk(states): |
252 for e in dir.walk(states): |
251 yield e |
253 yield e |
252 |
254 |
253 def lookup(self, states, path): |
255 def lookup(self, states, path, visited): |
254 """ |
256 """ |
255 yield root-relative filenames that match path, and whose |
257 yield root-relative filenames that match path, and whose |
256 status are in states: |
258 status are in states: |
257 * if path is a file, yield path |
259 * if path is a file, yield path |
258 * if path is a directory, yield directory files |
260 * if path is a directory, yield directory files |
270 try: |
272 try: |
271 for dir in paths: |
273 for dir in paths: |
272 tree = tree.dirs[dir] |
274 tree = tree.dirs[dir] |
273 except KeyError: |
275 except KeyError: |
274 # path is not tracked |
276 # path is not tracked |
|
277 visited.add(tree.path) |
275 return |
278 return |
276 |
279 |
277 try: |
280 try: |
278 # if path is a directory, walk it |
281 # if path is a directory, walk it |
279 for file, st in tree.dirs[last].walk(states): |
282 target = tree.dirs[last] |
|
283 visited.add(target.path) |
|
284 for file, st in target.walk(states, visited): |
280 yield file |
285 yield file |
281 except KeyError: |
286 except KeyError: |
282 try: |
287 try: |
283 if tree.files[last] in states: |
288 if tree.files[last] in states: |
284 # path is a file |
289 # path is a file |
|
290 visited.add(tree.path) |
285 yield path |
291 yield path |
286 except KeyError: |
292 except KeyError: |
287 # path is not tracked |
293 # path is not tracked |
288 pass |
294 pass |
289 |
295 |
723 # We got a query while a rescan is pending. Make sure we |
729 # We got a query while a rescan is pending. Make sure we |
724 # rescan before responding, or we could give back a wrong |
730 # rescan before responding, or we could give back a wrong |
725 # answer. |
731 # answer. |
726 self.repowatcher.handle_timeout() |
732 self.repowatcher.handle_timeout() |
727 |
733 |
|
734 visited = set() |
728 if not names: |
735 if not names: |
729 def genresult(states, tree): |
736 def genresult(states, tree): |
730 for fn, state in tree.walk(states): |
737 for fn, state in tree.walk(states): |
731 yield fn |
738 yield fn |
732 else: |
739 else: |
733 def genresult(states, tree): |
740 def genresult(states, tree): |
734 for fn in names: |
741 for fn in names: |
735 for f in tree.lookup(states, fn): |
742 for f in tree.lookup(states, fn, visited): |
736 yield f |
743 yield f |
737 |
744 |
738 return ['\0'.join(r) for r in [ |
745 return ['\0'.join(r) for r in [ |
739 genresult('l', self.repowatcher.statustrees['l']), |
746 genresult('l', self.repowatcher.statustrees['l']), |
740 genresult('m', self.repowatcher.statustrees['m']), |
747 genresult('m', self.repowatcher.statustrees['m']), |
744 '?' in states |
751 '?' in states |
745 and genresult('?', self.repowatcher.statustrees['?']) |
752 and genresult('?', self.repowatcher.statustrees['?']) |
746 or [], |
753 or [], |
747 [], |
754 [], |
748 'c' in states and genresult('n', self.repowatcher.tree) or [], |
755 'c' in states and genresult('n', self.repowatcher.tree) or [], |
|
756 visited |
749 ]] |
757 ]] |
750 |
758 |
751 def answer_dbug_query(self): |
759 def answer_dbug_query(self): |
752 return ['\0'.join(self.repowatcher.debug())] |
760 return ['\0'.join(self.repowatcher.debug())] |
753 |
761 |