Add support for display of locked status.
* docs/template-authoring-guide.html Document the new appearances of the lockinfo data. * templates/log.ezt, * templates/log_table.ezt Show lock status information. * templates/docroot/images/lock.png New icon. * lib/viewvc.py (view_log): Populate the log revision entry's new "lockinfo" member. * lib/vclib/svn/svn_repos.py (_log_helper): Accept 'lockinfo' parameter, used to populate the similarly named member of the Revision() object. (_fetch_log): Query the lock status of the input path, and update calls to _log_helper(). * lib/vclib/ccvs/ccvs.py (CCVSRepository.itemlog): Update call to _file_log(), passing lockinfo. (TreeSink.__init__): Init new lockinfo dictionary. (TreeSink.set_locker): New. * lib/vclib/ccvs/bincvs.py (_parse_log_header): Now parse and return lock information, too. (_file_log): Add 'lockinfo' parameter, used to populate the similarly named Revision() object members. (BinCVSRepository._get_tip_revision, BinCVSRepository.itemlog): Expect lockinfo back from _parse_log_header(), and pass to updated calls to _file_log(). (_get_logs): Expect lockinfo back from _parse_log_header(). * lib/vclib/svn/svn_ra.py (RemoteSubversionRepository.itemlog): Use svn_client_ls3() to fetch lock information. git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@1783 8cb11bc2-c004-0410-86c3-e597b4017df7remotes/merged-file-views
parent
2a9584a0fb
commit
d620498e9e
|
@ -1362,6 +1362,11 @@ td {
|
|||
<td>String</td>
|
||||
<td>URL to download the file revision as <tt>text/plain</tt>.</td>
|
||||
</tr>
|
||||
<tr class="varlevel2">
|
||||
<td class="varname">entries.lockinfo</td>
|
||||
<td>String</td>
|
||||
<td>Information about the lock status of this revision.</td>
|
||||
</tr>
|
||||
<tr class="varlevel2">
|
||||
<td class="varname">entries.log</td>
|
||||
<td>String</td>
|
||||
|
|
|
@ -139,13 +139,13 @@ class BinCVSRepository(BaseCVSRepository):
|
|||
"""Get the (basically) youngest revision (filtered by REV)."""
|
||||
args = rcs_file,
|
||||
fp = self.rcs_popen('rlog', args, 'rt', 0)
|
||||
filename, default_branch, tags, msg, eof = _parse_log_header(fp)
|
||||
filename, default_branch, tags, lockinfo, msg, eof = _parse_log_header(fp)
|
||||
revs = []
|
||||
while not eof:
|
||||
revision, eof = _parse_log_entry(fp)
|
||||
if revision:
|
||||
revs.append(revision)
|
||||
revs = _file_log(revs, tags, default_branch, rev)
|
||||
revs = _file_log(revs, tags, lockinfo, default_branch, rev)
|
||||
if revs:
|
||||
return revs[-1]
|
||||
return None
|
||||
|
@ -272,7 +272,7 @@ class BinCVSRepository(BaseCVSRepository):
|
|||
args = rcsfile,
|
||||
|
||||
fp = self.rcs_popen('rlog', args, 'rt', 0)
|
||||
filename, default_branch, tags, msg, eof = _parse_log_header(fp)
|
||||
filename, default_branch, tags, lockinfo, msg, eof = _parse_log_header(fp)
|
||||
|
||||
# Retrieve revision objects
|
||||
revs = []
|
||||
|
@ -281,7 +281,7 @@ class BinCVSRepository(BaseCVSRepository):
|
|||
if revision:
|
||||
revs.append(revision)
|
||||
|
||||
filtered_revs = _file_log(revs, tags, default_branch, rev)
|
||||
filtered_revs = _file_log(revs, tags, lockinfo, default_branch, rev)
|
||||
|
||||
options['cvs_tags'] = tags
|
||||
return filtered_revs
|
||||
|
@ -655,13 +655,14 @@ def _parse_log_header(fp):
|
|||
If there is no revision information (e.g. the "-h" switch was passed to
|
||||
rlog), then fp will consumed the file separator line on exit.
|
||||
|
||||
Returns: filename, default branch, tag dictionary, rlog error message,
|
||||
and eof flag
|
||||
Returns: filename, default branch, tag dictionary, lock dictionary,
|
||||
rlog error message, and eof flag
|
||||
"""
|
||||
|
||||
filename = head = branch = msg = ""
|
||||
taginfo = { } # tag name => number
|
||||
|
||||
parsing_tags = 0
|
||||
lockinfo = { } # revision => locker
|
||||
state = 0 # 0 = base, 1 = parsing symbols, 2 = parsing locks
|
||||
eof = None
|
||||
|
||||
while 1:
|
||||
|
@ -671,24 +672,35 @@ def _parse_log_header(fp):
|
|||
eof = _EOF_LOG
|
||||
break
|
||||
|
||||
if parsing_tags:
|
||||
if state == 1:
|
||||
if line[0] == '\t':
|
||||
[ tag, rev ] = map(string.strip, string.split(line, ':'))
|
||||
taginfo[tag] = rev
|
||||
else:
|
||||
# oops. this line isn't tag info. stop parsing tags.
|
||||
parsing_tags = 0
|
||||
state = 0
|
||||
|
||||
if not parsing_tags:
|
||||
if state == 2:
|
||||
if line[0] == '\t':
|
||||
[ locker, rev ] = map(string.strip, string.split(line, ':'))
|
||||
lockinfo[rev] = locker
|
||||
else:
|
||||
# oops. this line isn't lock info. stop parsing tags.
|
||||
state = 0
|
||||
|
||||
if state == 0:
|
||||
if line[:9] == 'RCS file:':
|
||||
filename = line[10:-1]
|
||||
elif line[:5] == 'head:':
|
||||
head = line[6:-1]
|
||||
elif line[:7] == 'branch:':
|
||||
branch = line[8:-1]
|
||||
elif line[:6] == 'locks:':
|
||||
# start parsing the lock information
|
||||
state = 2
|
||||
elif line[:14] == 'symbolic names':
|
||||
# start parsing the tag information
|
||||
parsing_tags = 1
|
||||
state = 1
|
||||
elif line == ENTRY_END_MARKER:
|
||||
# end of the headers
|
||||
break
|
||||
|
@ -717,7 +729,7 @@ def _parse_log_header(fp):
|
|||
eof = _EOF_ERROR
|
||||
break
|
||||
|
||||
return filename, branch, taginfo, msg, eof
|
||||
return filename, branch, taginfo, lockinfo, msg, eof
|
||||
|
||||
_re_log_info = re.compile(r'^date:\s+([^;]+);'
|
||||
r'\s+author:\s+([^;]+);'
|
||||
|
@ -817,7 +829,7 @@ def _paths_eq(path1, path2):
|
|||
# ======================================================================
|
||||
# Functions for interpreting and manipulating log information
|
||||
|
||||
def _file_log(revs, taginfo, cur_branch, filter):
|
||||
def _file_log(revs, taginfo, lockinfo, cur_branch, filter):
|
||||
"""Augment list of Revisions and a dictionary of Tags"""
|
||||
|
||||
# Add artificial ViewVC tag MAIN. If the file has a default branch, then
|
||||
|
@ -848,6 +860,10 @@ def _file_log(revs, taginfo, cur_branch, filter):
|
|||
# Match up tags and revisions
|
||||
_match_revs_tags(revs, tags)
|
||||
|
||||
# Match up lockinfo and revision
|
||||
for rev in revs:
|
||||
rev.lockinfo = lockinfo.get(rev.string)
|
||||
|
||||
# Add artificial ViewVC tag HEAD, which acts like a non-branch tag pointing
|
||||
# at the latest revision on the MAIN branch. The HEAD revision doesn't have
|
||||
# anything to do with the "head" revision number specified in the RCS file
|
||||
|
@ -936,7 +952,8 @@ def _get_logs(repos, dir_path_parts, entries, view_tag, get_dirs):
|
|||
chunk_idx = 0
|
||||
while chunk_idx < len(chunk):
|
||||
file = chunk[chunk_idx]
|
||||
filename, default_branch, taginfo, msg, eof = _parse_log_header(rlog)
|
||||
filename, default_branch, taginfo, lockinfo, msg, eof \
|
||||
= _parse_log_header(rlog)
|
||||
|
||||
if eof == _EOF_LOG:
|
||||
# the rlog output ended early. this can happen on errors that rlog
|
||||
|
|
|
@ -87,7 +87,7 @@ class CCVSRepository(BaseCVSRepository):
|
|||
path = self.rcsfile(path_parts, 1)
|
||||
sink = TreeSink()
|
||||
rcsparse.parse(open(path, 'rb'), sink)
|
||||
filtered_revs = _file_log(sink.revs.values(), sink.tags,
|
||||
filtered_revs = _file_log(sink.revs.values(), sink.tags, sink.lockinfo,
|
||||
sink.default_branch, rev)
|
||||
for rev in filtered_revs:
|
||||
if rev.prev and len(rev.number) == 2:
|
||||
|
@ -214,6 +214,7 @@ class TreeSink(rcsparse.Sink):
|
|||
self.tags = { }
|
||||
self.head = None
|
||||
self.default_branch = None
|
||||
self.lockinfo = { }
|
||||
|
||||
def set_head_revision(self, revision):
|
||||
self.head = revision
|
||||
|
@ -221,6 +222,9 @@ class TreeSink(rcsparse.Sink):
|
|||
def set_principal_branch(self, branch_number):
|
||||
self.default_branch = branch_number
|
||||
|
||||
def set_locker(self, rev, locker):
|
||||
self.lockinfo[rev] = locker
|
||||
|
||||
def define_tag(self, name, revision):
|
||||
# check !tags.has_key(tag_name)
|
||||
self.tags[name] = revision
|
||||
|
|
|
@ -282,6 +282,12 @@ class RemoteSubversionRepository(vclib.Repository):
|
|||
if full_name:
|
||||
dir_url = dir_url + '/' + full_name
|
||||
|
||||
# Use ls3 to fetch the lock status for this item.
|
||||
dirents, locks = client.svn_client_ls3(dir_url, _rev2optrev(rev),
|
||||
_rev2optrev(rev), 0, self.ctx)
|
||||
locker = locks.has_key(path_parts[-1]) \
|
||||
and locks[path_parts[-1]].owner or ''
|
||||
|
||||
cross_copies = options.get('svn_cross_copies', 0)
|
||||
client.svn_client_log([dir_url], _rev2optrev(rev), _rev2optrev(1),
|
||||
1, not cross_copies, lc.add_log, self.ctx)
|
||||
|
@ -289,6 +295,7 @@ class RemoteSubversionRepository(vclib.Repository):
|
|||
revs.sort()
|
||||
prev = None
|
||||
for rev in revs:
|
||||
rev.lockinfo = locker
|
||||
rev.prev = prev
|
||||
prev = rev
|
||||
|
||||
|
|
|
@ -174,7 +174,7 @@ def _get_history(svnrepos, full_name, rev, options={}):
|
|||
return history.histories
|
||||
|
||||
|
||||
def _log_helper(svnrepos, rev, path):
|
||||
def _log_helper(svnrepos, rev, path, lockinfo):
|
||||
rev_root = fs.revision_root(svnrepos.fs_ptr, rev)
|
||||
|
||||
# Was this path@rev the target of a copy?
|
||||
|
@ -189,14 +189,24 @@ def _log_helper(svnrepos, rev, path):
|
|||
entry = Revision(rev, date, author, msg, size, path,
|
||||
copyfrom_path and _cleanup_path(copyfrom_path),
|
||||
copyfrom_rev)
|
||||
entry.lockinfo = lockinfo
|
||||
return entry
|
||||
|
||||
|
||||
def _fetch_log(svnrepos, full_name, which_rev, options):
|
||||
revs = []
|
||||
lockinfo = None
|
||||
|
||||
# See is this path is locked.
|
||||
try:
|
||||
lock = fs.get_lock(svnrepos.fs_ptr, full_name)
|
||||
if lock:
|
||||
lockinfo = lock.owner
|
||||
except NameError:
|
||||
pass
|
||||
|
||||
if options.get('svn_latest_log', 0):
|
||||
rev = _log_helper(svnrepos, which_rev, full_name)
|
||||
rev = _log_helper(svnrepos, which_rev, full_name, lockinfo)
|
||||
if rev:
|
||||
revs.append(rev)
|
||||
else:
|
||||
|
@ -205,7 +215,8 @@ def _fetch_log(svnrepos, full_name, which_rev, options):
|
|||
history_revs.sort()
|
||||
history_revs.reverse()
|
||||
for history_rev in history_revs:
|
||||
rev = _log_helper(svnrepos, history_rev, history_set[history_rev])
|
||||
rev = _log_helper(svnrepos, history_rev, history_set[history_rev],
|
||||
lockinfo)
|
||||
if rev:
|
||||
revs.append(rev)
|
||||
return revs
|
||||
|
|
|
@ -2034,6 +2034,7 @@ def view_log(request):
|
|||
entry.ago = html_time(request, rev.date, 1)
|
||||
entry.log = htmlify(rev.log or "", cfg.options.mangle_email_addresses)
|
||||
entry.size = rev.size
|
||||
entry.lockinfo = rev.lockinfo
|
||||
entry.branch_point = None
|
||||
entry.next_main = None
|
||||
entry.orig_path = None
|
||||
|
|
Binary file not shown.
After Width: | Height: | Size: 303 B |
|
@ -6,6 +6,7 @@
|
|||
[for entries]
|
||||
[if-index entries first][define first_revision][entries.rev][end][end]
|
||||
[if-index entries last][define last_revision][entries.rev][end][end]
|
||||
|
||||
<div>
|
||||
<hr />
|
||||
|
||||
|
@ -97,6 +98,10 @@
|
|||
[end]
|
||||
[end]
|
||||
|
||||
[if-any entries.lockinfo]
|
||||
<br />Lock status: <img src="[docroot]/images/lock.png" alt="Locked" width="16" height="16" /> [entries.lockinfo]
|
||||
[end]
|
||||
|
||||
[is entries.state "dead"]
|
||||
<br /><strong><em>FILE REMOVED</em></strong>
|
||||
[else]
|
||||
|
|
|
@ -147,9 +147,14 @@
|
|||
</tr>
|
||||
<tr class="vc_row_[if-index entries even]even[else]odd[end]">
|
||||
<td colspan=5>
|
||||
|
||||
[if-any entries.lockinfo]
|
||||
<strong>Lock status</strong>: <img src="[docroot]/images/lock.png" alt="Locked" width="16" height="16" /> [entries.lockinfo]<br />
|
||||
[end]
|
||||
|
||||
[is roottype "svn"]
|
||||
[if-any entries.orig_path]
|
||||
Original Path: <a href="[entries.orig_href]"><em>[entries.orig_path]</em></a><br />
|
||||
<strong>Original Path</strong>: <a href="[entries.orig_href]"><em>[entries.orig_path]</em></a><br />
|
||||
[end]
|
||||
|
||||
[if-any entries.size]
|
||||
|
|
Loading…
Reference in New Issue