Handle CVS Attic paths transparently in the bincvs module
instead of exposing them to users. * templates/include/dir_footer.ezt add link to show dead files * templates/directory.ezt remove code for detecting Attic entries, change (in the attic) caption to (dead) * lib/viewcvs.py (Request.run_viewcvs): handle old Attic URL's by redirecting, remove unused request.full_name member (get_up_path, _re_up_attic_path, nav_header_data, generate_tarball, download_tarball): remove code for handling Attic directories (view_markup): remove unused "full_name" variable (view_directory): remove code for handling Attic directories, replace "no_match" template variable with "num_dead" (view_log): update call to get_up_path (view_annotate, view_cvsgraph_image, view_cvsgraph, view_diff): use CVSRepository.rcsfile to get path to rcs file * lib/vclib/bincvs/__init__.py (CVSRepository.itemtype): look in Attic for repository files (CVSRepository.listdir): remove "cvs_list_attic" option, now always list attic files. leave "Attic" and "CVS" directories out of returned listing. (CVSRepository.rcsfile, CVSRepository._atticpath): new methods (BinCVSRepository.openfile, BinCVSRepository.filelog): use CVSRepository.rcsfile to get path to rcs file (_get_logs): don't mark directories as dead * lib/vclib/ccvs/__init__.py (CCVSRepository.filelog, CCVSRepository.openfile): use CVSRepository.rcsfile to get path to rcs file * website/upgrading.html document "no_match" and "num_dead" template variables git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@908 8cb11bc2-c004-0410-86c3-e597b4017df7remotes/tags/1.0.0-rc1
parent
98b799adbf
commit
f3ca45b9a0
|
@ -44,19 +44,12 @@ class CVSRepository(vclib.Repository):
|
|||
return vclib.DIR
|
||||
if os.path.isfile(basepath + ',v'):
|
||||
return vclib.FILE
|
||||
atticpath = self._getpath(self._atticpath(path_parts))
|
||||
if os.path.isfile(atticpath + ',v'):
|
||||
return vclib.FILE
|
||||
raise vclib.ItemNotFound(path_parts)
|
||||
|
||||
def listdir(self, path_parts, options):
|
||||
"""see vclib.Repository.listdir docstring
|
||||
|
||||
Option values recognized by this implementation:
|
||||
|
||||
cvs_list_attic
|
||||
boolean, if true listing will include entries from the Attic
|
||||
subdirectory
|
||||
"""
|
||||
list_attic = options.get("cvs_list_attic", 1)
|
||||
|
||||
# Only RCS files (*,v) and subdirs are returned.
|
||||
data = [ ]
|
||||
|
||||
|
@ -66,22 +59,45 @@ class CVSRepository(vclib.Repository):
|
|||
if kind == vclib.FILE:
|
||||
if file[-2:] == ',v':
|
||||
data.append(CVSDirEntry(file[:-2], kind, verboten, 0))
|
||||
else:
|
||||
elif file != 'Attic' and file != 'CVS': # CVS directory is for fileattr
|
||||
data.append(CVSDirEntry(file, kind, verboten, 0))
|
||||
|
||||
if list_attic:
|
||||
full_name = os.path.join(full_name, 'Attic')
|
||||
if os.path.isdir(full_name):
|
||||
for file in os.listdir(full_name):
|
||||
kind, verboten = _check_path(os.path.join(full_name, file))
|
||||
if kind == vclib.FILE and file[-2:] == ',v':
|
||||
data.append(CVSDirEntry(file[:-2], kind, verboten, 1))
|
||||
full_name = os.path.join(full_name, 'Attic')
|
||||
if os.path.isdir(full_name):
|
||||
for file in os.listdir(full_name):
|
||||
kind, verboten = _check_path(os.path.join(full_name, file))
|
||||
if kind == vclib.FILE and file[-2:] == ',v':
|
||||
data.append(CVSDirEntry(file[:-2], kind, verboten, 1))
|
||||
|
||||
return data
|
||||
|
||||
def _getpath(self, path_parts):
|
||||
return apply(os.path.join, (self.rootpath,) + tuple(path_parts))
|
||||
|
||||
def _atticpath(self, path_parts):
|
||||
return path_parts[:-1] + ['Attic'] + path_parts[-1:]
|
||||
|
||||
def rcsfile(self, path_parts, root=0, v=1):
|
||||
"Return path to RCS file"
|
||||
|
||||
ret_parts = path_parts
|
||||
ret_file = self._getpath(ret_parts)
|
||||
if not os.path.isfile(ret_file + ',v'):
|
||||
ret_parts = self._atticpath(path_parts)
|
||||
ret_file = self._getpath(ret_parts)
|
||||
if not os.path.isfile(ret_file + ',v'):
|
||||
raise vclib.ItemNotFound(path_parts)
|
||||
|
||||
if root:
|
||||
ret = ret_file
|
||||
else:
|
||||
ret = string.join(ret_parts, "/")
|
||||
|
||||
if v:
|
||||
ret = ret + ",v"
|
||||
|
||||
return ret
|
||||
|
||||
class BinCVSRepository(CVSRepository):
|
||||
def __init__(self, name, rootpath, rcs_paths):
|
||||
CVSRepository.__init__(self, name, rootpath)
|
||||
|
@ -93,7 +109,7 @@ class BinCVSRepository(CVSRepository):
|
|||
else:
|
||||
rev_flag = '-p' + rev
|
||||
|
||||
full_name = self._getpath(path_parts)
|
||||
full_name = self.rcsfile(path_parts, root=1, v=0)
|
||||
|
||||
fp = self.rcs_popen('co', (rev_flag, full_name), 'rb')
|
||||
|
||||
|
@ -103,7 +119,7 @@ class BinCVSRepository(CVSRepository):
|
|||
# Bug at http://www.cvsnt.org/cgi-bin/bugzilla/show_bug.cgi?id=190
|
||||
# As a workaround, we invoke rlog to find the first non-dead revision
|
||||
# that precedes it and check out that revision instead
|
||||
args = self._getpath(path_parts) + ',v',
|
||||
args = full_name + ',v',
|
||||
fp = self.rcs_popen('rlog', args, 'rt', 0)
|
||||
filename, default_branch, tags, msg, eof = _parse_log_header(fp)
|
||||
|
||||
|
@ -179,7 +195,7 @@ class BinCVSRepository(CVSRepository):
|
|||
"""
|
||||
|
||||
# Invoke rlog
|
||||
args = self._getpath(path_parts) + ',v',
|
||||
args = self.rcsfile(path_parts, 1),
|
||||
fp = self.rcs_popen('rlog', args, 'rt', 0)
|
||||
filename, default_branch, tags, msg, eof = _parse_log_header(fp)
|
||||
|
||||
|
@ -871,7 +887,7 @@ def _get_logs(repos, dirpath, entries, view_tag, get_dirs):
|
|||
file.rev = wanted_entry.string
|
||||
file.date = wanted_entry.date
|
||||
file.author = wanted_entry.author
|
||||
file.dead = wanted_entry.dead
|
||||
file.dead = file.kind == vclib.FILE and wanted_entry.dead
|
||||
file.log = wanted_entry.log
|
||||
# suppress rlog errors if we find a usable revision in the end
|
||||
del file.log_errors[:]
|
||||
|
|
|
@ -92,7 +92,7 @@ class CCVSRepository(CVSRepository):
|
|||
cvs_tags
|
||||
dictionary of Tag objects for all tags encountered
|
||||
"""
|
||||
path = self._getpath(path_parts) + ',v'
|
||||
path = self.rcsfile(path_parts, 1)
|
||||
sink = TreeSink()
|
||||
rcsparse.Parser().parse(open(path, 'rb'), sink)
|
||||
filtered_revs = _file_log(sink.revs.values(), sink.tags,
|
||||
|
@ -105,7 +105,7 @@ class CCVSRepository(CVSRepository):
|
|||
return filtered_revs
|
||||
|
||||
def openfile(self, path_parts, rev=None):
|
||||
path = self._getpath(path_parts) + ',v'
|
||||
path = self.rcsfile(path_parts, 1)
|
||||
sink = COSink(rev)
|
||||
rcsparse.Parser().parse(open(path, 'rb'), sink)
|
||||
revision = sink.last and sink.last.string
|
||||
|
|
|
@ -280,17 +280,18 @@ class Request:
|
|||
# Make sure path exists
|
||||
self.pathtype = _repos_pathtype(self.repos, self.path_parts)
|
||||
|
||||
# If the path doesn't exist, but we have CVS repository, and the
|
||||
# path doesn't already include an 'Attic' component, see if maybe
|
||||
# the thing lives in the Attic.
|
||||
if self.pathtype is None \
|
||||
and self.roottype == 'cvs' \
|
||||
and len(self.path_parts) > 1 \
|
||||
and not self.path_parts[-2] == 'Attic':
|
||||
attic_parts = self.path_parts[0:-1] + ['Attic'] + [self.path_parts[-1]]
|
||||
if _repos_pathtype(self.repos, attic_parts) == vclib.FILE:
|
||||
# If we have an old ViewCVS Attic URL which is still valid, then redirect
|
||||
if self.roottype == 'cvs':
|
||||
attic_parts = None
|
||||
if (self.pathtype == vclib.FILE and len(self.path_parts) > 1
|
||||
and self.path_parts[-2] == 'Attic'):
|
||||
attic_parts = self.path_parts[:-2] + self.path_parts[-1:]
|
||||
elif (self.pathtype == vclib.DIR and len(self.path_parts) > 0
|
||||
and self.path_parts[-1] == 'Attic'):
|
||||
attic_parts = self.path_parts[:-1]
|
||||
if attic_parts:
|
||||
self.server.redirect(self.get_url(where=string.join(attic_parts, '/'),
|
||||
pathtype=vclib.FILE))
|
||||
pathtype=self.pathtype))
|
||||
|
||||
if self.pathtype is None:
|
||||
# path doesn't exist, try stripping known fake suffixes
|
||||
|
@ -340,7 +341,6 @@ class Request:
|
|||
|
||||
# Finally done parsing query string, set some extra variables
|
||||
# and call view_func
|
||||
self.full_name = self.rootpath + (self.where and '/' + self.where)
|
||||
if self.pathtype == vclib.FILE:
|
||||
self.setup_mime_type_info()
|
||||
|
||||
|
@ -582,12 +582,8 @@ _legal_params = {
|
|||
|
||||
# regex used to move from a file to a directory
|
||||
_re_up_path = re.compile('(^|/)[^/]+$')
|
||||
_re_up_attic_path = re.compile('(^|/)(Attic/)?[^/]+$')
|
||||
def get_up_path(request, path, hideattic=0):
|
||||
if request.roottype == 'svn' or hideattic:
|
||||
return re.sub(_re_up_path, '', path)
|
||||
else:
|
||||
return re.sub(_re_up_attic_path, '', path)
|
||||
def get_up_path(path):
|
||||
return re.sub(_re_up_path, '', path)
|
||||
|
||||
def _strip_suffix(suffix, where, path_parts, pathtype, repos, view_func):
|
||||
"""strip the suffix from a repository path if the resulting path
|
||||
|
@ -830,8 +826,6 @@ def common_template_data(request):
|
|||
|
||||
def nav_header_data(request, rev):
|
||||
path, filename = os.path.split(request.where)
|
||||
if request.roottype == 'cvs' and path[-6:] == '/Attic':
|
||||
path = path[:-6]
|
||||
|
||||
data = common_template_data(request)
|
||||
data.update({
|
||||
|
@ -1162,7 +1156,6 @@ def view_auto(request):
|
|||
view_checkout(request)
|
||||
|
||||
def view_markup(request):
|
||||
full_name = request.full_name
|
||||
where = request.where
|
||||
query_dict = request.query_dict
|
||||
rev = request.query_dict.get('rev')
|
||||
|
@ -1333,7 +1326,6 @@ def view_directory(request):
|
|||
view_tag = request.query_dict.get('only_with_tag')
|
||||
hideattic = int(request.query_dict.get('hideattic',
|
||||
cfg.options.hide_attic))
|
||||
options["cvs_list_attic"] = not hideattic or view_tag
|
||||
options["cvs_subdirs"] = (cfg.options.show_subdir_lastmod and
|
||||
cfg.options.show_logs)
|
||||
options["cvs_dir_tag"] = view_tag
|
||||
|
@ -1393,11 +1385,8 @@ def view_directory(request):
|
|||
continue
|
||||
|
||||
if file.kind == vclib.DIR:
|
||||
if (request.roottype == 'cvs' and
|
||||
((file.name == 'CVS') or # CVS directory is for fileattr
|
||||
(not hideattic and file.name == 'Attic') or
|
||||
(where == '' and (file.name == 'CVSROOT' and
|
||||
cfg.options.hide_cvsroot)))):
|
||||
if (request.roottype == 'cvs' and cfg.options.hide_cvsroot
|
||||
and where == '' and file.name == 'CVSROOT'):
|
||||
continue
|
||||
|
||||
row.href = request.get_url(view_func=view_directory,
|
||||
|
@ -1423,12 +1412,9 @@ def view_directory(request):
|
|||
continue
|
||||
num_displayed = num_displayed + 1
|
||||
|
||||
if request.roottype == 'cvs':
|
||||
file_where = where_prefix + (file.in_attic and 'Attic/' or '') \
|
||||
+ file.name
|
||||
else:
|
||||
file_where = where_prefix + file.name
|
||||
if request.roottype == 'svn':
|
||||
row.size = file.size
|
||||
file_where = where_prefix + file.name
|
||||
|
||||
### for Subversion, we should first try to get this from the properties
|
||||
mime_type, encoding = mimetypes.guess_type(file.name)
|
||||
|
@ -1475,7 +1461,7 @@ def view_directory(request):
|
|||
'sortdir': None}),
|
||||
'num_files' : num_files,
|
||||
'files_shown' : num_displayed,
|
||||
'no_match' : ezt.boolean(num_files and not num_displayed),
|
||||
'num_dead' : num_files - num_displayed,
|
||||
|
||||
### in the future, it might be nice to break this path up into
|
||||
### a list of elements, allowing the template to display it in
|
||||
|
@ -1607,7 +1593,6 @@ def view_log(request):
|
|||
diff_format = request.query_dict.get('diff_format', cfg.options.diff_format)
|
||||
logsort = request.query_dict.get('logsort', cfg.options.log_sort)
|
||||
view_tag = request.query_dict.get('only_with_tag')
|
||||
hide_attic = int(request.query_dict.get('hideattic',cfg.options.hide_attic))
|
||||
pathtype = request.pathtype
|
||||
|
||||
mime_type = None
|
||||
|
@ -1622,7 +1607,7 @@ def view_log(request):
|
|||
options['svn_cross_copies'] = cfg.options.cross_copies
|
||||
|
||||
if request.roottype == 'cvs':
|
||||
up_where = get_up_path(request, request.where, hide_attic)
|
||||
up_where = get_up_path(request.where)
|
||||
filename = os.path.basename(request.where)
|
||||
rev = view_tag
|
||||
else:
|
||||
|
@ -1920,8 +1905,9 @@ def view_annotate(request):
|
|||
|
||||
### be nice to hook this into the template...
|
||||
import blame
|
||||
rcsfile = request.repos.rcsfile(request.path_parts)
|
||||
data['lines'] = blame.BlameSource(request.repos.rootpath,
|
||||
request.where + ',v', rev,
|
||||
rcsfile, rev,
|
||||
compat.urlencode(request.get_options()))
|
||||
|
||||
request.server.header()
|
||||
|
@ -1935,11 +1921,12 @@ def view_cvsgraph_image(request):
|
|||
raise "cvsgraph no allows"
|
||||
|
||||
request.server.header('image/png')
|
||||
rcsfile = request.repos.rcsfile(request.path_parts)
|
||||
fp = popen.popen(os.path.normpath(os.path.join(cfg.options.cvsgraph_path,
|
||||
'cvsgraph')),
|
||||
("-c", cfg.options.cvsgraph_conf,
|
||||
"-r", request.repos.rootpath,
|
||||
request.where + ',v'), 'rb', 0)
|
||||
rcsfile), 'rb', 0)
|
||||
copy_stream(fp)
|
||||
fp.close()
|
||||
|
||||
|
@ -1950,12 +1937,6 @@ def view_cvsgraph(request):
|
|||
if not cfg.options.use_cvsgraph:
|
||||
raise "cvsgraph no allows"
|
||||
|
||||
where = request.where
|
||||
|
||||
pathname, filename = os.path.split(where)
|
||||
if pathname[-6:] == '/Attic':
|
||||
pathname = pathname[:-6]
|
||||
|
||||
data = nav_header_data(request, None)
|
||||
|
||||
# Required only if cvsgraph needs to find it's supporting libraries.
|
||||
|
@ -1969,13 +1950,14 @@ def view_cvsgraph(request):
|
|||
imagesrc = request.get_url(view_func=view_cvsgraph_image)
|
||||
|
||||
# Create an image map
|
||||
rcsfile = request.repos.rcsfile(request.path_parts)
|
||||
fp = popen.popen(os.path.join(cfg.options.cvsgraph_path, 'cvsgraph'),
|
||||
("-i",
|
||||
"-c", cfg.options.cvsgraph_conf,
|
||||
"-r", request.repos.rootpath,
|
||||
"-6", amp_query,
|
||||
"-7", qmark_query,
|
||||
request.where + ',v'), 'rb', 0)
|
||||
rcsfile), 'rb', 0)
|
||||
|
||||
data.update({
|
||||
'imagemap' : fp,
|
||||
|
@ -2447,7 +2429,8 @@ def view_diff(request):
|
|||
file1 = None
|
||||
file2 = None
|
||||
if request.roottype == 'cvs':
|
||||
args[len(args):] = ['-r' + rev1, '-r' + rev2, request.full_name]
|
||||
rcsfile = request.repos.rcsfile(request.path_parts, 1)
|
||||
args[len(args):] = ['-r' + rev1, '-r' + rev2, rcsfile]
|
||||
fp = request.repos.rcs_popen('rcsdiff', args, 'rt')
|
||||
else:
|
||||
try:
|
||||
|
@ -2644,9 +2627,8 @@ def generate_tarball(out, request, tar_top, rep_top,
|
|||
|
||||
subdirs.sort()
|
||||
for subdir in subdirs:
|
||||
if not cvs or subdir != 'Attic':
|
||||
generate_tarball(out, request, tar_top, rep_top,
|
||||
reldir + [subdir], options, stack)
|
||||
generate_tarball(out, request, tar_top, rep_top,
|
||||
reldir + [subdir], options, stack)
|
||||
|
||||
if len(stack):
|
||||
del stack[-1:]
|
||||
|
@ -2667,7 +2649,6 @@ def download_tarball(request):
|
|||
options = {}
|
||||
if request.roottype == 'cvs':
|
||||
tag = request.query_dict.get('only_with_tag')
|
||||
options['cvs_list_attic'] = tag and 1 or 0
|
||||
options['cvs_dir_tag'] = tag
|
||||
|
||||
### look for GZIP binary
|
||||
|
|
|
@ -56,15 +56,9 @@
|
|||
<img src="[icons]/small/[is rows.type "dir"]dir[else]text[end].gif" alt="" border=0 width=16 height=16>
|
||||
[rows.name][is rows.type "dir"]/[end]</a>
|
||||
[is roottype "cvs"]
|
||||
[is rows.type "dir"]
|
||||
[is rows.name "Attic"]
|
||||
<a href="[show_attic_href]#dirlist">[[]show contents]</a>
|
||||
[end]
|
||||
[else]
|
||||
[is rows.state "dead"]
|
||||
[# don't let this phrase/link be wrapped ]
|
||||
[if-any view_tag](not exist)[else](in the Attic)[end][if-any attic_showing] <a href="[hide_attic_href]#dirlist">[[]hide][end]</a>
|
||||
[end]
|
||||
[is rows.state "dead"]
|
||||
[# don't let this phrase/link be wrapped ]
|
||||
(dead) <a href="[hide_attic_href]#dirlist">[[]hide]</a>
|
||||
[end]
|
||||
[end]
|
||||
</td>
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
[if-any no_match]
|
||||
<p><b>NOTE:</b> There are [num_files] files, but none match the
|
||||
current selection criteria. Click <a href="[show_attic_href]#dirlist">here</a>
|
||||
to display dead files[if-any view_tag], or <a href="[main_href]#dirlist">here</a>
|
||||
[is num_dead "0"]
|
||||
[else]
|
||||
<p><b>NOTE:</b> There are [num_dead] dead files not displayed in this
|
||||
listing, click <a href="[show_attic_href]#dirlist">here</a> to display
|
||||
them[if-any view_tag], or <a href="[main_href]#dirlist">here</a>
|
||||
to view files on the default branch[end].
|
||||
[end]
|
||||
|
||||
|
|
|
@ -123,6 +123,15 @@
|
|||
Replaced by <var>rows.errors</var>
|
||||
</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>
|
||||
<code>directory.ezt</code> and <code>dir_alternate.ezt</code>:
|
||||
<var>no_match</var>
|
||||
</dt>
|
||||
<dd>
|
||||
Replaced by <var>num_dead</var>
|
||||
</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>
|
||||
<code>directory.ezt</code> and <code>dir_alternate.ezt</code>:
|
||||
|
@ -250,6 +259,13 @@
|
|||
</dt>
|
||||
<dd>List of error messages pertaining to an entry.</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>
|
||||
<code>directory.ezt</code> and <code>dir_alternate.ezt</code>:
|
||||
<var>num_dead</var>
|
||||
</dt>
|
||||
<dd>Number of dead files.</dd>
|
||||
</dl>
|
||||
<dl>
|
||||
<dt>
|
||||
<code>diff.ezt</code>:
|
||||
|
|
Loading…
Reference in New Issue