Origin: commit, revision id: jelmer@jelmer.uk-20181120000107-jfpvuxbu14fcx9j3
Author: Jelmer Vernooĳ <jelmer@jelmer.uk>
Bug: https://launchpad.net/bugs/1804072
Last-Update: 2018-11-20
Applied-Upstream: no
X-Bzr-Revision-Id: jelmer@jelmer.uk-20181120000107-jfpvuxbu14fcx9j3

=== modified file 'breezy/git/workingtree.py'
--- old/breezy/git/workingtree.py	2018-11-16 23:21:31 +0000
+++ new/breezy/git/workingtree.py	2018-11-19 23:04:59 +0000
@@ -535,8 +535,8 @@
                     except UnicodeDecodeError:
                         raise errors.BadFilenameEncoding(
                             relpath, osutils._fs_enc)
-                if not self._has_dir(relpath):
-                    dirnames.remove(name)
+                    if not self._has_dir(relpath):
+                        dirnames.remove(name)
             for name in filenames:
                 if not self.mapping.is_special_file(name):
                     yp = os.path.join(dir_relpath, name)
@@ -550,12 +550,10 @@
         """Yield all unversioned files in this WorkingTree.
         """
         with self.lock_read():
-            index_paths = set([p.decode('utf-8')
-                               for p, i in self._recurse_index_entries()])
-            all_paths = set(self._iter_files_recursive(include_dirs=True))
-            for p in (all_paths - index_paths):
-                if not self._has_dir(p.encode('utf-8')):
-                    yield p
+            index_paths = set(
+                [p.decode('utf-8') for p, i in self._recurse_index_entries()])
+            all_paths = set(self._iter_files_recursive(include_dirs=False))
+            return iter(all_paths - index_paths)
 
     def _gather_kinds(self, files, kinds):
         """See MutableTree._gather_kinds."""

=== modified file 'breezy/tests/per_intertree/test_compare.py'
--- old/breezy/tests/per_intertree/test_compare.py	2018-11-11 04:08:32 +0000
+++ new/breezy/tests/per_intertree/test_compare.py	2018-11-19 23:04:59 +0000
@@ -477,15 +477,8 @@
             else:
                 # Neither tree can be used
                 return
-        tree1.lock_read()
-        try:
-            tree2.lock_read()
-            try:
-                return tree2.has_changes(tree1)
-            finally:
-                tree2.unlock()
-        finally:
-            tree1.unlock()
+        with tree1.lock_read(), tree2.lock_read():
+            return tree2.has_changes(tree1)
 
     def mutable_trees_to_locked_test_trees(self, tree1, tree2):
         """Convert the working trees into test trees.
@@ -1761,14 +1754,24 @@
         tree1, tree2 = self.mutable_trees_to_locked_test_trees(tree1, tree2)
         self.not_applicable_if_cannot_represent_unversioned(tree2)
 
-        expected = self.sorted([
-            self.unversioned(tree2, u'a/file'),
-            self.unversioned(tree2, u'a/dir'),
-            ])
-        self.assertEqual(expected,
-                         self.do_iter_changes(tree1, tree2,
-                                              require_versioned=False,
-                                              want_unversioned=True))
+        if tree2.has_versioned_directories():
+            expected = self.sorted([
+                self.unversioned(tree2, u'a/file'),
+                self.unversioned(tree2, u'a/dir'),
+                ])
+            self.assertEqual(expected,
+                             self.do_iter_changes(tree1, tree2,
+                                                  require_versioned=False,
+                                                  want_unversioned=True))
+        else:
+            expected = self.sorted([
+                self.unversioned(tree2, u'a/file'),
+                self.unversioned(tree2, u'a/dir/subfile'),
+                ])
+            self.assertEqual(expected,
+                             self.do_iter_changes(tree1, tree2,
+                                                  require_versioned=False,
+                                                  want_unversioned=True))
 
     def test_rename_over_deleted(self):
         tree1 = self.make_branch_and_tree('tree1')

=== modified file 'breezy/tests/per_tree/test_test_trees.py'
--- old/breezy/tests/per_tree/test_test_trees.py	2018-11-16 23:21:31 +0000
+++ new/breezy/tests/per_tree/test_test_trees.py	2018-11-19 23:04:59 +0000
@@ -141,10 +141,7 @@
         self.addCleanup(tree.unlock)
         self.assertEqual([], tree.get_parent_ids())
         self.assertEqual([], tree.conflicts())
-        if tree.has_versioned_directories() or not tree.has_filename('b'):
-            self.assertEqual([], list(tree.unknowns()))
-        else:
-            self.assertEqual(['b'], list(tree.unknowns()))
+        self.assertEqual([], list(tree.unknowns()))
         # __iter__ has no strongly defined order
         expected_paths = (
             ['', 'a']
@@ -169,11 +166,7 @@
         self.addCleanup(tree.unlock)
         self.assertEqual([], tree.get_parent_ids())
         self.assertEqual([], tree.conflicts())
-        if tree.has_versioned_directories() or not tree.has_filename('1top-dir/1dir-in-1topdir'):
-            self.assertEqual([], list(tree.unknowns()))
-        else:
-            self.assertEqual(['1top-dir/1dir-in-1topdir'],
-                             list(tree.unknowns()))
+        self.assertEqual([], list(tree.unknowns()))
         # __iter__ has no strongly defined order
         tree_root = tree.path2id('')
         try:
@@ -227,11 +220,7 @@
         self.addCleanup(tree.unlock)
         self.assertEqual([], tree.get_parent_ids())
         self.assertEqual([], tree.conflicts())
-        if tree.has_versioned_directories() or not tree.has_filename('1top-dir/1dir-in-1topdir'):
-            self.assertEqual([], list(tree.unknowns()))
-        else:
-            self.assertEqual(['1top-dir/1dir-in-1topdir'],
-                             list(tree.unknowns()))
+        self.assertEqual([], list(tree.unknowns()))
         # __iter__ has no strongly defined order
         tree_root = tree.path2id('')
         if tree.has_versioned_directories():

=== modified file 'breezy/tests/per_workingtree/test_remove.py'
--- old/breezy/tests/per_workingtree/test_remove.py	2018-11-11 04:08:32 +0000
+++ new/breezy/tests/per_workingtree/test_remove.py	2018-11-20 00:01:07 +0000
@@ -26,6 +26,7 @@
     files = ['a', 'b/', 'b/c', 'd/']
     rfiles = ['b/c', 'b', 'a', 'd']
     backup_files = ['a.~1~', 'b.~1~/', 'b.~1~/c.~1~', 'd.~1~/']
+    backup_files_no_version_dirs = ['a.~1~', 'b.~1~/', 'b.~1~/c.~1~']
 
     def get_tree(self, files):
         tree = self.make_branch_and_tree('.')
@@ -84,7 +85,10 @@
         tree.add(TestRemove.files)
         tree.remove(TestRemove.files, keep_files=False)
         self.assertNotInWorkingTree(TestRemove.files)
-        self.assertPathExists(TestRemove.backup_files)
+        if tree.has_versioned_directories():
+            self.assertPathExists(TestRemove.backup_files)
+        else:
+            self.assertPathExists(TestRemove.backup_files_no_version_dirs)
         tree._validate()
 
     def test_remove_changed_file(self):
@@ -134,7 +138,8 @@
         tree.remove(rfilesx, keep_files=False)
         self.assertNotInWorkingTree(rfilesx)
         self.assertPathExists(['bx.~1~/cx.~1~', 'bx.~1~', 'ax.~1~'])
-        if tree.supports_rename_tracking():
+        if (tree.supports_rename_tracking() or
+                not tree.has_versioned_directories()):
             self.assertPathDoesNotExist('dx.~1~')  # unchanged file
         else:
             self.assertPathExists('dx.~1~')  # renamed, so appears changed
@@ -155,7 +160,10 @@
         tree = self.get_tree(TestRemove.files)
         tree.remove(TestRemove.files, keep_files=False)
         self.assertRemovedAndDeleted(TestRemove.files)
-        self.assertPathExists(TestRemove.backup_files)
+        if tree.has_versioned_directories():
+            self.assertPathExists(TestRemove.backup_files)
+        else:
+            self.assertPathExists(TestRemove.backup_files_no_version_dirs)
         tree._validate()
 
     def test_remove_nonexisting_files(self):

=== modified file 'breezy/tests/per_workingtree/test_workingtree.py'
--- old/breezy/tests/per_workingtree/test_workingtree.py	2018-11-17 16:19:11 +0000
+++ new/breezy/tests/per_workingtree/test_workingtree.py	2018-11-19 23:04:59 +0000
@@ -284,6 +284,14 @@
         self.assertEqual(list(tree.unknowns()),
                          ['hello.txt'])
 
+    def test_unknowns_empty_dir(self):
+        tree = self.make_branch_and_tree('.')
+        self.build_tree(['subdir/', 'subdir/somefile'])
+        if tree.has_versioned_directories():
+            self.assertEqual(list(tree.unknowns()), ['subdir'])
+        else:
+            self.assertEqual(list(tree.unknowns()), ['subdir/somefile'])
+
     def test_initialize(self):
         # initialize should create a working tree and branch in an existing dir
         t = self.make_branch_and_tree('.')

=== modified file 'breezy/workingtree.py'
--- old/breezy/workingtree.py	2018-11-16 18:33:17 +0000
+++ new/breezy/workingtree.py	2018-11-19 23:04:59 +0000
@@ -908,9 +908,10 @@
     def extras(self):
         """Yield all unversioned files in this WorkingTree.
 
-        If there are any unversioned directories then only the directory is
-        returned, not all its children.  But if there are unversioned files
-        under a versioned subdirectory, they are returned.
+        If there are any unversioned directories and the file format
+        supports versioning directories, then only the directory is returned,
+        not all its children. But if there are unversioned files under a
+        versioned subdirectory, they are returned.
 
         Currently returned depth-first, sorted by name within directories.
         This is the same order used by 'osutils.walkdirs'.

