Exemplo n.º 1
0
 def test__write_inventory(self):
     # The private interface _write_inventory is currently used by transform.
     tree = self.make_branch_and_tree('.')
     # if we write write an inventory then do a walkdirs we should get back
     # missing entries, and actual, and unknowns as appropriate.
     self.build_tree(['present', 'unknown'])
     inventory = Inventory(tree.get_root_id())
     inventory.add_path('missing', 'file', 'missing-id')
     inventory.add_path('present', 'file', 'present-id')
     # there is no point in being able to write an inventory to an unlocked
     # tree object - its a low level api not a convenience api.
     tree.lock_write()
     tree._write_inventory(inventory)
     tree.unlock()
     tree.lock_read()
     try:
         present_stat = os.lstat('present')
         unknown_stat = os.lstat('unknown')
         expected_results = [(('', tree.get_root_id()), [
             ('missing', 'missing', 'unknown', None, 'missing-id', 'file'),
             ('present', 'present', 'file', present_stat, 'present-id',
              'file'),
             ('unknown', 'unknown', 'file', unknown_stat, None, None),
         ])]
         self.assertEqual(expected_results, list(tree.walkdirs()))
     finally:
         tree.unlock()
Exemplo n.º 2
0
    def test_kind_changes(self):
        def do_file(inv, revid):
            self.add_file(inv, revid, 'path-id', 'root-id', 'path', '1' * 32,
                          12)

        def do_link(inv, revid):
            self.add_link(inv, revid, 'path-id', 'root-id', 'path', 'target')

        def do_dir(inv, revid):
            self.add_dir(inv, revid, 'path-id', 'root-id', 'path')

        for old_factory in (do_file, do_link, do_dir):
            for new_factory in (do_file, do_link, do_dir):
                if old_factory == new_factory:
                    continue
                old_revid = 'old-parent'
                basis_shape = Inventory(root_id=None)
                self.add_dir(basis_shape, old_revid, 'root-id', None, '')
                old_factory(basis_shape, old_revid)
                new_revid = 'new-parent'
                new_shape = Inventory(root_id=None)
                self.add_new_root(new_shape, old_revid, new_revid)
                new_factory(new_shape, new_revid)
                self.assertTransitionFromBasisToShape(basis_shape, old_revid,
                                                      new_shape, new_revid)
Exemplo n.º 3
0
 def test__write_inventory(self):
     # The private interface _write_inventory is currently used by transform.
     tree = self.make_branch_and_tree('.')
     # if we write write an inventory then do a walkdirs we should get back
     # missing entries, and actual, and unknowns as appropriate.
     self.build_tree(['present', 'unknown'])
     inventory = Inventory(tree.get_root_id())
     inventory.add_path('missing', 'file', 'missing-id')
     inventory.add_path('present', 'file', 'present-id')
     # there is no point in being able to write an inventory to an unlocked
     # tree object - its a low level api not a convenience api.
     tree.lock_write()
     tree._write_inventory(inventory)
     tree.unlock()
     tree.lock_read()
     try:
         present_stat = os.lstat('present')
         unknown_stat = os.lstat('unknown')
         expected_results = [
             (('', tree.get_root_id()),
              [('missing', 'missing', 'unknown', None, 'missing-id', 'file'),
               ('present', 'present', 'file', present_stat, 'present-id', 'file'),
               ('unknown', 'unknown', 'file', unknown_stat, None, None),
              ]
             )]
         self.assertEqual(expected_results, list(tree.walkdirs()))
     finally:
         tree.unlock()
Exemplo n.º 4
0
 def test_path_swap(self):
     # test a A->B and B->A path swap.
     old_revid = 'old-parent'
     basis_shape = Inventory(root_id=None)
     self.add_dir(basis_shape, old_revid, 'root-id', None, '')
     self.add_dir(basis_shape, old_revid, 'dir-id-A', 'root-id', 'A')
     self.add_dir(basis_shape, old_revid, 'dir-id-B', 'root-id', 'B')
     self.add_link(basis_shape, old_revid, 'link-id-C', 'root-id', 'C', 'C')
     self.add_link(basis_shape, old_revid, 'link-id-D', 'root-id', 'D', 'D')
     self.add_file(basis_shape, old_revid, 'file-id-E', 'root-id', 'E',
                   '1' * 32, 12)
     self.add_file(basis_shape, old_revid, 'file-id-F', 'root-id', 'F',
                   '2' * 32, 24)
     new_revid = 'new-parent'
     new_shape = Inventory(root_id=None)
     self.add_new_root(new_shape, old_revid, new_revid)
     self.add_dir(new_shape, new_revid, 'dir-id-A', 'root-id', 'B')
     self.add_dir(new_shape, new_revid, 'dir-id-B', 'root-id', 'A')
     self.add_link(new_shape, new_revid, 'link-id-C', 'root-id', 'D', 'C')
     self.add_link(new_shape, new_revid, 'link-id-D', 'root-id', 'C', 'D')
     self.add_file(new_shape, new_revid, 'file-id-E', 'root-id', 'F',
                   '1' * 32, 12)
     self.add_file(new_shape, new_revid, 'file-id-F', 'root-id', 'E',
                   '2' * 32, 24)
     self.assertTransitionFromBasisToShape(basis_shape, old_revid,
                                           new_shape, new_revid)
Exemplo n.º 5
0
 def test_text_from_ghost_revision(self):
     repo = self.make_repository('text-from-ghost')
     inv = Inventory(revision_id='final-revid')
     inv.root.revision = 'root-revid'
     ie = inv.add_path('bla', 'file', 'myfileid')
     ie.revision = 'ghostrevid'
     ie.text_size = 42
     ie.text_sha1 = "bee68c8acd989f5f1765b4660695275948bf5c00"
     rev = bzrlib.revision.Revision(timestamp=0,
                                    timezone=None,
                                    committer="Foo Bar <*****@*****.**>",
                                    message="Message",
                                    revision_id='final-revid')
     repo.lock_write()
     try:
         repo.start_write_group()
         try:
             repo.add_revision('final-revid', rev, inv)
             try:
                 repo.texts.add_lines(('myfileid', 'ghostrevid'),
                     (('myfileid', 'ghost-text-parent'),),
                     ["line1\n", "line2\n"])
             except errors.RevisionNotPresent:
                 raise TestSkipped("text ghost parents not supported")
             if repo.supports_rich_root():
                 root_id = inv.root.file_id
                 repo.texts.add_lines((inv.root.file_id, inv.root.revision),
                     [], [])
         finally:
             repo.commit_write_group()
     finally:
         repo.unlock()
     repo.reconcile(thorough=True)
Exemplo n.º 6
0
 def test_text_from_ghost_revision(self):
     repo = self.make_repository('text-from-ghost')
     inv = Inventory(revision_id='final-revid')
     inv.root.revision = 'root-revid'
     ie = inv.add_path('bla', 'file', 'myfileid')
     ie.revision = 'ghostrevid'
     ie.text_size = 42
     ie.text_sha1 = "bee68c8acd989f5f1765b4660695275948bf5c00"
     rev = bzrlib.revision.Revision(timestamp=0,
                                    timezone=None,
                                    committer="Foo Bar <*****@*****.**>",
                                    message="Message",
                                    revision_id='final-revid')
     repo.lock_write()
     try:
         repo.start_write_group()
         try:
             repo.add_revision('final-revid', rev, inv)
             try:
                 repo.texts.add_lines(('myfileid', 'ghostrevid'),
                                      (('myfileid', 'ghost-text-parent'), ),
                                      ["line1\n", "line2\n"])
             except errors.RevisionNotPresent:
                 raise TestSkipped("text ghost parents not supported")
             if repo.supports_rich_root():
                 root_id = inv.root.file_id
                 repo.texts.add_lines((inv.root.file_id, inv.root.revision),
                                      [], [])
         finally:
             repo.commit_write_group()
     finally:
         repo.unlock()
     repo.reconcile(thorough=True)
Exemplo n.º 7
0
 def test_tree_reference(self):
     s_v5 = bzrlib.xml5.serializer_v5
     s_v6 = bzrlib.xml6.serializer_v6
     s_v7 = xml7.serializer_v7
     inv = Inventory('tree-root-321', revision_id='rev-outer')
     inv.root.revision = 'root-rev'
     inv.add(
         inventory.TreeReference('nested-id', 'nested', 'tree-root-321',
                                 'rev-outer', 'rev-inner'))
     self.assertRaises(errors.UnsupportedInventoryKind,
                       s_v5.write_inventory_to_string, inv)
     self.assertRaises(errors.UnsupportedInventoryKind,
                       s_v6.write_inventory_to_string, inv)
     txt = s_v7.write_inventory_to_string(inv)
     lines = s_v7.write_inventory_to_lines(inv)
     self.assertEqual(bzrlib.osutils.split_lines(txt), lines)
     inv2 = s_v7.read_inventory_from_string(txt)
     self.assertEqual('tree-root-321', inv2['nested-id'].parent_id)
     self.assertEqual('rev-outer', inv2['nested-id'].revision)
     self.assertEqual('rev-inner', inv2['nested-id'].reference_revision)
     self.assertRaises(errors.UnsupportedInventoryKind,
                       s_v6.read_inventory_from_string,
                       txt.replace('format="7"', 'format="6"'))
     self.assertRaises(errors.UnsupportedInventoryKind,
                       s_v5.read_inventory_from_string,
                       txt.replace('format="7"', 'format="5"'))
Exemplo n.º 8
0
 def test_tree_reference(self):
     s_v5 = bzrlib.xml5.serializer_v5
     s_v6 = bzrlib.xml6.serializer_v6
     s_v7 = xml7.serializer_v7
     inv = Inventory('tree-root-321', revision_id='rev-outer')
     inv.root.revision = 'root-rev'
     inv.add(inventory.TreeReference('nested-id', 'nested', 'tree-root-321',
                                     'rev-outer', 'rev-inner'))
     self.assertRaises(errors.UnsupportedInventoryKind,
                       s_v5.write_inventory_to_string, inv)
     self.assertRaises(errors.UnsupportedInventoryKind,
                       s_v6.write_inventory_to_string, inv)
     txt = s_v7.write_inventory_to_string(inv)
     lines = s_v7.write_inventory_to_lines(inv)
     self.assertEqual(bzrlib.osutils.split_lines(txt), lines)
     inv2 = s_v7.read_inventory_from_string(txt)
     self.assertEqual('tree-root-321', inv2['nested-id'].parent_id)
     self.assertEqual('rev-outer', inv2['nested-id'].revision)
     self.assertEqual('rev-inner', inv2['nested-id'].reference_revision)
     self.assertRaises(errors.UnsupportedInventoryKind, 
                       s_v6.read_inventory_from_string,
                       txt.replace('format="7"', 'format="6"'))
     self.assertRaises(errors.UnsupportedInventoryKind, 
                       s_v5.read_inventory_from_string,
                       txt.replace('format="7"', 'format="5"'))
Exemplo n.º 9
0
 def test_empty_delta_to_lines(self):
     old_inv = Inventory(None)
     new_inv = Inventory(None)
     delta = new_inv._make_delta(old_inv)
     serializer = inventory_delta.InventoryDeltaSerializer(
         versioned_root=True, tree_references=True)
     self.assertEqual(StringIO(empty_lines).readlines(),
         serializer.delta_to_lines(NULL_REVISION, NULL_REVISION, delta))
 def test_empty_delta_to_lines(self):
     old_inv = Inventory(None)
     new_inv = Inventory(None)
     delta = new_inv._make_delta(old_inv)
     serializer = inventory_delta.InventoryDeltaSerializer(
         versioned_root=True, tree_references=True)
     self.assertEqual(
         StringIO(empty_lines).readlines(),
         serializer.delta_to_lines(NULL_REVISION, NULL_REVISION, delta))
Exemplo n.º 11
0
 def test_richroot_unversioned_root_errors(self):
     old_inv = Inventory(None)
     new_inv = Inventory(None)
     root = new_inv.make_entry('directory', '', None, 'TREE_ROOT')
     new_inv.add(root)
     delta = new_inv._make_delta(old_inv)
     serializer = inventory_delta.InventoryDeltaSerializer(
         versioned_root=True, tree_references=True)
     err = self.assertRaises(InventoryDeltaError,
         serializer.delta_to_lines, NULL_REVISION, 'entry-version', delta)
     self.assertEqual(str(err), 'no version for fileid TREE_ROOT')
Exemplo n.º 12
0
 def test_root_only_to_lines(self):
     old_inv = Inventory(None)
     new_inv = Inventory(None)
     root = new_inv.make_entry('directory', '', None, 'an-id')
     root.revision = 'a@e\xc3\xa5ample.com--2004'
     new_inv.add(root)
     delta = new_inv._make_delta(old_inv)
     serializer = inventory_delta.InventoryDeltaSerializer(
         versioned_root=True, tree_references=True)
     self.assertEqual(StringIO(root_only_lines).readlines(),
         serializer.delta_to_lines(NULL_REVISION, 'entry-version', delta))
Exemplo n.º 13
0
 def test_move_to_added_dir(self):
     old_revid = 'old-parent'
     basis_shape = Inventory(root_id=None)
     self.add_dir(basis_shape, old_revid, 'root-id', None, '')
     self.add_link(basis_shape, old_revid, 'link-id-B', 'root-id', 'B', 'C')
     new_revid = 'new-parent'
     new_shape = Inventory(root_id=None)
     self.add_new_root(new_shape, old_revid, new_revid)
     self.add_dir(new_shape, new_revid, 'dir-id-A', 'root-id', 'A')
     self.add_link(new_shape, new_revid, 'link-id-B', 'dir-id-A', 'B', 'C')
     self.assertTransitionFromBasisToShape(basis_shape, old_revid,
                                           new_shape, new_revid)
Exemplo n.º 14
0
 def test_nonrichroot_versioned_root_errors(self):
     old_inv = Inventory(None)
     new_inv = Inventory(None)
     root = new_inv.make_entry('directory', '', None, 'TREE_ROOT')
     root.revision = 'a@e\xc3\xa5ample.com--2004'
     new_inv.add(root)
     delta = new_inv._make_delta(old_inv)
     serializer = inventory_delta.InventoryDeltaSerializer(
         versioned_root=False, tree_references=True)
     err = self.assertRaises(InventoryDeltaError,
         serializer.delta_to_lines, NULL_REVISION, 'entry-version', delta)
     self.assertStartsWith(str(err), 'Version present for / in TREE_ROOT')
Exemplo n.º 15
0
 def test_file_content_change(self):
     old_revid = 'old-parent'
     basis_shape = Inventory(root_id=None)
     self.add_dir(basis_shape, old_revid, 'root-id', None, '')
     self.add_file(basis_shape, old_revid, 'file-id', 'root-id', 'file',
                   '1' * 32, 12)
     new_revid = 'new-parent'
     new_shape = Inventory(root_id=None)
     self.add_new_root(new_shape, old_revid, new_revid)
     self.add_file(new_shape, new_revid, 'file-id', 'root-id', 'file',
                   '2' * 32, 24)
     self.assertTransitionFromBasisToShape(basis_shape, old_revid,
                                           new_shape, new_revid)
Exemplo n.º 16
0
    def _unpack_inventory(self, elt, revision_id=None):
        """Construct from XML Element

        :param revision_id: Ignored parameter used by xml5.
        """
        root_id = elt.get('file_id') or ROOT_ID
        inv = Inventory(root_id)
        for e in elt:
            ie = self._unpack_entry(e)
            if ie.parent_id == ROOT_ID:
                ie.parent_id = root_id
            inv.add(ie)
        return inv
Exemplo n.º 17
0
 def test_link_content_change(self):
     old_revid = 'old-parent'
     basis_shape = Inventory(root_id=None)
     self.add_dir(basis_shape, old_revid, 'root-id', None, '')
     self.add_link(basis_shape, old_revid, 'link-id', 'root-id', 'link',
                   'old-target')
     new_revid = 'new-parent'
     new_shape = Inventory(root_id=None)
     self.add_new_root(new_shape, old_revid, new_revid)
     self.add_link(new_shape, new_revid, 'link-id', 'root-id', 'link',
                   'new-target')
     self.assertTransitionFromBasisToShape(basis_shape, old_revid,
                                           new_shape, new_revid)
Exemplo n.º 18
0
    def _unpack_inventory(self, elt, revision_id=None):
        """Construct from XML Element

        :param revision_id: Ignored parameter used by xml5.
        """
        root_id = elt.get('file_id') or ROOT_ID
        inv = Inventory(root_id)
        for e in elt:
            ie = self._unpack_entry(e)
            if ie.parent_id == ROOT_ID:
                ie.parent_id = root_id
            inv.add(ie)
        return inv
 def test_unversioned_non_root_errors(self):
     old_inv = Inventory(None)
     new_inv = Inventory(None)
     root = new_inv.make_entry('directory', '', None, 'TREE_ROOT')
     root.revision = 'a@e\xc3\xa5ample.com--2004'
     new_inv.add(root)
     non_root = new_inv.make_entry('directory', 'foo', root.file_id, 'id')
     new_inv.add(non_root)
     delta = new_inv._make_delta(old_inv)
     serializer = inventory_delta.InventoryDeltaSerializer(
         versioned_root=True, tree_references=True)
     err = self.assertRaises(InventoryDeltaError, serializer.delta_to_lines,
                             NULL_REVISION, 'entry-version', delta)
     self.assertEqual(str(err), 'no version for fileid id')
Exemplo n.º 20
0
 def test_no_parents_full_tree(self):
     """Test doing a regular initial commit with files and dirs."""
     basis_shape = Inventory(root_id=None)  # empty tree
     revid = 'new-parent'
     new_shape = Inventory(root_id=None)
     self.add_dir(new_shape, revid, 'root-id', None, '')
     self.add_link(new_shape, revid, 'link-id', 'root-id', 'link', 'target')
     self.add_file(new_shape, revid, 'file-id', 'root-id', 'file', '1' * 32,
                   12)
     self.add_dir(new_shape, revid, 'dir-id', 'root-id', 'dir')
     self.add_file(new_shape, revid, 'subfile-id', 'dir-id', 'subfile',
                   '2' * 32, 24)
     self.assertTransitionFromBasisToShape(basis_shape, None, new_shape,
                                           revid)
Exemplo n.º 21
0
 def test_name_changed(self):
     # test that when the only change to an entry is its name changing that
     # it is handled correctly (that is it keeps the same parent id)
     old_revid = 'old-parent'
     basis_shape = Inventory(root_id=None)
     self.add_dir(basis_shape, old_revid, 'root-id', None, '')
     self.add_dir(basis_shape, old_revid, 'parent-id', 'root-id', 'origdir')
     self.add_dir(basis_shape, old_revid, 'dir-id', 'parent-id', 'olddir')
     new_revid = 'new-parent'
     new_shape = Inventory(root_id=None)
     self.add_new_root(new_shape, old_revid, new_revid)
     self.add_dir(new_shape, new_revid, 'parent-id', 'root-id', 'newdir')
     self.add_dir(new_shape, new_revid, 'dir-id', 'parent-id', 'newdir')
     self.assertTransitionFromBasisToShape(basis_shape, old_revid,
                                           new_shape, new_revid)
Exemplo n.º 22
0
 def test_add_files_to_empty_directory(self):
     old_revid = 'old-parent'
     basis_shape = Inventory(root_id=None)
     self.add_dir(basis_shape, old_revid, 'root-id', None, '')
     self.add_dir(basis_shape, old_revid, 'dir-id-A', 'root-id', 'A')
     new_revid = 'new-parent'
     new_shape = Inventory(root_id=None)
     self.add_new_root(new_shape, old_revid, new_revid)
     self.add_dir(new_shape, old_revid, 'dir-id-A', 'root-id', 'A')
     self.add_file(new_shape, new_revid, 'file-id-B', 'dir-id-A', 'B',
                   '1' * 32, 24)
     self.assertTransitionFromBasisToShape(basis_shape,
                                           old_revid,
                                           new_shape,
                                           new_revid,
                                           set_current_inventory=False)
Exemplo n.º 23
0
 def test_parent_deleted_child_renamed(self):
     # test a A->None and A/B->A.
     old_revid = 'old-parent'
     basis_shape = Inventory(root_id=None)
     self.add_dir(basis_shape, old_revid, 'root-id', None, '')
     self.add_dir(basis_shape, old_revid, 'dir-id-A', 'root-id', 'A')
     self.add_dir(basis_shape, old_revid, 'dir-id-B', 'dir-id-A', 'B')
     self.add_link(basis_shape, old_revid, 'link-id-C', 'dir-id-B', 'C',
                   'C')
     new_revid = 'new-parent'
     new_shape = Inventory(root_id=None)
     self.add_new_root(new_shape, old_revid, new_revid)
     self.add_dir(new_shape, new_revid, 'dir-id-B', 'root-id', 'A')
     self.add_link(new_shape, old_revid, 'link-id-C', 'dir-id-B', 'C', 'C')
     self.assertTransitionFromBasisToShape(basis_shape, old_revid,
                                           new_shape, new_revid)
Exemplo n.º 24
0
 def test_does_something_reconcile(self):
     t = bzrdir.BzrDir.create_standalone_workingtree('.')
     # an empty inventory with no revision will trigger reconciliation.
     repo = t.branch.repository
     inv = Inventory(revision_id='missing')
     inv.root.revision = 'missing'
     repo.lock_write()
     repo.start_write_group()
     repo.add_inventory('missing', inv, [])
     repo.commit_write_group()
     repo.unlock()
     (out, err) = self.run_bzr('reconcile')
     if repo._reconcile_backsup_inventory:
         does_backup_text = ("Backup Inventory created.\n"
                             "Inventory regenerated.\n")
     else:
         does_backup_text = ""
     expected = (
         "Reconciling branch %s\n"
         "revision_history ok.\n"
         "Reconciling repository %s\n"
         "%s"
         "Reconciliation complete.\n" %
         (t.branch.base, t.bzrdir.root_transport.base, does_backup_text))
     self.assertEqualDiff(expected, out)
     self.assertEqualDiff(err, "")
Exemplo n.º 25
0
 def test_adds(self):
     # test adding paths and dirs, including adding to a newly added dir.
     old_revid = 'old-parent'
     basis_shape = Inventory(root_id=None)
     # with a root, so its a commit after the first.
     self.add_dir(basis_shape, old_revid, 'root-id', None, '')
     new_revid = 'new-parent'
     new_shape = Inventory(root_id=None)
     self.add_new_root(new_shape, old_revid, new_revid)
     self.add_dir(new_shape, new_revid, 'dir-id-A', 'root-id', 'A')
     self.add_link(new_shape, new_revid, 'link-id-B', 'root-id', 'B', 'C')
     self.add_file(new_shape, new_revid, 'file-id-C', 'root-id', 'C',
                   '1' * 32, 12)
     self.add_file(new_shape, new_revid, 'file-id-D', 'dir-id-A', 'D',
                   '2' * 32, 24)
     self.assertTransitionFromBasisToShape(basis_shape, old_revid,
                                           new_shape, new_revid)
 def test_tree_reference_enabled(self):
     old_inv = Inventory(None)
     new_inv = Inventory(None)
     root = new_inv.make_entry('directory', '', None, 'TREE_ROOT')
     root.revision = 'a@e\xc3\xa5ample.com--2004'
     new_inv.add(root)
     non_root = new_inv.make_entry('tree-reference', 'foo', root.file_id,
                                   'id')
     non_root.revision = 'changed'
     non_root.reference_revision = 'subtree-version'
     new_inv.add(non_root)
     delta = new_inv._make_delta(old_inv)
     serializer = inventory_delta.InventoryDeltaSerializer(
         versioned_root=True, tree_references=True)
     self.assertEqual(
         StringIO(reference_lines).readlines(),
         serializer.delta_to_lines(NULL_REVISION, 'entry-version', delta))
Exemplo n.º 27
0
 def test_removes(self):
     # test removing paths, including paths that are within other also
     # removed paths.
     old_revid = 'old-parent'
     basis_shape = Inventory(root_id=None)
     self.add_dir(basis_shape, old_revid, 'root-id', None, '')
     self.add_dir(basis_shape, old_revid, 'dir-id-A', 'root-id', 'A')
     self.add_link(basis_shape, old_revid, 'link-id-B', 'root-id', 'B', 'C')
     self.add_file(basis_shape, old_revid, 'file-id-C', 'root-id', 'C',
                   '1' * 32, 12)
     self.add_file(basis_shape, old_revid, 'file-id-D', 'dir-id-A', 'D',
                   '2' * 32, 24)
     new_revid = 'new-parent'
     new_shape = Inventory(root_id=None)
     self.add_new_root(new_shape, old_revid, new_revid)
     self.assertTransitionFromBasisToShape(basis_shape, old_revid,
                                           new_shape, new_revid)
Exemplo n.º 28
0
 def test_unversioned_root(self):
     old_inv = Inventory(None)
     new_inv = Inventory(None)
     root = new_inv.make_entry('directory', '', None, 'TREE_ROOT')
     # Implicit roots are considered modified in every revision.
     root.revision = 'entry-version'
     new_inv.add(root)
     delta = new_inv._make_delta(old_inv)
     serializer = inventory_delta.InventoryDeltaSerializer(
         versioned_root=False, tree_references=False)
     serialized_lines = serializer.delta_to_lines(
         NULL_REVISION, 'entry-version', delta)
     self.assertEqual(StringIO(root_only_unversioned).readlines(),
         serialized_lines)
     deserializer = inventory_delta.InventoryDeltaDeserializer()
     self.assertEqual(
         (NULL_REVISION, 'entry-version', False, False, delta),
         deserializer.parse_text_bytes(''.join(serialized_lines)))
Exemplo n.º 29
0
    def setUp(self):
        super(TestsNeedingReweave, self).setUp()

        t = get_transport(self.get_url())
        # an empty inventory with no revision for testing with.
        repo = self.make_repository('inventory_without_revision')
        repo.lock_write()
        repo.start_write_group()
        inv = Inventory(revision_id='missing')
        inv.root.revision = 'missing'
        repo.add_inventory('missing', inv, [])
        repo.commit_write_group()
        repo.unlock()

        def add_commit(repo, revision_id, parent_ids):
            repo.lock_write()
            repo.start_write_group()
            inv = Inventory(revision_id=revision_id)
            inv.root.revision = revision_id
            root_id = inv.root.file_id
            sha1 = repo.add_inventory(revision_id, inv, parent_ids)
            repo.texts.add_lines((root_id, revision_id), [], [])
            rev = bzrlib.revision.Revision(
                timestamp=0,
                timezone=None,
                committer="Foo Bar <*****@*****.**>",
                message="Message",
                inventory_sha1=sha1,
                revision_id=revision_id)
            rev.parent_ids = parent_ids
            repo.add_revision(revision_id, rev)
            repo.commit_write_group()
            repo.unlock()

        # an empty inventory with no revision for testing with.
        # this is referenced by 'references_missing' to let us test
        # that all the cached data is correctly converted into ghost links
        # and the referenced inventory still cleaned.
        repo = self.make_repository('inventory_without_revision_and_ghost')
        repo.lock_write()
        repo.start_write_group()
        repo.add_inventory('missing', inv, [])
        repo.commit_write_group()
        repo.unlock()
        add_commit(repo, 'references_missing', ['missing'])

        # a inventory with no parents and the revision has parents..
        # i.e. a ghost.
        repo = self.make_repository('inventory_one_ghost')
        add_commit(repo, 'ghost', ['the_ghost'])

        # a inventory with a ghost that can be corrected now.
        t.copy_tree('inventory_one_ghost', 'inventory_ghost_present')
        bzrdir_url = self.get_url('inventory_ghost_present')
        bzrdir = bzrlib.bzrdir.BzrDir.open(bzrdir_url)
        repo = bzrdir.open_repository()
        add_commit(repo, 'the_ghost', [])
Exemplo n.º 30
0
 def test_move_moves_children_recursively(self):
     old_revid = 'old-parent'
     basis_shape = Inventory(root_id=None)
     self.add_dir(basis_shape, old_revid, 'root-id', None, '')
     self.add_dir(basis_shape, old_revid, 'dir-id-A', 'root-id', 'A')
     self.add_dir(basis_shape, old_revid, 'dir-id-B', 'dir-id-A', 'B')
     self.add_link(basis_shape, old_revid, 'link-id-C', 'dir-id-B', 'C',
                   'D')
     new_revid = 'new-parent'
     new_shape = Inventory(root_id=None)
     self.add_new_root(new_shape, old_revid, new_revid)
     # the moved path:
     self.add_dir(new_shape, new_revid, 'dir-id-A', 'root-id', 'B')
     # unmoved children.
     self.add_dir(new_shape, old_revid, 'dir-id-B', 'dir-id-A', 'B')
     self.add_link(new_shape, old_revid, 'link-id-C', 'dir-id-B', 'C', 'D')
     self.assertTransitionFromBasisToShape(basis_shape, old_revid,
                                           new_shape, new_revid)
Exemplo n.º 31
0
def import_git_objects(repo, mapping, num_objects, object_iter, pb=None):
    """Import a set of git objects into a bzr repository.

    :param repo: Bazaar repository
    :param mapping: Mapping to use
    :param num_objects: Number of objects.
    :param object_iter: Iterator over Git objects.
    """
    # TODO: a more (memory-)efficient implementation of this
    objects = {}
    for i, o in enumerate(object_iter):
        if pb is not None:
            pb.update("fetching objects", i, num_objects) 
        objects[o.id] = o
    graph = []
    root_trees = {}
    revisions = {}
    # Find and convert commit objects
    for o in objects.itervalues():
        if isinstance(o, Commit):
            rev = mapping.import_commit(o)
            root_trees[rev.revision_id] = objects[o.tree]
            revisions[rev.revision_id] = rev
            graph.append((rev.revision_id, rev.parent_ids))
    # Order the revisions
    # Create the inventory objects
    for i, revid in enumerate(topo_sort(graph)):
        if pb is not None:
            pb.update("fetching revisions", i, len(graph))
        root_tree = root_trees[revid]
        rev = revisions[revid]
        # We have to do this here, since we have to walk the tree and 
        # we need to make sure to import the blobs / trees with the riht 
        # path; this may involve adding them more than once.
        inv = Inventory()
        inv.revision_id = rev.revision_id
        def lookup_object(sha):
            if sha in objects:
                return objects[sha]
            return reconstruct_git_object(repo, mapping, sha)
        parent_invs = [repo.get_inventory(r) for r in rev.parent_ids]
        import_git_tree(repo, mapping, "", root_tree, inv, parent_invs, 
            lookup_object)
        repo.add_revision(rev.revision_id, rev, inv)
Exemplo n.º 32
0
    def run_action(self, output):
        from bzrlib.add import AddAction
        from bzrlib.mutabletree import _FastPath
        inv = Inventory()
        stdout = StringIO()
        action = AddAction(to_file=stdout, should_print=bool(output))

        self.apply_redirected(None, stdout, None, action, inv, None,
                              _FastPath('path'), 'file')
        self.assertEqual(stdout.getvalue(), output)
Exemplo n.º 33
0
def read_inventory(inv_file):
    """Read inventory object from rio formatted inventory file"""
    from bzrlib.inventory import Inventory, InventoryFile
    s = read_stanza(inv_file)
    assert s['inventory_version'] == 7
    inv = Inventory()
    for s in read_stanzas(inv_file):
        kind, file_id = s.items[0]
        parent_id = None
        if 'parent_id' in s:
            parent_id = s['parent_id']
        if kind == 'file':
            ie = InventoryFile(file_id, s['name'], parent_id)
            ie.text_sha1 = s['text_sha1']
            ie.text_size = s['text_size']
        else:
            raise NotImplementedError()
        inv.add(ie)
    return inv
Exemplo n.º 34
0
def read_inventory(inv_file):
    """Read inventory object from rio formatted inventory file"""
    from bzrlib.inventory import Inventory, InventoryFile
    s = read_stanza(inv_file)
    assert s['inventory_version'] == 7
    inv = Inventory()
    for s in read_stanzas(inv_file):
        kind, file_id = s.items[0]
        parent_id = None
        if 'parent_id' in s:
            parent_id = s['parent_id']
        if kind == 'file':
            ie = InventoryFile(file_id, s['name'], parent_id)
            ie.text_sha1 = s['text_sha1']
            ie.text_size = s['text_size']
        else:
            raise NotImplementedError()
        inv.add(ie)
    return inv
 def test_tree_reference_disabled(self):
     old_inv = Inventory(None)
     new_inv = Inventory(None)
     root = new_inv.make_entry('directory', '', None, 'TREE_ROOT')
     root.revision = 'a@e\xc3\xa5ample.com--2004'
     new_inv.add(root)
     non_root = new_inv.make_entry('tree-reference', 'foo', root.file_id,
                                   'id')
     non_root.revision = 'changed'
     non_root.reference_revision = 'subtree-version'
     new_inv.add(non_root)
     delta = new_inv._make_delta(old_inv)
     serializer = inventory_delta.InventoryDeltaSerializer(
         versioned_root=True, tree_references=False)
     # we expect keyerror because there is little value wrapping this.
     # This test aims to prove that it errors more than how it errors.
     err = self.assertRaises(KeyError, serializer.delta_to_lines,
                             NULL_REVISION, 'entry-version', delta)
     self.assertEqual(('tree-reference', ), err.args)
Exemplo n.º 36
0
 def get_sample_inventory(self):
     inv = Inventory('tree-root-321', revision_id='rev_outer')
     inv.add(inventory.InventoryFile('file-id', 'file', 'tree-root-321'))
     inv.add(inventory.InventoryDirectory('dir-id', 'dir', 'tree-root-321'))
     inv.add(inventory.InventoryLink('link-id', 'link', 'tree-root-321'))
     inv['tree-root-321'].revision = 'rev_outer'
     inv['dir-id'].revision = 'rev_outer'
     inv['file-id'].revision = 'rev_outer'
     inv['file-id'].text_sha1 = 'A'
     inv['file-id'].text_size = 1
     inv['link-id'].revision = 'rev_outer'
     inv['link-id'].symlink_target = 'a'
     return inv
Exemplo n.º 37
0
    def setUp(self):
        super(TestCaseWithCorruptRepository, self).setUp()
        # a inventory with no parents and the revision has parents..
        # i.e. a ghost.
        repo = self.make_repository('inventory_with_unnecessary_ghost')
        repo.lock_write()
        repo.start_write_group()
        inv = Inventory(revision_id='ghost')
        inv.root.revision = 'ghost'
        sha1 = repo.add_inventory('ghost', inv, [])
        rev = bzrlib.revision.Revision(timestamp=0,
                                       timezone=None,
                                       committer="Foo Bar <*****@*****.**>",
                                       message="Message",
                                       inventory_sha1=sha1,
                                       revision_id='ghost')
        rev.parent_ids = ['the_ghost']
        try:
            repo.add_revision('ghost', rev)
        except (errors.NoSuchRevision, errors.RevisionNotPresent):
            raise TestNotApplicable("Cannot test with ghosts for this format.")

        inv = Inventory(revision_id='the_ghost')
        inv.root.revision = 'the_ghost'
        sha1 = repo.add_inventory('the_ghost', inv, [])
        rev = bzrlib.revision.Revision(timestamp=0,
                                       timezone=None,
                                       committer="Foo Bar <*****@*****.**>",
                                       message="Message",
                                       inventory_sha1=sha1,
                                       revision_id='the_ghost')
        rev.parent_ids = []
        repo.add_revision('the_ghost', rev)
        # check its setup usefully
        inv_weave = repo.inventories
        possible_parents = (None, (('ghost', ), ))
        self.assertSubset(
            inv_weave.get_parent_map([('ghost', )])[('ghost', )],
            possible_parents)
        repo.commit_write_group()
        repo.unlock()
Exemplo n.º 38
0
 def test_unversioned_non_root_errors(self):
     old_inv = Inventory(None)
     new_inv = Inventory(None)
     root = new_inv.make_entry('directory', '', None, 'TREE_ROOT')
     root.revision = 'a@e\xc3\xa5ample.com--2004'
     new_inv.add(root)
     non_root = new_inv.make_entry('directory', 'foo', root.file_id, 'id')
     new_inv.add(non_root)
     delta = new_inv._make_delta(old_inv)
     serializer = inventory_delta.InventoryDeltaSerializer(
         versioned_root=True, tree_references=True)
     err = self.assertRaises(InventoryDeltaError,
         serializer.delta_to_lines, NULL_REVISION, 'entry-version', delta)
     self.assertEqual(str(err), 'no version for fileid id')
 def test_richroot_unversioned_root_errors(self):
     old_inv = Inventory(None)
     new_inv = Inventory(None)
     root = new_inv.make_entry('directory', '', None, 'TREE_ROOT')
     new_inv.add(root)
     delta = new_inv._make_delta(old_inv)
     serializer = inventory_delta.InventoryDeltaSerializer(
         versioned_root=True, tree_references=True)
     err = self.assertRaises(InventoryDeltaError, serializer.delta_to_lines,
                             NULL_REVISION, 'entry-version', delta)
     self.assertEqual(str(err), 'no version for fileid TREE_ROOT')
Exemplo n.º 40
0
 def _populate_from_branch(self):
     """Populate the in-tree state from the branch."""
     self._set_basis()
     if self._branch_revision_id == _mod_revision.NULL_REVISION:
         self._parent_ids = []
     else:
         self._parent_ids = [self._branch_revision_id]
     self._inventory = Inventory(None, self._basis_tree.get_revision_id())
     self._file_transport = MemoryTransport()
     # TODO copy the revision trees content, or do it lazy, or something.
     inventory_entries = self._basis_tree.iter_entries_by_dir()
     for path, entry in inventory_entries:
         self._inventory.add(entry.copy())
         if path == '':
             continue
         if entry.kind == 'directory':
             self._file_transport.mkdir(path)
         elif entry.kind == 'file':
             self._file_transport.put_file(
                 path, self._basis_tree.get_file(entry.file_id))
         else:
             raise NotImplementedError(self._populate_from_branch)
 def test_nonrichroot_versioned_root_errors(self):
     old_inv = Inventory(None)
     new_inv = Inventory(None)
     root = new_inv.make_entry('directory', '', None, 'TREE_ROOT')
     root.revision = 'a@e\xc3\xa5ample.com--2004'
     new_inv.add(root)
     delta = new_inv._make_delta(old_inv)
     serializer = inventory_delta.InventoryDeltaSerializer(
         versioned_root=False, tree_references=True)
     err = self.assertRaises(InventoryDeltaError, serializer.delta_to_lines,
                             NULL_REVISION, 'entry-version', delta)
     self.assertStartsWith(str(err), 'Version present for / in TREE_ROOT')
Exemplo n.º 42
0
 def test_tree_reference_enabled(self):
     old_inv = Inventory(None)
     new_inv = Inventory(None)
     root = new_inv.make_entry('directory', '', None, 'TREE_ROOT')
     root.revision = 'a@e\xc3\xa5ample.com--2004'
     new_inv.add(root)
     non_root = new_inv.make_entry(
         'tree-reference', 'foo', root.file_id, 'id')
     non_root.revision = 'changed'
     non_root.reference_revision = 'subtree-version'
     new_inv.add(non_root)
     delta = new_inv._make_delta(old_inv)
     serializer = inventory_delta.InventoryDeltaSerializer(
         versioned_root=True, tree_references=True)
     self.assertEqual(StringIO(reference_lines).readlines(),
         serializer.delta_to_lines(NULL_REVISION, 'entry-version', delta))
Exemplo n.º 43
0
    def make_one_file_inventory(self, repo, revision, parents,
                                inv_revision=None, root_revision=None,
                                file_contents=None, make_file_version=True):
        """Make an inventory containing a version of a file with ID 'a-file'.

        The file's ID will be 'a-file', and its filename will be 'a file name',
        stored at the tree root.

        :param repo: a repository to add the new file version to.
        :param revision: the revision ID of the new inventory.
        :param parents: the parents for this revision of 'a-file'.
        :param inv_revision: if not None, the revision ID to store in the
            inventory entry.  Otherwise, this defaults to revision.
        :param root_revision: if not None, the inventory's root.revision will
            be set to this.
        :param file_contents: if not None, the contents of this file version.
            Otherwise a unique default (based on revision ID) will be
            generated.
        """
        inv = Inventory(revision_id=revision)
        if root_revision is not None:
            inv.root.revision = root_revision
        file_id = 'a-file-id'
        entry = InventoryFile(file_id, 'a file name', 'TREE_ROOT')
        if inv_revision is not None:
            entry.revision = inv_revision
        else:
            entry.revision = revision
        entry.text_size = 0
        if file_contents is None:
            file_contents = '%sline\n' % entry.revision
        entry.text_sha1 = osutils.sha_string(file_contents)
        inv.add(entry)
        if make_file_version:
            repo.texts.add_lines((file_id, revision),
                [(file_id, parent) for parent in parents], [file_contents])
        return inv
Exemplo n.º 44
0
 def get_sample_inventory(self):
     inv = Inventory('tree-root-321', revision_id='rev_outer')
     inv.add(inventory.InventoryFile('file-id', 'file', 'tree-root-321'))
     inv.add(inventory.InventoryDirectory('dir-id', 'dir',
                                          'tree-root-321'))
     inv.add(inventory.InventoryLink('link-id', 'link', 'tree-root-321'))
     inv['tree-root-321'].revision = 'rev_outer'
     inv['dir-id'].revision = 'rev_outer'
     inv['file-id'].revision = 'rev_outer'
     inv['file-id'].text_sha1 = 'A'
     inv['file-id'].text_size = 1
     inv['link-id'].revision = 'rev_outer'
     inv['link-id'].symlink_target = 'a'
     return inv
Exemplo n.º 45
0
 def test_tree_reference_disabled(self):
     old_inv = Inventory(None)
     new_inv = Inventory(None)
     root = new_inv.make_entry('directory', '', None, 'TREE_ROOT')
     root.revision = 'a@e\xc3\xa5ample.com--2004'
     new_inv.add(root)
     non_root = new_inv.make_entry(
         'tree-reference', 'foo', root.file_id, 'id')
     non_root.revision = 'changed'
     non_root.reference_revision = 'subtree-version'
     new_inv.add(non_root)
     delta = new_inv._make_delta(old_inv)
     serializer = inventory_delta.InventoryDeltaSerializer(
         versioned_root=True, tree_references=False)
     # we expect keyerror because there is little value wrapping this.
     # This test aims to prove that it errors more than how it errors.
     err = self.assertRaises(KeyError,
         serializer.delta_to_lines, NULL_REVISION, 'entry-version', delta)
     self.assertEqual(('tree-reference',), err.args)
Exemplo n.º 46
0
 def test_unknown_kind_errors(self):
     old_inv = Inventory(None)
     new_inv = Inventory(None)
     root = new_inv.make_entry('directory', '', None, 'my-rich-root-id')
     root.revision = 'changed'
     new_inv.add(root)
     class StrangeInventoryEntry(inventory.InventoryEntry):
         kind = 'strange'
     non_root = StrangeInventoryEntry('id', 'foo', root.file_id)
     non_root.revision = 'changed'
     new_inv.add(non_root)
     delta = new_inv._make_delta(old_inv)
     serializer = inventory_delta.InventoryDeltaSerializer(
         versioned_root=True, tree_references=True)
     # we expect keyerror because there is little value wrapping this.
     # This test aims to prove that it errors more than how it errors.
     err = self.assertRaises(KeyError,
         serializer.delta_to_lines, NULL_REVISION, 'entry-version', delta)
     self.assertEqual(('strange',), err.args)
Exemplo n.º 47
0
 def _populate_from_branch(self):
     """Populate the in-tree state from the branch."""
     self._set_basis()
     if self._branch_revision_id == _mod_revision.NULL_REVISION:
         self._parent_ids = []
     else:
         self._parent_ids = [self._branch_revision_id]
     self._inventory = Inventory(None, self._basis_tree.get_revision_id())
     self._file_transport = MemoryTransport()
     # TODO copy the revision trees content, or do it lazy, or something.
     inventory_entries = self._basis_tree.iter_entries_by_dir()
     for path, entry in inventory_entries:
         self._inventory.add(entry.copy())
         if path == '':
             continue
         if entry.kind == 'directory':
             self._file_transport.mkdir(path)
         elif entry.kind == 'file':
             self._file_transport.put_file(path,
                 self._basis_tree.get_file(entry.file_id))
         else:
             raise NotImplementedError(self._populate_from_branch)
Exemplo n.º 48
0
class MemoryTree(mutabletree.MutableInventoryTree):
    """A MemoryTree is a specialisation of MutableTree.

    It maintains nearly no state outside of read_lock and write_lock
    transactions. (it keeps a reference to the branch, and its last-revision
    only).
    """

    def __init__(self, branch, revision_id):
        """Construct a MemoryTree for branch using revision_id."""
        self.branch = branch
        self.bzrdir = branch.bzrdir
        self._branch_revision_id = revision_id
        self._locks = 0
        self._lock_mode = None

    def get_config_stack(self):
        return self.branch.get_config_stack()

    def is_control_filename(self, filename):
        # Memory tree doesn't have any control filenames
        return False

    @needs_tree_write_lock
    def _add(self, files, ids, kinds):
        """See MutableTree._add."""
        for f, file_id, kind in zip(files, ids, kinds):
            if kind is None:
                kind = 'file'
            if file_id is None:
                self._inventory.add_path(f, kind=kind)
            else:
                self._inventory.add_path(f, kind=kind, file_id=file_id)

    def basis_tree(self):
        """See Tree.basis_tree()."""
        return self._basis_tree

    @staticmethod
    def create_on_branch(branch):
        """Create a MemoryTree for branch, using the last-revision of branch."""
        revision_id = _mod_revision.ensure_null(branch.last_revision())
        return MemoryTree(branch, revision_id)

    def _gather_kinds(self, files, kinds):
        """See MutableTree._gather_kinds.

        This implementation does not care about the file kind of
        missing files, so is a no-op.
        """

    def get_file(self, file_id, path=None):
        """See Tree.get_file."""
        if path is None:
            path = self.id2path(file_id)
        return self._file_transport.get(path)

    def get_file_sha1(self, file_id, path=None, stat_value=None):
        """See Tree.get_file_sha1()."""
        if path is None:
            path = self.id2path(file_id)
        stream = self._file_transport.get(path)
        return sha_file(stream)

    def get_root_id(self):
        return self.path2id('')

    def _comparison_data(self, entry, path):
        """See Tree._comparison_data."""
        if entry is None:
            return None, False, None
        return entry.kind, entry.executable, None

    @needs_tree_write_lock
    def rename_one(self, from_rel, to_rel):
        file_id = self.path2id(from_rel)
        to_dir, to_tail = os.path.split(to_rel)
        to_parent_id = self.path2id(to_dir)
        self._file_transport.move(from_rel, to_rel)
        self._inventory.rename(file_id, to_parent_id, to_tail)

    def path_content_summary(self, path):
        """See Tree.path_content_summary."""
        id = self.path2id(path)
        if id is None:
            return 'missing', None, None, None
        kind = self.kind(id)
        if kind == 'file':
            bytes = self._file_transport.get_bytes(path)
            size = len(bytes)
            executable = self._inventory[id].executable
            sha1 = None # no stat cache
            return (kind, size, executable, sha1)
        elif kind == 'directory':
            # memory tree does not support nested trees yet.
            return kind, None, None, None
        elif kind == 'symlink':
            raise NotImplementedError('symlink support')
        else:
            raise NotImplementedError('unknown kind')

    def _file_size(self, entry, stat_value):
        """See Tree._file_size."""
        if entry is None:
            return 0
        return entry.text_size

    @needs_read_lock
    def get_parent_ids(self):
        """See Tree.get_parent_ids.

        This implementation returns the current cached value from
            self._parent_ids.
        """
        return list(self._parent_ids)

    def has_filename(self, filename):
        """See Tree.has_filename()."""
        return self._file_transport.has(filename)

    def is_executable(self, file_id, path=None):
        return self._inventory[file_id].executable

    def kind(self, file_id):
        return self._inventory[file_id].kind

    def mkdir(self, path, file_id=None):
        """See MutableTree.mkdir()."""
        self.add(path, file_id, 'directory')
        if file_id is None:
            file_id = self.path2id(path)
        self._file_transport.mkdir(path)
        return file_id

    @needs_read_lock
    def last_revision(self):
        """See MutableTree.last_revision."""
        return self._branch_revision_id

    def lock_read(self):
        """Lock the memory tree for reading.

        This triggers population of data from the branch for its revision.
        """
        self._locks += 1
        try:
            if self._locks == 1:
                self.branch.lock_read()
                self._lock_mode = "r"
                self._populate_from_branch()
        except:
            self._locks -= 1
            raise

    def lock_tree_write(self):
        """See MutableTree.lock_tree_write()."""
        self._locks += 1
        try:
            if self._locks == 1:
                self.branch.lock_read()
                self._lock_mode = "w"
                self._populate_from_branch()
            elif self._lock_mode == "r":
                raise errors.ReadOnlyError(self)
        except:
            self._locks -= 1
            raise

    def lock_write(self):
        """See MutableTree.lock_write()."""
        self._locks += 1
        try:
            if self._locks == 1:
                self.branch.lock_write()
                self._lock_mode = "w"
                self._populate_from_branch()
            elif self._lock_mode == "r":
                raise errors.ReadOnlyError(self)
        except:
            self._locks -= 1
            raise

    def _populate_from_branch(self):
        """Populate the in-tree state from the branch."""
        self._set_basis()
        if self._branch_revision_id == _mod_revision.NULL_REVISION:
            self._parent_ids = []
        else:
            self._parent_ids = [self._branch_revision_id]
        self._inventory = Inventory(None, self._basis_tree.get_revision_id())
        self._file_transport = MemoryTransport()
        # TODO copy the revision trees content, or do it lazy, or something.
        inventory_entries = self._basis_tree.iter_entries_by_dir()
        for path, entry in inventory_entries:
            self._inventory.add(entry.copy())
            if path == '':
                continue
            if entry.kind == 'directory':
                self._file_transport.mkdir(path)
            elif entry.kind == 'file':
                self._file_transport.put_file(path,
                    self._basis_tree.get_file(entry.file_id))
            else:
                raise NotImplementedError(self._populate_from_branch)

    def put_file_bytes_non_atomic(self, file_id, bytes):
        """See MutableTree.put_file_bytes_non_atomic."""
        self._file_transport.put_bytes(self.id2path(file_id), bytes)

    def unlock(self):
        """Release a lock.

        This frees all cached state when the last lock context for the tree is
        left.
        """
        if self._locks == 1:
            self._basis_tree = None
            self._parent_ids = []
            self._inventory = None
            try:
                self.branch.unlock()
            finally:
                self._locks = 0
                self._lock_mode = None
        else:
            self._locks -= 1

    @needs_tree_write_lock
    def unversion(self, file_ids):
        """Remove the file ids in file_ids from the current versioned set.

        When a file_id is unversioned, all of its children are automatically
        unversioned.

        :param file_ids: The file ids to stop versioning.
        :raises: NoSuchId if any fileid is not currently versioned.
        """
        # XXX: This should be in mutabletree, but the inventory-save action
        # is not relevant to memory tree. Until that is done in unlock by
        # working tree, we cannot share the implementation.
        for file_id in file_ids:
            if self._inventory.has_id(file_id):
                self._inventory.remove_recursive_id(file_id)
            else:
                raise errors.NoSuchId(self, file_id)

    def set_parent_ids(self, revision_ids, allow_leftmost_as_ghost=False):
        """See MutableTree.set_parent_trees()."""
        for revision_id in revision_ids:
            _mod_revision.check_not_reserved_id(revision_id)
        if len(revision_ids) == 0:
            self._parent_ids = []
            self._branch_revision_id = _mod_revision.NULL_REVISION
        else:
            self._parent_ids = revision_ids
            self._branch_revision_id = revision_ids[0]
        self._allow_leftmost_as_ghost = allow_leftmost_as_ghost
        self._set_basis()
    
    def _set_basis(self):
        try:
            self._basis_tree = self.branch.repository.revision_tree(
                self._branch_revision_id)
        except errors.NoSuchRevision:
            if self._allow_leftmost_as_ghost:
                self._basis_tree = self.branch.repository.revision_tree(
                    _mod_revision.NULL_REVISION)
            else:
                raise

    def set_parent_trees(self, parents_list, allow_leftmost_as_ghost=False):
        """See MutableTree.set_parent_trees()."""
        if len(parents_list) == 0:
            self._parent_ids = []
            self._basis_tree = self.branch.repository.revision_tree(
                                   _mod_revision.NULL_REVISION)
        else:
            if parents_list[0][1] is None and not allow_leftmost_as_ghost:
                # a ghost in the left most parent
                raise errors.GhostRevisionUnusableHere(parents_list[0][0])
            self._parent_ids = [parent_id for parent_id, tree in parents_list]
            if parents_list[0][1] is None or parents_list[0][1] == 'null:':
                self._basis_tree = self.branch.repository.revision_tree(
                                       _mod_revision.NULL_REVISION)
            else:
                self._basis_tree = parents_list[0][1]
            self._branch_revision_id = parents_list[0][0]