def test_text_from_ghost_revision(self): repo = self.make_repository('text-from-ghost') inv = Inventory(revision_id=b'final-revid') inv.root.revision = b'root-revid' ie = inv.add_path('bla', 'file', b'myfileid') ie.revision = b'ghostrevid' ie.text_size = 42 ie.text_sha1 = b"bee68c8acd989f5f1765b4660695275948bf5c00" rev = breezy.revision.Revision(timestamp=0, timezone=None, committer="Foo Bar <*****@*****.**>", message="Message", revision_id=b'final-revid') with repo.lock_write(): repo.start_write_group() try: repo.add_revision(b'final-revid', rev, inv) try: repo.texts.add_lines((b'myfileid', b'ghostrevid'), ((b'myfileid', b'ghost-text-parent'),), [b"line1\n", b"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() repo.reconcile(thorough=True)
def test_add_simple_rev(self): branch = self.make_svn_branch('d', lossy=True) #1 repos = branch.repository inv = Inventory(root_id=b'blabloe') mapping = repos.get_mapping() inventory_add_external( inv, b'blabloe', 'bla', mapping.revision_id_foreign_to_bzr( (repos.uuid, branch.get_branch_path(), 1)), 1, branch.base) expected_ie = TreeReference( mapping.generate_file_id((repos.uuid, branch.get_branch_path(), 1), u""), 'bla', b'blabloe', revision=mapping.revision_id_foreign_to_bzr( (repos.uuid, branch.get_branch_path(), 1)), reference_revision=branch.last_revision()) ie = inv.get_entry(inv.path2id('bla')) self.assertEqual(branch.last_revision(), ie.reference_revision) self.assertEquals(expected_ie.file_id, ie.file_id) self.assertEquals(expected_ie.revision, ie.revision) self.assertEquals(expected_ie.name, ie.name) self.assertEquals(expected_ie.reference_revision, ie.reference_revision) self.assertEquals(expected_ie.parent_id, ie.parent_id) self.assertEqual(expected_ie, ie)
def test_add_nested_norev(self): """Add a nested tree with no specific revision referenced.""" branch = self.make_svn_branch('d', lossy=True) repos = branch.repository mapping = repos.get_mapping() inv = Inventory(root_id=b'blabloe') inventory_add_external( inv, b'blabloe', 'blie/bla', mapping.revision_id_foreign_to_bzr( (repos.uuid, branch.get_branch_path(), 1)), None, branch.base) expected_ie = TreeReference( mapping.generate_file_id((repos.uuid, branch.get_branch_path(), 1), u""), 'bla', inv.path2id('blie'), reference_revision=CURRENT_REVISION, revision=mapping.revision_id_foreign_to_bzr( (repos.uuid, branch.get_branch_path(), 1))) ie = inv.get_entry(inv.path2id('blie/bla')) self.assertEquals(expected_ie.file_id, ie.file_id) self.assertEquals(expected_ie.revision, ie.revision) self.assertEquals(expected_ie.name, ie.name) self.assertEquals(expected_ie.reference_revision, ie.reference_revision) self.assertEquals(expected_ie.parent_id, ie.parent_id) self.assertEqual(expected_ie, ie)
def test_add_simple_norev(self): branch = self.make_svn_branch('d', lossy=True) repos = branch.repository mapping = repos.get_mapping() inv = Inventory(root_id='blabloe') inventory_add_external(inv, 'blabloe', 'bla', mapping.revision_id_foreign_to_bzr((repos.uuid, branch.get_branch_path(), 1)), None, branch.base) self.assertEqual(TreeReference( mapping.generate_file_id((repos.uuid, branch.get_branch_path(), 1), u""), 'bla', 'blabloe', reference_revision=CURRENT_REVISION, revision=mapping.revision_id_foreign_to_bzr((repos.uuid, branch.get_branch_path(), 1))), inv.get_entry(inv.path2id('bla')))
def setUp(self): super(TestsNeedingReweave, self).setUp() t = self.get_transport() # 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=b'missing') inv.root.revision = b'missing' repo.add_inventory(b'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 = breezy.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(b'missing', inv, []) repo.commit_write_group() repo.unlock() add_commit(repo, b'references_missing', [b'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, b'ghost', [b'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 = BzrDir.open(bzrdir_url) repo = bzrdir.open_repository() add_commit(repo, b'the_ghost', [])
def read_inventory(inv_file): """Read inventory object from rio formatted inventory file""" from breezy.bzr.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 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 = b'a-file-id' entry = InventoryFile(file_id, 'a file name', b'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 = b'%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
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 = breezy.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()
def root_inventory(self): # FIXME if self._bzr_inventory is not None: return self._bzr_inventory self._bzr_inventory = Inventory() self._bzr_inventory.revision_id = self.get_revision_id() root_repos = self._repository.svn_transport.get_svn_repos_root() editor = TreeBuildEditor(self) conn = self._repository.svn_transport.get_connection() try: reporter = conn.do_switch( self._revmeta.metarev.revnum, "", True, urlutils.join(root_repos, self._revmeta.metarev.branch_path).rstrip("/"), editor) try: reporter.set_path("", 0, True, None) reporter.finish() except: reporter.abort() raise finally: self._repository.svn_transport.add_connection(conn) return self._bzr_inventory
def setUp(self): self.reduceLockdirTimeout() super(TestReconcileWithIncorrectRevisionCache, self).setUp() t = self.get_transport() # we need a revision with two parents in the wrong order # which should trigger reinsertion. # and another with the first one correct but the other two not # which should not trigger reinsertion. # these need to be in different repositories so that we don't # trigger a reconcile based on the other case. # there is no api to construct a broken knit repository at # this point. if we ever encounter a bad graph in a knit repo # we should add a lower level api to allow constructing such cases. # first off the common logic: self.first_tree = self.make_branch_and_tree('wrong-first-parent') self.second_tree = self.make_branch_and_tree( 'reversed-secondary-parents') for t in [self.first_tree, self.second_tree]: t.commit('1', rev_id=b'1') uncommit(t.branch, tree=t) t.commit('2', rev_id=b'2') uncommit(t.branch, tree=t) t.commit('3', rev_id=b'3') uncommit(t.branch, tree=t) #second_tree = self.make_branch_and_tree('reversed-secondary-parents') # second_tree.pull(tree) # XXX won't copy the repo? repo_secondary = self.second_tree.branch.repository # now setup the wrong-first parent case repo = self.first_tree.branch.repository repo.lock_write() repo.start_write_group() inv = Inventory(revision_id=b'wrong-first-parent') inv.root.revision = b'wrong-first-parent' if repo.supports_rich_root(): root_id = inv.root.file_id repo.texts.add_lines((root_id, b'wrong-first-parent'), [], []) sha1 = repo.add_inventory(b'wrong-first-parent', inv, [b'2', b'1']) rev = Revision(timestamp=0, timezone=None, committer="Foo Bar <*****@*****.**>", message="Message", inventory_sha1=sha1, revision_id=b'wrong-first-parent') rev.parent_ids = [b'1', b'2'] repo.add_revision(b'wrong-first-parent', rev) repo.commit_write_group() repo.unlock() # now setup the wrong-secondary parent case repo = repo_secondary repo.lock_write() repo.start_write_group() inv = Inventory(revision_id=b'wrong-secondary-parent') inv.root.revision = b'wrong-secondary-parent' if repo.supports_rich_root(): root_id = inv.root.file_id repo.texts.add_lines((root_id, b'wrong-secondary-parent'), [], []) sha1 = repo.add_inventory( b'wrong-secondary-parent', inv, [b'1', b'3', b'2']) rev = Revision(timestamp=0, timezone=None, committer="Foo Bar <*****@*****.**>", message="Message", inventory_sha1=sha1, revision_id=b'wrong-secondary-parent') rev.parent_ids = [b'1', b'2', b'3'] repo.add_revision(b'wrong-secondary-parent', rev) repo.commit_write_group() repo.unlock()
def root_inventory(self): if self._bzr_inventory is not None: return self._bzr_inventory self._bzr_inventory = Inventory(root_id=None) if self.get_root_id() is None: return self._bzr_inventory def add_file_to_inv(relpath, id, revid, adm): if not isinstance(relpath, text_type): raise TypeError(relpath) (propchanges, props) = adm.get_prop_diffs( self.workingtree.abspath(relpath).encode("utf-8")) if props.has_key(properties.PROP_SPECIAL): is_symlink = (self.get_file_stream_by_path(relpath).read(5) == "link ") else: is_symlink = False if is_symlink: ie = self._bzr_inventory.add_path(relpath, 'symlink', id) ie.symlink_target = self.get_file_stream_by_path(relpath).read()[len("link "):] else: ie = self._bzr_inventory.add_path(relpath, 'file', id) data = osutils.fingerprint_file(self.get_file_stream_by_path(relpath)) ie.text_sha1 = data['sha1'] ie.text_size = data['size'] ie.executable = props.has_key(properties.PROP_EXECUTABLE) ie.revision = revid return ie def find_ids(entry): assert entry.url.startswith(self._repository.svn_transport.svn_url) relpath = urllib.unquote(entry.url[len(self._repository.svn_transport.svn_url):].strip("/")) assert isinstance(relpath, str) if entry.schedule in (wc.SCHEDULE_NORMAL, wc.SCHEDULE_DELETE, wc.SCHEDULE_REPLACE): return self.lookup_id( self.workingtree.unprefix(relpath.decode("utf-8"))) return (None, None) def add_dir_to_inv(relpath, adm, parent_id): if not isinstance(relpath, text_type): raise TypeError(relpath) entries = adm.entries_read(False) entry = entries[""] (id, revid) = find_ids(entry) if id is None: return # First handle directory itself ie = self._bzr_inventory.add_path(relpath, 'directory', id) ie.revision = revid if relpath == u"": self._bzr_inventory.revision_id = revid for name, entry in entries.iteritems(): if name == "": continue if not isinstance(relpath, text_type): raise TypeError(relpath) if not isinstance(name, bytes): raise TypeError(name) subrelpath = os.path.join(relpath, name.decode("utf-8")) assert entry if entry.kind == subvertpy.NODE_DIR: try: subwc = self.workingtree._get_wc(subrelpath) except subvertpy.SubversionException as e: msg, num = e.args if num == subvertpy.ERR_WC_NOT_DIRECTORY: raise BasisTreeIncomplete() raise try: add_dir_to_inv(subrelpath, subwc, id) finally: subwc.close() else: (subid, subrevid) = find_ids(entry) if subid is not None: add_file_to_inv(subrelpath, subid, subrevid, adm) with self.workingtree._get_wc() as adm: add_dir_to_inv(u"", adm, None) return self._bzr_inventory
class SvnBasisTree(SvnRevisionTreeCommon): """Optimized version of SvnRevisionTree.""" def __repr__(self): return "<%s for '%r'>" % (self.__class__.__name__, self.workingtree) def __init__(self, workingtree): mutter("opening basistree for %r", workingtree) self.workingtree = workingtree self._bzr_inventory = None self._repository = workingtree.branch.repository self.id_map = self.workingtree.basis_idmap self.mapping = self.workingtree.branch.mapping self._real_tree = None def get_file_verifier(self, path, file_id=None, stat_value=None): with self.workingtree._get_wc(write_lock=False) as root_adm: entry = self.workingtree._get_entry(root_adm, path) return ("MD5", entry.checksum) @property def root_inventory(self): if self._bzr_inventory is not None: return self._bzr_inventory self._bzr_inventory = Inventory(root_id=None) if self.get_root_id() is None: return self._bzr_inventory def add_file_to_inv(relpath, id, revid, adm): if not isinstance(relpath, text_type): raise TypeError(relpath) (propchanges, props) = adm.get_prop_diffs( self.workingtree.abspath(relpath).encode("utf-8")) if props.has_key(properties.PROP_SPECIAL): is_symlink = (self.get_file_stream_by_path(relpath).read(5) == "link ") else: is_symlink = False if is_symlink: ie = self._bzr_inventory.add_path(relpath, 'symlink', id) ie.symlink_target = self.get_file_stream_by_path(relpath).read()[len("link "):] else: ie = self._bzr_inventory.add_path(relpath, 'file', id) data = osutils.fingerprint_file(self.get_file_stream_by_path(relpath)) ie.text_sha1 = data['sha1'] ie.text_size = data['size'] ie.executable = props.has_key(properties.PROP_EXECUTABLE) ie.revision = revid return ie def find_ids(entry): assert entry.url.startswith(self._repository.svn_transport.svn_url) relpath = urllib.unquote(entry.url[len(self._repository.svn_transport.svn_url):].strip("/")) assert isinstance(relpath, str) if entry.schedule in (wc.SCHEDULE_NORMAL, wc.SCHEDULE_DELETE, wc.SCHEDULE_REPLACE): return self.lookup_id( self.workingtree.unprefix(relpath.decode("utf-8"))) return (None, None) def add_dir_to_inv(relpath, adm, parent_id): if not isinstance(relpath, text_type): raise TypeError(relpath) entries = adm.entries_read(False) entry = entries[""] (id, revid) = find_ids(entry) if id is None: return # First handle directory itself ie = self._bzr_inventory.add_path(relpath, 'directory', id) ie.revision = revid if relpath == u"": self._bzr_inventory.revision_id = revid for name, entry in entries.iteritems(): if name == "": continue if not isinstance(relpath, text_type): raise TypeError(relpath) if not isinstance(name, bytes): raise TypeError(name) subrelpath = os.path.join(relpath, name.decode("utf-8")) assert entry if entry.kind == subvertpy.NODE_DIR: try: subwc = self.workingtree._get_wc(subrelpath) except subvertpy.SubversionException as e: msg, num = e.args if num == subvertpy.ERR_WC_NOT_DIRECTORY: raise BasisTreeIncomplete() raise try: add_dir_to_inv(subrelpath, subwc, id) finally: subwc.close() else: (subid, subrevid) = find_ids(entry) if subid is not None: add_file_to_inv(subrelpath, subid, subrevid, adm) with self.workingtree._get_wc() as adm: add_dir_to_inv(u"", adm, None) return self._bzr_inventory def has_filename(self, path): try: self.lookup_id(path) except KeyError: return False else: return True def get_revision_id(self): """See Tree.get_revision_id().""" return self.workingtree.last_revision() def get_file_stream_by_path(self, name): """See Tree.get_file_stream_by_path().""" wt_path = self.workingtree.abspath(name) return wc.get_pristine_contents(wt_path) def kind(self, path, file_id=None): if file_id is None: file_id = self.path2id(path) if file_id is None: raise errors.NoSuchFile(path, self) return self.root_inventory.get_entry(file_id).kind def get_file_text(self, path, file_id=None): """See Tree.get_file_text().""" f = self.get_file_stream_by_path(path) try: return f.read() finally: f.close() def get_file(self, path, file_id=None): return self.get_file_stream_by_path(path) def get_file_properties(self, path, file_id=None): """See SubversionTree.get_file_properties().""" abspath = self.workingtree.abspath(path) if not os.path.isdir(abspath.encode(osutils._fs_enc)): wc_path = urlutils.dirname(path) else: wc_path = path with self.workingtree._get_wc(wc_path) as wc: (_, orig_props) = wc.get_prop_diffs(abspath.encode("utf-8")) return orig_props def annotate_iter(self, path, file_id=None, default_revision=CURRENT_REVISION): from .annotate import Annotater annotater = Annotater(self.workingtree.branch.repository) annotater.check_file_revs( self.get_revision_id(), self.workingtree.get_branch_path(), self.workingtree.base_revnum, self.mapping, path) return annotater.get_annotated() @property def real_tree(self): if self._real_tree is not None: return self._real_tree self._real_tree = self.workingtree.revision_tree(self.get_revision_id()) return self._real_tree def all_file_ids(self): return self.real_tree.all_file_ids() def iter_entries_by_dir(self, specific_files=None): # FIXME if specific_files is not None: specific_file_ids = [] for path in specific_files: file_id = self.path2id(path) if file_id is not None: specific_file_ids.append(file_id) else: specific_file_ids = None try: return self.root_inventory.iter_entries_by_dir( specific_file_ids=specific_file_ids) except BasisTreeIncomplete: return self.real_tree.iter_entries_by_dir( specific_files=specific_files) def find_related_paths_across_trees(self, paths, trees=[], require_versioned=True): """Find related paths in tree corresponding to specified filenames in any of `lookup_trees`. All matches in all trees will be used, and all children of matched directories will be used. :param paths: The filenames to find related paths for (if None, returns None) :param trees: The trees to find file_ids within :param require_versioned: if true, all specified filenames must occur in at least one tree. :return: a set of paths for the specified filenames and their children in `tree` """ if paths is None: return None; file_ids = self.paths2ids( paths, trees, require_versioned=require_versioned) ret = set() for file_id in file_ids: try: ret.add(self.id2path(file_id)) except errors.NoSuchId: pass return ret
def setUp(self): super(TestPulling, self).setUp() self.build_tree(['hg/', 'hg/a', 'hg/b', 'hg/dir/', 'hg/dir/c']) hgdir = HgControlDirFormat().initialize('hg') self.tree = hgdir.open_workingtree() mode = os.lstat('hg/b').st_mode os.chmod('hg/b', mode | stat.S_IEXEC) # do not add 'dir' to ensure that we pickup dir/c anyway : if hg # changes it behaviour, we want this test to start failing. self.tree.add(['a', 'b', 'dir/c']) self.tree.commit('foo') revone_inventory = Inventory() tip = self.tree.last_revision() revone_inventory.root.revision = tip entry = revone_inventory.add_path(u'a', kind='file', file_id='hg:a') entry.revision = tip entry.text_size = len('contents of hg/a\n') entry.text_sha1 = "72bcea9d6cba6ee7d3241bfa0c5e54506ad81a94" entry = revone_inventory.add_path(u'b', kind='file', file_id='hg:b') entry.executable = True entry.revision = tip entry.text_size = len('contents of hg/b\n') entry.text_sha1 = "b4d0c22d126cd0afeeeffa62961fb47c0932835a" entry = revone_inventory.add_path(u'dir', kind='directory', file_id='hg:dir') entry.revision = tip entry = revone_inventory.add_path(u'dir/c', kind='file', file_id='hg:dir_sc') entry.revision = tip entry.text_size = len('contents of hg/dir/c\n') entry.text_sha1 = "958be752affac0fee70471331b96fb3fc1809425" self.revone_inventory = revone_inventory self.revidone = tip #====== end revision one # in revisiontwo we add a new file to dir, which should not change # the revision_id on the inventory. self.build_tree(['hg/dir/d']) self.tree.add(['dir/d']) self.tree.commit('bar') self.revtwo_inventory = copy.deepcopy(revone_inventory) tip = self.tree.last_revision() entry = self.revtwo_inventory.add_path(u'dir/d', kind='file', file_id='hg:dir_sd') entry.revision = tip entry.text_size = len('contents of hg/dir/d\n') entry.text_sha1 = "f48fc342f707bfb4711790e1813c0df4d44e1a23" self.revidtwo = tip #====== end revision two # in revision three, we reset the exec flag on 'b' os.chmod('hg/b', mode) self.tree.commit('reset mode on b') self.revthree_inventory = copy.deepcopy(self.revtwo_inventory) tip = self.tree.last_revision() # should be a new file revision with exec reset entry = self.revthree_inventory.get_entry('hg:b') entry.revision = tip entry.executable = False self.revidthree = tip #====== end revision three # in revision four we change the file dir/c, which should not alter # the last-changed field for 'dir'. self.build_tree_contents([('hg/dir/c', 'new contents')]) self.tree.commit('change dir/c') self.revfour_inventory = copy.deepcopy(self.revthree_inventory) tip = self.tree.last_revision() entry = self.revfour_inventory.get_entry('hg:dir_sc') entry.revision = tip entry.text_size = len('new contents') entry.text_sha1 = "7ffa72b76d5d66da37f4b614b7a822c01f23c183" self.revidfour = tip