示例#1
0
 def test_file_detect_changes(self):
     left = inventory.InventoryFile('123', 'hello.c', ROOT_ID)
     left.text_sha1 = 123
     right = inventory.InventoryFile('123', 'hello.c', ROOT_ID)
     right.text_sha1 = 123
     self.assertEqual((False, False), left.detect_changes(right))
     self.assertEqual((False, False), right.detect_changes(left))
     left.executable = True
     self.assertEqual((False, True), left.detect_changes(right))
     self.assertEqual((False, True), right.detect_changes(left))
     right.text_sha1 = 321
     self.assertEqual((True, True), left.detect_changes(right))
     self.assertEqual((True, True), right.detect_changes(left))
示例#2
0
    def _unpack_entry(self, elt):
        kind = elt.tag
        if not InventoryEntry.versionable_kind(kind):
            raise AssertionError('unsupported entry kind %s' % kind)

        get_cached = _get_utf8_or_ascii

        parent_id = elt.get('parent_id')
        if parent_id is not None:
            parent_id = get_cached(parent_id)
        file_id = get_cached(elt.get('file_id'))

        if kind == 'directory':
            ie = inventory.InventoryDirectory(file_id, elt.get('name'),
                                              parent_id)
        elif kind == 'file':
            ie = inventory.InventoryFile(file_id, elt.get('name'), parent_id)
            ie.text_sha1 = elt.get('text_sha1')
            if elt.get('executable') == 'yes':
                ie.executable = True
            v = elt.get('text_size')
            ie.text_size = v and int(v)
        elif kind == 'symlink':
            ie = inventory.InventoryLink(file_id, elt.get('name'), parent_id)
            ie.symlink_target = elt.get('symlink_target')
        else:
            raise errors.UnsupportedInventoryKind(kind)
        revision = elt.get('revision')
        if revision is not None:
            revision = get_cached(revision)
        ie.revision = revision

        return ie
示例#3
0
    def _unpack_entry(self, elt):
        ## original format inventories don't have a parent_id for
        ## nodes in the root directory, but it's cleaner to use one
        ## internally.
        parent_id = elt.get('parent_id')
        if parent_id is None:
            parent_id = ROOT_ID

        kind = elt.get('kind')
        if kind == 'directory':
            ie = inventory.InventoryDirectory(elt.get('file_id'),
                                              elt.get('name'), parent_id)
        elif kind == 'file':
            ie = inventory.InventoryFile(elt.get('file_id'), elt.get('name'),
                                         parent_id)
            ie.text_id = elt.get('text_id')
            ie.text_sha1 = elt.get('text_sha1')
            v = elt.get('text_size')
            ie.text_size = v and int(v)
        elif kind == 'symlink':
            ie = inventory.InventoryLink(elt.get('file_id'), elt.get('name'),
                                         parent_id)
            ie.symlink_target = elt.get('symlink_target')
        else:
            raise BzrError("unknown kind %r" % kind)

        ## mutter("read inventoryentry: %r", elt.attrib)

        return ie
示例#4
0
 def add_file(self, repo, inv, filename, revision, parents):
     file_id = filename + '-id'
     entry = inventory.InventoryFile(file_id, filename, 'TREE_ROOT')
     entry.revision = revision
     entry.text_size = 0
     inv.add(entry)
     text_key = (file_id, revision)
     parent_keys = [(file_id, parent) for parent in parents]
     repo.texts.add_lines(text_key, parent_keys, ['line\n'])
示例#5
0
 def test_rename_file(self):
     wt = self.make_branch_and_tree('.')
     wt.lock_write()
     self.addCleanup(wt.unlock)
     self.build_tree(['foo/', 'foo/bar', 'baz/'])
     wt.add(['foo', 'foo/bar', 'baz'],
            ['foo-id', 'bar-id', 'baz-id'])
     wt.apply_inventory_delta([('foo/bar', 'baz/bar', 'bar-id',
         inventory.InventoryFile('bar-id', 'bar', 'baz-id'))])
     self.assertEqual('baz/bar', wt.id2path('bar-id'))
示例#6
0
 def test_add(self):
     wt = self.make_branch_and_tree('.')
     wt.lock_write()
     self.addCleanup(wt.unlock)
     root_id = wt.get_root_id()
     wt.apply_inventory_delta([(None, 'bar/foo', 'foo-id',
         inventory.InventoryFile('foo-id', 'foo', parent_id='bar-id')),
         (None, 'bar', 'bar-id', inventory.InventoryDirectory('bar-id',
         'bar', parent_id=root_id))])
     self.assertEqual('bar/foo', wt.id2path('foo-id'))
     self.assertEqual('bar', wt.id2path('bar-id'))
示例#7
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
示例#8
0
    def test_update_basis_with_invalid_delta(self):
        """When given an invalid delta, it should abort, and not be saved."""
        self.build_tree(['dir/', 'dir/file'])
        tree = self.create_wt4()
        tree.lock_write()
        self.addCleanup(tree.unlock)
        tree.add(['dir', 'dir/file'], ['dir-id', 'file-id'])
        first_revision_id = tree.commit('init')

        root_id = tree.path2id('')
        state = tree.current_dirstate()
        state._read_dirblocks_if_needed()
        self.assertEqual([
            ('', [(('', '', root_id), ['d', 'd'])]),
            ('', [(('', 'dir', 'dir-id'), ['d', 'd'])]),
            ('dir', [(('dir', 'file', 'file-id'), ['f', 'f'])]),
        ], self.get_simple_dirblocks(state))

        tree.remove(['dir/file'])
        self.assertEqual([
            ('', [(('', '', root_id), ['d', 'd'])]),
            ('', [(('', 'dir', 'dir-id'), ['d', 'd'])]),
            ('dir', [(('dir', 'file', 'file-id'), ['a', 'f'])]),
        ], self.get_simple_dirblocks(state))
        # Make sure the removal is written to disk
        tree.flush()

        # self.assertRaises(Exception, tree.update_basis_by_delta,
        new_dir = inventory.InventoryDirectory('dir-id', 'new-dir', root_id)
        new_dir.revision = 'new-revision-id'
        new_file = inventory.InventoryFile('file-id', 'new-file', root_id)
        new_file.revision = 'new-revision-id'
        self.assertRaises(
            errors.InconsistentDelta, tree.update_basis_by_delta,
            'new-revision-id', [
                ('dir', 'new-dir', 'dir-id', new_dir),
                ('dir/file', 'new-dir/new-file', 'file-id', new_file),
            ])
        del state

        # Now when we re-read the file it should not have been modified
        tree.unlock()
        tree.lock_read()
        self.assertEqual(first_revision_id, tree.last_revision())
        state = tree.current_dirstate()
        state._read_dirblocks_if_needed()
        self.assertEqual([
            ('', [(('', '', root_id), ['d', 'd'])]),
            ('', [(('', 'dir', 'dir-id'), ['d', 'd'])]),
            ('dir', [(('dir', 'file', 'file-id'), ['a', 'f'])]),
        ], self.get_simple_dirblocks(state))
示例#9
0
    def test_child_rename_ordering(self):
        """Test the rename-parent, move child edge case.

        (A naive implementation may move the parent first, and then be
         unable to find the child.)
        """
        wt = self.make_branch_and_tree('.')
        root_id = wt.get_root_id()
        self.build_tree(['dir/', 'dir/child', 'other/'])
        wt.add(['dir', 'dir/child', 'other'],
               ['dir-id', 'child-id', 'other-id'])
        # this delta moves dir-id to dir2 and reparents
        # child-id to a parent of other-id
        wt.apply_inventory_delta([('dir', 'dir2', 'dir-id',
            inventory.InventoryDirectory('dir-id', 'dir2', root_id)),
            ('dir/child', 'other/child', 'child-id',
             inventory.InventoryFile('child-id', 'child', 'other-id'))])
        self.assertEqual('dir2', wt.id2path('dir-id'))
        self.assertEqual('other/child', wt.id2path('child-id'))
示例#10
0
 def _build_inventory(self, tree_id, ie, path):
     assert isinstance(path, str)
     tree = self._repository._git.tree(tree_id)
     for mode, name, hexsha in tree.entries():
         basename = name.decode("utf-8")
         if path == "":
             child_path = name
         else:
             child_path = urlutils.join(path, name)
         file_id = self.mapping.generate_file_id(child_path)
         entry_kind = (mode & 0700000) / 0100000
         if entry_kind == 0:
             child_ie = inventory.InventoryDirectory(
                 file_id, basename, ie.file_id)
         elif entry_kind == 1:
             file_kind = (mode & 070000) / 010000
             b = self._repository._git.get_blob(hexsha)
             if file_kind == 0:
                 child_ie = inventory.InventoryFile(file_id, basename,
                                                    ie.file_id)
                 child_ie.text_sha1 = osutils.sha_string(b.data)
             elif file_kind == 2:
                 child_ie = inventory.InventoryLink(file_id, basename,
                                                    ie.file_id)
                 child_ie.text_sha1 = osutils.sha_string("")
             else:
                 raise AssertionError("Unknown file kind, perms=%o." %
                                      (mode, ))
             child_ie.text_id = b.id
             child_ie.text_size = len(b.data)
         else:
             raise AssertionError("Unknown blob kind, perms=%r." % (mode, ))
         fs_mode = mode & 0777
         child_ie.executable = bool(fs_mode & 0111)
         child_ie.revision = self.revision_id
         self._inventory.add(child_ie)
         if entry_kind == 0:
             self._build_inventory(hexsha, child_ie, child_path)
示例#11
0
 def test_file_has_text(self):
     file = inventory.InventoryFile('123', 'hello.c', ROOT_ID)
     self.failUnless(file.has_text())
示例#12
0
 def test_file_kind_character(self):
     file = inventory.InventoryFile('123', 'hello.c', ROOT_ID)
     self.assertEqual(file.kind_character(), '')
示例#13
0
def unpack_inventory_entry(elt, entry_cache=None, return_from_cache=False):
    elt_get = elt.get
    file_id = elt_get('file_id')
    revision = elt_get('revision')
    # Check and see if we have already unpacked this exact entry
    # Some timings for "repo.revision_trees(last_100_revs)"
    #               bzr     mysql
    #   unmodified  4.1s    40.8s
    #   using lru   3.5s
    #   using fifo  2.83s   29.1s
    #   lru._cache  2.8s
    #   dict        2.75s   26.8s
    #   inv.add     2.5s    26.0s
    #   no_copy     2.00s   20.5s
    #   no_c,dict   1.95s   18.0s
    # Note that a cache of 10k nodes is more than sufficient to hold all of
    # the inventory for the last 100 revs for bzr, but not for mysql (20k
    # is enough for mysql, which saves the same 2s as using a dict)

    # Breakdown of mysql using time.clock()
    #   4.1s    2 calls to element.get for file_id, revision_id
    #   4.5s    cache_hit lookup
    #   7.1s    InventoryFile.copy()
    #   2.4s    InventoryDirectory.copy()
    #   0.4s    decoding unique entries
    #   1.6s    decoding entries after FIFO fills up
    #   0.8s    Adding nodes to FIFO (including flushes)
    #   0.1s    cache miss lookups
    # Using an LRU cache
    #   4.1s    2 calls to element.get for file_id, revision_id
    #   9.9s    cache_hit lookup
    #   10.8s   InventoryEntry.copy()
    #   0.3s    cache miss lookus
    #   1.2s    decoding entries
    #   1.0s    adding nodes to LRU
    if entry_cache is not None and revision is not None:
        key = (file_id, revision)
        try:
            # We copy it, because some operations may mutate it
            cached_ie = entry_cache[key]
        except KeyError:
            pass
        else:
            # Only copying directory entries drops us 2.85s => 2.35s
            if return_from_cache:
                if cached_ie.kind == 'directory':
                    return cached_ie.copy()
                return cached_ie
            return cached_ie.copy()

    kind = elt.tag
    if not inventory.InventoryEntry.versionable_kind(kind):
        raise AssertionError('unsupported entry kind %s' % kind)

    file_id = get_utf8_or_ascii(file_id)
    if revision is not None:
        revision = get_utf8_or_ascii(revision)
    parent_id = elt_get('parent_id')
    if parent_id is not None:
        parent_id = get_utf8_or_ascii(parent_id)

    if kind == 'directory':
        ie = inventory.InventoryDirectory(file_id, elt_get('name'), parent_id)
    elif kind == 'file':
        ie = inventory.InventoryFile(file_id, elt_get('name'), parent_id)
        ie.text_sha1 = elt_get('text_sha1')
        if elt_get('executable') == 'yes':
            ie.executable = True
        v = elt_get('text_size')
        ie.text_size = v and int(v)
    elif kind == 'symlink':
        ie = inventory.InventoryLink(file_id, elt_get('name'), parent_id)
        ie.symlink_target = elt_get('symlink_target')
    elif kind == 'tree-reference':
        file_id = elt.attrib['file_id']
        name = elt.attrib['name']
        parent_id = elt.attrib['parent_id']
        revision = elt.get('revision')
        reference_revision = elt.get('reference_revision')
        ie = inventory.TreeReference(file_id, name, parent_id, revision,
                                     reference_revision)
    else:
        raise errors.UnsupportedInventoryKind(kind)
    ie.revision = revision
    if revision is not None and entry_cache is not None:
        # We cache a copy() because callers like to mutate objects, and
        # that would cause the item in cache to mutate as well.
        # This has a small effect on many-inventory performance, because
        # the majority fraction is spent in cache hits, not misses.
        entry_cache[key] = ie.copy()

    return ie