453
453
specified_path_ids = _find_ids_across_trees(filenames, trees,
454
454
require_versioned)
455
455
return _find_children_across_trees(specified_path_ids, trees)
456
# specified_ids = [id for path, id in _find_path_ids_across_trees(filenames, trees, require_versioned)]
457
# return _find_children_across_trees(specified_ids, trees)
459
def find_path_ids_across_trees(filenames, trees, require_versioned=True):
460
"""Find the paths and ids corresponding to specified filenames.
462
All matches in all trees will be used, and all children of matched
463
directories will be included
465
:param filenames: The filenames to find file_ids for
466
:param trees: The trees to find file_ids within
467
:param require_versioned: if true, all specified filenames must occur in
469
:return: a set of (path, file ids) for the specified filenames and their
470
children. The returned path is the path of the id in the first tree
471
that contains it. This matters when files have been moved
475
# This function needs to know the ids for filenames in all trees, then
476
# search for those same files and children in all the other trees.
477
# it is complicated by the same path in two trees being able to have
478
# different ids, which might both be present in both trees.
479
# consider two trees, which have had 'mv foo bar' and 'mv baz foo' done
480
# in this case, a diff of 'foo' should should changes to both the current
481
# 'bar' and the current 'foo' which was baz. Its arguable that if
482
# the situation is 'mv parent/foo bar' and 'mv baz parent/foo', that
483
# we should return the current bar and the current parent/foo' - at the
484
# moment we do, but we loop around all ids and all trees: I*T checks.
486
# Updating this algorithm to be fast in the common case:
487
# nothing has moved, all files have the same id in parent, child and there
488
# are only two trees (or one is working tree and the others are parents).
489
# walk the dirstate. as we find each path, gather the paths of that
490
# id in all trees. add a mapping from the id to the path in those trees.
491
# now lookup children by id, again in all trees; for these trees that
492
# nothing has moved in, the id->path mapping will allow us to find the
493
# parent trivially. To answer 'has anything been moved' in one of the
494
# dirstate parent trees though, we will need to stare harder at it.
496
# Now, given a path index, that is trivial for any one tree, and given
497
# that we can ask for additional data from a dirstate tree, its a single
498
# pass, though it will require scanning the entire tree to find paths
499
# that were at the current location.
500
# ideal results?: There are three things: tree, path, id. Pathologically
501
# we can have completely disjoint ids for each tree; but we cannot have
502
# disjoin paths for each tree, except if we scan each tree for the
503
# different ids from other trees.
505
specified_path_ids = _find_ids_across_trees(filenames, trees,
507
return _find_path_id_children_across_trees(specified_path_ids, trees)
510
458
def _find_ids_across_trees(filenames, trees, require_versioned):