From: Jelmer Vernooij Date: Sun, 15 Jun 2008 00:41:08 +0000 (+0200) Subject: Merge 0.4. X-Git-Tag: subvertpy-0.6.0~267^2~45 X-Git-Url: http://git.samba.org/samba.git/?p=jelmer%2Fsubvertpy.git;a=commitdiff_plain;h=85fce4946936c43a5c8f41a6d8a4a42396f0bc77 Merge 0.4. --- 85fce4946936c43a5c8f41a6d8a4a42396f0bc77 diff --cc commit.py index fc09dcd4,ed32e6cc..6bd36c3c --- a/commit.py +++ b/commit.py @@@ -224,10 -223,10 +224,10 @@@ class SvnCommitBuilder(RootCommitBuilde child_ie.parent_id != self.new_inventory[child_ie.file_id].parent_id or # ... name changed self.new_inventory[child_ie.file_id].name != child_name): - self.mutter('removing %r(%r)' % (child_name, child_ie.file_id)) - self.mutter('removing %r(%r)', (child_name, child_ie.file_id)) - self.editor.delete_entry( ++ self.mutter('removing %r(%r)', child_name, child_ie.file_id) + dir_editor.delete_entry( urlutils.join(self.branch.get_branch_path(), path, child_name), - self.base_revnum, baton, self.pool) + self.base_revnum) # Loop over file children of file_id in self.new_inventory for child_name in self.new_inventory[file_id].children: @@@ -242,26 -241,28 +242,25 @@@ new_child_path) # add them if they didn't exist in old_inv if not child_ie.file_id in self.old_inv: - self.mutter('adding %s %r' % (child_ie.kind, new_child_path)) + self.mutter('adding %s %r', child_ie.kind, new_child_path) - child_baton = self.editor.add_file( - full_new_child_path, baton, None, -1, self.pool) - + child_editor = dir_editor.add_file(full_new_child_path) - # copy if they existed at different location elif (self.old_inv.id2path(child_ie.file_id) != new_child_path or self.old_inv[child_ie.file_id].parent_id != child_ie.parent_id): - self.mutter('copy %s %r -> %r' % (child_ie.kind, + self.mutter('copy %s %r -> %r', child_ie.kind, self.old_inv.id2path(child_ie.file_id), - new_child_path)) + new_child_path) - child_baton = self.editor.add_file( - full_new_child_path, baton, + child_editor = dir_editor.add_file( + full_new_child_path, urlutils.join(self.repository.transport.svn_url, self.base_path, self.old_inv.id2path(child_ie.file_id)), - self.base_revnum, self.pool) + self.base_revnum) # open if they existed at the same location elif child_ie.revision is None: - self.mutter('open %s %r' % (child_ie.kind, new_child_path)) + self.mutter('open %s %r', child_ie.kind, new_child_path) - child_baton = self.editor.open_file( - full_new_child_path, baton, self.base_revnum, self.pool) + child_editor = dir_editor.open_file(full_new_child_path, self.base_revnum) else: # Old copy of the file was retained. No need to send changes @@@ -308,27 -311,28 +307,27 @@@ new_child_path = self.new_inventory.id2path(child_ie.file_id) # add them if they didn't exist in old_inv if not child_ie.file_id in self.old_inv: - self.mutter('adding dir %r' % child_ie.name) + self.mutter('adding dir %r', child_ie.name) - child_baton = self.editor.add_directory( + child_editor = dir_editor.add_directory( urlutils.join(self.branch.get_branch_path(), - new_child_path), baton, None, -1, self.pool) + new_child_path)) # copy if they existed at different location elif self.old_inv.id2path(child_ie.file_id) != new_child_path: old_child_path = self.old_inv.id2path(child_ie.file_id) - self.mutter('copy dir %r -> %r' % (old_child_path, new_child_path)) - self.mutter('copy dir %r -> %r', old_child_path, new_child_path) - child_baton = self.editor.add_directory( ++ self.mutter('copy dir %r -> %r', old_child_path, new_child_path) + child_editor = dir_editor.add_directory( urlutils.join(self.branch.get_branch_path(), new_child_path), - baton, - urlutils.join(self.repository.transport.svn_url, self.base_path, old_child_path), self.base_revnum, self.pool) + urlutils.join(self.repository.transport.svn_url, self.base_path, old_child_path), self.base_revnum) # open if they existed at the same location and # the directory was touched elif self.new_inventory[child_ie.file_id].revision is None: - self.mutter('open dir %r' % new_child_path) + self.mutter('open dir %r', new_child_path) - child_baton = self.editor.open_directory( + child_editor = dir_editor.open_directory( urlutils.join(self.branch.get_branch_path(), new_child_path), - baton, self.base_revnum, self.pool) + self.base_revnum) else: assert child_ie.file_id not in self.modified_dirs continue @@@ -379,15 -384,15 +378,15 @@@ if replace_existing: if name == "": raise ChangesRootLHSHistory() - self.mutter("removing branch dir %r" % name) + self.mutter("removing branch dir %r", name) - self.editor.delete_entry(name, -1, ret[-1]) + ret[-1].delete_entry(name, -1) if base_path is not None: base_url = urlutils.join(self.repository.transport.svn_url, base_path) else: base_url = None - self.mutter("adding branch dir %r" % name) + self.mutter("adding branch dir %r", name) - ret.append(self.editor.add_directory( - name, ret[-1], base_url, base_rev, self.pool)) + ret.append(ret[-1].add_directory( + name, base_url, base_rev)) return ret @@@ -448,65 -450,59 +447,65 @@@ try: existing_bp_parts = _check_dirs_exist(self.repository.transport, bp_parts, -1) - self.revision_metadata = None for prop in self._svn_revprops: if not properties.is_valid_property_name(prop): - warning("Setting property %r with invalid characters in name" % prop) + warning("Setting property %r with invalid characters in name", prop) + conn = self.repository.transport.get_connection() try: - self.editor = self.repository.transport.get_commit_editor( - self._svn_revprops, done, None, False) - self._svn_revprops = {} - except NotImplementedError: - if set_revprops: - raise - # Try without bzr: revprops - self.editor = self.repository.transport.get_commit_editor({ - properties.PROP_REVISION_LOG: self._svn_revprops[properties.PROP_REVISION_LOG]}, - done, None, False) - del self._svn_revprops[properties.PROP_REVISION_LOG] - - root = self.editor.open_root(self.base_revnum) - - replace_existing = False - # See whether the base of the commit matches the lhs parent - # if not, we need to replace the existing directory - if len(bp_parts) == len(existing_bp_parts): - if self.base_path.strip("/") != "/".join(bp_parts).strip("/"): - replace_existing = True - elif self.base_revnum < self.repository._log.find_latest_change(self.branch.get_branch_path(), repository_latest_revnum): - replace_existing = True - - if replace_existing and self.branch._get_append_revisions_only(): - raise AppendRevisionsOnlyViolation(self.branch.base) - - # TODO: Accept create_prefix argument (#118787) - branch_batons = self.open_branch_batons(root, bp_parts, - existing_bp_parts, self.base_path, self.base_revnum, - replace_existing) - - self._dir_process("", self.new_inventory.root.file_id, - branch_batons[-1]) - - # Set all the revprops - for prop, value in self._svnprops.items(): - if not properties.is_valid_property_name(prop): - warning("Setting property %r with invalid characters in name", prop) - if value is not None: - value = value.encode('utf-8') - self.editor.change_dir_prop(branch_batons[-1], prop, value, - self.pool) - self.mutter("Setting root file property %r -> %r", prop, value) - - for baton in reversed(branch_batons): - self.editor.close_directory(baton, self.pool) - - self.editor.close() + try: + self.editor = conn.get_commit_editor( + self._svn_revprops, done, None, False) + self._svn_revprops = {} + self.editor_active = True + except NotImplementedError: + if set_revprops: + raise + # Try without bzr: revprops + self.editor = conn.get_commit_editor({ + properties.PROP_REVISION_LOG: self._svn_revprops[properties.PROP_REVISION_LOG]}, + done, None, False) + del self._svn_revprops[properties.PROP_REVISION_LOG] + + root = self.editor.open_root(self.base_revnum) + + replace_existing = False + # See whether the base of the commit matches the lhs parent + # if not, we need to replace the existing directory + if len(bp_parts) == len(existing_bp_parts): + if self.base_path.strip("/") != "/".join(bp_parts).strip("/"): + replace_existing = True + elif self.base_revnum < self.repository._log.find_latest_change(self.branch.get_branch_path(), repository_latest_revnum): + replace_existing = True + + if replace_existing and self.branch._get_append_revisions_only(): + raise AppendRevisionsOnlyViolation(self.branch.base) + + # TODO: Accept create_prefix argument (#118787) + branch_editors = self.open_branch_editors(root, bp_parts, + existing_bp_parts, self.base_path, self.base_revnum, + replace_existing) + + self._dir_process("", self.new_inventory.root.file_id, + branch_editors[-1]) + + # Set all the revprops + for prop, value in self._svnprops.items(): + if not properties.is_valid_property_name(prop): - warning("Setting property %r with invalid characters in name" % prop) ++ warning("Setting property %r with invalid characters in name", prop) + if value is not None: + value = value.encode('utf-8') + branch_editors[-1].change_prop(prop, value) - self.mutter("Setting root file property %r -> %r" % (prop, value)) ++ self.mutter("Setting root file property %r -> %r", prop, value) + + for dir_editor in reversed(branch_editors): + dir_editor.close() + + self.editor.close() + self.editor_active = False + finally: + if self.editor_active: + self.editor.abort() + self.repository.transport.add_connection(conn) finally: lock.unlock() diff --cc fetch.py index 462102ad,aa8dcd1b..f78aa4e3 --- a/fetch.py +++ b/fetch.py @@@ -233,13 -217,13 +233,13 @@@ class DirectoryBuildEditor # other location hasn't been removed yet. if copyfrom_path is None: # This should ideally never happen! - copyfrom_path = self.old_inventory.id2path(file_id) + copyfrom_path = self.editor.old_inventory.id2path(file_id) - mutter('no copyfrom path set, assuming %r' % copyfrom_path) + mutter('no copyfrom path set, assuming %r', copyfrom_path) - assert copyfrom_path == self.old_inventory.id2path(file_id) - assert copyfrom_path not in self._premature_deletes - self._premature_deletes.add(copyfrom_path) - self._rename(file_id, new_parent_id, path) - ie = self.inventory[file_id] + assert copyfrom_path == self.editor.old_inventory.id2path(file_id) + assert copyfrom_path not in self.editor._premature_deletes + self.editor._premature_deletes.add(copyfrom_path) + self.editor._rename(file_id, self.new_id, path) + ie = self.editor.inventory[file_id] old_file_id = file_id else: old_file_id = None @@@ -290,80 -273,12 +290,80 @@@ elif (name.startswith(properties.PROP_WC_PREFIX)): pass elif name.startswith(properties.PROP_PREFIX): - mutter('unsupported dir property %r' % name) + mutter('unsupported dir property %r', name) - def change_file_prop(self, id, name, value, pool): + def add_file(self, path, copyfrom_path=None, copyfrom_revnum=-1): + assert isinstance(path, str) + path = path.decode("utf-8") + check_filename(path) + file_id = self.editor._get_new_id(self.new_id, path) + if file_id in self.editor.inventory: + # This file was moved here from somewhere else, but the + # other location hasn't been removed yet. + if copyfrom_path is None: + # This should ideally never happen + copyfrom_path = self.editor.old_inventory.id2path(file_id) + mutter('no copyfrom path set, assuming %r' % copyfrom_path) + assert copyfrom_path == self.editor.old_inventory.id2path(file_id) + assert copyfrom_path not in self.editor._premature_deletes + self.editor._premature_deletes.add(copyfrom_path) + # No need to rename if it's already in the right spot + self.editor._rename(file_id, self.new_id, path) + return FileBuildEditor(self.editor, path, file_id) + + def open_file(self, path, base_revnum): + assert isinstance(path, str) + path = path.decode("utf-8") + base_file_id = self.editor._get_old_id(self.old_id, path) + base_revid = self.editor.old_inventory[base_file_id].revision + file_id = self.editor._get_existing_id(self.old_id, self.new_id, path) + is_symlink = (self.editor.inventory[base_file_id].kind == 'symlink') + file_data = self.editor._get_file_data(base_file_id, base_revid) + if file_id == base_file_id: + file_parents = [base_revid] + else: + # Replace + del self.editor.inventory[base_file_id] + file_parents = [] + return FileBuildEditor(self.editor, path, file_id, + file_parents, file_data, is_symlink=is_symlink) + + def delete_entry(self, path, revnum): + assert isinstance(path, str) + path = path.decode("utf-8") + if path in self.editor._premature_deletes: + # Delete recursively + self.editor._premature_deletes.remove(path) + for p in self.editor._premature_deletes.copy(): + if p.startswith("%s/" % path): + self.editor._premature_deletes.remove(p) + else: + self.editor.inventory.remove_recursive_id(self.editor._get_old_id(self.old_id, path)) + +class FileBuildEditor: + def __init__(self, editor, path, file_id, file_parents=[], data="", + is_symlink=False): + self.path = path + self.editor = editor + self.file_id = file_id + self.file_data = data + self.is_symlink = is_symlink + self.file_parents = file_parents + self.is_executable = None + self.file_stream = None + + def apply_textdelta(self, base_checksum=None): + actual_checksum = md5.new(self.file_data).hexdigest() + assert (base_checksum is None or base_checksum == actual_checksum, + "base checksum mismatch: %r != %r" % (base_checksum, + actual_checksum)) + self.file_stream = StringIO() + return apply_txdelta_handler(self.file_data, self.file_stream) + + def change_prop(self, name, value): if name == properties.PROP_EXECUTABLE: # You'd expect executable to match - # properties.PROP_EXECUTABLE_VALUE, but that's not + # constants.PROP_EXECUTABLE_VALUE, but that's not # how SVN behaves. It appears to consider the presence # of the property sufficient to mark it executable. self.is_executable = (value != None) @@@ -379,14 -296,54 +379,14 @@@ pass elif name.startswith(properties.PROP_WC_PREFIX): pass + elif name == properties.PROP_EXTERNALS: + mutter('svn:externals property on file!') elif (name.startswith(properties.PROP_PREFIX) or name.startswith(SVN_PROP_BZR_PREFIX)): - mutter('unsupported file property %r' % name) + mutter('unsupported file property %r', name) - def add_file(self, path, (old_parent_id, new_parent_id), copyfrom_path, copyfrom_revnum, baton): - assert isinstance(path, str) - path = path.decode("utf-8") - check_filename(path) - self.is_symlink = False - self.is_executable = None - self.file_data = "" - self.file_parents = [] - self.file_stream = None - self.file_id = self._get_new_id(new_parent_id, path) - if self.file_id in self.inventory: - # This file was moved here from somewhere else, but the - # other location hasn't been removed yet. - if copyfrom_path is None: - # This should ideally never happen - copyfrom_path = self.old_inventory.id2path(self.file_id) - mutter('no copyfrom path set, assuming %r', copyfrom_path) - assert copyfrom_path == self.old_inventory.id2path(self.file_id) - assert copyfrom_path not in self._premature_deletes - self._premature_deletes.add(copyfrom_path) - # No need to rename if it's already in the right spot - self._rename(self.file_id, new_parent_id, path) - return path - - def open_file(self, path, (old_parent_id, new_parent_id), base_revnum, pool): - assert isinstance(path, str) - path = path.decode("utf-8") - base_file_id = self._get_old_id(old_parent_id, path) - base_revid = self.old_inventory[base_file_id].revision - self.file_id = self._get_existing_id(old_parent_id, new_parent_id, path) - self.is_executable = None - self.is_symlink = (self.inventory[base_file_id].kind == 'symlink') - self.file_data = self._get_file_data(base_file_id, base_revid) - self.file_stream = None - if self.file_id == base_file_id: - self.file_parents = [base_revid] - else: - # Replace - del self.inventory[base_file_id] - self.file_parents = [] - return path - - def close_file(self, path, checksum): - assert isinstance(path, unicode) + def close(self, checksum=None): + assert isinstance(self.path, unicode) if self.file_stream is not None: self.file_stream.seek(0) lines = osutils.split_lines(self.file_stream.read()) diff --cc mapping3/__init__.py index 41de5d95,28ad6670..d59d3862 --- a/mapping3/__init__.py +++ b/mapping3/__init__.py @@@ -16,9 -16,8 +16,10 @@@ from bzrlib import osutils, ui from bzrlib.errors import InvalidRevisionId from bzrlib.trace import mutter -from bzrlib.plugins.svn import mapping, properties ++ +from bzrlib.plugins.svn import core, mapping, properties +from bzrlib.plugins.svn.core import SubversionException - from bzrlib.plugins.svn.errors import ERR_FS_NOT_DIRECTORY, ERR_FS_NOT_FOUND + from bzrlib.plugins.svn.errors import ERR_FS_NOT_DIRECTORY, ERR_FS_NOT_FOUND, ERR_RA_DAV_PATH_NOT_FOUND from bzrlib.plugins.svn.layout import RepositoryLayout from bzrlib.plugins.svn.mapping3.scheme import (BranchingScheme, guess_scheme_from_branch_path, guess_scheme_from_history, ListBranchingScheme, @@@ -67,15 -67,12 +68,13 @@@ class SchemeDerivedLayout(RepositoryLay def get_branches(self, revnum, project=""): def check_path(path): - return self.repository.transport.check_path(path, revnum) == svn.core.svn_node_dir + return self.repository.transport.check_path(path, revnum) == core.NODE_DIR def find_children(path): try: + assert not path.startswith("/") dirents = self.repository.transport.get_dir(path, revnum)[0] except SubversionException, (msg, num): - if num == ERR_FS_NOT_DIRECTORY: - return None - if num == ERR_FS_NOT_FOUND: + if num in (ERR_FS_NOT_DIRECTORY, ERR_FS_NOT_FOUND, ERR_RA_DAV_PATH_NOT_FOUND): return None raise return dirents.keys() diff --cc tree.py index b9ce25b6,578bc07a..ee61ffeb --- a/tree.py +++ b/tree.py @@@ -168,27 -189,9 +168,27 @@@ class DirectoryTreeEditor elif name.startswith(properties.PROP_WC_PREFIX): pass elif name.startswith(properties.PROP_PREFIX): - mutter('unsupported dir property %r' % name) + mutter('unsupported dir property %r', name) - def change_file_prop(self, id, name, value, pool): + def add_file(self, path, copyfrom_path=None, copyfrom_revnum=-1): + path = path.decode("utf-8") + return FileTreeEditor(self.tree, path) + + def close(self): + pass + + +class FileTreeEditor: + def __init__(self, tree, path): + self.tree = tree + self.path = path + self.is_executable = False + self.is_symlink = False + self.last_file_rev = None + + def change_prop(self, name, value): + from mapping import SVN_PROP_BZR_PREFIX + if name == properties.PROP_EXECUTABLE: self.is_executable = (value != None) elif name == properties.PROP_SPECIAL: @@@ -205,15 -208,25 +205,15 @@@ pass elif name.startswith(properties.PROP_WC_PREFIX): pass - elif name.startswith(properties.SVN_PROP_PREFIX): - mutter('unsupported file property %r' % name) + elif name.startswith(properties.PROP_PREFIX): + mutter('unsupported file property %r', name) - def add_file(self, path, parent_id, copyfrom_path, copyfrom_revnum, baton): - path = path.decode("utf-8") - self.is_symlink = False - self.is_executable = False - return path - - def close_dir(self, id): - if id in self.tree._inventory and self.dir_ignores.has_key(id): - self.tree._inventory[id].ignores = self.dir_ignores[id] - - def close_file(self, path, checksum): - file_id, revision_id = self.tree.id_map[path] + def close(self, checksum=None): + file_id, revision_id = self.tree.id_map[self.path] if self.is_symlink: - ie = self.tree._inventory.add_path(path, 'symlink', file_id) + ie = self.tree._inventory.add_path(self.path, 'symlink', file_id) else: - ie = self.tree._inventory.add_path(path, 'file', file_id) + ie = self.tree._inventory.add_path(self.path, 'file', file_id) ie.revision = revision_id if self.file_stream: diff --cc workingtree.py index 33ac9429,e048f5a9..ca93fcf5 --- a/workingtree.py +++ b/workingtree.py @@@ -384,9 -372,9 +384,9 @@@ class SvnWorkingTree(WorkingTree) newrev = self.branch.repository.get_revision(revid) newrevtree = self.branch.repository.revision_tree(revid) - def update_settings(wc, path): + def update_settings(adm, path): id = newrevtree.inventory.path2id(path) - mutter("Updating settings for %r" % id) + mutter("Updating settings for %r", id) revnum = self.branch.lookup_revision_id( newrevtree.inventory[id].revision) @@@ -436,10 -502,10 +436,10 @@@ try: if not self.inventory.has_filename(f): if save: - mutter('adding %r' % file_path) + mutter('adding %r', file_path) - svn.wc.add2(file_path, wc, None, 0, None, None, None) + adm.add(file_path, None, 0, None, None, None) added.append(file_path) - if recurse and file_kind(file_path) == 'directory': + if recurse and osutils.file_kind(file_path) == 'directory': # Filter out ignored files and update ignored for c in os.listdir(file_path): if self.is_control_filename(c):