Rev 5351: (mbp) tree_files and internal_tree files moved to WorkingTree (Martin Pool) in file:///home/pqm/archives/thelove/bzr/%2Btrunk/

Canonical.com Patch Queue Manager pqm at pqm.ubuntu.com
Mon Jul 19 15:26:13 BST 2010


At file:///home/pqm/archives/thelove/bzr/%2Btrunk/

------------------------------------------------------------
revno: 5351 [merge]
revision-id: pqm at pqm.ubuntu.com-20100719142611-fbhst4ivcngc32d5
parent: pqm at pqm.ubuntu.com-20100719130851-igs92yvcf0y7j964
parent: mbp at canonical.com-20100716160455-fj4fpxsgjw1uy3d6
committer: Canonical.com Patch Queue Manager <pqm at pqm.ubuntu.com>
branch nick: +trunk
timestamp: Mon 2010-07-19 15:26:11 +0100
message:
  (mbp) tree_files and internal_tree files moved to WorkingTree (Martin Pool)
added:
  bzrlib/tests/per_workingtree/test_symlinks.py test_symlinks.py-20100715135626-4lw38d8njbzyec6l-1
  bzrlib/tests/test_treeshape.py test_treeshape.py-20100715135036-z8vz2u7f3w7wg2it-1
modified:
  NEWS                           NEWS-20050323055033-4e00b5db738777ff
  bzrlib/builtins.py             builtins.py-20050830033751-fc01482b9ca23183
  bzrlib/conflicts.py            conflicts.py-20051001061850-78ef952ba63d2b42
  bzrlib/diff.py                 diff.py-20050309040759-26944fbbf2ebbf36
  bzrlib/log.py                  log.py-20050505065812-c40ce11702fe5fb1
  bzrlib/mutabletree.py          mutabletree.py-20060906023413-4wlkalbdpsxi2r4y-2
  bzrlib/shelf_ui.py             shelver.py-20081005210102-33worgzwrtdw0yrm-1
  bzrlib/tests/__init__.py       selftest.py-20050531073622-8d0e3c8845c97a64
  bzrlib/tests/per_workingtree/__init__.py __init__.py-20060203003124-b2aa5aca21a8bfad
  bzrlib/tests/test_upgrade.py   test_upgrade.py-20051004040251-555fe1d2bae1bc71
  bzrlib/tests/treeshape.py      treeshape.py-20051004094628-312a98f0194306a8
  bzrlib/workingtree.py          workingtree.py-20050511021032-29b6ec0a681e02e3
=== modified file 'NEWS'
--- a/NEWS	2010-07-16 13:53:26 +0000
+++ b/NEWS	2010-07-16 15:49:06 +0000
@@ -18,6 +18,10 @@
   longer raised.
   (Martin Pool)
 
+* `tree_files` and `internal_tree_files` are now deprecated in favor of
+  `WorkingTree.open_containing_paths`.
+  (Martin Pool)
+
 New Features
 ************
 
@@ -1545,6 +1549,10 @@
   history no longer crash when deleted files are involved.
   (Vincent Ladeuil, John Arbash Meinel, #375898)
 
+* ``bzr commit SYMLINK`` now works, rather than trying to commit the
+  target of the symlink.
+  (Martin Pool, John Arbash Meinel, #128562)
+
 * ``bzr revert`` now only takes write lock on working tree, instead of on 
   both working tree and branch.
   (Danny van Heumen, #498409)
@@ -1579,6 +1587,13 @@
   (John Arbash Meinel, #583486)
 
 
+Testing
+*******
+
+* ``build_tree_contents`` can create symlinks.
+  (Martin Pool, John Arbash Meinel)
+
+
 bzr 2.0.5
 #########
 

=== modified file 'bzrlib/builtins.py'
--- a/bzrlib/builtins.py	2010-07-16 13:53:26 +0000
+++ b/bzrlib/builtins.py	2010-07-16 16:04:55 +0000
@@ -75,6 +75,7 @@
 from bzrlib.trace import mutter, note, warning, is_quiet, get_verbosity_level
 
 
+ at symbol_versioning.deprecated_function(symbol_versioning.deprecated_in((2, 3, 0)))
 def tree_files(file_list, default_branch=u'.', canonicalize=True,
     apply_view=True):
     return internal_tree_files(file_list, default_branch, canonicalize,
@@ -148,10 +149,13 @@
 
 # XXX: Bad function name; should possibly also be a class method of
 # WorkingTree rather than a function.
+ at symbol_versioning.deprecated_function(symbol_versioning.deprecated_in((2, 3, 0)))
 def internal_tree_files(file_list, default_branch=u'.', canonicalize=True,
     apply_view=True):
     """Convert command-line paths to a WorkingTree and relative paths.
 
+    Deprecated: use WorkingTree.open_containing_paths instead.
+
     This is typically used for command-line processors that take one or
     more filenames, and infer the workingtree that contains them.
 
@@ -167,50 +171,10 @@
 
     :return: workingtree, [relative_paths]
     """
-    if file_list is None or len(file_list) == 0:
-        tree = WorkingTree.open_containing(default_branch)[0]
-        if tree.supports_views() and apply_view:
-            view_files = tree.views.lookup_view()
-            if view_files:
-                file_list = view_files
-                view_str = views.view_display_str(view_files)
-                note("Ignoring files outside view. View is %s" % view_str)
-        return tree, file_list
-    tree = WorkingTree.open_containing(osutils.realpath(file_list[0]))[0]
-    return tree, safe_relpath_files(tree, file_list, canonicalize,
-        apply_view=apply_view)
-
-
-def safe_relpath_files(tree, file_list, canonicalize=True, apply_view=True):
-    """Convert file_list into a list of relpaths in tree.
-
-    :param tree: A tree to operate on.
-    :param file_list: A list of user provided paths or None.
-    :param apply_view: if True and a view is set, apply it or check that
-        specified files are within it
-    :return: A list of relative paths.
-    :raises errors.PathNotChild: When a provided path is in a different tree
-        than tree.
-    """
-    if file_list is None:
-        return None
-    if tree.supports_views() and apply_view:
-        view_files = tree.views.lookup_view()
-    else:
-        view_files = []
-    new_list = []
-    # tree.relpath exists as a "thunk" to osutils, but canonical_relpath
-    # doesn't - fix that up here before we enter the loop.
-    if canonicalize:
-        fixer = lambda p: osutils.canonical_relpath(tree.basedir, p)
-    else:
-        fixer = tree.relpath
-    for filename in file_list:
-        relpath = fixer(osutils.dereference_path(filename))
-        if  view_files and not osutils.is_inside_any(view_files, relpath):
-            raise errors.FileOutsideView(filename, view_files)
-        new_list.append(relpath)
-    return new_list
+    return WorkingTree.open_containing_paths(
+        file_list, default_directory='.',
+        canonicalize=True,
+        apply_view=True)
 
 
 def _get_view_info_for_change_reporter(tree):
@@ -316,7 +280,7 @@
             raise errors.BzrCommandError('bzr status --revision takes exactly'
                                          ' one or two revision specifiers')
 
-        tree, relfile_list = tree_files(file_list)
+        tree, relfile_list = WorkingTree.open_containing_paths(file_list)
         # Avoid asking for specific files when that is not needed.
         if relfile_list == ['']:
             relfile_list = None
@@ -754,7 +718,7 @@
             raise errors.BzrCommandError('invalid kind %r specified' % (kind,))
 
         revision = _get_one_revision('inventory', revision)
-        work_tree, file_list = tree_files(file_list)
+        work_tree, file_list = WorkingTree.open_containing_paths(file_list)
         self.add_cleanup(work_tree.lock_read().unlock)
         if revision is not None:
             tree = revision.as_tree(work_tree.branch)
@@ -825,7 +789,7 @@
             names_list = []
         if len(names_list) < 2:
             raise errors.BzrCommandError("missing file argument")
-        tree, rel_names = tree_files(names_list, canonicalize=False)
+        tree, rel_names = WorkingTree.open_containing_paths(names_list, canonicalize=False)
         self.add_cleanup(tree.lock_tree_write().unlock)
         self._run(tree, names_list, rel_names, after)
 
@@ -836,7 +800,8 @@
         if after:
             raise errors.BzrCommandError('--after cannot be specified with'
                                          ' --auto.')
-        work_tree, file_list = tree_files(names_list, default_branch='.')
+        work_tree, file_list = WorkingTree.open_containing_paths(
+            names_list, default_directory='.')
         self.add_cleanup(work_tree.lock_tree_write().unlock)
         rename_map.RenameMap.guess_renames(work_tree, dry_run)
 
@@ -1519,7 +1484,7 @@
 
     def run(self, file_list, verbose=False, new=False,
         file_deletion_strategy='safe'):
-        tree, file_list = tree_files(file_list)
+        tree, file_list = WorkingTree.open_containing_paths(file_list)
 
         if file_list is not None:
             file_list = [f for f in file_list]
@@ -3102,7 +3067,7 @@
 
         properties = {}
 
-        tree, selected_list = tree_files(selected_list)
+        tree, selected_list = WorkingTree.open_containing_paths(selected_list)
         if selected_list == ['']:
             # workaround - commit of root of tree should be exactly the same
             # as just default commit in that tree, and succeed even though
@@ -3182,7 +3147,7 @@
                         reporter=None, verbose=verbose, revprops=properties,
                         authors=author, timestamp=commit_stamp,
                         timezone=offset,
-                        exclude=safe_relpath_files(tree, exclude))
+                        exclude=tree.safe_relpath_files(exclude))
         except PointlessCommit:
             raise errors.BzrCommandError("No changes to commit."
                               " Use --unchanged to commit anyhow.")
@@ -4084,7 +4049,7 @@
         from bzrlib.conflicts import restore
         if merge_type is None:
             merge_type = _mod_merge.Merge3Merger
-        tree, file_list = tree_files(file_list)
+        tree, file_list = WorkingTree.open_containing_paths(file_list)
         self.add_cleanup(tree.lock_write().unlock)
         parents = tree.get_parent_ids()
         if len(parents) != 2:
@@ -4200,7 +4165,7 @@
 
     def run(self, revision=None, no_backup=False, file_list=None,
             forget_merges=None):
-        tree, file_list = tree_files(file_list)
+        tree, file_list = WorkingTree.open_containing_paths(file_list)
         self.add_cleanup(tree.lock_tree_write().unlock)
         if forget_merges:
             tree.set_parent_ids(tree.get_parent_ids()[:1])
@@ -5702,7 +5667,8 @@
             name=None,
             switch=None,
             ):
-        tree, file_list = tree_files(file_list, apply_view=False)
+        tree, file_list = WorkingTree.open_containing_paths(file_list,
+            apply_view=False)
         current_view, view_dict = tree.views.get_view_info()
         if name is None:
             name = current_view

=== modified file 'bzrlib/conflicts.py'
--- a/bzrlib/conflicts.py	2010-05-28 14:15:28 +0000
+++ b/bzrlib/conflicts.py	2010-07-16 15:35:43 +0000
@@ -24,7 +24,6 @@
 import errno
 
 from bzrlib import (
-    builtins,
     cleanup,
     commands,
     errors,
@@ -127,7 +126,8 @@
             if action is None:
                 action = 'done'
         else:
-            tree, file_list = builtins.tree_files(file_list)
+            tree, file_list = workingtree.WorkingTree.open_containing_paths(
+                file_list)
             if file_list is None:
                 if action is None:
                     # FIXME: There is a special case here related to the option

=== modified file 'bzrlib/diff.py'
--- a/bzrlib/diff.py	2010-07-16 13:53:26 +0000
+++ b/bzrlib/diff.py	2010-07-16 15:20:17 +0000
@@ -420,9 +420,9 @@
 
     # Get the specific files (all files is None, no files is [])
     if make_paths_wt_relative and working_tree is not None:
-        from bzrlib.builtins import safe_relpath_files
-        other_paths = safe_relpath_files(working_tree, other_paths,
-        apply_view=apply_view)
+        other_paths = working_tree.safe_relpath_files(
+            other_paths,
+            apply_view=apply_view)
     specific_files.extend(other_paths)
     if len(specific_files) == 0:
         specific_files = None

=== modified file 'bzrlib/log.py'
--- a/bzrlib/log.py	2010-06-30 12:03:30 +0000
+++ b/bzrlib/log.py	2010-07-16 13:29:07 +0000
@@ -2017,7 +2017,7 @@
       kind is one of values 'directory', 'file', 'symlink', 'tree-reference'.
       branch will be read-locked.
     """
-    from builtins import _get_revision_range, safe_relpath_files
+    from builtins import _get_revision_range
     tree, b, path = bzrdir.BzrDir.open_containing_tree_or_branch(file_list[0])
     add_cleanup(b.lock_read().unlock)
     # XXX: It's damn messy converting a list of paths to relative paths when
@@ -2029,7 +2029,7 @@
     # case of running log in a nested directory, assuming paths beyond the
     # first one haven't been deleted ...
     if tree:
-        relpaths = [path] + safe_relpath_files(tree, file_list[1:])
+        relpaths = [path] + tree.safe_relpath_files(file_list[1:])
     else:
         relpaths = [path] + file_list[1:]
     info_list = []

=== modified file 'bzrlib/mutabletree.py'
--- a/bzrlib/mutabletree.py	2010-05-10 11:34:20 +0000
+++ b/bzrlib/mutabletree.py	2010-07-16 13:06:33 +0000
@@ -375,6 +375,10 @@
         This is designed more towards DWIM for humans than API clarity.
         For the specific behaviour see the help for cmd_add().
 
+        :param file_list: List of zero or more paths.  *NB: these are 
+            interpreted relative to the process cwd, not relative to the 
+            tree.*  (Add and most other tree methods use tree-relative
+            paths.)
         :param action: A reporter to be called with the inventory, parent_ie,
             path and kind of the path being added. It may return a file_id if
             a specific one should be used.

=== modified file 'bzrlib/shelf_ui.py'
--- a/bzrlib/shelf_ui.py	2010-05-26 15:58:08 +0000
+++ b/bzrlib/shelf_ui.py	2010-07-16 13:29:07 +0000
@@ -175,7 +175,7 @@
         try:
             target_tree = builtins._get_one_revision_tree('shelf2', revision,
                 tree.branch, tree)
-            files = builtins.safe_relpath_files(tree, file_list)
+            files = tree.safe_relpath_files(file_list)
             return klass(tree, target_tree, diff_writer, all, all, files,
                          message, destroy)
         finally:

=== modified file 'bzrlib/tests/__init__.py'
--- a/bzrlib/tests/__init__.py	2010-07-08 10:34:12 +0000
+++ b/bzrlib/tests/__init__.py	2010-07-16 13:06:33 +0000
@@ -3813,6 +3813,7 @@
         'bzrlib.tests.test_transport_log',
         'bzrlib.tests.test_tree',
         'bzrlib.tests.test_treebuilder',
+        'bzrlib.tests.test_treeshape',
         'bzrlib.tests.test_tsort',
         'bzrlib.tests.test_tuned_gzip',
         'bzrlib.tests.test_ui',

=== modified file 'bzrlib/tests/per_workingtree/__init__.py'
--- a/bzrlib/tests/per_workingtree/__init__.py	2010-04-01 12:53:53 +0000
+++ b/bzrlib/tests/per_workingtree/__init__.py	2010-07-16 13:06:33 +0000
@@ -101,6 +101,7 @@
         'revision_tree',
         'set_root_id',
         'smart_add',
+        'symlinks',
         'uncommit',
         'unversion',
         'views',

=== added file 'bzrlib/tests/per_workingtree/test_symlinks.py'
--- a/bzrlib/tests/per_workingtree/test_symlinks.py	1970-01-01 00:00:00 +0000
+++ b/bzrlib/tests/per_workingtree/test_symlinks.py	2010-07-16 15:49:06 +0000
@@ -0,0 +1,98 @@
+# Copyright (C) 2010 Canonical Ltd
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+"""Test symlink support.
+
+See eg <https://bugs.launchpad.net/bzr/+bug/192859>
+"""
+
+from bzrlib import (
+    builtins,
+    tests,
+    workingtree,
+    )
+from bzrlib.tests.per_workingtree import TestCaseWithWorkingTree
+
+
+class TestSmartAddTree(TestCaseWithWorkingTree):
+
+    _test_needs_features = [tests.SymlinkFeature]
+
+    def test_smart_add_symlink(self):
+        tree = self.make_branch_and_tree('tree')
+        self.build_tree_contents([
+            ('tree/link@', 'target'),
+            ])
+        tree.smart_add(['tree/link'])
+        self.assertIsNot(None, tree.path2id('link'))
+        self.assertIs(None, tree.path2id('target'))
+        self.assertEqual('symlink',
+            tree.kind(tree.path2id('link')))
+
+    def test_smart_add_symlink_pointing_outside(self):
+        tree = self.make_branch_and_tree('tree')
+        self.build_tree_contents([
+            ('tree/link@', '../../../../target'),
+            ])
+        tree.smart_add(['tree/link'])
+        self.assertIsNot(None, tree.path2id('link'))
+        self.assertIs(None, tree.path2id('target'))
+        self.assertEqual('symlink',
+            tree.kind(tree.path2id('link')))
+
+    def test_open_containing_through_symlink(self):
+        self.make_test_tree()
+        self.check_open_containing('link/content', 'tree', 'content')
+        self.check_open_containing('link/sublink', 'tree', 'sublink')
+        # this next one is a bit debatable, but arguably it's better that
+        # open_containing is only concerned with opening the tree 
+        # and then you can deal with symlinks along the way if you want
+        self.check_open_containing('link/sublink/subcontent', 'tree',
+            'sublink/subcontent')
+
+    def check_open_containing(self, to_open, expected_tree_name,
+        expected_relpath):
+        wt, relpath = workingtree.WorkingTree.open_containing(to_open)
+        self.assertEquals(relpath, expected_relpath)
+        self.assertEndsWith(wt.basedir, expected_tree_name)
+
+    def test_tree_files(self):
+        # not strictly a WorkingTree method, but it should be
+        # probably the root cause for
+        # <https://bugs.launchpad.net/bzr/+bug/128562>
+        self.make_test_tree()
+        self.check_tree_files(['tree/outerlink'],
+            'tree', ['outerlink'])
+        self.check_tree_files(['link/outerlink'],
+            'tree', ['outerlink'])
+        self.check_tree_files(['link/sublink/subcontent'],
+            'tree', ['subdir/subcontent'])
+
+    def check_tree_files(self, to_open, expected_tree, expect_paths):
+        tree, relpaths = workingtree.WorkingTree.open_containing_paths(to_open)
+        self.assertEndsWith(tree.basedir, expected_tree)
+        self.assertEquals(expect_paths, relpaths)
+
+    def make_test_tree(self):
+        tree = self.make_branch_and_tree('tree')
+        self.build_tree_contents([
+            ('link@', 'tree'),
+            ('tree/outerlink@', '/not/there'),
+            ('tree/content', 'hello'),
+            ('tree/sublink@', 'subdir'),
+            ('tree/subdir/',),
+            ('tree/subdir/subcontent', 'subcontent stuff')
+            ])

=== added file 'bzrlib/tests/test_treeshape.py'
--- a/bzrlib/tests/test_treeshape.py	1970-01-01 00:00:00 +0000
+++ b/bzrlib/tests/test_treeshape.py	2010-07-15 13:55:46 +0000
@@ -0,0 +1,41 @@
+# Copyright (C) 2010 Canonical Ltd
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+
+import os
+
+
+from bzrlib import tests
+
+
+class TestTreeShape(tests.TestCaseWithTransport):
+
+    def test_build_tree(self):
+        """Test tree-building test helper"""
+        self.build_tree_contents([
+            ('foo', 'new contents'),
+            ('.bzr/',),
+            ('.bzr/README', 'hello'),
+            ])
+        self.failUnlessExists('foo')
+        self.failUnlessExists('.bzr/README')
+        self.assertFileEqual('hello', '.bzr/README')
+
+    def test_build_tree_symlink(self):
+        self.requireFeature(tests.SymlinkFeature)
+        self.build_tree_contents([('link@', 'target')])
+        self.assertEqual('target',
+            os.readlink('link'))

=== modified file 'bzrlib/tests/test_upgrade.py'
--- a/bzrlib/tests/test_upgrade.py	2010-06-20 11:18:38 +0000
+++ b/bzrlib/tests/test_upgrade.py	2010-07-16 13:06:33 +0000
@@ -43,12 +43,6 @@
 
 class TestUpgrade(TestCaseWithTransport):
 
-    def test_build_tree(self):
-        """Test tree-building test helper"""
-        self.build_tree_contents(_upgrade1_template)
-        self.failUnlessExists('foo')
-        self.failUnlessExists('.bzr/README')
-
     def test_upgrade_simple(self):
         """Upgrade simple v0.0.4 format to latest format"""
         eq = self.assertEquals

=== modified file 'bzrlib/tests/treeshape.py'
--- a/bzrlib/tests/treeshape.py	2010-05-05 00:05:29 +0000
+++ b/bzrlib/tests/treeshape.py	2010-07-16 13:06:33 +0000
@@ -1,4 +1,4 @@
-# Copyright (C) 2005 Canonical Ltd
+# Copyright (C) 2005, 2010 Canonical Ltd
 #
 # This program is free software; you can redistribute it and/or modify
 # it under the terms of the GNU General Public License as published by
@@ -51,7 +51,7 @@
         if name[-1] == '/':
             os.mkdir(name)
         elif name[-1] == '@':
-            raise NotImplementedError('symlinks not handled yet')
+            os.symlink(tt[1], tt[0][:-1])
         else:
             f = file(name, 'wb')
             try:

=== modified file 'bzrlib/workingtree.py'
--- a/bzrlib/workingtree.py	2010-07-15 13:33:30 +0000
+++ b/bzrlib/workingtree.py	2010-07-19 14:26:11 +0000
@@ -349,10 +349,67 @@
         if path is None:
             path = osutils.getcwd()
         control, relpath = bzrdir.BzrDir.open_containing(path)
-
         return control.open_workingtree(), relpath
 
     @staticmethod
+    def open_containing_paths(file_list, default_directory='.',
+        canonicalize=True, apply_view=True):
+        """Open the WorkingTree that contains a set of paths.
+
+        Fail if the paths given are not all in a single tree.
+
+        This is used for the many command-line interfaces that take a list of
+        any number of files and that require they all be in the same tree.
+        """
+        # recommended replacement for builtins.internal_tree_files
+        if file_list is None or len(file_list) == 0:
+            tree = WorkingTree.open_containing(default_directory)[0]
+            # XXX: doesn't really belong here, and seems to have the strange
+            # side effect of making it return a bunch of files, not the whole
+            # tree -- mbp 20100716
+            if tree.supports_views() and apply_view:
+                view_files = tree.views.lookup_view()
+                if view_files:
+                    file_list = view_files
+                    view_str = views.view_display_str(view_files)
+                    note("Ignoring files outside view. View is %s" % view_str)
+            return tree, file_list
+        tree = WorkingTree.open_containing(file_list[0])[0]
+        return tree, tree.safe_relpath_files(file_list, canonicalize,
+            apply_view=apply_view)
+
+    def safe_relpath_files(self, file_list, canonicalize=True, apply_view=True):
+        """Convert file_list into a list of relpaths in tree.
+
+        :param self: A tree to operate on.
+        :param file_list: A list of user provided paths or None.
+        :param apply_view: if True and a view is set, apply it or check that
+            specified files are within it
+        :return: A list of relative paths.
+        :raises errors.PathNotChild: When a provided path is in a different self
+            than self.
+        """
+        if file_list is None:
+            return None
+        if self.supports_views() and apply_view:
+            view_files = self.views.lookup_view()
+        else:
+            view_files = []
+        new_list = []
+        # self.relpath exists as a "thunk" to osutils, but canonical_relpath
+        # doesn't - fix that up here before we enter the loop.
+        if canonicalize:
+            fixer = lambda p: osutils.canonical_relpath(self.basedir, p)
+        else:
+            fixer = self.relpath
+        for filename in file_list:
+            relpath = fixer(osutils.dereference_path(filename))
+            if view_files and not osutils.is_inside_any(view_files, relpath):
+                raise errors.FileOutsideView(filename, view_files)
+            new_list.append(relpath)
+        return new_list
+
+    @staticmethod
     def open_downlevel(path=None):
         """Open an unsupported working tree.
 




More information about the bazaar-commits mailing list