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))
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
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
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'])
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'))
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'))
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
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))
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'))
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)
def test_file_has_text(self): file = inventory.InventoryFile('123', 'hello.c', ROOT_ID) self.failUnless(file.has_text())
def test_file_kind_character(self): file = inventory.InventoryFile('123', 'hello.c', ROOT_ID) self.assertEqual(file.kind_character(), '')
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