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-e597b4017df7
remotes/merged-file-views
cmpilato 2008-02-12 19:41:19 +00:00
parent 2a9584a0fb
commit d620498e9e
9 changed files with 77 additions and 22 deletions

View File

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

View File

@ -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
taginfo = { } # tag name => number
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

View File

@ -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,13 +214,17 @@ class TreeSink(rcsparse.Sink):
self.tags = { }
self.head = None
self.default_branch = None
self.lockinfo = { }
def set_head_revision(self, revision):
self.head = revision
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

View File

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

View File

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

View File

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

View File

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

View File

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