def dump_tree(fsob, root, pool, path, indent=0): path = path + '/' entries = fs.dir_entries(root, path, pool) names = entries.keys() names.sort() subpool = _util.svn_pool_create(pool) for name in names: child = path + name line = ' '*indent + name id = fs.dirent_t_id_get(entries[name]) is_dir = fs.is_dir(root, child, subpool) if is_dir: print line + '/' dump_tree(fsob, root, subpool, child, indent+2) else: rev = fs.node_created_rev(root, child, subpool) author = fs.revision_prop(fsob, rev, 'svn:author', pool) print line, author, rev _util.svn_pool_clear(subpool) _util.svn_pool_destroy(subpool)
def do_ls(self, arg): """list the contents of the current directory or provided path""" parent = self.path if not len(arg): # no arg -- show a listing for the current directory. entries = fs.dir_entries(self.root, self.path) else: # arg? show a listing of that path. newpath = self._parse_path(arg) kind = fs.check_path(self.root, newpath) if kind == core.svn_node_dir: parent = newpath entries = fs.dir_entries(self.root, parent) elif kind == core.svn_node_file: parts = self._path_to_parts(newpath) name = parts.pop(-1) parent = self._parts_to_path(parts) print(parent + ':' + name) tmpentries = fs.dir_entries(self.root, parent) if not tmpentries.get(name, None): return entries = {} entries[name] = tmpentries[name] else: print("Path '%s' not found." % newpath) return keys = sorted(entries.keys()) print(" REV AUTHOR NODE-REV-ID SIZE DATE NAME") print( "----------------------------------------------------------------------------" ) for entry in keys: fullpath = parent + '/' + entry size = '' is_dir = fs.is_dir(self.root, fullpath) if is_dir: name = entry + '/' else: size = str(fs.file_length(self.root, fullpath)) name = entry node_id = fs.unparse_id(entries[entry].id) created_rev = fs.node_created_rev(self.root, fullpath) author = fs.revision_prop(self.fs_ptr, created_rev, core.SVN_PROP_REVISION_AUTHOR) if not author: author = "" date = fs.revision_prop(self.fs_ptr, created_rev, core.SVN_PROP_REVISION_DATE) if not date: date = "" else: date = self._format_date(date) print("%6s %8s %12s %8s %12s %s" % (created_rev, author[:8], node_id, size, date, name))
def do_ls(self, arg): """list the contents of the current directory or provided path""" parent = self.path if not len(arg): # no arg -- show a listing for the current directory. entries = fs.dir_entries(self.root, self.path) else: # arg? show a listing of that path. newpath = self._parse_path(arg) kind = fs.check_path(self.root, newpath) if kind == core.svn_node_dir: parent = newpath entries = fs.dir_entries(self.root, parent) elif kind == core.svn_node_file: parts = self._path_to_parts(newpath) name = parts.pop(-1) parent = self._parts_to_path(parts) print(parent + ':' + name) tmpentries = fs.dir_entries(self.root, parent) if not tmpentries.get(name, None): return entries = {} entries[name] = tmpentries[name] else: print("Path '%s' not found." % newpath) return keys = sorted(entries.keys()) print(" REV AUTHOR NODE-REV-ID SIZE DATE NAME") print("----------------------------------------------------------------------------") for entry in keys: fullpath = parent + '/' + entry size = '' is_dir = fs.is_dir(self.root, fullpath) if is_dir: name = entry + '/' else: size = str(fs.file_length(self.root, fullpath)) name = entry node_id = fs.unparse_id(entries[entry].id) created_rev = fs.node_created_rev(self.root, fullpath) author = fs.revision_prop(self.fs_ptr, created_rev, core.SVN_PROP_REVISION_AUTHOR) if not author: author = "" date = fs.revision_prop(self.fs_ptr, created_rev, core.SVN_PROP_REVISION_DATE) if not date: date = "" else: date = self._format_date(date) print("%6s %8s %12s %8s %12s %s" % (created_rev, author[:8], node_id, size, date, name))
def dumpprops(path, filename='', rev=None): path = core.svn_path_canonicalize(path) repos_ptr = repos.open(path) fsob = repos.fs(repos_ptr) if rev is None: rev = fs.youngest_rev(fsob) root = fs.revision_root(fsob, rev) print_props(root, filename) if fs.is_dir(root, filename): walk_tree(root, filename)
def delete_entry(self, path, revision, parent_baton, pool=None): base_path = self._make_base_path(parent_baton[1], path) if _fs.is_dir(self._get_root(parent_baton[2]), base_path): item_type = _core.svn_node_dir else: item_type = _core.svn_node_file self.changes[path] = ChangedPath(item_type, False, False, base_path, parent_baton[2], # base_rev None, # (new) path False, # added ) self._send_change(path)
def delete_entry(self, path, revision, parent_baton, pool=None): base_path = self._make_base_path(parent_baton[1], path) if _svnfs.is_dir(self._get_root(parent_baton[2]), base_path): item_type = _svncore.svn_node_dir else: item_type = _svncore.svn_node_file self.changes[path] = ChangedPath(item_type, False, False, base_path, # base_path parent_baton[2], # base_rev path, # path False, # added CHANGE_ACTION_DELETE, ) self._send_change(path)
def delete_entry(self, path, revision, parent_baton, pool): ### need more logic to detect 'replace' if not fs.is_dir(self.base_root, '/' + path): self._do_diff(path, None)
def delete_entry(self, path, revision, parent_baton, pool): ### need more logic to detect 'replace' if fs.is_dir(self.base_root, '/' + path): self.callback('D', path + '/') else: self.callback('D', path)
def walk_tree(root, path): for name in fs.dir_entries(root, path).keys(): full = path + '/' + name print_props(root, full) if fs.is_dir(root, full): walk_tree(root, full)
def delete_entry(self, path, revision, parent_baton, pool): ### need more logic to detect 'replace' if fs.is_dir(self.base_root, '/' + path): print 'D ' + path + '/' else: print 'D ' + path
def delete_entry(self, path, revision, parent_baton, pool): ### need more logic to detect 'replace' if fs.is_dir(self.base_root, '/' + path, pool): self.deleted.append(path.decode('utf-8') + u'/') else: self.deleted.append(path.decode('utf-8'))
def MakeRecordsFromPath(srcrepo, srcrev, srcpath, dstpath, record_source): """Generate Records adding the contents of a given repo/rev/path. Args: srcrepo: path to the source repository srcrev: revision number srcpath: path within the source repository dstpath: destination path in the repository being filtered record_source: the source attribute of the Records generated Returns: a list of Records Raises: RuntimeError: if svnrdump seems to have failed This is the fundamental feature of a working svndumpfilter replacement. In the upstream svndumpfilter, copyfrom operations that reference paths that are excluded by filtering cannot be resolved. To fix that, each svndumpfilter replacement must find a way to turn that copy operation into a series of add operations. svndumpfilter2 originally did this by calling the svnlook utility to list the directory structure, grab file contents, list property names, and grab property values. This resulted in calling svnlook once per tree, twice per file, and once per property. For a time, we tried instead making a single call to svnrdump which, unlike svnadmin dump (which is used by svndumpfilter3 with disastrous results for performance) can output a dump file containing only the desired subdirectory. The dump file is parsed into Records, the paths have the destination path prepended, and the Records are inserted into the dump. Unfortunately, svnrdump always produces format 3 dumps which use deltas. Even though it was only used for a single non-incremental revision, every file's contents were in the form of a delta. Since some tools (such as p4convert-svn) do not support deltas, svnrdump was done away with, replaced by the SVN SWIG bindings. It turns out that this same functionality is critical to 'internalizing' SVN externals. By generating Records that add all of the files and directories in the repo/rev/path referenced by an svn:external property, the history can be made to look as though the actual files had been there all along, not just a reference to them. Further filtering of these generated Records must be done in the case of externals to delete externals when they are removed and modify the filesystem when the revision is changed, rather than deleting and reading it every time (see externals.FromRev, externals.Diff, Diff). """ srcrepo = svn_core.svn_path_canonicalize(srcrepo) repo_ptr = svn_repos.open(srcrepo) fs = svn_repos.fs(repo_ptr) root = svn_fs.revision_root(fs, srcrev) output = [] # Perform a depth-first search stack = [srcpath] while stack: path = stack.pop() if srcpath: relative_path = path[len(srcpath):] node_path = dstpath + relative_path else: node_path = (dstpath + '/' + path) if path else dstpath if svn_fs.is_dir(root, path): record = Record(action='add', kind='dir', path=node_path, source=record_source) # Add children to the stack prefix = (path + '/') if path else '' for name in svn_fs.dir_entries(root, path).keys(): stack.append(prefix + name) else: record = Record(action='add', kind='file', path=node_path, source=record_source) # Fetch file content stream = svn_fs.file_contents(root, path) record.text = _ReadSVNStream(stream) checksum = svn_fs.file_md5_checksum(root, path) record.headers['Text-content-md5'] = checksum.encode('hex_codec') # Fetch properties props = svn_fs.node_proplist(root, path) record.props = {key: str(value) for key, value in props.iteritems()} output.append(record) return output