Change vclib interface to accept 'rev' parameters wherever it accepts
path parameters so it is possible to use a single Repository object to request information about any path at any revision. Note: I wasn't able to test the svn_ra.get_location function because I only have subversion 1.2.3. * lib/vclib/__init__.py (Repository.itemtype, Repository.openfile, Repository.listdir, Repository.dirlogs, Repository.itemlog, Repository.annotate): add rev arguments, update docstrings * lib/vclib/bincvs/__init__.py (CVSRepository.itemtype, CVSRepository.listdir, BinCVSRepository.openfile, BinCVSRepository.dirlogs, BinCVSRepository.itemlog): same * lib/vclib/ccvs/__init__.py (CCVSRepository.dirlogs, CCVSRepository.itemlog): same * lib/vclib/svn/__init__.py (SubversionRepository.__init__): remove rev argument (get_location, created_rev, _get_history, get_revision_info, _fetch_log, _get_last_history_rev, get_logs, do_diff, SubversionRepository.itemtype, SubversionRepository.openfile, SubversionRepository.listdir, SubversionRepository.dirlogs, SubversionRepository.itemlog, SubversionRepository.annotate): add rev arguments, use new _getrev and _getroot functions to handle all revision string parsing and revision_root creation (SubversionRepository._getrev, SubversionRepository._getroot): new functions * lib/vclib/svn_ra/__init__.py (_rev2optrev): accept integers instead of strings, and eliminate head/unspecified revision handling which is already taken care of by _getrev (SubversionRepository.__init__): remove rev argument (get_location, created_rev, get_revision_info, get_logs, SubversionRepository.itemtype, SubversionRepository.openfile, SubversionRepository.listdir, SubversionRepository.dirlogs, SubversionRepository.itemlog, SubversionRepository.annotate, SubversionRepository.rawdiff, SubversionRepository._get_dirents): add rev arguments, use new _getrev function to handle all revision string parsing (SubversionRepository._getrev): new function * lib/blame.py (link_includes): update call to repos.itemtype * tools/cvsdbadmin (RecurseUpdate): update call to repos.listdir * lib/viewcvs.py (Request.run_viewcvs): update calls to SubversionRepository constructors and _strip_suffix (_strip_suffix): add rev parameter, remove redundant where parameter (_repos_pathtype, view_markup, search_files, _get_diff_path_parts, generate_tarball): update calls to vclib methods (nav_path, view_directory, view_log, setup_diff, download_tarball, view_revision): explicitly read 'rev' query param instead of relying on SubversionRepository.rev, and update vclib calls git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@1144 8cb11bc2-c004-0410-86c3-e597b4017df7remotes/tags/1.0.0-rc1
parent
7787585540
commit
5204e26666
|
@ -55,7 +55,7 @@ def link_includes(text, repos, path_parts, include_url):
|
|||
include_path = path_parts[:depth] + [incfile]
|
||||
try:
|
||||
# will throw if path doesn't exist
|
||||
if repos.itemtype(include_path) == vclib.FILE:
|
||||
if repos.itemtype(include_path, None) == vclib.FILE:
|
||||
break
|
||||
except vclib.ItemNotFound:
|
||||
pass
|
||||
|
|
|
@ -34,17 +34,19 @@ SIDE_BY_SIDE = 3
|
|||
class Repository:
|
||||
"""Abstract class representing a repository."""
|
||||
|
||||
def itemtype(self, path_parts):
|
||||
"""Return the type of the item (file or dir) at the given path.
|
||||
def itemtype(self, path_parts, rev):
|
||||
"""Return the type of the item (file or dir) at the given path and revision
|
||||
|
||||
The result will be vclib.DIR or vclib.FILE
|
||||
|
||||
The path is specified as a list of components, relative to the root
|
||||
of the repository. e.g. ["subdir1", "subdir2", "filename"]
|
||||
|
||||
rev is the revision of the item to check
|
||||
"""
|
||||
pass
|
||||
|
||||
def openfile(self, path_parts, rev=None):
|
||||
def openfile(self, path_parts, rev):
|
||||
"""Open a file object to read file contents at a given path and revision.
|
||||
|
||||
The return value is a 2-tuple of containg the file object and revision
|
||||
|
@ -53,10 +55,10 @@ class Repository:
|
|||
The path is specified as a list of components, relative to the root
|
||||
of the repository. e.g. ["subdir1", "subdir2", "filename"]
|
||||
|
||||
The revision number can be None to access a default revision.
|
||||
rev is the revision of the file to check out
|
||||
"""
|
||||
|
||||
def listdir(self, path_parts, options):
|
||||
def listdir(self, path_parts, rev, options):
|
||||
"""Return list of files in a directory
|
||||
|
||||
The result is a list of DirEntry objects
|
||||
|
@ -64,10 +66,12 @@ class Repository:
|
|||
The path is specified as a list of components, relative to the root
|
||||
of the repository. e.g. ["subdir1", "subdir2", "filename"]
|
||||
|
||||
rev is the revision of the directory to list
|
||||
|
||||
options is a dictionary of implementation specific options
|
||||
"""
|
||||
|
||||
def dirlogs(self, path_parts, entries, options):
|
||||
def dirlogs(self, path_parts, rev, entries, options):
|
||||
"""Augment directory entries with log information
|
||||
|
||||
New properties will be set on all of the DirEntry objects in the entries
|
||||
|
@ -78,6 +82,9 @@ class Repository:
|
|||
The path is specified as a list of components, relative to the root
|
||||
of the repository. e.g. ["subdir1", "subdir2", "filename"]
|
||||
|
||||
rev is the revision of the directory listing and will effect which log
|
||||
messages are returned
|
||||
|
||||
entries is a list of DirEntry objects returned from a previous call to
|
||||
the listdir() method
|
||||
|
||||
|
@ -92,9 +99,7 @@ class Repository:
|
|||
The path is specified as a list of components, relative to the root
|
||||
of the repository. e.g. ["subdir1", "subdir2", "filename"]
|
||||
|
||||
The rev parameter can be set to only retrieve log information for a
|
||||
specified revision, or it can be None to return information on all
|
||||
file revisions.
|
||||
rev is the revision of the item to return information about
|
||||
|
||||
options is a dictionary of implementation specific options
|
||||
"""
|
||||
|
@ -114,7 +119,7 @@ class Repository:
|
|||
Return value is a python file object
|
||||
"""
|
||||
|
||||
def annotate(self, path_parts, rev=None):
|
||||
def annotate(self, path_parts, rev):
|
||||
"""Return a list of annotate file content lines and a revision.
|
||||
|
||||
The annotated lines are an collection of objects with the
|
||||
|
|
|
@ -38,7 +38,7 @@ class CVSRepository(vclib.Repository):
|
|||
self.name = name
|
||||
self.rootpath = rootpath
|
||||
|
||||
def itemtype(self, path_parts):
|
||||
def itemtype(self, path_parts, rev):
|
||||
basepath = self._getpath(path_parts)
|
||||
if os.path.isdir(basepath):
|
||||
return vclib.DIR
|
||||
|
@ -49,7 +49,7 @@ class CVSRepository(vclib.Repository):
|
|||
return vclib.FILE
|
||||
raise vclib.ItemNotFound(path_parts)
|
||||
|
||||
def listdir(self, path_parts, options):
|
||||
def listdir(self, path_parts, rev, options):
|
||||
# Only RCS files (*,v) and subdirs are returned.
|
||||
data = [ ]
|
||||
|
||||
|
@ -124,7 +124,7 @@ class BinCVSRepository(CVSRepository):
|
|||
return revs[-1]
|
||||
return None
|
||||
|
||||
def openfile(self, path_parts, rev=None):
|
||||
def openfile(self, path_parts, rev):
|
||||
if not rev or rev == 'HEAD' or rev == 'MAIN':
|
||||
rev_flag = '-p'
|
||||
else:
|
||||
|
@ -177,29 +177,27 @@ class BinCVSRepository(CVSRepository):
|
|||
|
||||
return fp, revision
|
||||
|
||||
def dirlogs(self, path_parts, entries, options):
|
||||
def dirlogs(self, path_parts, rev, entries, options):
|
||||
"""see vclib.Repository.dirlogs docstring
|
||||
|
||||
rev can be a tag name or None. if set only information from revisions
|
||||
matching the tag will be retrieved
|
||||
|
||||
Option values recognized by this implementation:
|
||||
|
||||
cvs_subdirs
|
||||
boolean. true to fetch logs of the most recently modified file in each
|
||||
subdirectory
|
||||
|
||||
cvs_dir_tag
|
||||
string set to a tag name. if set only logs from revisions matching the
|
||||
tag will be retrieved
|
||||
|
||||
Option values returned by this implementation:
|
||||
|
||||
cvs_tags, cvs_branches
|
||||
lists of tag and branch names encountered in the directory
|
||||
"""
|
||||
subdirs = options.get('cvs_subdirs', 0)
|
||||
tag = options.get('cvs_dir_tag')
|
||||
|
||||
dirpath = self._getpath(path_parts)
|
||||
alltags = _get_logs(self, dirpath, entries, tag, subdirs)
|
||||
alltags = _get_logs(self, dirpath, entries, rev, subdirs)
|
||||
|
||||
branches = options['cvs_branches'] = []
|
||||
tags = options['cvs_tags'] = []
|
||||
|
@ -212,7 +210,9 @@ class BinCVSRepository(CVSRepository):
|
|||
def itemlog(self, path_parts, rev, options):
|
||||
"""see vclib.Repository.itemlog docstring
|
||||
|
||||
rev parameter can be a revision number, branch number or tag name
|
||||
rev parameter can be a revision number, a branch number, a tag name,
|
||||
or None. If None, will return information about all revisions, otherwise,
|
||||
will only return information about the specified revision or branch.
|
||||
|
||||
Option values recognized by this implementation:
|
||||
|
||||
|
|
|
@ -35,26 +35,24 @@ from vclib.bincvs import CVSRepository, Revision, Tag, \
|
|||
_file_log, _log_path
|
||||
|
||||
class CCVSRepository(CVSRepository):
|
||||
def dirlogs(self, path_parts, entries, options):
|
||||
def dirlogs(self, path_parts, rev, entries, options):
|
||||
"""see vclib.Repository.dirlogs docstring
|
||||
|
||||
rev can be a tag name or None. if set only information from revisions
|
||||
matching the tag will be retrieved
|
||||
|
||||
Option values recognized by this implementation:
|
||||
|
||||
cvs_subdirs
|
||||
boolean. true to fetch logs of the most recently modified file in each
|
||||
subdirectory
|
||||
|
||||
cvs_dir_tag
|
||||
string set to a tag name. if set only logs from revisions matching the
|
||||
tag will be retrieved
|
||||
|
||||
Option values returned by this implementation:
|
||||
|
||||
cvs_tags, cvs_branches
|
||||
lists of tag and branch names encountered in the directory
|
||||
"""
|
||||
subdirs = options.get('cvs_subdirs', 0)
|
||||
tag = options.get('cvs_dir_tag')
|
||||
|
||||
dirpath = self._getpath(path_parts)
|
||||
alltags = { # all the tags seen in the files of this dir
|
||||
|
@ -67,7 +65,7 @@ class CCVSRepository(CVSRepository):
|
|||
path = _log_path(entry, dirpath, subdirs)
|
||||
if path:
|
||||
try:
|
||||
rcsparse.Parser().parse(open(path, 'rb'), InfoSink(entry, tag, alltags))
|
||||
rcsparse.Parser().parse(open(path, 'rb'), InfoSink(entry, rev, alltags))
|
||||
except IOError, e:
|
||||
entry.errors.append("rcsparse error: %s" % e)
|
||||
except RuntimeError, e:
|
||||
|
@ -86,7 +84,9 @@ class CCVSRepository(CVSRepository):
|
|||
def itemlog(self, path_parts, rev, options):
|
||||
"""see vclib.Repository.itemlog docstring
|
||||
|
||||
rev parameter can be a revision number, branch number or tag name
|
||||
rev parameter can be a revision number, a branch number, a tag name,
|
||||
or None. If None, will return information about all revisions, otherwise,
|
||||
will only return information about the specified revision or branch.
|
||||
|
||||
Option values returned by this implementation:
|
||||
|
||||
|
|
|
@ -108,18 +108,27 @@ def date_from_rev(svnrepos, rev):
|
|||
return _datestr_to_date(datestr, svnrepos.pool)
|
||||
|
||||
|
||||
def get_location(svnrepos, path, rev):
|
||||
def get_location(svnrepos, path, rev, old_rev):
|
||||
try:
|
||||
results = repos.svn_repos_trace_node_locations(svnrepos.fs_ptr, path,
|
||||
svnrepos.rev, [int(rev)],
|
||||
rev, [old_rev],
|
||||
_allow_all, svnrepos.pool)
|
||||
return results[int(rev)]
|
||||
except:
|
||||
raise vclib.ItemNotFound(filter(None, string.split(path, '/')))
|
||||
|
||||
except core.SubversionException, e:
|
||||
if e.apr_err == core.SVN_ERR_FS_NOT_FOUND:
|
||||
raise vclib.ItemNotFound(path)
|
||||
raise
|
||||
|
||||
def created_rev(svnrepos, full_name):
|
||||
return fs.node_created_rev(svnrepos.fsroot, full_name, svnrepos.pool)
|
||||
try:
|
||||
old_path = results[old_rev]
|
||||
except KeyError:
|
||||
raise vclib.ItemNotFound(path)
|
||||
|
||||
return _cleanup_path(old_path)
|
||||
|
||||
|
||||
def created_rev(svnrepos, full_name, rev):
|
||||
fsroot = svnrepos._getroot(rev)
|
||||
return fs.node_created_rev(fsroot, full_name, svnrepos.pool)
|
||||
|
||||
|
||||
class Revision(vclib.Revision):
|
||||
|
@ -171,11 +180,12 @@ class NodeHistory:
|
|||
self.histories[revision] = _cleanup_path(path)
|
||||
|
||||
|
||||
def _get_history(svnrepos, full_name, options):
|
||||
def _get_history(svnrepos, full_name, rev, options):
|
||||
fsroot = svnrepos._getroot(rev)
|
||||
show_all_logs = options.get('svn_show_all_dir_logs', 0)
|
||||
if not show_all_logs:
|
||||
# See if the path is a file or directory.
|
||||
kind = fs.check_path(svnrepos.fsroot, full_name, svnrepos.pool)
|
||||
kind = fs.check_path(fsroot, full_name, svnrepos.pool)
|
||||
if kind is core.svn_node_file:
|
||||
show_all_logs = 1
|
||||
|
||||
|
@ -187,7 +197,7 @@ def _get_history(svnrepos, full_name, options):
|
|||
|
||||
# Get the history items for PATH.
|
||||
repos.svn_repos_history(svnrepos.fs_ptr, full_name, history.add_history,
|
||||
1, svnrepos.rev, cross_copies, svnrepos.pool)
|
||||
1, rev, cross_copies, svnrepos.pool)
|
||||
return history.histories
|
||||
|
||||
|
||||
|
@ -244,15 +254,15 @@ class ChangedPathSet:
|
|||
return changes
|
||||
|
||||
|
||||
def get_revision_info(svnrepos):
|
||||
fsroot = fs.revision_root(svnrepos.fs_ptr, svnrepos.rev, svnrepos.pool)
|
||||
def get_revision_info(svnrepos, rev):
|
||||
fsroot = svnrepos._getroot(rev)
|
||||
|
||||
# Get the changes for the revision
|
||||
cps = ChangedPathSet()
|
||||
editor = repos.ChangeCollector(svnrepos.fs_ptr, fsroot,
|
||||
svnrepos.pool, cps.add_change)
|
||||
e_ptr, e_baton = delta.make_editor(editor, svnrepos.pool)
|
||||
repos.svn_repos_replay(svnrepos.fsroot, e_ptr, e_baton, svnrepos.pool)
|
||||
repos.svn_repos_replay(fsroot, e_ptr, e_baton, svnrepos.pool)
|
||||
|
||||
# Now get the revision property info
|
||||
props = editor.get_root_props()
|
||||
|
@ -286,14 +296,12 @@ def _log_helper(svnrepos, rev, path, pool):
|
|||
def _fetch_log(svnrepos, full_name, which_rev, options, pool):
|
||||
revs = []
|
||||
|
||||
if which_rev is not None:
|
||||
if (which_rev < 0) or (which_rev > svnrepos.youngest):
|
||||
raise vclib.InvalidRevision(which_rev)
|
||||
if options.get('svn_latest_log', 0):
|
||||
rev = _log_helper(svnrepos, which_rev, full_name, pool)
|
||||
if rev:
|
||||
revs.append(rev)
|
||||
else:
|
||||
history_set = _get_history(svnrepos, full_name, options)
|
||||
history_set = _get_history(svnrepos, full_name, which_rev, options)
|
||||
history_revs = history_set.keys()
|
||||
history_revs.sort()
|
||||
history_revs.reverse()
|
||||
|
@ -308,19 +316,20 @@ def _fetch_log(svnrepos, full_name, which_rev, options, pool):
|
|||
return revs
|
||||
|
||||
|
||||
def _get_last_history_rev(svnrepos, path, pool):
|
||||
history = fs.node_history(svnrepos.fsroot, path, pool)
|
||||
def _get_last_history_rev(fsroot, path, pool):
|
||||
history = fs.node_history(fsroot, path, pool)
|
||||
history = fs.history_prev(history, 0, pool)
|
||||
history_path, history_rev = fs.history_location(history, pool);
|
||||
return history_rev
|
||||
|
||||
|
||||
def get_logs(svnrepos, full_name, files):
|
||||
def get_logs(svnrepos, full_name, rev, files):
|
||||
fsroot = svnrepos._getroot(rev)
|
||||
subpool = core.svn_pool_create(svnrepos.pool)
|
||||
for file in files:
|
||||
core.svn_pool_clear(subpool)
|
||||
path = _fs_path_join(full_name, file.name)
|
||||
rev = _get_last_history_rev(svnrepos, path, subpool)
|
||||
rev = _get_last_history_rev(fsroot, path, subpool)
|
||||
datestr, author, msg = _fs_rev_props(svnrepos.fs_ptr, rev, subpool)
|
||||
date = _datestr_to_date(datestr, subpool)
|
||||
file.rev = str(rev)
|
||||
|
@ -328,7 +337,7 @@ def get_logs(svnrepos, full_name, files):
|
|||
file.author = author
|
||||
file.log = msg
|
||||
if file.kind == vclib.FILE:
|
||||
file.size = fs.file_length(svnrepos.fsroot, path, subpool)
|
||||
file.size = fs.file_length(fsroot, path, subpool)
|
||||
core.svn_pool_destroy(subpool)
|
||||
|
||||
|
||||
|
@ -337,8 +346,8 @@ def get_youngest_revision(svnrepos):
|
|||
|
||||
|
||||
def do_diff(svnrepos, path1, rev1, path2, rev2, diffoptions):
|
||||
root1 = fs.revision_root(svnrepos.fs_ptr, rev1, svnrepos.pool)
|
||||
root2 = fs.revision_root(svnrepos.fs_ptr, rev2, svnrepos.pool)
|
||||
root1 = svnrepos._getroot(rev1)
|
||||
root2 = svnrepos._getroot(rev2)
|
||||
|
||||
date1 = date_from_rev(svnrepos, rev1)
|
||||
date2 = date_from_rev(svnrepos, rev2)
|
||||
|
@ -475,7 +484,7 @@ class BlameSequencingError(Exception):
|
|||
|
||||
|
||||
class SubversionRepository(vclib.Repository):
|
||||
def __init__(self, name, rootpath, svn_path, rev=None):
|
||||
def __init__(self, name, rootpath, svn_path):
|
||||
if not os.path.isdir(rootpath):
|
||||
raise vclib.ReposNotFound(name)
|
||||
|
||||
|
@ -484,7 +493,6 @@ class SubversionRepository(vclib.Repository):
|
|||
self.apr_init = 0
|
||||
self.rootpath = rootpath
|
||||
self.name = name
|
||||
self.rev = rev
|
||||
self.svn_client_path = os.path.normpath(os.path.join(svn_path, 'svn'))
|
||||
|
||||
# Register a handler for SIGTERM so we can have a chance to
|
||||
|
@ -514,11 +522,7 @@ class SubversionRepository(vclib.Repository):
|
|||
self.repos = repos.svn_repos_open(rootpath, self.pool)
|
||||
self.fs_ptr = repos.svn_repos_fs(self.repos)
|
||||
self.youngest = fs.youngest_rev(self.fs_ptr, self.pool)
|
||||
if self.rev is None:
|
||||
self.rev = self.youngest
|
||||
if (self.rev < 0) or (self.rev > self.youngest):
|
||||
raise vclib.InvalidRevision(self.rev)
|
||||
self.fsroot = fs.revision_root(self.fs_ptr, self.rev, self.pool)
|
||||
self._fsroots = {}
|
||||
|
||||
def __del__(self):
|
||||
self._close()
|
||||
|
@ -533,10 +537,11 @@ class SubversionRepository(vclib.Repository):
|
|||
|
||||
def _scratch_clear(self):
|
||||
core.svn_pool_clear(self.scratch_pool)
|
||||
|
||||
def itemtype(self, path_parts):
|
||||
|
||||
def itemtype(self, path_parts, rev):
|
||||
rev = self._getrev(rev)
|
||||
basepath = self._getpath(path_parts)
|
||||
kind = fs.check_path(self.fsroot, basepath, self.scratch_pool)
|
||||
kind = fs.check_path(self._getroot(rev), basepath, self.scratch_pool)
|
||||
self._scratch_clear()
|
||||
if kind == core.svn_node_dir:
|
||||
return vclib.DIR
|
||||
|
@ -544,20 +549,23 @@ class SubversionRepository(vclib.Repository):
|
|||
return vclib.FILE
|
||||
raise vclib.ItemNotFound(path_parts)
|
||||
|
||||
def openfile(self, path_parts, rev=None):
|
||||
assert rev is None or int(rev) == self.rev
|
||||
def openfile(self, path_parts, rev):
|
||||
path = self._getpath(path_parts)
|
||||
revision = str(_get_last_history_rev(self, path, self.scratch_pool))
|
||||
rev = self._getrev(rev)
|
||||
fsroot = self._getroot(rev)
|
||||
revision = str(_get_last_history_rev(fsroot, path, self.scratch_pool))
|
||||
self._scratch_clear()
|
||||
fp = FileContentsPipe(self.fsroot, path, self.pool)
|
||||
fp = FileContentsPipe(fsroot, path, self.pool)
|
||||
return fp, revision
|
||||
|
||||
def listdir(self, path_parts, options):
|
||||
def listdir(self, path_parts, rev, options):
|
||||
basepath = self._getpath(path_parts)
|
||||
if self.itemtype(path_parts) != vclib.DIR:
|
||||
if self.itemtype(path_parts, rev) != vclib.DIR:
|
||||
raise vclib.Error("Path '%s' is not a directory." % basepath)
|
||||
|
||||
dirents = fs.dir_entries(self.fsroot, basepath, self.scratch_pool)
|
||||
rev = self._getrev(rev)
|
||||
fsroot = self._getroot(rev)
|
||||
dirents = fs.dir_entries(fsroot, basepath, self.scratch_pool)
|
||||
entries = [ ]
|
||||
for entry in dirents.values():
|
||||
if entry.kind == core.svn_node_dir:
|
||||
|
@ -568,19 +576,30 @@ class SubversionRepository(vclib.Repository):
|
|||
self._scratch_clear()
|
||||
return entries
|
||||
|
||||
def dirlogs(self, path_parts, entries, options):
|
||||
get_logs(self, self._getpath(path_parts), entries)
|
||||
def dirlogs(self, path_parts, rev, entries, options):
|
||||
get_logs(self, self._getpath(path_parts), self._getrev(rev), entries)
|
||||
|
||||
def itemlog(self, path_parts, rev, options):
|
||||
full_name = self._getpath(path_parts)
|
||||
"""see vclib.Repository.itemlog docstring
|
||||
|
||||
if rev is not None:
|
||||
try:
|
||||
rev = int(rev)
|
||||
except ValueError:
|
||||
vclib.InvalidRevision(rev)
|
||||
Option values recognized by this implementation
|
||||
|
||||
revs = _fetch_log(self, full_name, rev, options, self.scratch_pool)
|
||||
svn_show_all_dir_logs
|
||||
boolean, default false. if set for a directory path, will include
|
||||
revisions where files underneath the directory have changed
|
||||
|
||||
svn_cross_copies
|
||||
boolean, default false. if set for a path created by a copy, will
|
||||
include revisions from before the copy
|
||||
|
||||
svn_latest_log
|
||||
boolean, default false. if set will return only newest single log
|
||||
entry
|
||||
"""
|
||||
path = self._getpath(path_parts)
|
||||
rev = self._getrev(rev)
|
||||
|
||||
revs = _fetch_log(self, path, rev, options, self.scratch_pool)
|
||||
self._scratch_clear()
|
||||
|
||||
revs.sort()
|
||||
|
@ -591,11 +610,11 @@ class SubversionRepository(vclib.Repository):
|
|||
|
||||
return revs
|
||||
|
||||
def annotate(self, path_parts, rev=None):
|
||||
if not rev:
|
||||
rev = self.rev
|
||||
def annotate(self, path_parts, rev):
|
||||
path = self._getpath(path_parts)
|
||||
revision = str(_get_last_history_rev(self, path, self.scratch_pool))
|
||||
rev = self._getrev(rev)
|
||||
fsroot = self._getroot(rev)
|
||||
revision = str(_get_last_history_rev(fsroot, path, self.scratch_pool))
|
||||
|
||||
### Something's buggy in BlameSource, and the results are
|
||||
### catastrophic for users of Mozilla and Firefox (it seems that
|
||||
|
@ -615,13 +634,15 @@ class SubversionRepository(vclib.Repository):
|
|||
"""
|
||||
p1 = self._getpath(path_parts1)
|
||||
p2 = self._getpath(path_parts2)
|
||||
r1 = self._getrev(rev1)
|
||||
r2 = self._getrev(rev2)
|
||||
args = vclib._diff_args(type, options)
|
||||
|
||||
# Need to keep a reference to the FileDiff object around long
|
||||
# enough to use. It destroys its underlying temporary files when
|
||||
# the class is destroyed.
|
||||
diffobj = options['diffobj'] = \
|
||||
do_diff(self, p1, int(rev1), p2, int(rev2), args)
|
||||
do_diff(self, p1, r1, p2, r2, args)
|
||||
|
||||
try:
|
||||
return diffobj.get_pipe()
|
||||
|
@ -633,6 +654,23 @@ class SubversionRepository(vclib.Repository):
|
|||
def _getpath(self, path_parts):
|
||||
return string.join(path_parts, '/')
|
||||
|
||||
def _getrev(self, rev):
|
||||
if rev is None or rev == 'HEAD':
|
||||
return self.youngest
|
||||
try:
|
||||
rev = int(rev)
|
||||
except ValueError:
|
||||
raise vclib.InvalidRevision(rev)
|
||||
if (rev < 0) or (rev > self.youngest):
|
||||
raise vclib.InvalidRevision(rev)
|
||||
return rev
|
||||
|
||||
def _getroot(self, rev):
|
||||
try:
|
||||
return self._fsroots[rev]
|
||||
except KeyError:
|
||||
r = self._fsroots[rev] = fs.revision_root(self.fs_ptr, rev, self.pool)
|
||||
return r
|
||||
|
||||
class _item:
|
||||
def __init__(self, **kw):
|
||||
|
|
|
@ -25,7 +25,7 @@ import re
|
|||
import tempfile
|
||||
import popen2
|
||||
import time
|
||||
from vclib.svn import Revision, ChangedPath, _datestr_to_date, _compare_paths
|
||||
from vclib.svn import Revision, ChangedPath, _datestr_to_date, _compare_paths, _cleanup_path
|
||||
from svn import core, delta, client, wc, ra
|
||||
|
||||
|
||||
|
@ -35,15 +35,10 @@ if (core.SVN_VER_MAJOR, core.SVN_VER_MINOR, core.SVN_VER_PATCH) < (1, 3, 0):
|
|||
|
||||
|
||||
def _rev2optrev(rev):
|
||||
assert type(rev) is int
|
||||
rt = core.svn_opt_revision_t()
|
||||
if rev is not None:
|
||||
if str(rev) == 'HEAD':
|
||||
rt.kind = core.svn_opt_revision_head
|
||||
else:
|
||||
rt.kind = core.svn_opt_revision_number
|
||||
rt.value.number = rev
|
||||
else:
|
||||
rt.kind = core.svn_opt_revision_unspecified
|
||||
rt.kind = core.svn_opt_revision_number
|
||||
rt.value.number = rev
|
||||
return rt
|
||||
|
||||
|
||||
|
@ -53,21 +48,29 @@ def date_from_rev(svnrepos, rev):
|
|||
return _datestr_to_date(datestr, svnrepos.pool)
|
||||
|
||||
|
||||
def get_location(svnrepos, path, rev):
|
||||
def get_location(svnrepos, path, rev, old_rev):
|
||||
try:
|
||||
results = ra.get_locations(svnrepos.ra_session, path, svnrepos.rev,
|
||||
[int(rev)], svnrepos.pool)
|
||||
return results[int(rev)]
|
||||
except:
|
||||
raise vclib.ItemNotFound(filter(None, string.split(path, '/')))
|
||||
results = ra.get_locations(svnrepos.ra_session, path, rev,
|
||||
[old_rev], svnrepos.pool)
|
||||
except core.SubversionException, e:
|
||||
if e.apr_err == core.SVN_ERR_FS_NOT_FOUND:
|
||||
raise vclib.ItemNotFound(path)
|
||||
raise
|
||||
|
||||
try:
|
||||
old_path = results[old_rev]
|
||||
except KeyError:
|
||||
raise vclib.ItemNotFound(path)
|
||||
|
||||
return _cleanup_path(old_path)
|
||||
|
||||
|
||||
def created_rev(svnrepos, full_name):
|
||||
kind = ra.svn_ra_check_path(svnrepos.ra_session, full_name, svnrepos.rev,
|
||||
def created_rev(svnrepos, full_name, rev):
|
||||
kind = ra.svn_ra_check_path(svnrepos.ra_session, full_name, rev,
|
||||
svnrepos.pool)
|
||||
if kind == core.svn_node_dir:
|
||||
props = ra.svn_ra_get_dir(svnrepos.ra_session, full_name,
|
||||
svnrepos.rev, svnrepos.pool)
|
||||
rev, svnrepos.pool)
|
||||
return int(props[core.SVN_PROP_ENTRY_COMMITTED_REV])
|
||||
return core.SVN_INVALID_REVNUM
|
||||
|
||||
|
@ -122,9 +125,9 @@ def _get_rev_details(svnrepos, rev, pool):
|
|||
return lhc.get_history()
|
||||
|
||||
|
||||
def get_revision_info(svnrepos):
|
||||
def get_revision_info(svnrepos, rev):
|
||||
rev, author, date, log, changes = \
|
||||
_get_rev_details(svnrepos, svnrepos.rev, svnrepos.pool)
|
||||
_get_rev_details(svnrepos, rev, svnrepos.pool)
|
||||
return _datestr_to_date(date, svnrepos.pool), author, log, changes
|
||||
|
||||
|
||||
|
@ -166,9 +169,8 @@ class LogCollector:
|
|||
self.path = this_path
|
||||
|
||||
|
||||
def get_logs(svnrepos, full_name, files):
|
||||
parts = filter(None, string.split(full_name, '/'))
|
||||
dirents = svnrepos.get_dirents(parts, svnrepos.rev)
|
||||
def get_logs(svnrepos, full_name, rev, files):
|
||||
dirents = svnrepos._get_dirents(full_name, rev)
|
||||
subpool = core.svn_pool_create(svnrepos.pool)
|
||||
rev_info_cache = { }
|
||||
for file in files:
|
||||
|
@ -342,7 +344,7 @@ class SelfCleanFP:
|
|||
|
||||
|
||||
class SubversionRepository(vclib.Repository):
|
||||
def __init__(self, name, rootpath, rev=None):
|
||||
def __init__(self, name, rootpath):
|
||||
# Init the client app
|
||||
core.apr_initialize()
|
||||
pool = core.svn_pool_create(None)
|
||||
|
@ -370,22 +372,18 @@ class SubversionRepository(vclib.Repository):
|
|||
self.ra_session = ra.svn_ra_open(self.rootpath, ra_callbacks, None,
|
||||
ctx.config, pool)
|
||||
self.youngest = ra.svn_ra_get_latest_revnum(self.ra_session, pool)
|
||||
if rev is not None:
|
||||
self.rev = rev
|
||||
if self.rev > self.youngest:
|
||||
raise vclib.InvalidRevision(self.rev)
|
||||
else:
|
||||
self.rev = self.youngest
|
||||
self._dirent_cache = { }
|
||||
|
||||
def __del__(self):
|
||||
core.svn_pool_destroy(self.pool)
|
||||
core.apr_terminate()
|
||||
|
||||
def itemtype(self, path_parts):
|
||||
def itemtype(self, path_parts, rev):
|
||||
path = self._getpath(path_parts[:-1])
|
||||
rev = self._getrev(rev)
|
||||
if not len(path_parts):
|
||||
return vclib.DIR
|
||||
dirents = self.get_dirents(path_parts[:-1], self.rev)
|
||||
dirents = self._get_dirents(path, rev)
|
||||
try:
|
||||
entry = dirents[path_parts[-1]]
|
||||
if entry.kind == core.svn_node_dir:
|
||||
|
@ -395,11 +393,8 @@ class SubversionRepository(vclib.Repository):
|
|||
except KeyError:
|
||||
raise vclib.ItemNotFound(path_parts)
|
||||
|
||||
def openfile(self, path_parts, rev=None):
|
||||
if rev is None:
|
||||
rev = self.rev
|
||||
else:
|
||||
rev = int(rev)
|
||||
def openfile(self, path_parts, rev):
|
||||
rev = self._getrev(rev)
|
||||
url = self.rootpath
|
||||
if len(path_parts):
|
||||
url = self.rootpath + '/' + self._getpath(path_parts)
|
||||
|
@ -411,9 +406,11 @@ class SubversionRepository(vclib.Repository):
|
|||
core.svn_stream_close(stream)
|
||||
return SelfCleanFP(tmp_file), rev
|
||||
|
||||
def listdir(self, path_parts, options):
|
||||
def listdir(self, path_parts, rev, options):
|
||||
path = self._getpath(path_parts)
|
||||
rev = self._getrev(rev)
|
||||
entries = [ ]
|
||||
dirents = self.get_dirents(path_parts, self.rev)
|
||||
dirents = self._get_dirents(path, rev)
|
||||
for name in dirents.keys():
|
||||
entry = dirents[name]
|
||||
if entry.kind == core.svn_node_dir:
|
||||
|
@ -423,17 +420,12 @@ class SubversionRepository(vclib.Repository):
|
|||
entries.append(vclib.DirEntry(name, kind))
|
||||
return entries
|
||||
|
||||
def dirlogs(self, path_parts, entries, options):
|
||||
get_logs(self, self._getpath(path_parts), entries)
|
||||
def dirlogs(self, path_parts, rev, entries, options):
|
||||
get_logs(self, self._getpath(path_parts), self._getrev(rev), entries)
|
||||
|
||||
def itemlog(self, path_parts, rev, options):
|
||||
full_name = self._getpath(path_parts)
|
||||
|
||||
if rev is not None:
|
||||
try:
|
||||
rev = int(rev)
|
||||
except ValueError:
|
||||
vclib.InvalidRevision(rev)
|
||||
rev = self._getrev(rev)
|
||||
|
||||
# It's okay if we're told to not show all logs on a file -- all
|
||||
# the revisions should match correctly anyway.
|
||||
|
@ -443,7 +435,7 @@ class SubversionRepository(vclib.Repository):
|
|||
dir_url = dir_url + '/' + full_name
|
||||
|
||||
cross_copies = options.get('svn_cross_copies', 0)
|
||||
client.svn_client_log([dir_url], _rev2optrev(self.rev), _rev2optrev(1),
|
||||
client.svn_client_log([dir_url], _rev2optrev(rev), _rev2optrev(1),
|
||||
1, not cross_copies, lc.add_log,
|
||||
self.ctx, self.pool)
|
||||
revs = lc.logs
|
||||
|
@ -455,13 +447,10 @@ class SubversionRepository(vclib.Repository):
|
|||
|
||||
return revs
|
||||
|
||||
def annotate(self, path_parts, rev=None):
|
||||
def annotate(self, path_parts, rev):
|
||||
path = self._getpath(path_parts)
|
||||
rev = self._getrev(rev)
|
||||
url = self.rootpath + (path and '/' + path)
|
||||
if rev is None:
|
||||
rev = self.rev
|
||||
else:
|
||||
rev = int(rev)
|
||||
|
||||
blame_data = []
|
||||
|
||||
|
@ -487,13 +476,15 @@ class SubversionRepository(vclib.Repository):
|
|||
"""
|
||||
p1 = self._getpath(path_parts1)
|
||||
p2 = self._getpath(path_parts2)
|
||||
r1 = self._getrev(rev1)
|
||||
r2 = self._getrev(rev2)
|
||||
args = vclib._diff_args(type, options)
|
||||
|
||||
# Need to keep a reference to the FileDiff object around long
|
||||
# enough to use. It destroys its underlying temporary files when
|
||||
# the class is destroyed.
|
||||
diffobj = options['diffobj'] = \
|
||||
do_diff(self, p1, int(rev1), p2, int(rev2), args)
|
||||
do_diff(self, p1, r1, p2, r2, args)
|
||||
|
||||
try:
|
||||
return diffobj.get_pipe()
|
||||
|
@ -505,13 +496,22 @@ class SubversionRepository(vclib.Repository):
|
|||
def _getpath(self, path_parts):
|
||||
return string.join(path_parts, '/')
|
||||
|
||||
def get_dirents(self, path_parts, rev):
|
||||
if len(path_parts):
|
||||
path = self._getpath(path_parts)
|
||||
def _getrev(self, rev):
|
||||
if rev is None or rev == 'HEAD':
|
||||
return self.youngest
|
||||
try:
|
||||
rev = int(rev)
|
||||
except ValueError:
|
||||
raise vclib.InvalidRevision(rev)
|
||||
if (rev < 0) or (rev > self.youngest):
|
||||
raise vclib.InvalidRevision(rev)
|
||||
return rev
|
||||
|
||||
def _get_dirents(self, path, rev):
|
||||
if path:
|
||||
key = str(rev) + '/' + path
|
||||
dir_url = self.rootpath + '/' + path
|
||||
else:
|
||||
path = None
|
||||
key = str(rev)
|
||||
dir_url = self.rootpath
|
||||
dirents = self._dirent_cache.get(key)
|
||||
|
|
125
lib/viewcvs.py
125
lib/viewcvs.py
|
@ -248,25 +248,19 @@ class Request:
|
|||
elif cfg.general.svn_roots.has_key(self.rootname):
|
||||
self.rootpath = cfg.general.svn_roots[self.rootname]
|
||||
try:
|
||||
rev = None
|
||||
if self.query_dict.has_key('rev') \
|
||||
and self.query_dict['rev'] != 'HEAD':
|
||||
rev = int(self.query_dict['rev'])
|
||||
if re.match(_re_rewrite_url, self.rootpath):
|
||||
# If the rootpath is a URL, we'll use the svn_ra module, but
|
||||
# lie about its name.
|
||||
import vclib.svn_ra
|
||||
vclib.svn = vclib.svn_ra
|
||||
self.repos = vclib.svn.SubversionRepository(self.rootname,
|
||||
self.rootpath,
|
||||
rev)
|
||||
self.rootpath)
|
||||
else:
|
||||
self.rootpath = os.path.normpath(self.rootpath)
|
||||
import vclib.svn
|
||||
self.repos = vclib.svn.SubversionRepository(self.rootname,
|
||||
self.rootpath,
|
||||
cfg.general.svn_path,
|
||||
rev)
|
||||
cfg.general.svn_path)
|
||||
self.roottype = 'svn'
|
||||
except vclib.ReposNotFound:
|
||||
raise debug.ViewCVSException(
|
||||
|
@ -283,18 +277,20 @@ class Request:
|
|||
% self.rootname, "404 Repository not found")
|
||||
|
||||
# Make sure path exists
|
||||
self.pathtype = _repos_pathtype(self.repos, self.path_parts)
|
||||
rev = self.query_dict.get('rev')
|
||||
self.pathtype = _repos_pathtype(self.repos, self.path_parts, rev)
|
||||
|
||||
if self.pathtype is None:
|
||||
# path doesn't exist, try stripping known fake suffixes
|
||||
result = _strip_suffix('.diff', self.where, self.path_parts, \
|
||||
vclib.FILE, self.repos, view_diff) or \
|
||||
_strip_suffix('.tar.gz', self.where, self.path_parts, \
|
||||
vclib.DIR, self.repos, download_tarball) or \
|
||||
_strip_suffix('root.tar.gz', self.where, self.path_parts, \
|
||||
vclib.DIR, self.repos, download_tarball)
|
||||
result = _strip_suffix('.diff', path_parts, rev, vclib.FILE, \
|
||||
self.repos, view_diff) or \
|
||||
_strip_suffix('.tar.gz', path_parts, rev, vclib.DIR, \
|
||||
self.repos, download_tarball) or \
|
||||
_strip_suffix('root.tar.gz', path_parts, rev, vclib.DIR, \
|
||||
self.repos, download_tarball)
|
||||
if result:
|
||||
self.where, self.path_parts, self.pathtype, self.view_func = result
|
||||
self.path_parts, self.pathtype, self.view_func = result
|
||||
self.where = _path_join(path_parts)
|
||||
else:
|
||||
raise debug.ViewCVSException('%s: unknown location'
|
||||
% self.where, '404 Not Found')
|
||||
|
@ -647,30 +643,27 @@ _legal_params = {
|
|||
def _path_join(path_parts):
|
||||
return string.join(path_parts, '/')
|
||||
|
||||
def _strip_suffix(suffix, where, path_parts, pathtype, repos, view_func):
|
||||
def _strip_suffix(suffix, path_parts, rev, pathtype, repos, view_func):
|
||||
"""strip the suffix from a repository path if the resulting path
|
||||
is of the specified type, otherwise return None"""
|
||||
l = len(suffix)
|
||||
if where[-l:] == suffix:
|
||||
if path_parts[-1][-l:] == suffix:
|
||||
path_parts = path_parts[:]
|
||||
if len(path_parts[-1]) == l:
|
||||
del path_parts[-1]
|
||||
else:
|
||||
path_parts[-1] = path_parts[-1][:-l]
|
||||
t = _repos_pathtype(repos, path_parts)
|
||||
t = _repos_pathtype(repos, path_parts, rev)
|
||||
if pathtype == t:
|
||||
return where[:-l], path_parts, t, view_func
|
||||
return path_parts, t, view_func
|
||||
return None
|
||||
|
||||
def _repos_pathtype(repos, path_parts):
|
||||
"""return the type of a repository path, or None if the path
|
||||
does not exist"""
|
||||
type = None
|
||||
def _repos_pathtype(repos, path_parts, rev):
|
||||
"""return the type of a repository path, or None if the path doesn't exist"""
|
||||
try:
|
||||
type = repos.itemtype(path_parts)
|
||||
return repos.itemtype(path_parts, rev)
|
||||
except vclib.ItemNotFound:
|
||||
pass
|
||||
return type
|
||||
return None
|
||||
|
||||
def check_freshness(request, mtime=None, etag=None, weak=0):
|
||||
# See if we are supposed to disable etags (for debugging, usually)
|
||||
|
@ -757,8 +750,8 @@ def nav_path(request):
|
|||
|
||||
# set convenient "rev" and "is_dir" values
|
||||
rev = None
|
||||
if request.roottype == "svn" and request.query_dict.get('rev'):
|
||||
rev = request.repos.rev
|
||||
if request.roottype == 'svn':
|
||||
rev = request.query_dict.get('rev')
|
||||
is_dir = request.pathtype == vclib.DIR
|
||||
|
||||
# add root item
|
||||
|
@ -1301,7 +1294,7 @@ def view_markup(request):
|
|||
})
|
||||
|
||||
if cfg.options.show_log_in_markup:
|
||||
options = {}
|
||||
options = {'svn_latest_log': 1}
|
||||
revs = request.repos.itemlog(request.path_parts, revision, options)
|
||||
entry = revs[-1]
|
||||
|
||||
|
@ -1429,34 +1422,38 @@ def view_roots(request):
|
|||
generate_page(request, "roots", data)
|
||||
|
||||
def view_directory(request):
|
||||
if request.roottype == 'svn':
|
||||
rev = request.query_dict.get('rev')
|
||||
elif request.roottype == 'cvs':
|
||||
rev = view_tag = request.query_dict.get('only_with_tag')
|
||||
|
||||
# For Subversion repositories, the revision acts as a weak validator for
|
||||
# the directory listing (to take into account template changes or
|
||||
# revision property changes).
|
||||
if request.roottype == 'svn':
|
||||
revision = str(vclib.svn.created_rev(request.repos, request.where))
|
||||
revision = str(vclib.svn.created_rev(request.repos, request.where,
|
||||
request.repos._getrev(rev)))
|
||||
if check_freshness(request, None, revision, weak=1):
|
||||
return
|
||||
|
||||
# List current directory
|
||||
options = {}
|
||||
if request.roottype == 'cvs':
|
||||
view_tag = request.query_dict.get('only_with_tag')
|
||||
hideattic = int(request.query_dict.get('hideattic',
|
||||
cfg.options.hide_attic))
|
||||
options["cvs_subdirs"] = (cfg.options.show_subdir_lastmod and
|
||||
cfg.options.show_logs)
|
||||
options["cvs_dir_tag"] = view_tag
|
||||
|
||||
file_data = request.repos.listdir(request.path_parts, options)
|
||||
file_data = request.repos.listdir(request.path_parts, rev, options)
|
||||
|
||||
# Filter file list if a regex is specified
|
||||
search_re = request.query_dict.get('search', '')
|
||||
if cfg.options.use_re_search and search_re:
|
||||
file_data = search_files(request.repos, request.path_parts,
|
||||
file_data = search_files(request.repos, request.path_parts, rev,
|
||||
file_data, search_re)
|
||||
|
||||
# Retrieve log messages, authors, revision numbers, timestamps
|
||||
request.repos.dirlogs(request.path_parts, file_data, options)
|
||||
request.repos.dirlogs(request.path_parts, rev, file_data, options)
|
||||
|
||||
# sort with directories first, and using the "sortby" criteria
|
||||
sortby = request.query_dict.get('sortby', cfg.options.sort_by) or 'file'
|
||||
|
@ -1473,7 +1470,7 @@ def view_directory(request):
|
|||
where = request.where
|
||||
where_prefix = where and where + '/'
|
||||
if request.roottype == 'svn':
|
||||
dir_params = {'rev': request.query_dict.get('rev')}
|
||||
dir_params = {'rev': rev}
|
||||
else:
|
||||
dir_params = {}
|
||||
|
||||
|
@ -1653,10 +1650,7 @@ def view_directory(request):
|
|||
data['youngest_rev_href'] = request.get_url(view_func=view_revision,
|
||||
params={},
|
||||
escape=1)
|
||||
if request.query_dict.has_key('rev'):
|
||||
data['rev'] = request.query_dict['rev']
|
||||
else:
|
||||
data['rev'] = str(request.repos.rev)
|
||||
data['rev'] = str(request.repos._getrev(rev))
|
||||
url, params = request.get_link(params={'rev': None})
|
||||
data['jump_rev_action'] = urllib.quote(url, _URL_SAFE_CHARS)
|
||||
data['jump_rev_hidden_values'] = prepare_hidden_values(params)
|
||||
|
@ -1664,8 +1658,8 @@ def view_directory(request):
|
|||
|
||||
if is_query_supported(request):
|
||||
params = {}
|
||||
if options.has_key('cvs_dir_tag'):
|
||||
params['branch'] = options['cvs_dir_tag']
|
||||
if request.roottype == 'cvs' and view_tag:
|
||||
params['branch'] = view_tag
|
||||
data['queryform_href'] = request.get_url(view_func=view_queryform,
|
||||
params=params,
|
||||
escape=1)
|
||||
|
@ -1749,7 +1743,7 @@ def view_log(request):
|
|||
if request.roottype == 'cvs':
|
||||
rev = view_tag
|
||||
else:
|
||||
rev = None
|
||||
rev = request.query_dict.get('rev')
|
||||
|
||||
show_revs = request.repos.itemlog(request.path_parts, rev, options)
|
||||
if logsort == 'date':
|
||||
|
@ -1906,7 +1900,7 @@ def view_log(request):
|
|||
'r2': entry.rev,
|
||||
'diff_format': None},
|
||||
escape=1)
|
||||
# moves aren't handled here but they are only supported by CVS right now.
|
||||
|
||||
if entry.next_main:
|
||||
entry.diff_to_main_href = \
|
||||
request.get_url(view_func=view_diff,
|
||||
|
@ -2144,7 +2138,7 @@ def view_cvsgraph(request):
|
|||
request.server.header()
|
||||
generate_page(request, "graph", data)
|
||||
|
||||
def search_files(repos, path_parts, files, search_re):
|
||||
def search_files(repos, path_parts, rev, files, search_re):
|
||||
""" Search files in a directory for a regular expression.
|
||||
|
||||
Does a check-out of each file in the directory. Only checks for
|
||||
|
@ -2179,9 +2173,8 @@ def search_files(repos, path_parts, files, search_re):
|
|||
|
||||
# Only text files at this point
|
||||
|
||||
# process_checkout will checkout the head version out of the repository
|
||||
# Assign contents of checked out file to fp.
|
||||
fp = repos.openfile(path_parts + [file.name])[0]
|
||||
fp = repos.openfile(path_parts + [file.name], rev)[0]
|
||||
|
||||
# Read in each line, use re.search to search line.
|
||||
# If successful, add file to new_file_list and break.
|
||||
|
@ -2459,13 +2452,15 @@ def diff_parse_headers(fp, diff_type, rev1, rev2, sym1=None, sym2=None):
|
|||
return date1, date2, flag, string.join(header_lines, '')
|
||||
|
||||
|
||||
def _get_diff_path_parts(request, query_key, rev):
|
||||
def _get_diff_path_parts(request, query_key, rev, base_rev):
|
||||
if request.query_dict.has_key(query_key):
|
||||
parts = _path_parts(request.query_dict[query_key])
|
||||
elif request.roottype == 'svn':
|
||||
try:
|
||||
parts = _path_parts(vclib.svn.get_location(request.repos,
|
||||
request.where, rev))
|
||||
repos = request.repos
|
||||
parts = _path_parts(vclib.svn.get_location(repos, request.where,
|
||||
repos._getrev(base_rev),
|
||||
repos._getrev(rev)))
|
||||
except vclib.InvalidRevision:
|
||||
raise debug.ViewCVSException('Invalid path(s) or revision(s) passed '
|
||||
'to diff', '400 Bad Request')
|
||||
|
@ -2482,6 +2477,7 @@ def setup_diff(request):
|
|||
|
||||
rev1 = r1 = query_dict['r1']
|
||||
rev2 = r2 = query_dict['r2']
|
||||
base_rev = query_dict.get('rev')
|
||||
sym1 = sym2 = None
|
||||
|
||||
# hack on the diff revisions
|
||||
|
@ -2512,8 +2508,8 @@ def setup_diff(request):
|
|||
rev2 = r2[:idx]
|
||||
sym2 = r2[idx+1:]
|
||||
|
||||
p1 = _get_diff_path_parts(request, 'p1', rev1)
|
||||
p2 = _get_diff_path_parts(request, 'p2', rev2)
|
||||
p1 = _get_diff_path_parts(request, 'p1', rev1, base_rev)
|
||||
p2 = _get_diff_path_parts(request, 'p2', rev2, base_rev)
|
||||
|
||||
try:
|
||||
if revcmp(rev1, rev2) > 0:
|
||||
|
@ -2523,7 +2519,6 @@ def setup_diff(request):
|
|||
except ValueError:
|
||||
raise debug.ViewCVSException('Invalid revision(s) passed to diff',
|
||||
'400 Bad Request')
|
||||
|
||||
return p1, p2, rev1, rev2, sym1, sym2
|
||||
|
||||
|
||||
|
@ -2693,11 +2688,11 @@ def generate_tarball_header(out, name, size=0, mode=None, mtime=0,
|
|||
|
||||
out.write(block)
|
||||
|
||||
def generate_tarball(out, request, options, reldir, stack):
|
||||
def generate_tarball(out, request, rev, reldir, stack):
|
||||
# get directory info from repository
|
||||
rep_path = request.path_parts + reldir
|
||||
entries = request.repos.listdir(rep_path, options)
|
||||
request.repos.dirlogs(rep_path, entries, options)
|
||||
entries = request.repos.listdir(rep_path, rev, {})
|
||||
request.repos.dirlogs(rep_path, rev, entries, {})
|
||||
entries.sort(lambda a, b: cmp(a.name, b.name))
|
||||
|
||||
# figure out corresponding path in tar file. everything gets put underneath
|
||||
|
@ -2764,7 +2759,7 @@ def generate_tarball(out, request, options, reldir, stack):
|
|||
or (cvs and cfg.options.hide_cvsroot and file.name == 'CVSROOT')):
|
||||
continue
|
||||
|
||||
generate_tarball(out, request, options, reldir + [file.name], stack)
|
||||
generate_tarball(out, request, rev, reldir + [file.name], stack)
|
||||
|
||||
# pop directory (if it's being pruned. otherwise stack is already empty)
|
||||
del stack[-1:]
|
||||
|
@ -2774,10 +2769,10 @@ def download_tarball(request):
|
|||
raise debug.ViewCVSException('Tarball generation is disabled',
|
||||
'403 Forbidden')
|
||||
|
||||
options = {}
|
||||
if request.roottype == 'cvs':
|
||||
tag = request.query_dict.get('only_with_tag')
|
||||
options['cvs_dir_tag'] = tag
|
||||
if request.roottype == 'svn':
|
||||
rev = request.query_dict.get('rev')
|
||||
elif request.roottype == 'cvs':
|
||||
rev = request.query_dict.get('only_with_tag')
|
||||
|
||||
### look for GZIP binary
|
||||
|
||||
|
@ -2785,7 +2780,7 @@ def download_tarball(request):
|
|||
sys.stdout.flush()
|
||||
fp = popen.pipe_cmds([('gzip', '-c', '-n')])
|
||||
|
||||
generate_tarball(fp, request, options, [], [])
|
||||
generate_tarball(fp, request, rev, [], [])
|
||||
|
||||
fp.write('\0' * 1024)
|
||||
fp.close()
|
||||
|
@ -2797,9 +2792,9 @@ def view_revision(request):
|
|||
|
||||
data = common_template_data(request)
|
||||
query_dict = request.query_dict
|
||||
date, author, msg, changes = vclib.svn.get_revision_info(request.repos)
|
||||
rev = request.repos._getrev(query_dict.get('rev'))
|
||||
date, author, msg, changes = vclib.svn.get_revision_info(request.repos, rev)
|
||||
date_str = make_time_string(date)
|
||||
rev = request.repos.rev
|
||||
|
||||
# The revision number acts as a weak validator.
|
||||
if check_freshness(request, None, str(rev), weak=1):
|
||||
|
|
|
@ -71,7 +71,7 @@ def UpdateFile(db, repository, path, update):
|
|||
|
||||
|
||||
def RecurseUpdate(db, repository, directory, update):
|
||||
for entry in repository.listdir(directory, {}):
|
||||
for entry in repository.listdir(directory, None, {}):
|
||||
path = directory + [entry.name]
|
||||
|
||||
if entry.errors:
|
||||
|
|
Loading…
Reference in New Issue