33
33
from bzrlib.decorators import needs_read_lock
34
from bzrlib.errors import BzrError, BzrCheckError
34
from bzrlib.errors import BzrError, BzrCheckError, NoSuchId
35
35
from bzrlib import errors
36
36
from bzrlib.inventory import Inventory, InventoryFile
37
37
from bzrlib.inter import InterObject
346
346
raise NotImplementedError(self.get_symlink_target)
348
def get_canonical_path(self, path):
349
"""Returns the first path that case-insensitively matches the input.
348
def get_canonical_inventory_paths(self, paths):
349
"""Returns a list with each item the first path that
350
case-insensitively matches the specified input paths.
351
352
If a path matches exactly, it is returned. If no path matches exactly
352
353
but more than one path matches case-insensitively, it is implementation
355
356
If no path matches case-insensitively, the input path is returned, but
356
357
with as many path entries that do exist changed to their canonical form.
358
NOTE: There is a risk that this will cause O(N) behaviour if called
359
for every path in a working tree. However, it is expected this should
360
only be used on path specified by the users. A cache with lifetime
361
controlled by the caller would probably resolve this if it becomes a
364
:param path: A path, relative to the root of the tree.
365
:return: The input path adjusted to account for existing elements that
366
match case insensitively.
368
# First, if the path as specified exists exactly, just use it.
369
if self.path2id(path) is not None:
372
cur_id = self.get_root_id()
374
bit_iter = iter(path.split("/"))
377
for child in self.iter_children(cur_id):
378
child_base = os.path.basename(self.id2path(child))
379
if child_base.lower() == lelt:
381
cur_path = osutils.pathjoin(cur_path, child_base)
359
:param paths: A sequence of paths relative to the root of the tree.
360
:return: A list of paths, with each item the corresponding input path
361
adjusted to account for existing elements that match case
364
return list(self._yield_canonical_inventory_paths(paths))
366
def get_canonical_inventory_path(self, path):
367
"""A convenience version of get_canonical_inventory_path which
370
If you need to resolve many names from the same tree, you should
371
use get_canonical_inventory_paths() to avoid O(N) behaviour.
373
return self._yield_canonical_inventory_paths([path]).next()
375
def _yield_canonical_inventory_paths(self, paths):
377
# First, if the path as specified exists exactly, just use it.
378
if self.path2id(path) is not None:
382
cur_id = self.get_root_id()
384
bit_iter = iter(path.split("/"))
387
for child in self.iter_children(cur_id):
389
child_base = os.path.basename(self.id2path(child))
390
if child_base.lower() == lelt:
392
cur_path = osutils.pathjoin(cur_path, child_base)
395
# before a change is committed we can see this error...
398
# got to the end of this directory and no entries matched.
399
# Return what matched so far, plus the rest as specified.
400
cur_path = osutils.pathjoin(cur_path, elt, *list(bit_iter))
384
# got to the end of this directory and no entries matched.
385
# Return what matched so far, plus the rest as specified.
386
cur_path = osutils.pathjoin(cur_path, elt, *list(bit_iter))
390
405
def get_root_id(self):
391
406
"""Return the file_id for the root of this tree."""