Re: [viewvc-dev] Various patches for ViewVC
Виталий Филиппов <[email protected]> Thu, 21 May 2009 18:00:46 +0400
| Newsgroups | gmane.comp.version-control.cvs.viewcvs.devel |
|---|---|
| Organization | CustIS |
| Message-ID | <[email protected]> |
> Decoding to ... Unicode? Yeah > Don't you have to read a block of file data to feed to libmagic? Yes > Do you do this for every directory listing and other codepath that wants to > populate the "mimetype" entry property? No, only in annotate and checkout views > I know it's a pain to keep these changes separable, but if you look at It's a... kind of very big pain :) I've now tried to separate some of them, see the attaches. But as the result, I think, they won't apply on a "trunk" ViewVC copy... Also I think these patches are stupid rather than smart... but they work. And when separated... They need much more debug. :) I don't insist on accepting the "fat patch", I agree with your opinion. I'm just informing about "it". :) -- With best regards, Vitaliy Filippov ------------------------------------------------------ http://viewvc.tigris.org/ds/viewMessage.do?dsForumId=4251&dsMessageId=2349779 To unsubscribe from this discussion, e-mail: [[email protected]].
libmagic-mime-type-guessing.diff
(application/octet-stream, 12.3 KB)
Index: viewvc.org/trunk/lib/viewvc.py
===================================================================
--- viewvc.org/trunk/lib/viewvc.py 2008/12/09 18:44:05 54
+++ viewvc.org/trunk/lib/viewvc.py 2008/12/10 13:21:37 58
@@ -67,6 +67,8 @@
viewcvs_mime_type = 'text/vnd.viewcvs-markup'
alt_mime_type = 'text/x-cvsweb-markup'
view_roots_magic = '*viewroots*'
+magic_buf_size = 4096
+default_mime_type = 'application/octet-stream'
# Put here the variables we need in order to hold our state - they
# will be added (with their current value) to (almost) any link/query
@@ -100,6 +102,7 @@
def __init__(self, server, cfg):
self.server = server
self.cfg = cfg
+ self.cfg.options.binary_mime_re = re.compile(self.cfg.options.binary_mime_re)
self.script_name = _normalize_path(server.getenv('SCRIPT_NAME', ''))
self.browser = server.getenv('HTTP_USER_AGENT', 'unknown')
@@ -114,6 +117,10 @@
# check for an authenticated username
self.username = server.getenv('REMOTE_USER')
+ # construct MIME magic
+ self.ms = None
+ self.ms_fail = 0
+
# if we allow compressed output, see if the client does too
self.gzip_compress_level = 0
if cfg.options.allow_compress:
@@ -989,6 +996,9 @@
def is_viewable_image(mime_type):
return mime_type and mime_type in ('image/gif', 'image/jpeg', 'image/png')
+def is_binary(cfg, mime_type):
+ return mime_type and re.match(cfg.options.binary_mime_re, mime_type)
+
def is_text(mime_type):
return not mime_type or mime_type[:5] == 'text/'
@@ -1335,6 +1345,7 @@
# Reasons not to include a) being told not to by the configuration,
# b) not being able to import the Pygments modules, and c) Pygments
# not having a lexer for our file's format.
+
blame_source = []
if blame_data:
for i in blame_data:
@@ -1376,9 +1387,10 @@
lines = []
line_no = 0
while 1:
- line = cvsdb.utf8string(fp.readline())
+ line = fp.readline()
if not line:
break
+ line = cvsdb.utf8string(line)
line_no = line_no + 1
item = vclib.Annotation(cgi.escape(line), line_no,
None, None, None, None)
@@ -1490,18 +1502,41 @@
revision = None
mime_type = calculate_mime_type(request, path, rev)
- # Is this a viewable image type?
- if is_viewable_image(mime_type) \
- and 'co' in cfg.options.allowed_views:
+ if not mime_type or mime_type == default_mime_type:
+ if request.ms is None and not request.ms_fail:
+ try:
+ import magic
+ request.ms = magic.open(magic.MAGIC_NONE | magic.MAGIC_MIME)
+ request.ms.load()
+ except:
+ request.ms_fail = 1
+ if request.ms:
+ try:
+ fp, revision = request.repos.openfile(path, rev)
+ buffer = fp.read(magic_buf_size)
+ fp.close()
+ mime_type = request.ms.buffer(buffer)
+ except:
+ pass
+
+ # Is this a binary type?
+ if is_binary(request.cfg, mime_type):
fp, revision = request.repos.openfile(path, rev)
fp.close()
if check_freshness(request, None, revision, weak=1):
return
annotation = 'binary'
- image_src_href = request.get_url(view_func=view_checkout,
- params={'revision': rev}, escape=1)
+ if 'co' in cfg.options.allowed_views:
+ # Is this a viewable image type?
+ if is_viewable_image(mime_type) \
+ and 'co' in cfg.options.allowed_views:
+ image_src_href = request.get_url(view_func=view_checkout,
+ params={'revision': rev}, escape=1)
+ else:
+ download_href = request.get_url(view_func=view_checkout,
+ params={'revision': rev}, escape=1)
- # Not a viewable image.
+ # Text type
else:
blame_source = None
if is_annotate:
@@ -1584,9 +1619,9 @@
pathtype=vclib.FILE,
params={'pathrev': revision},
escape=1)
-
+
generate_page(request, "file", data)
-
+
def view_markup(request):
if 'markup' not in request.cfg.options.allowed_views:
raise debug.ViewVCException('Markup view is disabled',
@@ -1748,7 +1783,7 @@
rows = [ ]
num_displayed = 0
num_dead = 0
-
+
# set some values to be used inside loop
where = request.where
where_prefix = where and where + '/'
@@ -2557,11 +2592,11 @@
def _format_text(self, text):
text = string.expandtabs(string.rstrip(text))
hr_breakable = self.cfg.options.hr_breakable
-
+
# in the code below, "\x01" will be our stand-in for "&". We don't want
# to insert "&" because it would get escaped by htmlify(). Similarly,
# we use "\x02" as a stand-in for "<br>"
-
+
if hr_breakable > 1 and len(text) > hr_breakable:
text = re.sub('(' + ('.' * hr_breakable) + ')', '\\1\x02', text)
if hr_breakable:
@@ -2574,7 +2609,7 @@
text = string.replace(text, '\x02',
'<span style="color:red">\</span><br />')
return text
-
+
def _get_row(self):
if self.state[:5] == 'flush':
item = self._flush_row()
@@ -2614,7 +2649,7 @@
line_info_left=match.group(1),
line_info_right=match.group(2),
line_info_extra=match.group(3))
-
+
if line[0] == '\\':
# \ No newline at end of file
@@ -2626,7 +2661,7 @@
diff_code = line[0]
output = self._format_text(line[1:])
output = cvsdb.utf8string(output)
-
+
if diff_code == '+':
if self.state == 'dump':
self.line_number = self.line_number + 1
@@ -2782,7 +2817,7 @@
else:
rev1 = r1[:idx]
sym1 = r1[idx+1:]
-
+
if r2 == 'text':
rev2 = query_dict.get('tr2', None)
if not rev2:
@@ -2804,7 +2839,7 @@
except vclib.InvalidRevision:
raise debug.ViewVCException('Invalid revision(s) passed to diff',
'400 Bad Request')
-
+
p1 = _get_diff_path_parts(request, 'p1', rev1, request.pathrev)
p2 = _get_diff_path_parts(request, 'p2', rev2, request.pathrev)
@@ -2836,7 +2871,7 @@
else:
raise debug.ViewVCException('Diff format %s not understood'
% format, '400 Bad Request')
-
+
try:
fp = request.repos.rawdiff(p1, rev1, p2, rev2, diff_type)
except vclib.InvalidRevision:
@@ -2856,7 +2891,7 @@
cfg = request.cfg
query_dict = request.query_dict
p1, p2, rev1, rev2, sym1, sym2 = setup_diff(request)
-
+
# since templates are in use and subversion allows changes to the dates,
# we can't provide a strong etag
if check_freshness(request, None, '%s-%s' % (rev1, rev2), weak=1):
@@ -2915,7 +2950,7 @@
else:
unified = idiff.unified(lines_left, lines_right,
diff_options.get("context", 2))
- else:
+ else:
fp = request.repos.rawdiff(p1, rev1, p2, rev2, diff_type, diff_options)
except vclib.InvalidRevision:
raise debug.ViewVCException('Invalid path(s) or revision(s) passed '
@@ -2949,13 +2984,13 @@
left.view_href, left.download_href, left.download_text_href, \
left.annotate_href, left.revision_href, left.prefer_markup \
= get_file_view_info(request, path_left, rev1)
-
+
right = _item(date=rcsdiff_date_reformat(date2, cfg),
path=path_right, rev=rev2, tag=sym2)
right.view_href, right.download_href, right.download_text_href, \
right.annotate_href, right.revision_href, right.prefer_markup \
= get_file_view_info(request, path_right, rev2)
-
+
data = common_template_data(request)
data.update({
'left' : left,
@@ -3053,7 +3088,7 @@
tar_dir = tar_dir + _path_join(reldir) + '/'
cvs = request.roottype == 'cvs'
-
+
# If our caller doesn't dictate a datestamp to use for the current
# directory, its datestamps will be the youngest of the datestamps
# of versioned items in that subdirectory. We'll be ignoring dead
@@ -3128,14 +3163,14 @@
def download_tarball(request):
cfg = request.cfg
-
+
if 'tar' not in request.cfg.options.allowed_views:
raise debug.ViewVCException('Tarball generation is disabled',
'403 Forbidden')
if debug.TARFILE_PATH:
fp = open(debug.TARFILE_PATH, 'w')
- else:
+ else:
tarfile = request.rootname
if request.path_parts:
tarfile = "%s-%s" % (tarfile, request.path_parts[-1])
@@ -3261,7 +3296,7 @@
'r2' : str(change.base_rev),
},
escape=1)
-
+
# use same variable names as the log template
change.path = _path_join(change.path_parts)
@@ -3382,7 +3417,7 @@
def parse_date(datestr):
"""Parse a date string from the query form."""
-
+
match = re.match(r'^(\d\d\d\d)-(\d\d)-(\d\d)(?:\ +'
'(\d\d):(\d\d)(?::(\d\d))?)?$', datestr)
if match:
@@ -3824,7 +3859,7 @@
limited_files = 0
current_desc = commit_desc
current_rev = commit_rev
-
+
# we need to tack on our last commit grouping, if any
commit_item = build_commit(request, files, limit_changes,
dir_strip, format)
@@ -3833,7 +3868,7 @@
plus_count = plus_count + commit_item.plus
minus_count = minus_count + commit_item.minus
commits.append(commit_item)
-
+
# only show the branch column if we are querying all branches
# or doing a non-exact branch match on a CVS repository.
show_branch = ezt.boolean(request.roottype == 'cvs' and
@@ -3908,7 +3943,7 @@
def list_roots(request):
cfg = request.cfg
allroots = { }
-
+
# Add the viewable Subversion roots
for root in cfg.general.svn_roots.keys():
auth = setup_authorizer(cfg, request.username, root)
@@ -3928,7 +3963,7 @@
except vclib.ReposNotFound:
continue
allroots[root] = [cfg.general.cvs_roots[root], 'cvs']
-
+
return allroots
def find_root_in_parents(cfg, rootname, roottype):
@@ -3999,7 +4034,7 @@
# load mime types file
if cfg.general.mime_types_file:
mimetypes.init([cfg.general.mime_types_file])
-
+
debug.t_end('load-config')
return cfg
@@ -4013,7 +4048,7 @@
exc_dict['stacktrace'] = htmlify(exc_dict['stacktrace'],
mangle_email_addrs=0)
handled = 0
-
+
# use the configured error template if possible
try:
if cfg and not server.headerSent:
Index: viewvc.org/trunk/templates/file.ezt
===================================================================
--- viewvc.org/trunk/templates/file.ezt 2008/12/09 18:44:05 54
+++ viewvc.org/trunk/templates/file.ezt 2008/12/10 12:26:16 55
@@ -8,7 +8,7 @@
<hr />
<div class="vc_summary">
Revision [if-any revision_href]<a href="[revision_href]"><strong>[rev]</strong></a>[else]<strong>[rev]</strong>[end] -
-([if-any annotation][is annotation "annotated"]<a href="[view_href]"><strong>hide annotations</strong></a>[end][else]<a href="[annotate_href]"><strong>show annotations</strong></a>[end])
+([if-any annotation][is annotation "annotated"]<a href="[view_href]"><strong>hide annotations</strong></a>[end][is annotation "binary"]binary[end][else]<a href="[annotate_href]"><strong>show annotations</strong></a>[end])
[if-any download_href](<a href="[download_href]"><strong>download</strong></a>)[end]
[if-any download_text_href](<a href="[download_text_href]"><strong>as text</strong></a>)[end]
@@ -45,7 +45,7 @@
[end]
[if-any annotation]
[is annotation "binary"]
- <br /><strong>Unable to calculate annotation data on binary file contents.</strong>
+ <br /><strong>Unable to calculate annotation data on binary file contents [if-any download_href](<a href="[download_href]">download</a>)[end].</strong>
[end]
[is annotation "error"]
<br /><strong>Error occurred while calculating annotation data.</strong>
Index: viewvc.org/trunk/lib/config.py
===================================================================
--- viewvc.org/trunk/lib/config.py 2008/12/09 18:44:05 54
+++ viewvc.org/trunk/lib/config.py 2008/12/10 12:26:16 55
@@ -279,6 +279,7 @@
self.options.use_pagesize = 0
self.options.limit_changes = 100
self.options.cvs_ondisk_charset = 'cp1251'
+ self.options.binary_mime_re = '^(?!text/|application/xml)'
self.templates.diff = None
self.templates.directory = None
patches-from-search-results.diff
(application/octet-stream, 16.4 KB)
Index: viewvc.org/trunk/lib/vclib/__init__.py
===================================================================
--- viewvc.org/trunk/lib/vclib/__init__.py 2009/01/15 09:11:40 98
+++ viewvc.org/trunk/lib/vclib/__init__.py 2009/01/15 10:00:38 99
@@ -381,13 +381,13 @@
self.fp = None
finally:
try:
- if self.temp1:
+ if self.temp1 and self.temp1 != '/dev/null':
os.remove(self.temp1)
- self.temp1 = None
+ self.temp1 = None
finally:
- if self.temp2:
+ if self.temp2 and self.temp2 != '/dev/null':
os.remove(self.temp2)
- self.temp2 = None
+ self.temp2 = None
def __del__(self):
self.close()
Index: viewvc.org/trunk/lib/vclib/ccvs/bincvs.py
===================================================================
--- viewvc.org/trunk/lib/vclib/ccvs/bincvs.py 2009/01/15 09:11:40 98
+++ viewvc.org/trunk/lib/vclib/ccvs/bincvs.py 2009/01/15 10:00:38 99
@@ -338,13 +338,19 @@
ignore_keyword_subst - boolean, ignore keyword substitution
"""
+ if not path_parts1:
+ path_parts1 = path_parts2
+ rev1 = '1.0'
+ if not path_parts2:
+ path_parts2 = path_parts1
+ rev2 = '1.0'
if self.itemtype(path_parts1, rev1) != vclib.FILE: # does auth-check
raise vclib.Error("Path '%s' is not a file."
% (string.join(path_parts1, "/")))
if self.itemtype(path_parts2, rev2) != vclib.FILE: # does auth-check
raise vclib.Error("Path '%s' is not a file."
% (string.join(path_parts2, "/")))
-
+
args = vclib._diff_args(type, options)
if options.get('ignore_keyword_subst', 0):
args.append('-kk')
@@ -352,7 +358,7 @@
rcsfile = self.rcsfile(path_parts1, 1)
if path_parts1 != path_parts2:
raise NotImplementedError, "cannot diff across paths in cvs"
- args.extend(['-r' + rev1, '-r' + rev2, rcsfile])
+ args.extend(['-N', '-r' + rev1, '-r' + rev2, rcsfile])
fp = self.rcs_popen('rcsdiff', args, 'rt')
# Eat up the non-GNU-diff-y headers.
@@ -361,7 +367,6 @@
if not line or line[0:5] == 'diff ':
break
return fp
-
class CVSDirEntry(vclib.DirEntry):
def __init__(self, name, kind, errors, in_attic, absent=0):
Index: viewvc.org/trunk/templates/query_results.ezt
===================================================================
--- viewvc.org/trunk/templates/query_results.ezt 2009/01/13 15:23:11 96
+++ viewvc.org/trunk/templates/query_results.ezt 2009/01/14 14:07:41 97
@@ -9,6 +9,10 @@
[# <!-- {sql} --> ]
<p><a href="[queryform_href]">Modify query</a></p>
<p><a href="[backout_href]">Show commands which could be used to back out these changes</a></p>
+<p>
+ <a href="[patch_href]">Show a patch built from these changes</a>
+ [if-any patch_unsecure]<br /><b>CAUTION: selected changes are not contiguous, patch may include differences from other commits.</b>[end]
+</p>
<p><strong>+[plus_count]/-[minus_count]</strong> changed lines total.</p>
Index: viewvc.org/trunk/lib/viewvc.py
===================================================================
--- viewvc.org/trunk/lib/viewvc.py 2009/01/13 15:23:11 96
+++ viewvc.org/trunk/lib/viewvc.py 2009/01/27 11:27:05 108
@@ -36,6 +36,7 @@
import time
import types
import urllib
+import datetime
# These modules come from our library (the stub has set up the path)
import accept
@@ -163,6 +164,7 @@
'rootname' : rootname,
'auth' : authorizer,
'rootpath' : rootpath,
+ 'roottype' : roottype,
}
return None
@@ -1320,13 +1322,16 @@
return chunk
def copy_stream(src, dst, cfg, htmlize=0):
+ nch = 0
while 1:
chunk = retry_read(src)
if not chunk:
break
+ nch = nch+1
if htmlize:
chunk = htmlify(chunk, mangle_email_addrs=0)
dst.write(chunk)
+ return nch
class MarkupPipeWrapper:
"""An EZT callback that outputs a filepointer, plus some optional
@@ -3518,6 +3523,16 @@
r = r[:-2]
return string.join(r, '.')
+def rev_cmp(rev1, rev2):
+ """Compares two revision numbers rev1 and rev2"""
+ r1 = string.split(str(rev1), '.')
+ r2 = string.split(str(rev2), '.')
+ l = max(map(lambda s: len(s), r1 + r2))
+ f = '%%0%ds' % (l)
+ rev1 = '.'.join(map(lambda s: f % (s), r1))
+ rev2 = '.'.join(map(lambda s: f % (s), r2))
+ return cmp(rev1, rev2)
+
def build_commit(request, files, max_files, dir_strip, format):
"""Return a commit object build from the information in FILES, or
None if no allowed files are present in the set. DIR_STRIP is the
@@ -3655,7 +3670,8 @@
view_href=view_href,
download_href=download_href,
prefer_markup=prefer_markup,
- diff_href=diff_href))
+ diff_href=diff_href,
+ root=my_repos))
# No files survived authz checks? Let's just pretend this
# little commit didn't happen, shall we?
@@ -3717,6 +3733,109 @@
% (fileinfo.rev, prev_rev(fileinfo.rev),
fileinfo.dir, fileinfo.file)
+def query_is_unsecure_patch(request, commits):
+ if not commits:
+ return None
+ mr = {}
+ lr = {}
+ for commit in commits:
+ for fileinfo in commit.files:
+ fn = _path_join([fileinfo.dir, fileinfo.file])
+ if mr.get(fn, ''):
+ pr = mr[fn]
+ if fileinfo.root['roottype'] == 'svn':
+ pr = lr[fileinfo.root['rootname']]
+ pr = prev_rev(pr)
+ if rev_cmp(pr, fileinfo.rev) > 0:
+ return True
+ if fileinfo.root['roottype'] == 'svn':
+ lr[fileinfo.root['rootname']] = fileinfo.rev
+ mr[fn] = fileinfo.rev
+ return None
+
+def query_patch(request, commits):
+ request.server.header('text/x-diff')
+ if not commits:
+ print '# No changes were selected by the query.'
+ print '# There is nothing to show in the patch.'
+ return
+ files = {}
+ rev = ''
+ for commit in commits:
+ for fileinfo in commit.files:
+ fn = _path_join([fileinfo.dir, fileinfo.file])
+ rev = files.get(fn, '')
+ if not rev:
+ files[fn] = [ fileinfo.rev, fileinfo.rev, fileinfo.root ]
+ elif rev_cmp(rev[0], fileinfo.rev) > 0:
+ files[fn] = [ fileinfo.rev, rev[1], rev[2] ]
+ server_fp = get_writeready_server_file(request, 'text/plain')
+ for file in files.keys():
+ rev1 = prev_rev(files[file][0])
+ rev2 = files[file][1]
+ repos = files[file][2]['repos']
+ roottype = files[file][2]['roottype']
+ if roottype == 'svn':
+ try:
+ rev1 = repos._getrev(rev1)
+ rev2 = repos._getrev(rev2)
+ except vclib.InvalidRevision:
+ raise debug.ViewVCException('Invalid revision(s) passed to diff',
+ '400 Bad Request')
+ server_fp.write('Index: %s\n===================================================================\n' % (file))
+ try:
+ rdate1, _, _, _ = repos.revinfo(rev1)
+ rdate2, _, _, _ = repos.revinfo(rev2)
+ rdate1 = datetime.date.fromtimestamp(rdate1).strftime(' %Y/%m/%d %H:%M:%S')
+ rdate2 = datetime.date.fromtimestamp(rdate2).strftime(' %Y/%m/%d %H:%M:%S')
+ except vclib.UnsupportedFeature:
+ rdate1 = ''
+ rdate2 = ''
+ pr = rev2
+ try:
+ if roottype == 'svn':
+ p2 = _path_parts(repos.get_location(file, rev2, rev2))
+ else:
+ p2 = _path_parts(file)
+ fd, fr = repos.openfile(p2, rev2)
+ if not fd or rev2 != fr:
+ raise vclib.ItemNotFound(p2)
+ if fd:
+ fd.close()
+ except vclib.ItemNotFound:
+ # file removed at rev2
+ p2 = None
+ pr = prev_rev(str(rev2))
+ try:
+ if roottype == 'svn':
+ trev1, p1 = repos.last_rev(file, pr, rev1)
+ if trev1 != rev1:
+ p1 = None
+ else:
+ p1 = _path_parts(repos.get_location(p1, rev1, rev1))
+ else:
+ p1 = _path_parts(file)
+ fd, fr = repos.openfile(p1, rev1)
+ if fd:
+ fd.close()
+ rev1 = fr
+ else:
+ rev1 = '0'
+ if rev_cmp(rev1, rev2) >= 0:
+ # file added at rev2
+ p1 = None
+ except:
+ p1 = None
+ try:
+ fp = repos.rawdiff(p1, rev1, p2, rev2, vclib.UNIFIED)
+ nc = copy_stream(fp, server_fp, request.cfg)
+ if not nc and p1 and p2 and _path_join(p1) != _path_join(p2):
+ server_fp.write('--- %s%s\t%s\n' % (_path_join(p1), rdate1, rev1))
+ server_fp.write('+++ %s%s\t%s\n' % (_path_join(p2), rdate2, rev2))
+ fp.close()
+ except:
+ pass
+
def view_query(request):
if not is_query_supported(request):
raise debug.ViewVCException('Can not query project root "%s" at "%s".'
@@ -3890,6 +4009,12 @@
backout_href = request.get_url(params=params,
escape=1)
+ # patch link
+ params = request.query_dict.copy()
+ params['format'] = 'patch'
+ patch_href = request.get_url(params=params,
+ escape=1)
+
# link to zero limit_changes value
params = request.query_dict.copy()
params['limit_changes'] = 0
@@ -3904,12 +4029,18 @@
query_backout(request, commits)
return
+ if format == 'patch':
+ query_patch(request, commits)
+ return
+
data = common_template_data(request)
data.update({
'sql': sql,
'english_query': english_query(request),
'queryform_href': request.get_url(view_func=view_queryform, escape=1),
'backout_href': backout_href,
+ 'patch_href' : patch_href,
+ 'patch_unsecure' : ezt.boolean(query_is_unsecure_patch(request, commits)),
'plus_count': plus_count,
'minus_count': minus_count,
'show_branch': show_branch,
Index: viewvc.org/trunk/lib/vclib/svn/svn_repos.py
===================================================================
--- viewvc.org/trunk/lib/vclib/svn/svn_repos.py 2009/01/15 09:11:40 98
+++ viewvc.org/trunk/lib/vclib/svn/svn_repos.py 2009/01/15 10:18:33 100
@@ -649,15 +649,24 @@
return cached_info[0], cached_info[1], cached_info[2], cached_info[3]
def rawdiff(self, path_parts1, rev1, path_parts2, rev2, type, options={}):
- p1 = self._getpath(path_parts1)
- p2 = self._getpath(path_parts2)
- r1 = self._getrev(rev1)
- r2 = self._getrev(rev2)
- if not vclib.check_path_access(self, path_parts1, vclib.FILE, rev1):
- raise vclib.ItemNotFound(path_parts1)
- if not vclib.check_path_access(self, path_parts2, vclib.FILE, rev2):
- raise vclib.ItemNotFound(path_parts2)
-
+ if path_parts1:
+ p1 = self._getpath(path_parts1)
+ r1 = self._getrev(rev1)
+ if not vclib.check_path_access(self, path_parts1, vclib.FILE, rev1):
+ raise vclib.ItemNotFound(path_parts1)
+ else:
+ p1 = None
+
+ if path_parts2:
+ p2 = self._getpath(path_parts2)
+ r2 = self._getrev(rev2)
+ if not vclib.check_path_access(self, path_parts2, vclib.FILE, rev2):
+ raise vclib.ItemNotFound(path_parts2)
+ else:
+ if not p1:
+ raise vclib.ItemNotFound(path_parts2)
+ p2 = None
+
args = vclib._diff_args(type, options)
def _date_from_rev(rev):
@@ -665,10 +674,18 @@
return date
try:
- temp1 = temp_checkout(self, p1, r1)
- temp2 = temp_checkout(self, p2, r2)
- info1 = p1, _date_from_rev(r1), r1
- info2 = p2, _date_from_rev(r2), r2
+ if p1:
+ temp1 = temp_checkout(self, p1, r1)
+ info1 = p1, _date_from_rev(r1), r1
+ else:
+ temp1 = '/dev/null'
+ info1 = '/dev/null', _date_from_rev(rev1), rev1
+ if p2:
+ temp2 = temp_checkout(self, p2, r2)
+ info2 = p2, _date_from_rev(r2), r2
+ else:
+ temp2 = '/dev/null'
+ info2 = '/dev/null', _date_from_rev(rev2), rev2
return vclib._diff_fp(temp1, temp2, info1, info2, self.diff_cmd, args)
except core.SubversionException, e:
if e.apr_err == core.SVN_ERR_FS_NOT_FOUND:
Index: viewvc.org/trunk/lib/vclib/svn/svn_ra.py
===================================================================
--- viewvc.org/trunk/lib/vclib/svn/svn_ra.py 2009/01/15 09:11:40 98
+++ viewvc.org/trunk/lib/vclib/svn/svn_ra.py 2009/01/15 10:00:38 99
@@ -340,32 +340,47 @@
return cached_info[0], cached_info[1], cached_info[2], cached_info[3]
def rawdiff(self, path_parts1, rev1, path_parts2, rev2, type, options={}):
- p1 = self._getpath(path_parts1)
- p2 = self._getpath(path_parts2)
- r1 = self._getrev(rev1)
- r2 = self._getrev(rev2)
- if not vclib.check_path_access(self, path_parts1, vclib.FILE, rev1):
- raise vclib.ItemNotFound(path_parts1)
- if not vclib.check_path_access(self, path_parts2, vclib.FILE, rev2):
- raise vclib.ItemNotFound(path_parts2)
+
+ if path_parts1 is not None:
+ p1 = self._getpath(path_parts1)
+ r1 = self._getrev(rev1)
+ if not vclib.check_path_access(self, path_parts1, vclib.FILE, rev1):
+ raise vclib.ItemNotFound(path_parts1)
+ else:
+ p1 = None
+
+ if path_parts2 is not None:
+ if not p1:
+ raise vclib.ItemNotFound(parh_parts2)
+ p2 = self._getpath(path_parts2)
+ r2 = self._getrev(rev2)
+ if not vclib.check_path_access(self, path_parts2, vclib.FILE, rev2):
+ raise vclib.ItemNotFound(path_parts2)
+ else:
+ p2 = None
args = vclib._diff_args(type, options)
def _date_from_rev(rev):
date, author, msg, changes = self.revinfo(rev)
return date
-
+
try:
- temp1 = temp_checkout(self, p1, r1)
- temp2 = temp_checkout(self, p2, r2)
info1 = p1, _date_from_rev(r1), r1
info2 = p2, _date_from_rev(r2), r2
+ if p1:
+ temp1 = temp_checkout(self, p1, r1)
+ else:
+ temp1 = '/dev/null'
+ if p2:
+ temp2 = temp_checkout(self, p2, r2)
+ else:
+ temp2 = '/dev/null'
return vclib._diff_fp(temp1, temp2, info1, info2, self.diff_cmd, args)
except core.SubversionException, e:
- if e.apr_err == vclib.svn.core.SVN_ERR_FS_NOT_FOUND:
+ if e.apr_err == core.SVN_ERR_FS_NOT_FOUND:
raise vclib.InvalidRevision
raise
-
def isexecutable(self, path_parts, rev):
props = self.itemprops(path_parts, rev) # does authz-check
return props.has_key(core.SVN_PROP_EXECUTABLE)
Index: viewvc.org/trunk/lib/vclib/ccvs/ccvs.py
===================================================================
--- viewvc.org/trunk/lib/vclib/ccvs/ccvs.py 2009/01/15 09:11:40 98
+++ viewvc.org/trunk/lib/vclib/ccvs/ccvs.py 2009/01/15 10:00:38 99
@@ -121,23 +121,32 @@
return filtered_revs
def rawdiff(self, path_parts1, rev1, path_parts2, rev2, type, options={}):
- if self.itemtype(path_parts1, rev1) != vclib.FILE: # does auth-check
+ if path_parts1 and self.itemtype(path_parts1, rev1) != vclib.FILE: # does auth-check
raise vclib.Error("Path '%s' is not a file."
% (string.join(path_parts1, "/")))
- if self.itemtype(path_parts2, rev2) != vclib.FILE: # does auth-check
+ if path_parts2 and self.itemtype(path_parts2, rev2) != vclib.FILE: # does auth-check
raise vclib.Error("Path '%s' is not a file."
% (string.join(path_parts2, "/")))
-
- temp1 = tempfile.mktemp()
- open(temp1, 'wb').write(self.openfile(path_parts1, rev1)[0].getvalue())
- temp2 = tempfile.mktemp()
- open(temp2, 'wb').write(self.openfile(path_parts2, rev2)[0].getvalue())
+ if not path_parts1 and not path_parts2:
+ raise vclib.Error("Nothing to diff.")
- r1 = self.itemlog(path_parts1, rev1, vclib.SORTBY_DEFAULT, 0, 0, {})[-1]
- r2 = self.itemlog(path_parts2, rev2, vclib.SORTBY_DEFAULT, 0, 0, {})[-1]
+ if path_parts1:
+ temp1 = tempfile.mktemp()
+ open(temp1, 'wb').write(self.openfile(path_parts1, rev1)[0].getvalue())
+ r1 = self.itemlog(path_parts1, rev1, vclib.SORTBY_DEFAULT, 0, 0, {})[-1]
+ info1 = (self.rcsfile(path_parts1, root=1, v=0), r1.date, r1.string)
+ else:
+ temp1 = '/dev/null'
+ info1 = ('/dev/null', '', '')
- info1 = (self.rcsfile(path_parts1, root=1, v=0), r1.date, r1.string)
- info2 = (self.rcsfile(path_parts2, root=1, v=0), r2.date, r2.string)
+ if path_parts2:
+ temp2 = tempfile.mktemp()
+ open(temp2, 'wb').write(self.openfile(path_parts2, rev2)[0].getvalue())
+ r2 = self.itemlog(path_parts2, rev2, vclib.SORTBY_DEFAULT, 0, 0, {})[-1]
+ info2 = (self.rcsfile(path_parts2, root=1, v=0), r2.date, r2.string)
+ else:
+ temp2 = '/dev/null'
+ info2 = ('/dev/null', '', '')
diff_args = vclib._diff_args(type, options)
repository-type-selection.diff
(application/octet-stream, 5.3 KB)
Index: viewvc.org/trunk/templates/query_results.ezt
===================================================================
--- viewvc.org/trunk/templates/query_results.ezt 2009/02/03 12:03:05 120
+++ viewvc.org/trunk/templates/query_results.ezt 2009/02/03 12:19:33 121
@@ -7,7 +7,14 @@
<p><strong>[english_query]</strong></p>
[# <!-- {sql} --> ]
-<p><a href="[queryform_href]">Modify query</a></p>
+<p><a href="[queryform_href]">Modify query</a>[if-any repos_root] [else]
+ [if-any repos_type]
+ [is repos_type "cvs"]| <a href="[querysvn_href]">Look only in SVN</a> | <a href="[queryall_href]">Look in all repos</a> [end]
+ [is repos_type "svn"]| <a href="[querycvs_href]">Look only in CVS</a> | <a href="[queryall_href]">Look in all repos</a> [end]
+ [else]
+ | <a href="[querysvn_href]">Look only in SVN</a> | <a href="[querycvs_href]">Look only in CVS</a>
+ [end]
+[end]</p>
<p><a href="[backout_href]">Show commands which could be used to back out these changes</a></p>
<p>
<a href="[patch_href]">Show a patch built from these changes</a>
Index: viewvc.org/trunk/lib/viewvc.py
===================================================================
--- viewvc.org/trunk/lib/viewvc.py 2009/02/02 12:39:26 118
+++ viewvc.org/trunk/lib/viewvc.py 2009/02/03 12:19:33 121
@@ -711,6 +711,7 @@
# for query
'repos' : _validate_regex,
'repos_match' : _re_validate_alpha,
+ 'repos_type' : None,
'branch' : _validate_regex,
'branch_match' : _re_validate_alpha,
'dir' : None,
@@ -3400,6 +3401,7 @@
# default values ...
data['repos'] = request.query_dict.get('repos', '')
data['repos_match'] = request.query_dict.get('repos_match', 'exact')
+ data['repos_type'] = request.query_dict.get('repos_type', '')
if not data['repos']:
data['repos'] = request.rootpath
data['repos_match'] = 'exact'
@@ -3846,7 +3848,9 @@
# get form data
repos_root = request.query_dict.get('repos', '')
+ repos_root_t = repos_root
repos_match = request.query_dict.get('repos_match', 'exact')
+ repos_type = request.query_dict.get('repos_type', '')
branch = request.query_dict.get('branch', '')
branch_match = request.query_dict.get('branch_match', 'exact')
dir = request.query_dict.get('dir', '')
@@ -3893,6 +3897,15 @@
query = cvsdb.CreateCheckinQuery()
if repos_root:
query.SetRepository(repos_root, repos_match)
+ elif repos_type == 'cvs' or repos_type == 'svn':
+ # select only CVS/SVN repositories
+ all = list_roots(request)
+ re = []
+ for r in all.keys():
+ if all[r][1] == repos_type:
+ re.append('^'+all[r][0]+'$')
+ re = '|'.join(re)
+ query.SetRepository(re, 'regex')
# treat "HEAD" specially ...
if branch_match == 'exact' and branch == 'HEAD':
query.SetBranch('')
@@ -4006,14 +4019,21 @@
# backout link
params = request.query_dict.copy()
params['format'] = 'backout'
- backout_href = request.get_url(params=params,
- escape=1)
+ backout_href = request.get_url(params=params, escape=1)
# patch link
params = request.query_dict.copy()
params['format'] = 'patch'
- patch_href = request.get_url(params=params,
- escape=1)
+ patch_href = request.get_url(params=params, escape=1)
+
+ # look only in... links
+ params = request.query_dict.copy()
+ params['repos_type'] = 'cvs'
+ lookcvs_href = request.get_url(params=params, escape=1)
+ params['repos_type'] = 'svn'
+ looksvn_href = request.get_url(params=params, escape=1)
+ params['repos_type'] = ''
+ lookall_href = request.get_url(params=params, escape=1)
# link to zero limit_changes value
params = request.query_dict.copy()
@@ -4036,11 +4056,16 @@
data = common_template_data(request)
data.update({
'sql': sql,
+ 'repos_root': repos_root_t,
+ 'repos_type': repos_type,
'english_query': english_query(request),
'queryform_href': request.get_url(view_func=view_queryform, escape=1),
+ 'querycvs_href': lookcvs_href,
+ 'querysvn_href': looksvn_href,
+ 'queryall_href': lookall_href,
'backout_href': backout_href,
- 'patch_href' : patch_href,
- 'patch_unsecure' : ezt.boolean(query_is_unsecure_patch(request, commits)),
+ 'patch_href': patch_href,
+ 'patch_unsecure': ezt.boolean(query_is_unsecure_patch(request, commits)),
'plus_count': plus_count,
'minus_count': minus_count,
'show_branch': show_branch,
Index: viewvc.org/trunk/templates/query_form.ezt
===================================================================
--- viewvc.org/trunk/templates/query_form.ezt 2009/02/02 12:39:26 118
+++ viewvc.org/trunk/templates/query_form.ezt 2009/02/02 17:20:11 119
@@ -17,7 +17,13 @@
<tr>
<th style="text-align:right;vertical-align:top;">Repository:</th>
<td>
- <input type="text" name="repos" value="[repos]" /><br />
+ <input type="text" name="repos" value="[repos]" /> <b>Repository type:</b>
+ <select name="repos_type">
+ <option value="">Any</option>
+ <option value="cvs" [is repos_type "cvs"]selected[end]>CVS</option>
+ <option value="svn" [is repos_type "svn"]selected[end]>Subversion</option>
+ </select>
+ <br />
<label for="repos_match_exact">
<input type="radio" name="repos_match" id="repos_match_exact"
value="exact" [is repos_match "exact"]checked="checked"[end] />
search-results-check-commit-access.diff
(application/octet-stream, 5.8 KB)
Index: viewvc.org/trunk/lib/cvsdb.py
===================================================================
--- viewvc.org/trunk/lib/cvsdb.py 2008/11/17 17:04:16 26
+++ viewvc.org/trunk/lib/cvsdb.py 2008/11/18 13:36:33 27
@@ -30,7 +30,7 @@
## complient database interface
class CheckinDatabase:
- def __init__(self, host, port, socket, user, passwd, database, row_limit, min_relevance):
+ def __init__(self, host, port, socket, user, passwd, database, row_limit, min_relevance, authorizer = None):
self._host = host
self._port = port
self._socket = socket
@@ -39,7 +39,7 @@
self._database = database
self._row_limit = row_limit
self._min_relevance = min_relevance
- self.text_query = ""
+ self.authorizer = authorizer
## database lookup caches
self._get_cache = {}
@@ -341,8 +341,16 @@
return "(%s)" % (string.join(sqlList, " OR "))
def CreateSQLQueryString(self, query):
- fields = ["checkins.*"]
- tableList = [("checkins", None)]
+ fields = [
+ "checkins.*",
+ "repositories.repository AS repository_name",
+ "dirs.dir AS dir_name",
+ "files.file AS file_name"]
+ tableList = [
+ ("checkins", None),
+ ("repositories","(checkins.repositoryid=repositories.id)"),
+ ("dirs", "(checkins.dirid=dirs.id)"),
+ ("files", "(checkins.fileid=files.id)")]
condList = []
if len(query.text_query):
@@ -354,8 +362,6 @@
fields.append("'' AS relevance")
if len(query.repository_list):
- tableList.append(("repositories",
- "(checkins.repositoryid=repositories.id)"))
temp = self.SQLQueryListString("repositories.repository",
query.repository_list)
condList.append(temp)
@@ -367,7 +373,6 @@
condList.append(temp)
if len(query.directory_list):
- tableList.append(("dirs", "(checkins.dirid=dirs.id)"))
temp = self.SQLQueryListString("dirs.dir", query.directory_list)
condList.append(temp)
@@ -434,6 +439,15 @@
fields, tables, conditions, order_by, limit)
return sql
+
+ def check_commit_access(self, repos, dir, file, rev):
+ if self.authorizer:
+ rootname = repos.split('/')
+ rootname = rootname.pop()
+ path_parts = dir.split('/')
+ path_parts.append(file)
+ return self.authorizer.check_path_access(rootname, path_parts, vclib.FILE, rev)
+ return True
def RunQuery(self, query):
sql = self.CreateSQLQueryString(query)
@@ -447,7 +461,11 @@
(dbType, dbCI_When, dbAuthorID, dbRepositoryID, dbDirID,
dbFileID, dbRevision, dbStickyTag, dbBranchID, dbAddedLines,
- dbRemovedLines, dbDescID, dbRelevance) = row
+ dbRemovedLines, dbDescID, dbRepositoryName, dbDirName,
+ dbFileName, dbRelevance) = row
+
+ if not self.check_commit_access(dbRepositoryName, dbDirName, dbFileName, dbRevision):
+ continue
commit = LazyCommit(self)
if dbType == 'Add':
@@ -456,6 +474,7 @@
commit.SetTypeRemove()
else:
commit.SetTypeChange()
+
commit.SetTime(dbi.TicksFromDateTime(dbCI_When))
commit.SetFileID(dbFileID)
commit.SetDirectoryID(dbDirID)
@@ -806,7 +825,7 @@
def CreateCheckinQuery():
return CheckinDatabaseQuery()
-def ConnectDatabase(cfg, readonly=0):
+def ConnectDatabase(cfg, authorizer=None, readonly=0):
if readonly:
user = cfg.cvsdb.readonly_user
passwd = cfg.cvsdb.readonly_passwd
@@ -814,12 +833,13 @@
user = cfg.cvsdb.user
passwd = cfg.cvsdb.passwd
db = CheckinDatabase(cfg.cvsdb.host, cfg.cvsdb.port, cfg.cvsdb.socket, user, passwd,
- cfg.cvsdb.database_name, cfg.cvsdb.row_limit, cfg.cvsdb.fulltext_min_relevance)
+ cfg.cvsdb.database_name, cfg.cvsdb.row_limit, cfg.cvsdb.fulltext_min_relevance,
+ authorizer)
db.Connect()
return db
-def ConnectDatabaseReadOnly(cfg):
- return ConnectDatabase(cfg, 1)
+def ConnectDatabaseReadOnly(cfg, authorizer):
+ return ConnectDatabase(cfg, authorizer, 1)
def GetCommitListFromRCSFile(repository, path_parts, revision=None):
commit_list = []
Index: viewvc.org/trunk/lib/viewvc.py
===================================================================
--- viewvc.org/trunk/lib/viewvc.py 2008/11/17 17:04:16 26
+++ viewvc.org/trunk/lib/viewvc.py 2008/11/18 13:36:33 27
@@ -3312,7 +3312,7 @@
if request.cfg.cvsdb.check_database_for_root:
global cvsdb
import cvsdb
- db = cvsdb.ConnectDatabaseReadOnly(request.cfg)
+ db = cvsdb.ConnectDatabaseReadOnly(request.cfg, request.auth)
repos_root, repos_dir = cvsdb.FindRepository(db, request.rootpath)
if repos_root:
return 1
@@ -3684,7 +3684,7 @@
global cvsdb
import cvsdb
- db = cvsdb.ConnectDatabaseReadOnly(cfg)
+ db = cvsdb.ConnectDatabaseReadOnly(cfg, request.auth)
repos_root, repos_dir = cvsdb.FindRepository(db, request.rootpath)
if not repos_root:
raise debug.ViewVCException(
Index: viewvc.org/trunk/lib/query.py
===================================================================
--- viewvc.org/trunk/lib/query.py 2008/11/18 13:36:33 27
+++ viewvc.org/trunk/lib/query.py 2008/11/18 13:49:12 28
@@ -422,7 +422,7 @@
form = server.FieldStorage()
form_data = FormData(form)
- db = cvsdb.ConnectDatabaseReadOnly(cfg)
+ db = cvsdb.ConnectDatabaseReadOnly(cfg, None)
if form_data.valid:
commits = run_query(server, cfg, db, form_data, viewvc_link)
query = None
utf8-encoding-guess.diff
(application/octet-stream, 10.9 KB)
Index: viewvc.org/trunk/lib/cvsdb.py
===================================================================
--- viewvc.org/trunk/lib/cvsdb.py 2008/11/13 14:56:58 20
+++ viewvc.org/trunk/lib/cvsdb.py 2009/02/11 12:57:01 126
@@ -29,14 +29,29 @@
## defined to actually be complete; it should run well off of any DBI 2.0
## complient database interface
+encs = [ "utf-8", "cp1251", "iso-8859-1" ]
+
+def utf8string(value):
+ for e in encs:
+ try:
+ value = value.decode(e)
+ break
+ except: pass
+ return value.encode("utf-8")
+
+def setencs(e):
+ global encs
+ encs = e
+
class CheckinDatabase:
- def __init__(self, host, port, user, passwd, database, row_limit):
+ def __init__(self, host, port, socket, user, passwd, database, row_limit):
self._host = host
self._port = port
+ self._socket = socket
self._user = user
self._passwd = passwd
self._database = database
self._row_limit = row_limit
## database lookup caches
self._get_cache = {}
@@ -45,14 +62,16 @@
def Connect(self):
self.db = dbi.connect(
- self._host, self._port, self._user, self._passwd, self._database)
+ self._host, self._port, self._socket, self._user, self._passwd, self._database)
cursor = self.db.cursor()
cursor.execute("SET AUTOCOMMIT=1")
def sql_get_id(self, table, column, value, auto_set):
+ value = utf8string(value)
+
sql = "SELECT id FROM %s WHERE %s=%%s" % (table, column)
sql_args = (value, )
cursor = self.db.cursor()
cursor.execute(sql, sql_args)
try:
@@ -53,9 +67,11 @@
cursor.execute("SET AUTOCOMMIT=1")
def sql_get_id(self, table, column, value, auto_set):
+ value = utf8string(value)
+
sql = "SELECT id FROM %s WHERE %s=%%s" % (table, column)
sql_args = (value, )
cursor = self.db.cursor()
cursor.execute(sql, sql_args)
try:
@@ -184,12 +200,13 @@
return self.get_list("repositories", repository)
def SQLGetDescriptionID(self, description, auto_set = 1):
+ description = utf8string(description)
## lame string hash, blame Netscape -JMP
hash = len(description)
sql = "SELECT id FROM descs WHERE hash=%s AND description=%s"
sql_args = (hash, description)
cursor = self.db.cursor()
cursor.execute(sql, sql_args)
try:
Index: viewvc.org/trunk/lib/vclib/ccvs/bincvs.py
===================================================================
--- viewvc.org/trunk/lib/vclib/ccvs/bincvs.py 2008/12/02 14:55:27 40
+++ viewvc.org/trunk/lib/vclib/ccvs/bincvs.py 2008/12/12 12:36:39 61
@@ -21,6 +21,7 @@
import string
import re
import time
+import cvsdb
# ViewVC libs
import compat
@@ -322,7 +323,7 @@
if self.itemtype(path_parts, rev) != vclib.FILE: # does auth-check
raise vclib.Error("Path '%s' is not a file."
% (string.join(path_parts, "/")))
-
+
from vclib.ccvs import blame
source = blame.BlameSource(self.rcsfile(path_parts, 1), rev)
return source, source.revision
@@ -833,6 +834,8 @@
raise ValueError, 'invalid year'
date = compat.timegm(tm)
+ log = cvsdb.utf8string(log)
+
return Revision(rev, date,
# author, state, lines changed
match.group(2), match.group(3) == "dead", match.group(5),
Index: viewvc.org/trunk/lib/vclib/ccvs/blame.py
===================================================================
--- viewvc.org/trunk/lib/vclib/ccvs/blame.py 2008/12/16 12:11:16 67
+++ viewvc.org/trunk/lib/vclib/ccvs/blame.py 2008/12/16 14:29:30 68
@@ -32,6 +32,7 @@
import math
import rcsparse
import vclib
+import cvsdb
class CVSParser(rcsparse.Sink):
# Precompiled regular expressions
@@ -446,7 +447,7 @@
prev_rev = self.parser.prev_revision.get(rev)
line_number = idx + 1
author = self.parser.revision_author[rev]
- thisline = self.lines[idx]
+ thisline = cvsdb.utf8string(self.lines[idx])
### TODO: Put a real date in here.
item = vclib.Annotation(thisline, line_number, rev, prev_rev, author, None)
self.last = item
Index: viewvc.org/trunk/lib/config.py
===================================================================
--- viewvc.org/trunk/lib/config.py 2008/11/27 15:20:35 34
+++ viewvc.org/trunk/lib/config.py 2009/02/11 12:57:01 126
@@ -22,6 +22,7 @@
import vclib
import vclib.ccvs
import vclib.svn
+import cvsdb
#########################################################################
#
@@ -64,6 +65,7 @@
if rootname:
self._process_root_options(self.parser, rootname)
self.expand_root_parents()
+ cvsdb.setencs(self.options.encodings.split(':'))
def expand_root_parents(self):
"""Expand the configured root parents into individual roots."""
@@ -278,6 +280,9 @@
self.options.use_re_search = 0
self.options.use_pagesize = 0
self.options.limit_changes = 100
+ self.options.cvs_ondisk_charset = 'cp1251'
+ self.options.binary_mime_re = '^(?!text/|.*\Wxml)'
+ self.options.encodings = 'utf-8:cp1251:iso-8859-1'
self.templates.diff = None
self.templates.directory = None
Index: viewvc.org/trunk/lib/viewvc.py
===================================================================
--- viewvc.org/trunk/lib/viewvc.py 2008/11/27 15:20:35 34
+++ viewvc.org/trunk/lib/viewvc.py 2008/12/12 16:19:41 62
@@ -41,6 +41,7 @@
import accept
import compat
import config
+import cvsdb
import ezt
import popen
import sapi
@@ -935,7 +936,10 @@
path_parts.append(part)
is_last = len(path_parts) == len(request.path_parts)
- item = _item(name=part, href=None)
+ if request.roottype == 'cvs':
+ item = _item(name=cvsdb.utf8string(part), href=None)
+ else:
+ item = _item(name=part, href=None)
if not is_last or (is_dir and request.view_func is not view_directory):
item.href = request.get_url(view_func=view_directory,
@@ -1158,6 +1188,10 @@
def common_template_data(request, revision=None, mime_type=None):
cfg = request.cfg
+ where = request.where
+ if request.roottype == 'cvs':
+ where = cvsdb.utf8string(where)
+ where = request.server.escape(where)
data = {
'cfg' : cfg,
'vsn' : __version__,
@@ -1166,7 +1200,7 @@
and request.script_name + '/' + docroot_magic_path \
or cfg.options.docroot,
'username' : request.username,
- 'where' : request.server.escape(request.where),
+ 'where' : where,
'roottype' : request.roottype,
'rootname' : request.rootname \
and request.server.escape(request.rootname) or None,
@@ -1362,6 +1397,7 @@
line = fp.readline()
if not line:
break
+ line = cvsdb.utf8string(line)
line_no = line_no + 1
item = vclib.Annotation(cgi.escape(line), line_no,
None, None, None, None)
@@ -1756,8 +1815,8 @@
row.short_log = format_log(file.log, cfg)
row.log = htmlify(file.log, cfg.options.mangle_email_addresses)
row.lockinfo = file.lockinfo
- row.anchor = request.server.escape(file.name)
- row.name = request.server.escape(file.name)
+ row.name = request.server.escape(cvsdb.utf8string(file.name))
+ row.anchor = row.name
row.pathtype = (file.kind == vclib.FILE and 'file') or \
(file.kind == vclib.DIR and 'dir')
row.errors = file.errors
@@ -2106,7 +2165,10 @@
entry.ago = None
if rev.date is not None:
entry.ago = html_time(request, rev.date, 1)
- entry.log = htmlify(rev.log or "", cfg.options.mangle_email_addresses)
+ entry.log = rev.log or ""
+ if cvs:
+ entry.log = cvsdb.utf8string(entry.log)
+ entry.log = htmlify(entry.log, cfg.options.mangle_email_addresses)
entry.size = rev.size
entry.lockinfo = rev.lockinfo
entry.branch_point = None
@@ -2605,7 +2667,8 @@
diff_code = line[0]
output = self._format_text(line[1:])
-
+ output = cvsdb.utf8string(output)
+
if diff_code == '+':
if self.state == 'dump':
self.line_number = self.line_number + 1
@@ -3493,14 +3562,19 @@
# Check path access (since the commits database logic bypasses the
# vclib layer and, thus, the vcauth stuff that layer uses).
+ if request.roottype == 'cvs':
+ try: where = unicode(where,'utf-8')
+ except: pass
+ try: where = where.encode(cfg.options.cvs_ondisk_charset)
+ except: pass
path_parts = _path_parts(where)
if path_parts:
# Skip files in CVSROOT if asked to hide such.
if cfg.options.hide_cvsroot \
and is_cvsroot_path(request.roottype, path_parts):
found_unreadable = 1
continue
# We have to do a rare authz check here because this data comes
# from the CVSdb, not from the vclib providers.
#
Index: viewvc.org/trunk/lib/vclib/ccvs/ccvs.py
===================================================================
--- viewvc.org/trunk/lib/vclib/ccvs/ccvs.py 2008/12/11 16:02:02 60
+++ viewvc.org/trunk/lib/vclib/ccvs/ccvs.py 2008/12/12 12:36:39 61
@@ -19,6 +19,7 @@
import vclib
import rcsparse
import blame
+import cvsdb
### The functionality shared with bincvs should probably be moved to a
### separate module
@@ -66,6 +67,7 @@
entry.path = path
try:
rcsparse.parse(open(path, 'rb'), InfoSink(entry, rev, alltags))
+ entry.log = cvsdb.utf8string(entry.log)
except IOError, e:
entry.errors.append("rcsparse error: %s" % e)
except RuntimeError, e:
Index: viewvc.org/trunk/lib/dbi.py
===================================================================
--- viewvc.org/trunk/lib/dbi.py 2008/11/13 16:51:57 21
+++ viewvc.org/trunk/lib/dbi.py 2008/11/14 14:53:48 22
@@ -59,5 +59,13 @@
else:
return time.mktime(t[:8] + (-1,))
-def connect(host, port, socket, user, passwd, db):
- return MySQLdb.connect(host=host, port=port, unix_socket=socket, user=user, passwd=passwd, db=db)
+def connect(host, port, socket, user, passwd, db, charset = 'utf8'):
+ return MySQLdb.connect(
+ host = host,
+ port = port,
+ unix_socket = socket,
+ user = user,
+ passwd = passwd,
+ db = db,
+ charset = charset,
+ use_unicode = charset == 'utf8')
Index: viewvc.org/trunk/lib/ezt.py
===================================================================
--- viewvc.org/trunk/lib/ezt.py 2008/11/13 16:51:57 21
+++ viewvc.org/trunk/lib/ezt.py 2008/12/11 10:46:42 59
@@ -790,12 +790,18 @@
"""The format specifier is an unknown value."""
def _raw_printer(ctx, s):
+ try: s = s.encode('utf-8')
+ except: pass
ctx.fp.write(s)
-
+
def _html_printer(ctx, s):
+ try: s = s.encode('utf-8')
+ except: pass
ctx.fp.write(cgi.escape(s))
def _uri_printer(ctx, s):
+ try: s = s.encode('utf-8')
+ except: pass
ctx.fp.write(urllib.quote(s))
_printers = {