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)
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