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-e597b4017df7
remotes/tags/1.0.0-rc1
rey4 2004-07-31 22:34:51 +00:00
parent 98b799adbf
commit f3ca45b9a0
6 changed files with 93 additions and 85 deletions

View File

@ -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[:]

View File

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

View File

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

View File

@ -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"]
&nbsp; <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&nbsp;exist)[else](in&nbsp;the&nbsp;Attic)[end][if-any attic_showing]&nbsp;<a href="[hide_attic_href]#dirlist">[[]hide][end]</a>
[end]
[is rows.state "dead"]
[# don't let this phrase/link be wrapped ]
(dead)&nbsp;<a href="[hide_attic_href]#dirlist">[[]hide]</a>
[end]
[end]
</td>

View File

@ -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]

View File

@ -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>: