405
405
if not filenames:
407
specified_ids = _find_filename_ids_across_trees(filenames, trees,
409
return _find_children_across_trees(specified_ids, trees)
412
def _find_filename_ids_across_trees(filenames, trees, require_versioned):
407
specified_path_ids = _find_ids_across_trees(filenames, trees,
409
return _find_children_across_trees(specified_path_ids, trees)
410
# specified_ids = [id for path, id in _find_path_ids_across_trees(filenames, trees, require_versioned)]
411
# return _find_children_across_trees(specified_ids, trees)
413
def find_path_ids_across_trees(filenames, trees, require_versioned=True):
414
"""Find the paths and ids corresponding to specified filenames.
416
All matches in all trees will be used, and all children of matched
417
directories will be included
419
:param filenames: The filenames to find file_ids for
420
:param trees: The trees to find file_ids within
421
:param require_versioned: if true, all specified filenames must occur in
423
:return: a set of (path, file ids) for the specified filenames and their
424
children. The returned path is the path of the id in the first tree
425
that contains it. This matters when files have been moved
429
# This function needs to know the ids for filenames in all trees, then
430
# search for those same files and children in all the other trees.
431
# it is complicated by the same path in two trees being able to have
432
# different ids, which might both be present in both trees.
433
# consider two trees, which have had 'mv foo bar' and 'mv baz foo' done
434
# in this case, a diff of 'foo' should should changes to both the current
435
# 'bar' and the current 'foo' which was baz. Its arguable that if
436
# the situation is 'mv parent/foo bar' and 'mv baz parent/foo', that
437
# we should return the current bar and the current parent/foo' - at the
438
# moment we do, but we loop around all ids and all trees: I*T checks.
440
# Updating this algorithm to be fast in the common case:
441
# nothing has moved, all files have the same id in parent, child and there
442
# are only two trees (or one is working tree and the others are parents).
443
# walk the dirstate. as we find each path, gather the paths of that
444
# id in all trees. add a mapping from the id to the path in those trees.
445
# now lookup children by id, again in all trees; for these trees that
446
# nothing has moved in, the id->path mapping will allow us to find the
447
# parent trivially. To answer 'has anything been moved' in one of the
448
# dirstate parent trees though, we will need to stare harder at it.
450
# Now, given a path index, that is trivial for any one tree, and given
451
# that we can ask for additional data from a dirstate tree, its a single
452
# pass, though it will require scanning the entire tree to find paths
453
# that were at the current location.
454
# ideal results?: There are three things: tree, path, id. Pathologically
455
# we can have completely disjoint ids for each tree; but we cannot have
456
# disjoin paths for each tree, except if we scan each tree for the
457
# different ids from other trees.
459
specified_path_ids = _find_ids_across_trees(filenames, trees,
461
return _find_path_id_children_across_trees(specified_path_ids, trees)
464
def _find_ids_across_trees(filenames, trees, require_versioned):
413
465
"""Find the ids corresponding to specified filenames.
415
All matches in all trees will be used.
467
All matches in all trees will be used, but subdirectories are not scanned.
417
469
:param filenames: The filenames to find file_ids for
418
470
:param trees: The trees to find file_ids within
419
471
:param require_versioned: if true, all specified filenames must occur in
421
:return: a set of file ids for the specified filenames
473
:return: a set of (path, file ids) for the specified filenames
423
475
not_versioned = []
424
476
interesting_ids = set()
425
477
for tree_path in filenames:
427
479
for tree in trees:
428
file_id = tree.inventory.path2id(tree_path)
480
file_id = tree.path2id(tree_path)
429
481
if file_id is not None:
430
482
interesting_ids.add(file_id)
431
483
not_found = False