1
0
mirror of https://github.com/vitalif/viewvc-4intranet synced 2019-04-16 04:14:59 +03:00

Compare commits

..

52 Commits
V0_6 ... V0_7

Author SHA1 Message Date
(no author)
f7920e796c This commit was manufactured by cvs2svn to create tag 'V0_7'.
git-svn-id: http://viewvc.tigris.org/svn/viewvc/tags/V0_7@197 8cb11bc2-c004-0410-86c3-e597b4017df7
2001-05-30 09:19:18 +00:00
gstein
02f2243cc7 *) updated for new CVS site
*) use cvs export and require a tag


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@196 8cb11bc2-c004-0410-86c3-e597b4017df7
2001-05-30 09:19:18 +00:00
gstein
8766cf00ca rolling 0.7
git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@195 8cb11bc2-c004-0410-86c3-e597b4017df7
2001-05-30 09:15:03 +00:00
gstein
ba039d5a8f add a reference to Karl's book. delete a broken link.
git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@194 8cb11bc2-c004-0410-86c3-e597b4017df7
2001-05-30 08:54:12 +00:00
gstein
007ad51b2c change web site references from www.lyra.org/viewcvs/ to the new
viewcvs.sourceforge.net/ site.


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@193 8cb11bc2-c004-0410-86c3-e597b4017df7
2001-05-30 08:49:19 +00:00
gstein
c3d12bb0c8 add a persistent URL format for reaching the HEAD revision
git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@192 8cb11bc2-c004-0410-86c3-e597b4017df7
2001-05-30 08:37:17 +00:00
gstein
d0de5e7ad0 add the two new lib/ modules.
git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@191 8cb11bc2-c004-0410-86c3-e597b4017df7
2001-05-30 08:18:28 +00:00
gstein
4a00a0bb4f add an item for the next release
git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@190 8cb11bc2-c004-0410-86c3-e597b4017df7
2001-05-30 08:16:38 +00:00
gstein
abb4a468fc The single/double find stuff was stupid. single would always be <= double.
Looking for a double is simply looking at the character following the '@'.
Removing the second find also solved some cache-thrashing that occurred with
big CHUNK_SIZE values. Plus a general speedup. :-)


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@189 8cb11bc2-c004-0410-86c3-e597b4017df7
2001-05-14 10:49:39 +00:00
gstein
cc3807f964 More speedups.
* avoid lstrip() -- it can take a while on large strings
* use loops instead of more complex ops. loops have a higher per-iteration
  cost, but a lower constant time. since N is small, it is a win.
* avoid "re" altogether; use string.digits in class Parser

(rcsparse is now over 10x faster since I started optimizing)


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@188 8cb11bc2-c004-0410-86c3-e597b4017df7
2001-05-14 08:44:33 +00:00
gstein
3bff6b7378 More performance tweaks.
git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@187 8cb11bc2-c004-0410-86c3-e597b4017df7
2001-05-14 05:53:35 +00:00
gstein
fc6d80e2fb Speed up the get() method by being smarter about regular expression use,
avoiding slicing of strings, and more fine-tuned parsing.

(some debug stuff, too; this will disappear soon; just checkpointing now)


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@186 8cb11bc2-c004-0410-86c3-e597b4017df7
2001-05-13 02:52:26 +00:00
gstein
425ae2e8ec Speed up the log extraction by avoiding regular expressions (there are
simple equivalents which are faster).

Add a test function for profiling.


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@185 8cb11bc2-c004-0410-86c3-e597b4017df7
2001-05-13 02:50:24 +00:00
gstein
c2a29c83cd save a little test program for comparing rcsparse vs rlog output parsing
git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@184 8cb11bc2-c004-0410-86c3-e597b4017df7
2001-05-13 00:16:42 +00:00
gstein
799816c21f minor nit: fetch_log's last return value is a list, not a dict.
git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@183 8cb11bc2-c004-0410-86c3-e597b4017df7
2001-05-13 00:13:12 +00:00
gstein
e3dbdb4fcc Update copyright years to include 2001.
git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@182 8cb11bc2-c004-0410-86c3-e597b4017df7
2001-05-12 22:51:02 +00:00
gstein
c28afba169 removed unneeded #! marker
git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@181 8cb11bc2-c004-0410-86c3-e597b4017df7
2001-05-12 12:33:17 +00:00
gstein
d790f07d2c Apply a patch from apache.org: watch out (and recover) for files which have
"illegal" timestamps in them.


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@180 8cb11bc2-c004-0410-86c3-e597b4017df7
2001-05-12 12:26:46 +00:00
gstein
edf252fb2f Now, make the appropriate changes to get the split CGI script/library to
actually work: move imports, wrap run_cgi() around the logic in viewcvs.py,
shift around the CONF_PATHNAME stuff, etc.


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@179 8cb11bc2-c004-0410-86c3-e597b4017df7
2001-05-12 12:22:51 +00:00
gstein
6942dd6b4b Slice a big chunk out of viewcvs.cgi and move it to viewcvs.py.
Absolutely no other changes. No additions, no reformat, no nothing...


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@178 8cb11bc2-c004-0410-86c3-e597b4017df7
2001-05-12 12:05:08 +00:00
gstein
a75f32fc3c Older versions of Python do not like lists passed to mktime(). Ensure that
we pass a tuple.

Fixes bug #421282
Submitted by: mjpieters@users.sourceforge.net


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@177 8cb11bc2-c004-0410-86c3-e597b4017df7
2001-05-12 11:42:08 +00:00
gstein
e243a0e1ad Record that we couldn't stat the file, or that it is unreadable. This allows
us to actually tell the user about it (and do so!).

Also removed a spurious try/except in generate_tarball; get_file_data()
shouldn't be raising one any more.


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@176 8cb11bc2-c004-0410-86c3-e597b4017df7
2001-05-12 11:34:17 +00:00
gstein
755e4e74c3 In directory views (and tarballs), don't include files or dirs that we
cannot read.

Reported by: Jaime E. Villate <villate@fe.up.pt>


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@175 8cb11bc2-c004-0410-86c3-e597b4017df7
2001-05-12 10:23:59 +00:00
gstein
a46b9dd3ba The (colored) links need to specify the diff_format=h option. Also correct a
spelling/typo and add missing right parents.

Submitted by: Chris Tillman <tillman@azstarnet.com>


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@174 8cb11bc2-c004-0410-86c3-e597b4017df7
2001-05-12 09:25:53 +00:00
gstein
ab987dc6fa *) some updates for the move to SourceForge.
*) add information about ViewCVS' increased security


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@173 8cb11bc2-c004-0410-86c3-e597b4017df7
2001-05-11 21:21:50 +00:00
akr
a6ac1d1892 handle FreeBSD's rlog output which has extra "----------------------------\n".
git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@172 8cb11bc2-c004-0410-86c3-e597b4017df7
2001-05-11 07:24:15 +00:00
akr
945cb91e38 (link_includes): use sticky parameters for a link.
git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@171 8cb11bc2-c004-0410-86c3-e597b4017df7
2001-05-10 09:12:45 +00:00
gstein
262f3569c7 way different nowadays, so make the header reflect current reality. update
commentary, and keep appropriate recognition of Curt's work.


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@170 8cb11bc2-c004-0410-86c3-e597b4017df7
2001-05-09 11:35:54 +00:00
gstein
1b358fc88d switch from a line-oriented processing to buffer-oriented. provides
approximately 3x performance increase.


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@169 8cb11bc2-c004-0410-86c3-e597b4017df7
2001-05-09 11:32:47 +00:00
gstein
455faa1fe6 switch to a TokenStream plus the parser. provides for better isolation of
the token parsing semantics.


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@168 8cb11bc2-c004-0410-86c3-e597b4017df7
2001-05-09 10:30:12 +00:00
gstein
01facd113b commit a checkpoint, with some tools, before doing some heavy lifting
git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@167 8cb11bc2-c004-0410-86c3-e597b4017df7
2001-05-09 09:23:00 +00:00
gstein
67daa9e5e2 Extract the RCS parsing code into a separate module. It now uses a "sink"
model, sending events/info to the blame script.

(this allows the RCS parser to be used in numerous contexts by simply
 switching the Sink that is used)


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@166 8cb11bc2-c004-0410-86c3-e597b4017df7
2001-05-08 19:34:58 +00:00
akr
03a5620947 (_re_rewrite_url): recognize fragment identifier.
http://sourceforge.net/tracker/?func=detail&atid=318760&aid=421284&group_id=18760


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@165 8cb11bc2-c004-0410-86c3-e597b4017df7
2001-05-06 10:06:23 +00:00
akr
424521d40e (get_file_data): ignore files which causes failures on stat(2) such
as dangling symlinks.


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@164 8cb11bc2-c004-0410-86c3-e597b4017df7
2001-05-06 09:13:01 +00:00
akr
1eeb39f264 (html_time): Since very old timestamp (82 years, 6 months in this case)
causes overflow of plain integer, use long integer.

use `year' correctly for these old timestamps.

http://sourceforge.net/tracker/index.php?func=detail&aid=418428&group_id=1&atid=100001
http://sourceforge.net/tracker/index.php?func=detail&aid=421096&group_id=18760&atid=118760


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@163 8cb11bc2-c004-0410-86c3-e597b4017df7
2001-05-05 19:52:42 +00:00
akr
7aa5c33589 (urlencode): Don't add redundant '?'.
http://sourceforge.net/tracker/?func=detail&atid=118760&aid=421281&group_id=18760


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@162 8cb11bc2-c004-0410-86c3-e597b4017df7
2001-05-05 18:02:00 +00:00
gstein
60236803e4 This background will be needed when the website moves to SF.
git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@161 8cb11bc2-c004-0410-86c3-e597b4017df7
2001-05-02 19:50:51 +00:00
gstein
a26cfff0ad fix viewcvs-browsing link on the page
git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@160 8cb11bc2-c004-0410-86c3-e597b4017df7
2001-05-02 19:27:36 +00:00
akr
f0c34a715d fixed at viewcvs.cgi:1.57.
git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@159 8cb11bc2-c004-0410-86c3-e597b4017df7
2001-05-01 05:34:41 +00:00
akr
4cb1282b70 change option name for tarball generation from tarball' to allow_tar'.
git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@158 8cb11bc2-c004-0410-86c3-e597b4017df7
2001-04-28 10:38:16 +00:00
akr
f34424ca20 make tarball generation configurable.
git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@157 8cb11bc2-c004-0410-86c3-e597b4017df7
2001-04-28 08:50:28 +00:00
akr
bc6851ea6f separate branch and non-branch tags in tag menu.
git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@156 8cb11bc2-c004-0410-86c3-e597b4017df7
2001-04-27 09:56:18 +00:00
akr
3b10a1763f tarball generation implemented.
git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@155 8cb11bc2-c004-0410-86c3-e597b4017df7
2001-04-27 09:25:38 +00:00
akr
329d20633a use state instead of Attic/ to determine file existence if a tag is
specified.


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@154 8cb11bc2-c004-0410-86c3-e597b4017df7
2001-04-27 08:26:14 +00:00
akr
5251065e6d fix blame for empty deltatext especially 1.1 to 1.1.1.1.
git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@153 8cb11bc2-c004-0410-86c3-e597b4017df7
2001-04-27 07:05:49 +00:00
akr
3d6f71ce00 couldn't handle multiple RCS-encoded string in single line.
git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@152 8cb11bc2-c004-0410-86c3-e597b4017df7
2001-04-27 06:51:36 +00:00
akr
1a69430064 couldn't scan RCS-encoded string ends with @.
git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@151 8cb11bc2-c004-0410-86c3-e597b4017df7
2001-04-27 06:44:20 +00:00
akr
050ad1f8fe add sticky info to blame link to fix problem with non-default repository.
git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@150 8cb11bc2-c004-0410-86c3-e597b4017df7
2001-04-27 06:12:33 +00:00
akr
3965ce9221 ignore CVS directory in the repository which is used for fileattr.
git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@149 8cb11bc2-c004-0410-86c3-e597b4017df7
2001-04-27 06:03:10 +00:00
akr
12003f27b5 branch selection fix. branchpoint entry may precede revisions on the
branch in rlog output.


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@148 8cb11bc2-c004-0410-86c3-e597b4017df7
2001-04-27 05:53:46 +00:00
gstein
b0b1b5603e Revamp the "co" output processing to give clearer errors. Be wary of
warnings that may be generated when doing the "co".


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@147 8cb11bc2-c004-0410-86c3-e597b4017df7
2001-04-10 06:08:11 +00:00
gstein
2b8cc9d34c *) ignore a warning from rlog
*) fix the "hide_cvsroot" option flag processing


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@146 8cb11bc2-c004-0410-86c3-e597b4017df7
2001-04-10 05:36:06 +00:00
28 changed files with 3340 additions and 2557 deletions

View File

@@ -174,7 +174,7 @@ If you've trouble to make viewcvs.cgi work:
o check the ViewCVS home page:
http://www.lyra.org/viewcvs/
http://viewcvs.sourceforge.net/
o review the ViewCVS mailing list archive to see if somebody else had
the same problem, and it was solved:

7
TODO
View File

@@ -27,12 +27,13 @@ TODO ITEMS
*) add a page that describes how to reach anonymous CVS for ViewCVS
*) have a "check" mode that verifies binaries are available on rcs_path
-> alternately (probably?): use rcsparse rather than external tools
KNOWN BUGS
----------
*) from Harri Pasanen, Feb 7: when hideattic is set, files added in a
branch are not visible.
*) from Dieter Deyke, Jan 12: if the CVS revisions differ by just a
keyword, then the diff output chokes.

View File

@@ -1,22 +1,22 @@
#!/usr/bin/python
# -*- Mode: python -*-
#
# Copyright (C) 2000 The ViewCVS Group. All Rights Reserved.
# Copyright (C) 2000-2001 The ViewCVS Group. All Rights Reserved.
#
# By using this file, you agree to the terms and conditions set forth in
# the LICENSE.html file which can be found at the top level of the ViewCVS
# distribution or at http://www.lyra.org/viewcvs/license-1.html.
# distribution or at http://viewcvs.sourceforge.net/license-1.html.
#
# Contact information:
# Greg Stein, PO Box 760, Palo Alto, CA, 94302
# gstein@lyra.org, http://www.lyra.org/viewcvs/
# gstein@lyra.org, http://viewcvs.sourceforge.net/
#
# -----------------------------------------------------------------------
#
# CGI script to process and display queries to CVSdb
#
# This script is part of the ViewCVS package. More information can be
# found at http://www.lyra.org/viewcvs/.
# found at http://viewcvs.sourceforge.net/.
#
# -----------------------------------------------------------------------
#

View File

@@ -1,15 +1,15 @@
#!/usr/bin/python
# -*- Mode: python -*-
#
# Copyright (C) 2000 The ViewCVS Group. All Rights Reserved.
# Copyright (C) 2000-2001 The ViewCVS Group. All Rights Reserved.
#
# By using this file, you agree to the terms and conditions set forth in
# the LICENSE.html file which can be found at the top level of the ViewCVS
# distribution or at http://www.lyra.org/viewcvs/license-1.html.
# distribution or at http://viewcvs.sourceforge.net/license-1.html.
#
# Contact information:
# Greg Stein, PO Box 760, Palo Alto, CA, 94302
# gstein@lyra.org, http://www.lyra.org/viewcvs/
# gstein@lyra.org, http://viewcvs.sourceforge.net/
#
# -----------------------------------------------------------------------
#

File diff suppressed because it is too large Load Diff

View File

@@ -3,7 +3,7 @@
# Configuration file for ViewCVS
#
# Information on ViewCVS is located at the following web site:
# http://www.lyra.org/viewcvs/
# http://viewcvs.sourceforge.net/
#
#---------------------------------------------------------------------------
@@ -240,7 +240,7 @@ long_intro =
</p>
<p>
This script
(<a href="http://www.lyra.org/viewcvs/">ViewCVS</a>)
(<a href="http://viewcvs.sourceforge.net/">ViewCVS</a>)
has been written by Greg Stein
&lt;<a href="mailto:gstein@lyra.org">gstein@lyra.org</a>&gt;
based on the
@@ -252,7 +252,7 @@ long_intro =
Licence</a>.
If you would like to use this CGI script on your own web server and
CVS tree, see Greg's
<a href="http://www.lyra.org/viewcvs/">ViewCVS distribution
<a href="http://viewcvs.sourceforge.net/">ViewCVS distribution
site</a>.
Please send any suggestions, comments, etc. to
<a href="mailto:gstein@lyra.org">Greg Stein</a>.
@@ -262,9 +262,9 @@ doc_info =
<h3>CVS Documentation</h3>
<blockquote>
<p>
<a href="http://cvsbook.red-bean.com/">Karl Fogel's CVS book</a><br>
<a href="http://www.loria.fr/~molli/cvs/doc/cvs_toc.html">CVS
User's Guide</a><br>
<a href="http://www.arc.unm.edu/~rsahu/cvs.html">CVS Tutorial</a><br>
<a href="http://cellworks.washington.edu/pub/docs/cvs/tutorial/cvs_tutorial_1.html">Another CVS tutorial</a><br>
<a href="http://www.csc.calpoly.edu/~dbutler/tutorials/winter96/cvs/">Yet
another CVS tutorial (a little old, but nice)</a><br>
@@ -434,6 +434,12 @@ enscript_path =
disable_enscript_lang =
# disable_enscript_lang = perl, cpp
#
# ViewCVS can generate tarball from a repository on the fly.
#
allow_tar = 0
# allow_tar = 1
#---------------------------------------------------------------------------
[vhosts]
### DOC

View File

@@ -1,16 +1,16 @@
#!/usr/local/bin/python
# -*-python-*-
#
# Copyright (C) 2000 The ViewCVS Group. All Rights Reserved.
# Copyright (C) 2000-2001 The ViewCVS Group. All Rights Reserved.
# Copyright (C) 2000 Curt Hagenlocher <curt@hagenlocher.org>
#
# By using this file, you agree to the terms and conditions set forth in
# the LICENSE.html file which can be found at the top level of the ViewCVS
# distribution or at http://www.lyra.org/viewcvs/license-1.html.
# distribution or at http://viewcvs.sourceforge.net/license-1.html.
#
# Contact information:
# Greg Stein, PO Box 760, Palo Alto, CA, 94302
# gstein@lyra.org, http://www.lyra.org/viewcvs/
# gstein@lyra.org, http://viewcvs.sourceforge.net/
#
# -----------------------------------------------------------------------
#
@@ -21,7 +21,7 @@
#
# This software is being maintained as part of the ViewCVS project.
# Information is available at:
# http://www.lyra.org/viewcvs/
# http://viewcvs.sourceforge.net/
#
# This file is based on the cvsblame.pl portion of the Bonsai CVS tool,
# developed by Steve Lamm for Netscape Communications Corporation. More
@@ -40,17 +40,10 @@ import re
import time
import math
import cgi
import rcsparse
path_sep = os.path.normpath('/')[-1]
class CVSParser:
class CVSParser(rcsparse.Sink):
# Precompiled regular expressions
nonws_token = re.compile('^([^;@][^;\\s]*)\\s*')
semic_token = re.compile('^;\\s*')
rcsen_token = re.compile('^@([^@]*)')
undo_escape = re.compile('@@')
single_at = re.compile('([^@]|^)@([^@]|$)')
rcs_tree = re.compile('^\\d')
trunk_rev = re.compile('^[0-9]+\\.[0-9]+$')
last_branch = re.compile('(.*)\\.[0-9]+')
is_branch = re.compile('(.*)\\.0\\.([0-9]+)')
@@ -63,9 +56,6 @@ class CVSParser:
self.Reset()
def Reset(self):
self.line_buffer = ''
self.rcsfile = None
self.debug = 0
self.last_revision = {}
self.prev_revision = {}
self.revision_date = {}
@@ -73,7 +63,6 @@ class CVSParser:
self.revision_branches = {}
self.next_delta = {}
self.prev_delta = {}
self.feof = 0
self.tag_revision = {}
self.revision_symbolic_name = {}
self.timestamp = {}
@@ -85,69 +74,6 @@ class CVSParser:
self.lines_added = {}
self.lines_removed = {}
# Get the next token from the RCS file
def get_token(self):
# Erase all-whitespace lines
while len(self.line_buffer) == 0:
self.line_buffer = self.rcsfile.readline()
if self.line_buffer == '':
raise RuntimeError, 'EOF'
self.line_buffer = string.lstrip(self.line_buffer)
# A string of non-whitespace characters is a token
match = self.nonws_token.match(self.line_buffer)
if match:
self.line_buffer = self.nonws_token.sub('', self.line_buffer)
return match.group(1)
# ...and so is a single semicolon
if self.semic_token.match(self.line_buffer):
self.line_buffer = self.semic_token.sub('', self.line_buffer)
return ';'
# ...or an RCS-encoded string that starts with an @ character
match = self.rcsen_token.match(self.line_buffer)
self.line_buffer = self.rcsen_token.sub('', self.line_buffer)
token = match.group(1)
# Detect single @ character used to close RCS-encoded string
while string.find(self.line_buffer, '@') < 0 or not self.single_at.search(self.line_buffer):
token = token + self.line_buffer
self.line_buffer = self.rcsfile.readline()
if self.line_buffer == '':
raise RuntimeError, 'EOF'
# Retain the remainder of the line after the terminating @ character
i = string.rindex(self.line_buffer, '@')
token = token + self.line_buffer[:i]
self.line_buffer = self.line_buffer[i+1:]
# Undo escape-coding of @ characters.
token = self.undo_escape.sub('@', token)
# Digest any extra blank lines
while len(self.line_buffer) == 0 or self.line_buffer == '\n':
self.line_buffer = self.rcsfile.readline()
if self.line_buffer == '':
self.feof = 1
break
if token[-1:] == '\n':
token = token[:-1]
return token
# Try to match the next token from the input buffer
def match_token(self, match):
token = self.get_token()
if token != match:
raise RuntimeError, ('Unexpected parsing error in RCS file.\n' +
'Expected token: %s, but saw: %s' % (match, token))
# Push RCS token back into the input buffer.
def unget_token(self, token):
self.line_buffer = token + " " + self.line_buffer
# Map a tag to a numerical revision number. The tag can be a symbolic
# branch tag, a symbolic revision tag, or an ordinary numerical
# revision number.
@@ -182,6 +108,13 @@ class CVSParser:
return ancestors
# Split deltatext specified by rev to each line.
def deltatext_split(self, rev):
lines = string.split(self.revision_deltatext[rev], '\n')
if lines[-1] == '':
del lines[-1]
return lines
# Extract the given revision from the digested RCS file.
# (Essentially the equivalent of cvs up -rXXX)
def extract_revision(self, revision):
@@ -195,12 +128,12 @@ class CVSParser:
path.reverse()
path = path[1:] # Get rid of head revision
text = string.split(self.revision_deltatext[self.head_revision], '\n')
text = self.deltatext_split(self.head_revision)
# Iterate, applying deltas to previous revision
for revision in path:
adjust = 0
diffs = string.split(self.revision_deltatext[revision], '\n')
diffs = self.deltatext_split(revision)
self.lines_added[revision] = 0
self.lines_removed[revision] = 0
lines_added_now = 0
@@ -235,49 +168,25 @@ class CVSParser:
self.lines_removed[revision] = self.lines_removed[revision] + lines_removed_now
return text
def parse_rcs_admin(self):
while 1:
# Read initial token at beginning of line
token = self.get_token()
def set_head_revision(self, revision):
self.head_revision = revision
# We're done once we reach the description of the RCS tree
if self.rcs_tree.match(token):
self.unget_token(token)
return
def set_principal_branch(self, branch_name):
self.principal_branch = branch_name
# print "token:", token
def define_tag(self, name, revision):
# Create an associate array that maps from tag name to
# revision number and vice-versa.
self.tag_revision[name] = revision
if token == "head":
self.head_revision = self.get_token()
self.get_token() # Eat semicolon
elif token == "branch":
self.principal_branch = self.get_token()
self.get_token() # Eat semicolon
elif token == "symbols":
# Create an associate array that maps from tag name to
# revision number and vice-versa.
while 1:
tag = self.get_token()
if tag == ';':
break
(tag_name, tag_rev) = string.split(tag, ':')
self.tag_revision[tag_name] = tag_rev
self.revision_symbolic_name[tag_rev] = tag_name
elif token == "comment":
self.file_description = self.get_token()
self.get_token() # Eat semicolon
### actually, this is a bit bogus... a rev can have multiple names
self.revision_symbolic_name[revision] = name
# Ignore all these other fields - We don't care about them.
elif token in ("locks", "strict", "expand", "access"):
while 1:
tag = self.get_token()
if tag == ';':
break
else:
pass
# warn("Unexpected RCS token: $token\n")
def set_comment(self, comment):
self.file_description = comment
raise RuntimeError, "Unexpected EOF";
def set_description(self, description):
self.rcs_file_description = description
# Construct dicts that represent the topology of the RCS tree
# and other arrays that contain info about individual revisions.
@@ -301,91 +210,47 @@ class CVSParser:
# Also creates self.last_revision, keyed by a branch revision number, which
# indicates the latest revision on a given branch,
# e.g. self.last_revision{"1.2.8"} == 1.2.8.5
def define_revision(self, revision, timestamp, author, state,
branches, next):
self.tag_revision[revision] = revision
branch = self.last_branch.match(revision).group(1)
self.last_revision[branch] = revision
def parse_rcs_tree(self):
while 1:
revision = self.get_token()
#self.revision_date[revision] = date
self.timestamp[revision] = timestamp
# End of RCS tree description ?
if revision == 'desc':
self.unget_token(revision)
return
# Pretty print the date string
ltime = time.localtime(self.timestamp[revision])
formatted_date = time.strftime("%d %b %Y %H:%M", ltime)
self.revision_ctime[revision] = formatted_date
# Save age
self.revision_age[revision] = ((time.time() - self.timestamp[revision])
/ self.SECONDS_PER_DAY)
# save author
self.revision_author[revision] = author
# ignore the state
# process the branch information
branch_text = ''
for branch in branches:
self.prev_revision[branch] = revision
self.next_delta[revision] = branch
self.prev_delta[branch] = revision
branch_text = branch_text + branch + ''
self.revision_branches[revision] = branch_text
# process the "next revision" information
if next:
self.next_delta[revision] = next
self.prev_delta[next] = revision
is_trunk_revision = self.trunk_rev.match(revision) is not None
self.tag_revision[revision] = revision
branch = self.last_branch.match(revision).group(1)
self.last_revision[branch] = revision
# Parse date
self.match_token('date')
date = self.get_token()
self.revision_date[revision] = date
self.match_token(';')
# Convert date into timestamp
date_fields = string.split(date, '.') + ['0', '0', '0']
date_fields = map(string.atoi, date_fields)
if date_fields[0] < 100:
date_fields[0] = date_fields[0] + 1900
self.timestamp[revision] = time.mktime(date_fields)
# Pretty print the date string
ltime = time.localtime(self.timestamp[revision])
formatted_date = time.strftime("%d %b %Y %H:%M", ltime)
self.revision_ctime[revision] = formatted_date
# Save age
self.revision_age[revision] = (
(time.time() - self.timestamp[revision]) / self.SECONDS_PER_DAY)
# Parse author
self.match_token('author')
author = self.get_token()
self.revision_author[revision] = author
self.match_token(';')
# Parse state
self.match_token('state')
while self.get_token() != ';':
pass
# Parse branches
self.match_token('branches')
branches = ''
while 1:
token = self.get_token()
if token == ';':
break
self.prev_revision[token] = revision
self.prev_delta[token] = revision
branches = branches + token + ' '
self.revision_branches[revision] = branches
# Parse revision of next delta in chain
self.match_token('next')
next = ''
token = self.get_token()
if token != ';':
next = token
self.get_token() # Eat semicolon
self.next_delta[revision] = next
self.prev_delta[next] = revision
if is_trunk_revision:
self.prev_revision[revision] = next
else:
self.prev_revision[next] = revision
if self.debug >= 3:
print "<pre>revision =", revision
print "date = ", date
print "author = ", author
print "branches = ", branches
print "next = ", next + "</pre>\n"
def parse_rcs_description(self):
self.match_token('desc')
self.rcs_file_description = self.get_token()
if is_trunk_revision:
self.prev_revision[revision] = next
else:
self.prev_revision[next] = revision
# Construct associative arrays containing info about individual revisions.
#
@@ -398,36 +263,9 @@ class CVSParser:
# revision if this revision is on the trunk or
# relative to its immediate predecessor if this
# revision is on a branch.
def parse_rcs_deltatext(self):
while not self.feof:
revision = self.get_token()
if self.debug >= 3:
print "Reading delta for revision:", revision
self.match_token('log')
self.revision_log[revision] = self.get_token()
self.match_token('text')
self.revision_deltatext[revision] = self.get_token()
def parse_rcs_file(self):
if self.debug >= 2:
print "Reading RCS admin..."
self.parse_rcs_admin()
if self.debug >= 2:
print "Reading RCS revision tree topology..."
self.parse_rcs_tree()
if self.debug >= 3:
print "<pre>Keys:\n"
for i in self.tag_revision.keys():
print "yoyuo %s: %s" % (i, self.tag_revision[i])
print "</pre>"
self.parse_rcs_description()
if self.debug >= 2:
print "Reading RCS revision deltas..."
self.parse_rcs_deltatext()
if self.debug >= 2:
print "Done reading RCS file..."
def set_revision_info(self, revision, log, text):
self.revision_log[revision] = log
self.revision_deltatext[revision] = text
def parse_cvs_file(self, rcs_pathname, opt_rev = None, opt_m_timestamp = None):
# Args in: opt_rev - requested revision
@@ -438,13 +276,13 @@ class CVSParser:
# CheckHidden(rcs_pathname);
try:
self.rcsfile = open(rcs_pathname, 'r')
rcsfile = open(rcs_pathname, 'r')
except:
raise RuntimeError, ('error: %s appeared to be under CVS control, ' +
'but the RCS file is inaccessible.') % rcs_pathname
self.parse_rcs_file()
self.rcsfile.close()
rcsparse.Parser().parse(rcsfile, self)
rcsfile.close()
if opt_rev in [None, '', 'HEAD']:
# Explicitly specified topmost revision in tree
@@ -470,14 +308,14 @@ class CVSParser:
# first revision.
line_count = 0
if self.revision_deltatext.get(self.head_revision):
tmp_array = string.split(self.revision_deltatext[self.head_revision], '\n')
tmp_array = self.deltatext_split(self.head_revision)
line_count = len(tmp_array)
skip = 0
rev = self.prev_revision.get(self.head_revision)
while rev:
diffs = string.split(self.revision_deltatext[rev], '\n')
diffs = self.deltatext_split(rev)
for command in diffs:
dmatch = self.d_command.match(command)
amatch = self.a_command.match(command)
@@ -522,7 +360,7 @@ class CVSParser:
is_trunk_revision = self.trunk_rev.match(revision) is not None
if is_trunk_revision:
diffs = string.split(self.revision_deltatext[last_revision], '\n')
diffs = self.deltatext_split(last_revision)
# Revisions on the trunk specify deltas that transform a
# revision into an earlier revision, so invert the translation
@@ -555,7 +393,7 @@ class CVSParser:
# the trunk. They specify deltas that transform a revision
# into a later revision.
adjust = 0
diffs = string.split(self.revision_deltatext[revision], '\n')
diffs = self.deltatext_split(revision)
for command in diffs:
if skip > 0:
skip = skip - 1
@@ -589,21 +427,24 @@ class CVSParser:
re_includes = re.compile('\\#(\\s*)include(\\s*)"(.*?)"')
re_filename = re.compile('(.*[\\\\/])?(.+)')
def link_includes(text, root, rcs_path):
def link_includes(text, root, rcs_path, sticky = None):
match = re_includes.match(text)
if match:
incfile = match.group(3)
for rel_path in ('', 'Attic', '..'):
trial_root = os.path.join(rcs_path, rel_path)
file = os.path.normpath('%s%s%s%s%s,v' % (root, path_sep, trial_root, path_sep, incfile))
file = os.path.join(root, trial_root)
file = os.path.normpath(os.path.join(file, incfile + ',v'))
if os.access(file, os.F_OK):
url = os.path.join(rel_path, incfile)
if sticky:
url = url + '?' + sticky
return '#%sinclude%s"<a href="%s">%s</a>"' % \
(match.group(1), match.group(2),
os.path.join(rel_path, incfile), incfile)
(match.group(1), match.group(2), url, incfile)
return text
def make_html(root, rcs_path, opt_rev = None):
filename = root + path_sep + rcs_path
def make_html(root, rcs_path, opt_rev = None, sticky = None):
filename = os.path.join(root, rcs_path)
parser = CVSParser()
revision = parser.parse_cvs_file(filename, opt_rev)
count = len(parser.revision_map)
@@ -649,7 +490,7 @@ def make_html(root, rcs_path, opt_rev = None):
# Add a link to traverse to included files
if 1: # opt_includes
thisline = link_includes(thisline, root, file_head)
thisline = link_includes(thisline, root, file_head, sticky)
output = ''
@@ -685,9 +526,11 @@ def make_html(root, rcs_path, opt_rev = None):
if parser.prev_revision.get(revision):
fname = file_tail[:-2] # strip the ",v"
### need the sticky options! need cvsroot if not-default
output = output + ' <a href="%s.diff?r1=%s&amp;r2=%s"' % \
(fname, parser.prev_revision[revision], revision)
url = '%s.diff?r1=%s&amp;r2=%s' % \
(fname, parser.prev_revision[revision], revision)
if sticky:
url = url + '&' + sticky
output = output + ' <a href="%s"' % (url, )
if 0: # use_layers
output = output + " onmouseover='return log(event,\"%s\",\"%s\");'" % (
parser.prev_revision[revision], revision)

View File

@@ -1,14 +1,14 @@
# -*- Mode: python -*-
#
# Copyright (C) 2000 The ViewCVS Group. All Rights Reserved.
# Copyright (C) 2000-2001 The ViewCVS Group. All Rights Reserved.
#
# By using this file, you agree to the terms and conditions set forth in
# the LICENSE.html file which can be found at the top level of the ViewCVS
# distribution or at http://www.lyra.org/viewcvs/license-1.html.
# distribution or at http://viewcvs.sourceforge.net/license-1.html.
#
# Contact information:
# Greg Stein, PO Box 760, Palo Alto, CA, 94302
# gstein@lyra.org, http://www.lyra.org/viewcvs/
# gstein@lyra.org, http://viewcvs.sourceforge.net/
#
# -----------------------------------------------------------------------
#

View File

@@ -1,14 +1,14 @@
# -*- Mode: python -*-
#
# Copyright (C) 2000 The ViewCVS Group. All Rights Reserved.
# Copyright (C) 2000-2001 The ViewCVS Group. All Rights Reserved.
#
# By using this file, you agree to the terms and conditions set forth in
# the LICENSE.html file which can be found at the top level of the ViewCVS
# distribution or at http://www.lyra.org/viewcvs/license-1.html.
# distribution or at http://viewcvs.sourceforge.net/license-1.html.
#
# Contact information:
# Greg Stein, PO Box 760, Palo Alto, CA, 94302
# gstein@lyra.org, http://www.lyra.org/viewcvs/
# gstein@lyra.org, http://viewcvs.sourceforge.net/
#
# -----------------------------------------------------------------------
#
@@ -38,7 +38,7 @@ except AttributeError:
keyvalue = [ ]
for key, value in dict.items():
keyvalue.append(quote(key) + '=' + quote(str(value)))
return '?' + string.join(keyvalue, '&')
return string.join(keyvalue, '&')
#
# time.strptime() is new to Python 1.5.2

View File

@@ -1,14 +1,14 @@
# -*- Mode: python -*-
#
# Copyright (C) 2000 The ViewCVS Group. All Rights Reserved.
# Copyright (C) 2000-2001 The ViewCVS Group. All Rights Reserved.
#
# By using this file, you agree to the terms and conditions set forth in
# the LICENSE.html file which can be found at the top level of the ViewCVS
# distribution or at http://www.lyra.org/viewcvs/license-1.html.
# distribution or at http://viewcvs.sourceforge.net/license-1.html.
#
# Contact information:
# Greg Stein, PO Box 760, Palo Alto, CA, 94302
# gstein@lyra.org, http://www.lyra.org/viewcvs/
# gstein@lyra.org, http://viewcvs.sourceforge.net/
#
# -----------------------------------------------------------------------
#
@@ -189,6 +189,7 @@ class Config:
self.options.use_enscript = 0
self.options.enscript_path = ''
self.options.disable_enscript_lang = ()
self.options.allow_tar = 0
self.text.long_intro = """\
<p>
@@ -205,7 +206,7 @@ class Config:
</p>
<p>
This script
(<a href="http://www.lyra.org/viewcvs/">ViewCVS</a>)
(<a href="http://viewcvs.sourceforge.net/">ViewCVS</a>)
has been written by Greg Stein
&lt;<a href="mailto:gstein@lyra.org">gstein@lyra.org</a>&gt;
based on the
@@ -216,7 +217,7 @@ class Config:
<a href="http://www.opensource.org/licenses/bsd-license.html">BSD-License</a>.
If you would like to use this CGI script on your own web server and
CVS tree, see Greg's
<a href="http://www.lyra.org/viewcvs/">ViewCVS distribution
<a href="http://viewcvs.sourceforge.net/">ViewCVS distribution
site</a>.
Please send any suggestions, comments, etc. to
<a href="mailto:gstein@lyra.org">Greg Stein</a>.
@@ -228,9 +229,9 @@ class Config:
<h3>CVS Documentation</h3>
<blockquote>
<p>
<a href="http://cvsbook.red-bean.com/">Karl Fogel's CVS book</a><br>
<a href="http://www.loria.fr/~molli/cvs/doc/cvs_toc.html">CVS
User's Guide</a><br>
<a href="http://www.arc.unm.edu/~rsahu/cvs.html">CVS Tutorial</a><br>
<a href="http://cellworks.washington.edu/pub/docs/cvs/tutorial/cvs_tutorial_1.html">Another CVS tutorial</a><br>
<a href="http://www.csc.calpoly.edu/~dbutler/tutorials/winter96/cvs/">Yet another CVS tutorial (a little old, but nice)</a><br>
<a href="http://www.cs.utah.edu/dept/old/texinfo/cvs/FAQ.txt">An old but very useful FAQ about CVS</a>

View File

@@ -1,14 +1,14 @@
# -*- Mode: python -*-
#
# Copyright (C) 2000 The ViewCVS Group. All Rights Reserved.
# Copyright (C) 2000-2001 The ViewCVS Group. All Rights Reserved.
#
# By using this file, you agree to the terms and conditions set forth in
# the LICENSE.html file which can be found at the top level of the ViewCVS
# distribution or at http://www.lyra.org/viewcvs/license-1.html.
# distribution or at http://viewcvs.sourceforge.net/license-1.html.
#
# Contact information:
# Greg Stein, PO Box 760, Palo Alto, CA, 94302
# gstein@lyra.org, http://www.lyra.org/viewcvs/
# gstein@lyra.org, http://viewcvs.sourceforge.net/
#
# -----------------------------------------------------------------------
#

View File

@@ -1,14 +1,14 @@
# -*- Mode: python -*-
#
# Copyright (C) 2000 The ViewCVS Group. All Rights Reserved.
# Copyright (C) 2000-2001 The ViewCVS Group. All Rights Reserved.
#
# By using this file, you agree to the terms and conditions set forth in
# the LICENSE.html file which can be found at the top level of the ViewCVS
# distribution or at http://www.lyra.org/viewcvs/license-1.html.
# distribution or at http://viewcvs.sourceforge.net/license-1.html.
#
# Contact information:
# Greg Stein, PO Box 760, Palo Alto, CA, 94302
# gstein@lyra.org, http://www.lyra.org/viewcvs/
# gstein@lyra.org, http://viewcvs.sourceforge.net/
#
# -----------------------------------------------------------------------
#

View File

@@ -1,14 +1,14 @@
# -*- Mode: python -*-
#
# Copyright (C) 2000 The ViewCVS Group. All Rights Reserved.
# Copyright (C) 2000-2001 The ViewCVS Group. All Rights Reserved.
#
# By using this file, you agree to the terms and conditions set forth in
# the LICENSE.html file which can be found at the top level of the ViewCVS
# distribution or at http://www.lyra.org/viewcvs/license-1.html.
# distribution or at http://viewcvs.sourceforge.net/license-1.html.
#
# Contact information:
# Greg Stein, PO Box 760, Palo Alto, CA, 94302
# gstein@lyra.org, http://www.lyra.org/viewcvs/
# gstein@lyra.org, http://viewcvs.sourceforge.net/
#
# -----------------------------------------------------------------------
#

View File

@@ -1,13 +1,13 @@
#
# Copyright (C) 2000 The ViewCVS Group. All Rights Reserved.
# Copyright (C) 2000-2001 The ViewCVS Group. All Rights Reserved.
#
# By using this file, you agree to the terms and conditions set forth in
# the LICENSE.html file which can be found at the top level of the ViewCVS
# distribution or at http://www.lyra.org/viewcvs/license-1.html.
# distribution or at http://viewcvs.sourceforge.net/license-1.html.
#
# Contact information:
# Greg Stein, PO Box 760, Palo Alto, CA, 94302
# gstein@lyra.org, http://www.lyra.org/viewcvs/
# gstein@lyra.org, http://viewcvs.sourceforge.net/
#
# -----------------------------------------------------------------------
#

View File

@@ -1,14 +1,14 @@
# -*- Mode: python -*-
#
# Copyright (C) 2000 The ViewCVS Group. All Rights Reserved.
# Copyright (C) 2000-2001 The ViewCVS Group. All Rights Reserved.
#
# By using this file, you agree to the terms and conditions set forth in
# the LICENSE.html file which can be found at the top level of the ViewCVS
# distribution or at http://www.lyra.org/viewcvs/license-1.html.
# distribution or at http://viewcvs.sourceforge.net/license-1.html.
#
# Contact information:
# Greg Stein, PO Box 760, Palo Alto, CA, 94302
# gstein@lyra.org, http://www.lyra.org/viewcvs/
# gstein@lyra.org, http://viewcvs.sourceforge.net/
#
# -----------------------------------------------------------------------
#

441
lib/rcsparse.py Normal file
View File

@@ -0,0 +1,441 @@
#
# Copyright (C) 2000-2001 The ViewCVS Group. All Rights Reserved.
#
# By using this file, you agree to the terms and conditions set forth in
# the LICENSE.html file which can be found at the top level of the ViewCVS
# distribution or at http://viewcvs.sourceforge.net/license-1.html.
#
# Contact information:
# Greg Stein, PO Box 760, Palo Alto, CA, 94302
# gstein@lyra.org, http://viewcvs.sourceforge.net/
#
# -----------------------------------------------------------------------
#
# This software is being maintained as part of the ViewCVS project.
# Information is available at:
# http://viewcvs.sourceforge.net/
#
# This file was originally based on portions of the blame.py script by
# Curt Hagenlocher.
#
# -----------------------------------------------------------------------
import string
import time
class _TokenStream:
token_term = string.whitespace + ';'
# the algorithm is about the same speed for any CHUNK_SIZE chosen.
# grab a good-sized chunk, but not too large to overwhelm memory.
CHUNK_SIZE = 100000
# CHUNK_SIZE = 5 # for debugging, make the function grind...
def __init__(self, file):
self.rcsfile = file
self.idx = 0
self.buf = self.rcsfile.read(self.CHUNK_SIZE)
if self.buf == '':
raise RuntimeError, 'EOF'
def get(self):
"Get the next token from the RCS file."
# Note: we can afford to loop within Python, examining individual
# characters. For the whitespace and tokens, the number of iterations
# is typically quite small. Thus, a simple iterative loop will beat
# out more complex solutions.
buf = self.buf
idx = self.idx
while 1:
if idx == len(buf):
buf = self.rcsfile.read(self.CHUNK_SIZE)
if buf == '':
# signal EOF by returning None as the token
del self.buf # so we fail if get() is called again
return None
idx = 0
if buf[idx] not in string.whitespace:
break
idx = idx + 1
if buf[idx] == ';':
self.buf = buf
self.idx = idx + 1
return ';'
if buf[idx] != '@':
end = idx + 1
token = ''
while 1:
# find token characters in the current buffer
while end < len(buf) and buf[end] not in self.token_term:
end = end + 1
token = token + buf[idx:end]
if end < len(buf):
# we stopped before the end, so we have a full token
idx = end
break
# we stopped at the end of the buffer, so we may have a partial token
buf = self.rcsfile.read(self.CHUNK_SIZE)
idx = end = 0
self.buf = buf
self.idx = idx
return token
# a "string" which starts with the "@" character. we'll skip it when we
# search for content.
idx = idx + 1
chunks = [ ]
while 1:
if idx == len(buf):
idx = 0
buf = self.rcsfile.read(self.CHUNK_SIZE)
if buf == '':
raise RuntimeError, 'EOF'
i = string.find(buf, '@', idx)
if i == -1:
chunks.append(buf[idx:])
idx = len(buf)
continue
if i == len(buf) - 1:
chunks.append(buf[idx:i])
idx = 0
buf = '@' + self.rcsfile.read(self.CHUNK_SIZE)
if buf == '@':
raise RuntimeError, 'EOF'
continue
if buf[i + 1] == '@':
chunks.append(buf[idx:i+1])
idx = i + 2
continue
chunks.append(buf[idx:i])
self.buf = buf
self.idx = i + 1
return string.join(chunks, '')
# _get = get
# def get(self):
token = self._get()
print 'T:', `token`
return token
def match(self, match):
"Try to match the next token from the input buffer."
token = self.get()
if token != match:
raise RuntimeError, ('Unexpected parsing error in RCS file.\n' +
'Expected token: %s, but saw: %s' % (match, token))
def unget(self, token):
"Put this token back, for the next get() to return."
# Override the class' .get method with a function which clears the
# overridden method then returns the pushed token. Since this function
# will not be looked up via the class mechanism, it should be a "normal"
# function, meaning it won't have "self" automatically inserted.
# Therefore, we need to pass both self and the token thru via defaults.
# note: we don't put this into the input buffer because it may have been
# @-unescaped already.
def give_it_back(self=self, token=token):
del self.get
return token
self.get = give_it_back
class Parser:
def parse_rcs_admin(self):
while 1:
# Read initial token at beginning of line
token = self.ts.get()
# We're done once we reach the description of the RCS tree
if token[0] in string.digits:
self.ts.unget(token)
return
if token == "head":
self.sink.set_head_revision(self.ts.get())
self.ts.match(';')
elif token == "branch":
self.sink.set_principal_branch(self.ts.get())
self.ts.match(';')
elif token == "symbols":
while 1:
tag = self.ts.get()
if tag == ';':
break
(tag_name, tag_rev) = string.split(tag, ':')
self.sink.define_tag(tag_name, tag_rev)
elif token == "comment":
self.sink.set_comment(self.ts.get())
self.ts.match(';')
# Ignore all these other fields - We don't care about them. Also chews
# up "newphrase".
elif token in ("locks", "strict", "expand", "access"):
while 1:
tag = self.ts.get()
if tag == ';':
break
else:
pass
# warn("Unexpected RCS token: $token\n")
raise RuntimeError, "Unexpected EOF";
def parse_rcs_tree(self):
while 1:
revision = self.ts.get()
# End of RCS tree description ?
if revision == 'desc':
self.ts.unget(revision)
return
# Parse date
self.ts.match('date')
date = self.ts.get()
self.ts.match(';')
# Convert date into timestamp
date_fields = string.split(date, '.') + ['0', '0', '0']
date_fields = map(string.atoi, date_fields)
if date_fields[0] < 100:
date_fields[0] = date_fields[0] + 1900
timestamp = time.mktime(tuple(date_fields))
# Parse author
self.ts.match('author')
author = self.ts.get()
self.ts.match(';')
# Parse state
self.ts.match('state')
state = ''
while 1:
token = self.ts.get()
if token == ';':
break
state = state + token + ' '
state = state[:-1] # toss the trailing space
# Parse branches
self.ts.match('branches')
branches = [ ]
while 1:
token = self.ts.get()
if token == ';':
break
branches.append(token)
# Parse revision of next delta in chain
self.ts.match('next')
next = self.ts.get()
if next == ';':
next = None
else:
self.ts.match(';')
# there are some files with extra tags in them. for example:
# owner 640;
# group 15;
# permissions 644;
# hardlinks @configure.in@;
# this is "newphrase" in RCSFILE(5). we just want to skip over these.
while 1:
token = self.ts.get()
if token == 'desc' or token[0] in string.digits:
self.ts.unget(token)
break
# consume everything up to the semicolon
while self.ts.get() != ';':
pass
self.sink.define_revision(revision, timestamp, author, state, branches,
next)
def parse_rcs_description(self):
self.ts.match('desc')
self.sink.set_description(self.ts.get())
def parse_rcs_deltatext(self):
while 1:
revision = self.ts.get()
if revision is None:
# EOF
break
self.ts.match('log')
log = self.ts.get()
### need to add code to chew up "newphrase"
self.ts.match('text')
text = self.ts.get()
self.sink.set_revision_info(revision, log, text)
def parse(self, file, sink):
self.ts = _TokenStream(file)
self.sink = sink
self.parse_rcs_admin()
self.parse_rcs_tree()
# many sinks want to know when the tree has been completed so they can
# do some work to prep for the arrival of the deltatext
self.sink.tree_completed()
self.parse_rcs_description()
self.parse_rcs_deltatext()
# easiest for us to tell the sink it is done, rather than worry about
# higher level software doing it.
self.sink.parse_completed()
self.ts = self.sink = None
class Sink:
def set_head_revision(self, revision):
pass
def set_principal_branch(self, branch_name):
pass
def define_tag(self, name, revision):
pass
def set_comment(self, comment):
pass
def set_description(self, description):
pass
def define_revision(self, revision, timestamp, author, state,
branches, next):
pass
def set_revision_info(self, revision, log, text):
pass
def tree_completed(self):
pass
def parse_completed(self):
pass
# --------------------------------------------------------------------------
#
# TESTING AND DEBUGGING TOOLS
#
class DebugSink:
def set_head_revision(self, revision):
print 'head:', revision
def set_principal_branch(self, branch_name):
print 'branch:', branch_name
def define_tag(self, name, revision):
print 'tag:', name, '=', revision
def set_comment(self, comment):
print 'comment:', comment
def set_description(self, description):
print 'description:', description
def define_revision(self, revision, timestamp, author, state,
branches, next):
print 'revision:', revision
print ' timestamp:', timestamp
print ' author:', author
print ' state:', state
print ' branches:', branches
print ' next:', next
def set_revision_info(self, revision, log, text):
print 'revision:', revision
print ' log:', log
print ' text:', text[:100], '...'
class DumpSink:
"""Dump all the parse information directly to stdout.
The output is relatively unformatted and untagged. It is intended as a
raw dump of the data in the RCS file. A copy can be saved, then changes
made to the parsing engine, then a comparison of the new output against
the old output.
"""
def __init__(self):
global sha
import sha
def set_head_revision(self, revision):
print revision
def set_principal_branch(self, branch_name):
print branch_name
def define_tag(self, name, revision):
print name, revision
def set_comment(self, comment):
print comment
def set_description(self, description):
print description
def define_revision(self, revision, timestamp, author, state,
branches, next):
print revision, timestamp, author, state, branches, next
def set_revision_info(self, revision, log, text):
print revision, sha.new(log).hexdigest(), sha.new(text).hexdigest()
def tree_completed(self):
print 'tree_completed'
def parse_completed(self):
print 'parse_completed'
def dump_file(fname):
Parser().parse(open(fname), DumpSink())
def time_file(fname):
import time
p = Parser().parse
f = open(fname)
s = Sink()
t = time.time()
p(f, s)
t = time.time() - t
print t
def _usage():
print 'This is normally a module for importing, but it has a couple'
print 'features for testing as an executable script.'
print 'USAGE: %s COMMAND filename,v' % sys.argv[0]
print ' where COMMAND is one of:'
print ' dump: filename is "dumped" to stdout'
print ' time: filename is parsed with the time written to stdout'
sys.exit(1)
if __name__ == '__main__':
import sys
if len(sys.argv) != 3:
usage()
if sys.argv[1] == 'dump':
dump_file(sys.argv[2])
elif sys.argv[1] == 'time':
time_file(sys.argv[2])
else:
usage()

View File

@@ -1,14 +1,14 @@
# -*- Mode: python -*-
#
# Copyright (C) 2000 The ViewCVS Group. All Rights Reserved.
# Copyright (C) 2000-2001 The ViewCVS Group. All Rights Reserved.
#
# By using this file, you agree to the terms and conditions set forth in
# the LICENSE.html file which can be found at the top level of the ViewCVS
# distribution or at http://www.lyra.org/viewcvs/license-1.html.
# distribution or at http://viewcvs.sourceforge.net/license-1.html.
#
# Contact information:
# Greg Stein, PO Box 760, Palo Alto, CA, 94302
# gstein@lyra.org, http://www.lyra.org/viewcvs/
# gstein@lyra.org, http://viewcvs.sourceforge.net/
#
# -----------------------------------------------------------------------
#
@@ -245,7 +245,9 @@ class RLogOutputParser:
def parse_one_rlog_entry(self):
## revision line/first line
line = self.rlog.readline()
if not line:
# Since FreeBSD's rlog outputs extra "---...---\n" before
# "===...===\n", _rlog_end may be occured here.
if not line or line == _rlog_end:
return None
## revision

2526
lib/viewcvs.py Normal file

File diff suppressed because it is too large Load Diff

139
tests/timelog.py Normal file
View File

@@ -0,0 +1,139 @@
import time
import string
import profile
import rcsparse
import viewcvs
def lines_changed(delta):
idx = 0
added = deleted = 0
while idx < len(delta):
op = delta[idx]
i = string.find(delta, ' ', idx + 1)
j = string.find(delta, '\n', i + 1)
line = int(delta[idx+1:i])
count = int(delta[i+1:j])
idx = j + 1
if op == 'd':
deleted = deleted + count
else: # 'a' for adding text
added = added + count
# skip new text
while count > 0:
nl = string.find(delta, '\n', idx)
assert nl > 0, 'missing a newline in the delta in the RCS file'
idx = nl + 1
count = count - 1
return added, deleted
class FetchSink(rcsparse.Sink):
def __init__(self, which_rev=None):
self.head = self.branch = ''
self.tags = { }
self.meta = { }
self.revs = [ ]
self.base = { }
self.entries = { }
self.which = which_rev
def set_head_revision(self, revision):
self.head = revision
def set_principal_branch(self, branch_name):
self.branch = branch_name
def define_tag(self, name, revision):
self.tags[name] = revision
def define_revision(self, revision, timestamp, author, state,
branches, next):
self.meta[revision] = (timestamp, author, state)
self.base[next] = revision
for b in branches:
self.base[b] = revision
def set_revision_info(self, revision, log, text):
timestamp, author, state = self.meta[revision]
entry = viewcvs.LogEntry(revision, int(timestamp) - time.timezone, author,
state, None, log)
# .revs is "order seen" and .entries is for random access
self.revs.append(entry)
self.entries[revision] = entry
if revision != self.head:
added, deleted = lines_changed(text)
if string.count(revision, '.') == 1:
# on the trunk. reverse delta.
changed = '+%d -%d' % (deleted, added)
self.entries[self.base[revision]].changed = changed
else:
# on a branch. forward delta.
changed = '+%d -%d' % (added, deleted)
self.entries[revision].changed = changed
def parse_completed(self):
if self.which:
self.revs = [ self.entries[self.which] ]
def fetch_log2(full_name, which_rev=None):
sink = FetchSink(which_rev)
rcsparse.Parser().parse(open(full_name), sink)
return sink.head, sink.branch, sink.tags, sink.revs
def compare_fetch(full_name, which_rev=None):
d1 = viewcvs.fetch_log(full_name, which_rev)
d2 = fetch_log2(full_name, which_rev)
if d1[:3] != d2[:3]:
print 'd1:', d1[:3]
print 'd2:', d2[:3]
return
if len(d1[3]) != len(d2[3]):
print 'len(d1[3])=%d len(d2[3])=%d' % (len(d1[3]), len(d2[3]))
return
def sort_func(e, f):
return cmp(e.rev, f.rev)
d1[3].sort(sort_func)
d2[3].sort(sort_func)
import pprint
for i in range(len(d1[3])):
if vars(d1[3][i]) != vars(d2[3][i]):
pprint.pprint((i, vars(d1[3][i]), vars(d2[3][i])))
def time_fetch(full_name, which_rev=None):
t = time.time()
viewcvs.fetch_log(full_name, which_rev)
t1 = time.time() - t
t = time.time()
fetch_log2(full_name, which_rev)
t2 = time.time() - t
print t1, t2
def profile_fetch(full_name, which_rev=None):
p = profile.Profile()
def many_calls(*args):
for i in xrange(10):
apply(fetch_log2, args)
p.runcall(many_calls, full_name, which_rev)
p.print_stats()
def varysize(full_name, which_rev=None):
def one_run(n, *args):
rcsparse._TokenStream.CHUNK_SIZE = n
t = time.time()
for i in xrange(5):
apply(fetch_log2, args)
print n, time.time() - t
#one_run(2020, full_name, which_rev)
#one_run(4070, full_name, which_rev)
#one_run(8170, full_name, which_rev)
#one_run(8192, full_name, which_rev)
#one_run(16384, full_name, which_rev)
one_run(32740, full_name, which_rev)
one_run(65500, full_name, which_rev)
one_run(100000, full_name, which_rev)
one_run(200000, full_name, which_rev)
one_run(500000, full_name, which_rev)

View File

@@ -1,15 +1,15 @@
#!/usr/bin/env python
# -*- Mode: python -*-
#
# Copyright (C) 2000 The ViewCVS Group. All Rights Reserved.
# Copyright (C) 2000-2001 The ViewCVS Group. All Rights Reserved.
#
# By using this file, you agree to the terms and conditions set forth in
# the LICENSE.html file which can be found at the top level of the ViewCVS
# distribution or at http://www.lyra.org/viewcvs/license-1.html.
# distribution or at http://viewcvs.sourceforge.net/license-1.html.
#
# Contact information:
# Greg Stein, PO Box 760, Palo Alto, CA, 94302
# gstein@lyra.org, http://www.lyra.org/viewcvs/
# gstein@lyra.org, http://viewcvs.sourceforge.net/
#
# -----------------------------------------------------------------------
#

View File

@@ -1,15 +1,15 @@
#!/usr/bin/python
# -*- Mode: python -*-
#
# Copyright (C) 2000 The ViewCVS Group. All Rights Reserved.
# Copyright (C) 2000-2001 The ViewCVS Group. All Rights Reserved.
#
# By using this file, you agree to the terms and conditions set forth in
# the LICENSE.html file which can be found at the top level of the ViewCVS
# distribution or at http://www.lyra.org/viewcvs/license-1.html.
# distribution or at http://viewcvs.sourceforge.net/license-1.html.
#
# Contact information:
# Greg Stein, PO Box 760, Palo Alto, CA, 94302
# gstein@lyra.org, http://www.lyra.org/viewcvs/
# gstein@lyra.org, http://viewcvs.sourceforge.net/
#
# -----------------------------------------------------------------------
#

View File

@@ -1,15 +1,15 @@
#!/usr/bin/env python
# -*- Mode: python -*-
#
# Copyright (C) 2000 The ViewCVS Group. All Rights Reserved.
# Copyright (C) 2000-2001 The ViewCVS Group. All Rights Reserved.
#
# By using this file, you agree to the terms and conditions set forth in
# the LICENSE.html file which can be found at the top level of the ViewCVS
# distribution or at http://www.lyra.org/viewcvs/license-1.html.
# distribution or at http://viewcvs.sourceforge.net/license-1.html.
#
# Contact information:
# Greg Stein, PO Box 760, Palo Alto, CA, 94302
# gstein@lyra.org, http://www.lyra.org/viewcvs/
# gstein@lyra.org, http://viewcvs.sourceforge.net/
#
# -----------------------------------------------------------------------
#

View File

@@ -1,14 +1,14 @@
#!/bin/sh
#
# Copyright (C) 2000 The ViewCVS Group. All Rights Reserved.
# Copyright (C) 2000-2001 The ViewCVS Group. All Rights Reserved.
#
# By using this file, you agree to the terms and conditions set forth in
# the LICENSE.html file which can be found at the top level of the ViewCVS
# distribution or at http://www.lyra.org/viewcvs/license-1.html.
# distribution or at http://viewcvs.sourceforge.net/license-1.html.
#
# Contact information:
# Greg Stein, PO Box 760, Palo Alto, CA, 94302
# gstein@lyra.org, http://www.lyra.org/viewcvs/
# gstein@lyra.org, http://viewcvs.sourceforge.net/
#
# -----------------------------------------------------------------------
#
@@ -18,22 +18,22 @@
#
if [ "x$1" = "x" ]; then
echo "USAGE: $0 target-directory"
echo "USAGE: $0 tagname target-directory"
exit 1
fi
# grab a copy of the CVS repository (export requires a tag, so just use 'co')
rm -r $1
echo 'Checking out into:' $1
cvs -d /home/cvsroot co -d $1 -kv -P -R viewcvs
if test -e $2; then
echo "ERROR: must remove $2 first."
exit 1
fi
echo 'Cleaning up...'
# clean out the CVS crap
find $1 -name CVS | xargs rm -r
# grab a copy of the CVS repository
echo 'Checking out into:' $2
cvs -d :pserver:anonymous@cvs.viewcvs.sourceforge.net:/cvsroot/viewcvs export -r $1 -d $2 viewcvs
# various shifting, cleanup
mv $1/website/license-1.html $1/LICENSE.html
rm -r $1/website
rm $1/tools/make-release
mv $2/website/license-1.html $2/LICENSE.html
rm -r $2/website
rm $2/tools/make-release
echo 'Done.'

View File

@@ -1,15 +1,15 @@
#!/usr/bin/env python
# -*- Mode: python -*-
#
# Copyright (C) 2000 The ViewCVS Group. All Rights Reserved.
# Copyright (C) 2000-2001 The ViewCVS Group. All Rights Reserved.
#
# By using this file, you agree to the terms and conditions set forth in
# the LICENSE.html file which can be found at the top level of the ViewCVS
# distribution or at http://www.lyra.org/viewcvs/license-1.html.
# distribution or at http://viewcvs.sourceforge.net/license-1.html.
#
# Contact information:
# Greg Stein, PO Box 760, Palo Alto, CA, 94302
# gstein@lyra.org, http://www.lyra.org/viewcvs/
# gstein@lyra.org, http://viewcvs.sourceforge.net/
#
# -----------------------------------------------------------------------
#
@@ -69,8 +69,10 @@ FILE_INFO_LIST = [
("lib/dbi.py", "lib/dbi.py", 0644, 0, 0, 1),
("lib/popen.py", "lib/popen.py", 0644, 0, 0, 1),
("lib/py2html.py", "lib/py2html.py", 0644, 0, 0, 1),
("lib/rlog.py", "lib/rlog.py", 0644, 1, 0, 1),
("lib/query.py", "lib/query.py", 0644, 1, 0, 1),
("lib/rcsparse.py", "lib/rcsparse.py", 0644, 1, 0, 1),
("lib/rlog.py", "lib/rlog.py", 0644, 1, 0, 1),
("lib/viewcvs.py", "lib/viewcvs.py", 0644, 1, 0, 1),
("tools/loginfo-handler", "loginfo-handler", 0755, 1, 0, 0),
("tools/cvsdbadmin", "cvsdbadmin", 0755, 1, 0, 0),

BIN
website/images/chalk.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 755 B

View File

@@ -5,16 +5,33 @@
</head>
<body background="/images/chalk.jpg">
<h1>ViewCVS: Viewing CVS Repositories</h1>
<table width="100&#37;" cellspacing=5>
<tr>
<td>
<h1>ViewCVS: Viewing CVS Repositories</h1>
</td>
<td align=center valign=top bgcolor="white" width="1%">
<b>Quickstart:</b>
<a href="viewcvs-0.6.tar.gz">download</a>
</td>
<td width="1%"><a href="http://sourceforge.net/"><img border=0
src="http://sourceforge.net/sflogo.php?group_id=18760&type=1"></a><br><a href="http://sourceforge.net/projects/viewcvs/">ViewCVS&nbsp;project&nbsp;page</a>
</td>
</tr>
</table>
<p>
The ViewCVS software was inspired by
<a href="http://stud.fh-heilbronn.de/~zeller/cgi/cvsweb.cgi/"><i>cvsweb</i></a>
(by <a href="mailto:zeller@think.de">Henner Zeller</a>).
I wanted to make some changes and updates, but cvsweb was
implemented in Perl (and rather poorly, IMO). So I undertook the
implemented in Perl. While I can manage some Perl, cvsweb was
rather unmaintainable for me. So I undertook the
task to convert the software to
<a href="http://www.python.org/"><i>Python</i></a>.
<a href="http://www.python.org/"><i>Python</i></a>. As a result,
I've actually been able to go <em>way</em> beyond the simple
changes that I had envisioned.
</p>
<p>
ViewCVS can browse directories, change logs, and specific
@@ -41,7 +58,7 @@
Of course, it is also available through ViewCVS itself:
</p>
<blockquote>
<a href="/cgi-bin/viewcvs.cgi/viewcvs/">http://www.lyra.org/cgi-bin/viewcvs.cgi/viewcvs/</a>
<a href="http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/viewcvs/">http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/viewcvs/</a>
</blockquote>
<p>
@@ -117,6 +134,16 @@
<li>
Directories with a large number of files can be viewed.
</li>
<li>
<strong>Security</strong>: ViewCVS only requires read access
to the CVS repository (not read/write). With the correct
security partitioning, this means that even if ViewCVS were to
be subverted, your source code is safe. Further, ViewCVS does
not use any <code>system()</code> or <code>popen()</code>
calls, which are very susceptible to abuse.
<br>
<small>(cvsweb had a hole due to a popen() call)</small>
</li>
</ul>
<p>
@@ -174,19 +201,11 @@
you want to use this feature.
</p>
<hr width="75&#37;">
<h3>Other links</h3>
<p>
[ <a href="/greg/">Greg's page</a> ]
[ <a href="/greg/python/">other Python software</a> ]
</p>
<hr>
<address><a href="mailto:gstein@lyra.org">Greg Stein</a></address>
<!-- Created: Fri Dec 3 02:51:37 PST 1999 -->
<!-- hhmts start -->
Last modified: Tue Jul 25 05:14:15 PDT 2000
Last modified: Fri May 11 14:22:36 PDT 2001
<!-- hhmts end -->
</body>
</html>

View File

@@ -14,12 +14,20 @@
<a href="who.html">The ViewCVS
Group</a> and the users of ViewCVS.
</p>
<p>
<small>
<em>
Note: the copyright years were updated on May 12, 2001. No
other changes were made to the license.
</em>
</small>
</p>
<hr>
<p>
<b>
Copyright &copy; 1999-2000 The ViewCVS Group. All rights reserved.
Copyright &copy; 1999-2001 The ViewCVS Group. All rights reserved.
</b>
</p>
<p>
@@ -69,7 +77,7 @@
<address><a href="mailto:gstein@lyra.org">Greg Stein</a></address>
<!-- Created: Mon May 8 19:01:27 PDT 2000 -->
<!-- hhmts start -->
Last modified: Mon May 8 19:28:37 PDT 2000
Last modified: Sat May 12 15:53:33 PDT 2001
<!-- hhmts end -->
</body>
</html>

View File

@@ -12,7 +12,7 @@
developing the ViewCVS package. The current set of members are:
</p>
<ul>
<li><a href="/greg/"><b>Greg Stein</b></a></li>
<li><a href="http://www.lyra.org/greg/"><b>Greg Stein</b></a></li>
<li>Jay Painter</li>
</ul>
@@ -26,7 +26,7 @@
<address><a href="mailto:gstein@lyra.org">Greg Stein</a></address>
<!-- Created: Mon May 8 19:08:58 PDT 2000 -->
<!-- hhmts start -->
Last modified: Mon May 8 19:14:45 PDT 2000
Last modified: Fri May 11 14:10:54 PDT 2001
<!-- hhmts end -->
</body>
</html>