mirror of
https://github.com/vitalif/viewvc-4intranet
synced 2019-04-16 04:14:59 +03:00
Compare commits
3 Commits
1.1.7
...
1.1.0-beta
Author | SHA1 | Date | |
---|---|---|---|
![]() |
fab88fb6c3 | ||
![]() |
cc1cf127a3 | ||
![]() |
c3ba043654 |
92
CHANGES
92
CHANGES
@@ -1,71 +1,4 @@
|
||||
Version 1.1.7 (released 09-Sep-2010)
|
||||
|
||||
* display Subversion revision properties in the revision view (issue #453)
|
||||
* fix exception in 'standalone.py -r REPOS' when run without a config file
|
||||
* fix standalone.py server root deployments (--script-alias='')
|
||||
* add rudimentary Basic authentication support to standalone.py (issue #49)
|
||||
* fix obscure "unexpected NULL parent pool" Subversion bindings error
|
||||
* enable path info / link display in remote Subversion root revision view
|
||||
* fix vhost name case handling inconsistency (issue #466)
|
||||
* use svn:mime-type property charset param as encoding hint
|
||||
* markup Subversion revision references in log messages (issue #313)
|
||||
* add rudimentary support for FastCGI-based deployments (issue #464)
|
||||
* fix query script WSGI deployment
|
||||
* add configuration to fix query script cross-linking to ViewVC
|
||||
|
||||
Version 1.1.6 (released 02-Jun-2010)
|
||||
|
||||
* add rudimentary support for WSGI-based deployments (issue #397)
|
||||
* fix exception caused by trying to HTML-escape non-string data (issue #454)
|
||||
* fix incorrect RSS feed Content-Type header (issue #449)
|
||||
* fix RSS <title> encoding problem (issue #451)
|
||||
* allow 'svndbadmin purge' to work on missing repositories (issue #452)
|
||||
|
||||
Version 1.1.5 (released 29-Mar-2010)
|
||||
|
||||
* security fix: escape user-provided search_re input to avoid XSS attack
|
||||
|
||||
Version 1.1.4 (released 10-Mar-2010)
|
||||
|
||||
* security fix: escape user-provided query form input to avoid XSS attack
|
||||
* fix standalone.py failure (when per-root options aren't used) (issue #445)
|
||||
* fix annotate failure caused by ignored svn_config_dir (issue #447)
|
||||
|
||||
Version 1.1.3 (released 22-Dec-2009)
|
||||
|
||||
* security fix: add root listing support of per-root authz config
|
||||
* security fix: query.py requires 'forbidden' authorizer (or none) in config
|
||||
* fix URL-ification of truncated log messages (issue #3)
|
||||
* fix regexp input validation (issue #426, #427, #440)
|
||||
* add support for configurable tab-to-spaces conversion
|
||||
* fix not-a-sequence error in diff view
|
||||
* allow viewvc-install to work when templates-contrib is absent
|
||||
* minor template improvements/corrections
|
||||
* expose revision metadata in diff view (issue #431)
|
||||
* markup file/directory item property URLs and email addresses (issue #434)
|
||||
* make ViewVC cross copies in Subversion history by default
|
||||
* fix bug that caused standalone.py failure under Python 1.5.2 (issue #442)
|
||||
* fix support for per-vhost overrides of authorizer parameters (issue #411)
|
||||
* fix root name identification in query.py interface
|
||||
|
||||
Version 1.1.2 (released 11-Aug-2009)
|
||||
|
||||
* security fix: validate the 'view' parameter to avoid XSS attack
|
||||
* security fix: avoid printing illegal parameter names and values
|
||||
* add optional support for character encoding detection (issue #400)
|
||||
* fix username case handling in svnauthz module (issue #419)
|
||||
* fix cvsdbadmin/svnadmin rebuild error on missing repos (issue #420)
|
||||
* don't drop leading blank lines from colorized file contents (issue #422)
|
||||
* add file.ezt template logic for optionally hiding binary file contents
|
||||
|
||||
Version 1.1.1 (released 03-Jun-2009)
|
||||
|
||||
* fix broken query form (missing required template variables) (issue #416)
|
||||
* fix bug in cvsdb which caused rebuild operations to lose data (issue #417)
|
||||
* fix cvsdb purge/rebuild repos lookup to error on missing repos
|
||||
* fix misleading file contents view page title
|
||||
|
||||
Version 1.1.0 (released 13-May-2009)
|
||||
Version 1.1.0 (released ??-???-????)
|
||||
|
||||
* add support for full content diffs (issue #153)
|
||||
* make many more data dictionary items available to all views
|
||||
@@ -79,7 +12,9 @@ Version 1.1.0 (released 13-May-2009)
|
||||
* add support for query by log message (issues #22, #121)
|
||||
* fix bug parsing 'svn blame' output with too-long author names (issue #221)
|
||||
* fix default standalone.py port to be within private IANA range (issue #234)
|
||||
* add unified configury of allowed views; checkout view disabled by default
|
||||
* add support for integration with GNU source-highlight (issue #285)
|
||||
* add unified configury of allowed views
|
||||
* add support for disabling the checkout view (now the default state)
|
||||
* add support for ranges of revisions to svndbadmin (issue #224)
|
||||
* make the query handling more forgiving of malformatted subdirs (issue #244)
|
||||
* add support for per-root configuration overrides (issue #371)
|
||||
@@ -101,24 +36,7 @@ Version 1.1.0 (released 13-May-2009)
|
||||
* show RSS/query links only for roots found in commits database (issue #357)
|
||||
* recognize Subversion svn:mime-type property values (issue #364)
|
||||
* hide CVS files when viewing tags/branches on which they don't exist
|
||||
* allow hiding of errorful entries from the directory view (issue #105)
|
||||
* fix directory view sorting UI
|
||||
* tolerate malformed Accept-Language headers (issue #396)
|
||||
* allow MIME type mapping overrides in ViewVC configuration (issue #401)
|
||||
* fix exception in rev-sorted remote Subversion directory views (issue #409)
|
||||
* allow setting of page sizes for log and dir views individually (issue #402)
|
||||
|
||||
Version 1.0.9 (released 11-Aug-2009)
|
||||
|
||||
* security fix: validate the 'view' parameter to avoid XSS attack
|
||||
* security fix: avoid printing illegal parameter names and values
|
||||
|
||||
Version 1.0.8 (released 05-May-2009)
|
||||
|
||||
* fix directory view sorting UI
|
||||
* tolerate malformed Accept-Language headers (issue #396)
|
||||
* fix directory log views in revision-less Subversion repositories
|
||||
* fix exception in rev-sorted remote Subversion directory views (issue #409)
|
||||
* add support for hiding errorful entries from the directory view (issue #105)
|
||||
|
||||
Version 1.0.7 (released 14-Oct-2008)
|
||||
|
||||
|
119
INSTALL
119
INSTALL
@@ -139,7 +139,7 @@ installation instructions.
|
||||
default_root
|
||||
root_as_url_component
|
||||
rcs_dir
|
||||
mime_types_files
|
||||
mime_types_file
|
||||
|
||||
There are some other options that are usually nice to change. See
|
||||
viewvc.conf for more information. ViewVC provides a working,
|
||||
@@ -168,23 +168,14 @@ checkin database working are below.
|
||||
APACHE CONFIGURATION
|
||||
--------------------
|
||||
|
||||
1) Locate your Apache configuration file(s).
|
||||
1) Find out where the web server configuration file is kept. Typical
|
||||
locations are /etc/httpd/httpd.conf, /etc/httpd/conf/httpd.conf,
|
||||
and /etc/apache/httpd.conf. Depending on how apache was installed,
|
||||
you may also look under /usr/local/etc or /etc/local. Use the vendor
|
||||
documentation or the find utility if in doubt.
|
||||
|
||||
Typical locations are /etc/httpd/httpd.conf,
|
||||
/etc/httpd/conf/httpd.conf, and /etc/apache/httpd.conf. Depending
|
||||
on how Apache was installed, you may also look under /usr/local/etc
|
||||
or /etc/local. Use the vendor documentation or the find utility if
|
||||
in doubt.
|
||||
|
||||
2) Configure Apache to expose ViewVC to users at the URL of your choice.
|
||||
|
||||
ViewVC provides several different ways to do this. Choose one of
|
||||
the following methods:
|
||||
|
||||
-----------------------------------
|
||||
METHOD A: CGI mode via ScriptAlias
|
||||
-----------------------------------
|
||||
The ScriptAlias directive is very useful for pointing
|
||||
Either METHOD A:
|
||||
2) The ScriptAlias directive is very useful for pointing
|
||||
directly to the viewvc.cgi script. Simply insert a line containing
|
||||
|
||||
ScriptAlias /viewvc <VIEWVC_INSTALLATION_DIRECTORY>/bin/cgi/viewvc.cgi
|
||||
@@ -195,34 +186,34 @@ APACHE CONFIGURATION
|
||||
ScriptAlias /viewvc /usr/local/viewvc-1.0/bin/cgi/viewvc.cgi
|
||||
ScriptAlias /query /usr/local/viewvc-1.0/bin/cgi/query.cgi
|
||||
|
||||
----------------------------------------
|
||||
METHOD B: CGI mode in cgi-bin directory
|
||||
----------------------------------------
|
||||
Copy the CGI scripts from
|
||||
continue with step 3).
|
||||
|
||||
or alternatively METHOD B:
|
||||
2) Copy the CGI scripts from
|
||||
<VIEWVC_INSTALLATION_DIRECTORY>/bin/cgi/*.cgi
|
||||
to the /cgi-bin/ directory configured in your httpd.conf file.
|
||||
|
||||
continue with step 3).
|
||||
|
||||
------------------------------------------
|
||||
METHOD C: CGI mode in ExecCGI'd directory
|
||||
------------------------------------------
|
||||
Copy the CGI scripts from
|
||||
and then there's METHOD C:
|
||||
2) Copy the CGI scripts from
|
||||
<VIEWVC_INSTALLATION_DIRECTORY>/bin/cgi/*.cgi
|
||||
to the directory of your choosing in the Document Root adding the following
|
||||
Apache directives for the directory in httpd.conf or an .htaccess file:
|
||||
apache directives for the directory in httpd.conf or an .htaccess file:
|
||||
|
||||
Options +ExecCGI
|
||||
AddHandler cgi-script .cgi
|
||||
|
||||
Note: For this to work mod_cgi has to be loaded. And for the .htaccess file
|
||||
(Note: For this to work mod_cgi has to be loaded. And for the .htaccess file
|
||||
to be effective, "AllowOverride All" or "AllowOverride Options FileInfo"
|
||||
needs to have been specified for the directory.
|
||||
need to have been specified for the directory.)
|
||||
|
||||
------------------------------------------
|
||||
METHOD D: Using mod_python (if installed)
|
||||
------------------------------------------
|
||||
Copy the Python scripts and .htaccess file from
|
||||
continue with step 3).
|
||||
|
||||
or if you've got Mod_Python installed you can use METHOD D:
|
||||
2) Copy the Python scripts and .htaccess file from
|
||||
<VIEWVC_INSTALLATION_DIRECTORY>/bin/mod_python/
|
||||
to a directory being served by Apache.
|
||||
to a directory being served by apache.
|
||||
|
||||
In httpd.conf, make sure that "AllowOverride All" or at least
|
||||
"AllowOverride FileInfo Options" are enabled for the directory
|
||||
@@ -232,63 +223,17 @@ APACHE CONFIGURATION
|
||||
feature may not work because it uses multithreading. This works fine
|
||||
under Apache 2.
|
||||
|
||||
----------------------------------------
|
||||
METHOD E: Using mod_wsgi (if installed)
|
||||
----------------------------------------
|
||||
Copy the Python scripts file from
|
||||
<VIEWVC_INSTALLATION_DIRECTORY>/bin/mod_python/
|
||||
to the directory of your choosing. Modify httpd.conf with the
|
||||
following directives:
|
||||
continue with step 3).
|
||||
|
||||
WSGIScriptAlias /viewvc <VIEWVC_INSTALLATION_DIRECTORY>/bin/wsgi/viewvc.wsgi
|
||||
WSGIScriptAlias /query <VIEWVC_INSTALLATION_DIRECTORY>/bin/wsgi/query.wsgi
|
||||
3) Restart apache. The commands to do this vary. "httpd -k restart" and
|
||||
"apache -k restart" are two common variants. On RedHat Linux it is
|
||||
done using the command "/sbin/service httpd restart" and on SuSE Linux
|
||||
it is done with "rcapache restart"
|
||||
|
||||
You'll probably also need the following directive because of the
|
||||
not-quite-sanctioned way that ViewVC manipulates Python objects.
|
||||
4) Optional: Add access control.
|
||||
|
||||
WSGIApplicationGroup %{GLOBAL}
|
||||
|
||||
Note: WSGI support in ViewVC is at this time quite rudimentary,
|
||||
bordering on downright experimental. Your mileage may vary.
|
||||
|
||||
-----------------------------------------
|
||||
METHOD F: Using mod_fcgid (if installed)
|
||||
-----------------------------------------
|
||||
|
||||
This uses ViewVC's WSGI support (from above), but supports using FastCGI,
|
||||
and is a somewhat hybrid approach of several of the above methods.
|
||||
|
||||
Especially if fcgi is already being used for other purposes, e.g. PHP,
|
||||
also using fcgi can prevent the need for including additional modules
|
||||
(e.g. mod_python or mod_wsgi) within Apache, which may help lessen Apache's
|
||||
memory usage and/or help improve performance.
|
||||
|
||||
This depends on mod_fcgid:
|
||||
|
||||
http://httpd.apache.org/mod_fcgid/
|
||||
|
||||
as well as the fcgi server from Python's flup package:
|
||||
|
||||
http://pypi.python.org/pypi/flup
|
||||
http://trac.saddi.com/flup
|
||||
|
||||
The following are some example httpd.conf fragments you can use to
|
||||
support this configuration:
|
||||
|
||||
ScriptAlias /viewvc /usr/local/viewvc/bin/wsgi/viewvc.fcgi
|
||||
ScriptAlias /query /usr/local/viewvc/bin/wsgi/query.fcgi
|
||||
|
||||
3) Restart Apache.
|
||||
|
||||
The commands to do this vary. "httpd -k restart" and "apache -k
|
||||
restart" are two common variants. On RedHat Linux it is done using
|
||||
the command "/sbin/service httpd restart" and on SuSE Linux it is
|
||||
done with "rcapache restart". Other systems use "apachectl restart".
|
||||
|
||||
4) [Optional] Add access control.
|
||||
|
||||
In your httpd.conf you can control access to certain modules by
|
||||
adding directives like this:
|
||||
In your httpd.conf you can control access to certain modules by adding
|
||||
directives like this:
|
||||
|
||||
<Location "<url to viewvc.cgi>/<modname_you_wish_to_access_ctl>">
|
||||
AllowOverride None
|
||||
|
@@ -15,7 +15,7 @@
|
||||
|
||||
<blockquote>
|
||||
|
||||
<p><strong>Copyright © 1999-2010 The ViewCVS Group. All rights
|
||||
<p><strong>Copyright © 1999-2008 The ViewCVS Group. All rights
|
||||
reserved.</strong></p>
|
||||
|
||||
<p>By using ViewVC, you agree to the terms and conditions set forth
|
||||
@@ -59,8 +59,6 @@
|
||||
<li>March 17, 2006 — software renamed from "ViewCVS"</li>
|
||||
<li>April 10, 2007 — copyright years updated</li>
|
||||
<li>February 22, 2008 — copyright years updated</li>
|
||||
<li>March 18, 2009 — copyright years updated</li>
|
||||
<li>March 29, 2010 — copyright years updated</li>
|
||||
</ul>
|
||||
|
||||
</body>
|
||||
|
@@ -54,10 +54,7 @@ import query
|
||||
server = sapi.AspServer(Server, Request, Response, Application)
|
||||
try:
|
||||
cfg = viewvc.load_config(CONF_PATHNAME, server)
|
||||
viewvc_base_url = cfg.query.viewvc_base_url
|
||||
if viewvc_base_url is None:
|
||||
viewvc_base_url = "viewvc.asp"
|
||||
query.main(server, cfg, viewvc_base_url)
|
||||
query.main(server, cfg, "viewvc.asp")
|
||||
finally:
|
||||
s.close()
|
||||
|
||||
|
@@ -54,7 +54,4 @@ import query
|
||||
|
||||
server = sapi.CgiServer()
|
||||
cfg = viewvc.load_config(CONF_PATHNAME, server)
|
||||
viewvc_base_url = cfg.query.viewvc_base_url
|
||||
if viewvc_base_url is None:
|
||||
viewvc_base_url = "viewvc.cgi"
|
||||
query.main(server, cfg, viewvc_base_url)
|
||||
query.main(server, cfg, "viewvc.cgi")
|
||||
|
@@ -177,12 +177,7 @@ if __name__ == '__main__':
|
||||
if command in ('rebuild', 'purge'):
|
||||
if quiet_level < 2:
|
||||
print "Purging existing data for repository root `%s'" % root
|
||||
try:
|
||||
db.PurgeRepository(root)
|
||||
except cvsdb.UnknownRepositoryError, e:
|
||||
if command == 'purge':
|
||||
sys.stderr.write("ERROR: " + str(e) + "\n")
|
||||
sys.exit(1)
|
||||
db.PurgeRepository(root)
|
||||
|
||||
if command in ('rebuild', 'update'):
|
||||
repository = vclib.ccvs.CVSRepository(None, rootpath, None,
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2009 The ViewCVS Group. All Rights Reserved.
|
||||
# Copyright (C) 1999-2007 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 ViewVC
|
||||
@@ -18,22 +18,22 @@
|
||||
|
||||
import os, sys, string
|
||||
import popen2
|
||||
import getopt
|
||||
|
||||
## ------------------------------------------------------------------------
|
||||
## Stuff common to all schemas
|
||||
##
|
||||
DATABASE_SCRIPT_COMMON="""\
|
||||
INTRO_TEXT = """\
|
||||
This script creates the database and tables in MySQL used by the
|
||||
ViewVC checkin database. You will be prompted for: database server
|
||||
hostname, database user, database user password, and database name.
|
||||
This script will use the 'mysql' program to create the database for
|
||||
you. You will then need to set the appropriate parameters in the
|
||||
[cvsdb] section of your viewvc.conf file.
|
||||
"""
|
||||
|
||||
DATABASE_SCRIPT="""\
|
||||
DROP DATABASE IF EXISTS <dbname>;
|
||||
CREATE DATABASE <dbname>;
|
||||
|
||||
USE <dbname>;
|
||||
"""
|
||||
|
||||
## ------------------------------------------------------------------------
|
||||
## Version 0: The original, Bonsai-compatible schema.
|
||||
##
|
||||
DATABASE_SCRIPT_VERSION_0="""\
|
||||
DROP TABLE IF EXISTS branches;
|
||||
CREATE TABLE branches (
|
||||
id mediumint(9) NOT NULL auto_increment,
|
||||
@@ -121,213 +121,28 @@ CREATE TABLE tags (
|
||||
) TYPE=MyISAM;
|
||||
"""
|
||||
|
||||
## ------------------------------------------------------------------------
|
||||
## Version 1: Adds the 'metadata' table. Adds 'descid' index to
|
||||
## 'checkins' table, and renames that table to 'commits'.
|
||||
##
|
||||
DATABASE_SCRIPT_VERSION_1="""\
|
||||
DROP TABLE IF EXISTS branches;
|
||||
CREATE TABLE branches (
|
||||
id mediumint(9) NOT NULL auto_increment,
|
||||
branch varchar(64) binary DEFAULT '' NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE branch (branch)
|
||||
) TYPE=MyISAM;
|
||||
|
||||
DROP TABLE IF EXISTS commits;
|
||||
CREATE TABLE commits (
|
||||
type enum('Change','Add','Remove'),
|
||||
ci_when datetime DEFAULT '0000-00-00 00:00:00' NOT NULL,
|
||||
whoid mediumint(9) DEFAULT '0' NOT NULL,
|
||||
repositoryid mediumint(9) DEFAULT '0' NOT NULL,
|
||||
dirid mediumint(9) DEFAULT '0' NOT NULL,
|
||||
fileid mediumint(9) DEFAULT '0' NOT NULL,
|
||||
revision varchar(32) binary DEFAULT '' NOT NULL,
|
||||
stickytag varchar(255) binary DEFAULT '' NOT NULL,
|
||||
branchid mediumint(9) DEFAULT '0' NOT NULL,
|
||||
addedlines int(11) DEFAULT '0' NOT NULL,
|
||||
removedlines int(11) DEFAULT '0' NOT NULL,
|
||||
descid mediumint(9),
|
||||
UNIQUE repositoryid (repositoryid,dirid,fileid,revision),
|
||||
KEY ci_when (ci_when),
|
||||
KEY whoid (whoid),
|
||||
KEY repositoryid_2 (repositoryid),
|
||||
KEY dirid (dirid),
|
||||
KEY fileid (fileid),
|
||||
KEY branchid (branchid),
|
||||
KEY descid (descid)
|
||||
) TYPE=MyISAM;
|
||||
|
||||
DROP TABLE IF EXISTS descs;
|
||||
CREATE TABLE descs (
|
||||
id mediumint(9) NOT NULL auto_increment,
|
||||
description text,
|
||||
hash bigint(20) DEFAULT '0' NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
KEY hash (hash)
|
||||
) TYPE=MyISAM;
|
||||
|
||||
DROP TABLE IF EXISTS dirs;
|
||||
CREATE TABLE dirs (
|
||||
id mediumint(9) NOT NULL auto_increment,
|
||||
dir varchar(255) binary DEFAULT '' NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE dir (dir)
|
||||
) TYPE=MyISAM;
|
||||
|
||||
DROP TABLE IF EXISTS files;
|
||||
CREATE TABLE files (
|
||||
id mediumint(9) NOT NULL auto_increment,
|
||||
file varchar(255) binary DEFAULT '' NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE file (file)
|
||||
) TYPE=MyISAM;
|
||||
|
||||
DROP TABLE IF EXISTS people;
|
||||
CREATE TABLE people (
|
||||
id mediumint(9) NOT NULL auto_increment,
|
||||
who varchar(128) binary DEFAULT '' NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE who (who)
|
||||
) TYPE=MyISAM;
|
||||
|
||||
DROP TABLE IF EXISTS repositories;
|
||||
CREATE TABLE repositories (
|
||||
id mediumint(9) NOT NULL auto_increment,
|
||||
repository varchar(64) binary DEFAULT '' NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE repository (repository)
|
||||
) TYPE=MyISAM;
|
||||
|
||||
DROP TABLE IF EXISTS tags;
|
||||
CREATE TABLE tags (
|
||||
repositoryid mediumint(9) DEFAULT '0' NOT NULL,
|
||||
branchid mediumint(9) DEFAULT '0' NOT NULL,
|
||||
dirid mediumint(9) DEFAULT '0' NOT NULL,
|
||||
fileid mediumint(9) DEFAULT '0' NOT NULL,
|
||||
revision varchar(32) binary DEFAULT '' NOT NULL,
|
||||
UNIQUE repositoryid (repositoryid,dirid,fileid,branchid,revision),
|
||||
KEY repositoryid_2 (repositoryid),
|
||||
KEY dirid (dirid),
|
||||
KEY fileid (fileid),
|
||||
KEY branchid (branchid)
|
||||
) TYPE=MyISAM;
|
||||
|
||||
DROP TABLE IF EXISTS metadata;
|
||||
CREATE TABLE metadata (
|
||||
name varchar(255) binary DEFAULT '' NOT NULL,
|
||||
value text,
|
||||
PRIMARY KEY (name),
|
||||
UNIQUE name (name)
|
||||
) TYPE=MyISAM;
|
||||
INSERT INTO metadata (name, value) VALUES ('version', '1');
|
||||
"""
|
||||
|
||||
BONSAI_COMPAT="""
|
||||
WARNING: Creating Bonsai-compatible legacy database version. Some ViewVC
|
||||
features may not be available, or may not perform especially well.
|
||||
|
||||
"""
|
||||
|
||||
## ------------------------------------------------------------------------
|
||||
|
||||
def usage_and_exit(errmsg=None):
|
||||
stream = errmsg is None and sys.stdout or sys.stderr
|
||||
stream.write("""\
|
||||
Usage: %s [OPTIONS]
|
||||
|
||||
This script creates the database and tables in MySQL used by the
|
||||
ViewVC checkin database. In order to operate correctly, it needs to
|
||||
know the following: your database server hostname, database user,
|
||||
database user password, and database name. (You will be prompted for
|
||||
any of this information that you do not provide via command-line
|
||||
options.) This script will use the 'mysql' program to create the
|
||||
database for you. You will then need to set the appropriate
|
||||
parameters in the [cvsdb] section of your viewvc.conf file.
|
||||
|
||||
Options:
|
||||
|
||||
--dbname=ARG Use ARG as the ViewVC database name to create.
|
||||
[Default: ViewVC]
|
||||
|
||||
--help Show this usage message.
|
||||
|
||||
--hostname=ARG Use ARG as the hostname for the MySQL connection.
|
||||
[Default: localhost]
|
||||
|
||||
--password=ARG Use ARG as the password for the MySQL connection.
|
||||
|
||||
--username=ARG Use ARG as the username for the MySQL connection.
|
||||
|
||||
--version=ARG Create the database using the schema employed by
|
||||
version ARG of ViewVC. Valid values are:
|
||||
[ "1.0" ]
|
||||
|
||||
""" % (os.path.basename(sys.argv[0])))
|
||||
if errmsg is not None:
|
||||
stream.write("[ERROR] %s.\n" % (errmsg))
|
||||
sys.exit(1)
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
# Parse the command-line options, if any.
|
||||
dbname = version = hostname = username = password = None
|
||||
opts, args = getopt.getopt(sys.argv[1:], '', [ 'dbname=',
|
||||
'help',
|
||||
'hostname=',
|
||||
'password=',
|
||||
'username=',
|
||||
'version=',
|
||||
])
|
||||
if len(args) > 0:
|
||||
usage_and_exit("Unexpected command-line parameters")
|
||||
for name, value in opts:
|
||||
if name == '--help':
|
||||
usage_and_exit(0)
|
||||
elif name == '--dbname':
|
||||
dbname = value
|
||||
elif name == '--hostname':
|
||||
hostname = value
|
||||
elif name == '--username':
|
||||
username = value
|
||||
elif name == '--password':
|
||||
password = value
|
||||
elif name == '--version':
|
||||
if value in ["1.0"]:
|
||||
version = value
|
||||
else:
|
||||
usage_and_exit("Invalid version specified")
|
||||
print INTRO_TEXT
|
||||
|
||||
# Prompt for information not provided via command-line options.
|
||||
if hostname is None:
|
||||
hostname = raw_input("MySQL Hostname [default: localhost]: ") or ""
|
||||
if username is None:
|
||||
username = raw_input("MySQL User: ")
|
||||
if password is None:
|
||||
password = raw_input("MySQL Password: ")
|
||||
if dbname is None:
|
||||
dbname = raw_input("ViewVC Database Name [default: ViewVC]: ") or "ViewVC"
|
||||
# Prompt for necessary information
|
||||
host = raw_input("MySQL Hostname [default: localhost]: ") or ""
|
||||
user = raw_input("MySQL User: ")
|
||||
passwd = raw_input("MySQL Password: ")
|
||||
dbase = raw_input("ViewVC Database Name [default: ViewVC]: ") or "ViewVC"
|
||||
|
||||
# Create the database
|
||||
dscript = string.replace(DATABASE_SCRIPT_COMMON, "<dbname>", dbname)
|
||||
if version == "1.0":
|
||||
print BONSAI_COMPAT
|
||||
dscript = dscript + DATABASE_SCRIPT_VERSION_0
|
||||
else:
|
||||
dscript = dscript + DATABASE_SCRIPT_VERSION_1
|
||||
|
||||
host_option = hostname and "--host=%s" % (hostname) or ""
|
||||
dscript = string.replace(DATABASE_SCRIPT, "<dbname>", dbase)
|
||||
host_option = host and "--host=%s" % (host) or ""
|
||||
if sys.platform == "win32":
|
||||
cmd = "mysql --user=%s --password=%s %s "\
|
||||
% (username, password, host_option)
|
||||
% (user, passwd, host_option)
|
||||
mysql = os.popen(cmd, "w") # popen2.Popen3 is not provided on windows
|
||||
mysql.write(dscript)
|
||||
status = mysql.close()
|
||||
else:
|
||||
cmd = "{ mysql --user=%s --password=%s %s ; } 2>&1" \
|
||||
% (username, password, host_option)
|
||||
% (user, passwd, host_option)
|
||||
pipes = popen2.Popen3(cmd)
|
||||
pipes.tochild.write(dscript)
|
||||
pipes.tochild.close()
|
||||
@@ -335,11 +150,10 @@ if __name__ == "__main__":
|
||||
status = pipes.wait()
|
||||
|
||||
if status:
|
||||
print "[ERROR] The database did not create sucessfully."
|
||||
print "[ERROR] the database did not create sucessfully."
|
||||
sys.exit(1)
|
||||
|
||||
print "Database created successfully. Don't forget to configure the "
|
||||
print "[cvsdb] section of your viewvc.conf file."
|
||||
print "Database created successfully."
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
sys.exit(0)
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2010 The ViewCVS Group. All Rights Reserved.
|
||||
# Copyright (C) 1999-2006 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 ViewVC
|
||||
@@ -65,10 +65,7 @@ cfg = viewvc.load_config(CONF_PATHNAME)
|
||||
def index(req):
|
||||
server = sapi.ModPythonServer(req)
|
||||
try:
|
||||
viewvc_base_url = cfg.query.viewvc_base_url
|
||||
if viewvc_base_url is None:
|
||||
viewvc_base_url = "viewvc.py"
|
||||
query.main(server, cfg, viewvc_base_url)
|
||||
query.main(server, cfg, "viewvc.py")
|
||||
finally:
|
||||
server.close()
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2008 The ViewCVS Group. All Rights Reserved.
|
||||
# Copyright (C) 1999-2006 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 ViewVC
|
||||
|
1174
bin/standalone.py
1174
bin/standalone.py
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 2004-2008 The ViewCVS Group. All Rights Reserved.
|
||||
# Copyright (C) 2004-2007 James Henstridge
|
||||
#
|
||||
# By using this file, you agree to the terms and conditions set forth in
|
||||
@@ -242,35 +241,23 @@ def main(command, repository, revs=[], verbose=0, force=0):
|
||||
cfg = viewvc.load_config(CONF_PATHNAME)
|
||||
db = cvsdb.ConnectDatabase(cfg)
|
||||
|
||||
# Purge what must be purged.
|
||||
if command in ('rebuild', 'purge'):
|
||||
if verbose:
|
||||
print "Purging commit info for repository root `%s'" % repository
|
||||
try:
|
||||
db.PurgeRepository(repository)
|
||||
except cvsdb.UnknownRepositoryError, e:
|
||||
if command == 'purge':
|
||||
sys.stderr.write("ERROR: " + str(e) + "\n")
|
||||
sys.exit(1)
|
||||
db.PurgeRepository(repository)
|
||||
|
||||
# Record what must be recorded.
|
||||
if command in ('rebuild', 'update'):
|
||||
if not os.path.exists(repository):
|
||||
sys.stderr.write('ERROR: could not find repository %s\n'
|
||||
% (repository))
|
||||
sys.exit(1)
|
||||
repo = SvnRepo(repository)
|
||||
if command == 'rebuild' or (command == 'update' and not revs):
|
||||
for rev in range(repo.rev_max+1):
|
||||
handle_revision(db, command, repo, rev, verbose)
|
||||
elif command == 'update':
|
||||
if revs[0] is None:
|
||||
revs[0] = repo.rev_max
|
||||
if revs[1] is None:
|
||||
revs[1] = repo.rev_max
|
||||
revs.sort()
|
||||
for rev in range(revs[0], revs[1]+1):
|
||||
handle_revision(db, command, repo, rev, verbose, force)
|
||||
repo = SvnRepo(repository)
|
||||
if command == 'rebuild' or (command == 'update' and not revs):
|
||||
for rev in range(repo.rev_max+1):
|
||||
handle_revision(db, command, repo, rev, verbose)
|
||||
elif command == 'update':
|
||||
if revs[0] is None:
|
||||
revs[0] = repo.rev_max
|
||||
if revs[1] is None:
|
||||
revs[1] = repo.rev_max
|
||||
revs.sort()
|
||||
for rev in range(revs[0], revs[1]+1):
|
||||
handle_revision(db, command, repo, rev, verbose, force)
|
||||
|
||||
def _rev2int(r):
|
||||
if r == 'HEAD':
|
||||
@@ -337,6 +324,12 @@ if __name__ == '__main__':
|
||||
sys.stderr.write('ERROR: unknown command %s\n' % command)
|
||||
usage()
|
||||
|
||||
repository = args[2]
|
||||
if not os.path.exists(repository):
|
||||
sys.stderr.write('ERROR: could not find repository %s\n' % args[2])
|
||||
usage()
|
||||
repository = vclib.svn.canonicalize_rootpath(repository)
|
||||
|
||||
revs = []
|
||||
if len(sys.argv) > 3:
|
||||
if command == 'rebuild':
|
||||
@@ -359,7 +352,6 @@ if __name__ == '__main__':
|
||||
rev = None
|
||||
|
||||
try:
|
||||
repository = vclib.svn.canonicalize_rootpath(args[2])
|
||||
repository = cvsdb.CleanRepository(os.path.abspath(repository))
|
||||
main(command, repository, revs, verbose, force)
|
||||
except KeyboardInterrupt:
|
||||
|
@@ -1,54 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2010 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 ViewVC
|
||||
# distribution or at http://viewvc.org/license-1.html.
|
||||
#
|
||||
# For more information, visit http://viewvc.org/
|
||||
#
|
||||
# -----------------------------------------------------------------------
|
||||
#
|
||||
# viewvc: View CVS/SVN repositories via a web browser
|
||||
#
|
||||
# -----------------------------------------------------------------------
|
||||
#
|
||||
# This is a fcgi entry point for the query ViewVC app. It's appropriate
|
||||
# for use with mod_fcgid and flup. It defines a single application function
|
||||
# that is a valid fcgi entry point.
|
||||
#
|
||||
# mod_fcgid: http://httpd.apache.org/mod_fcgid/
|
||||
# flup:
|
||||
# http://pypi.python.org/pypi/flup
|
||||
# http://trac.saddi.com/flup
|
||||
#
|
||||
# -----------------------------------------------------------------------
|
||||
|
||||
import sys, os
|
||||
|
||||
LIBRARY_DIR = None
|
||||
CONF_PATHNAME = None
|
||||
|
||||
if LIBRARY_DIR:
|
||||
sys.path.insert(0, LIBRARY_DIR)
|
||||
else:
|
||||
sys.path.insert(0, os.path.abspath(os.path.join(sys.argv[0],
|
||||
"../../../lib")))
|
||||
|
||||
import sapi
|
||||
import viewvc
|
||||
import query
|
||||
from flup.server import fcgi
|
||||
|
||||
def application(environ, start_response):
|
||||
server = sapi.WsgiServer(environ, start_response)
|
||||
cfg = viewvc.load_config(CONF_PATHNAME, server)
|
||||
viewvc_base_url = cfg.query.viewvc_base_url
|
||||
if viewvc_base_url is None:
|
||||
viewvc_base_url = "viewvc.fcgi"
|
||||
query.main(server, cfg, viewvc_base_url)
|
||||
return []
|
||||
|
||||
fcgi.WSGIServer(application).run()
|
@@ -1,45 +0,0 @@
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2010 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 ViewVC
|
||||
# distribution or at http://viewvc.org/license-1.html.
|
||||
#
|
||||
# For more information, visit http://viewvc.org/
|
||||
#
|
||||
# -----------------------------------------------------------------------
|
||||
#
|
||||
# viewvc: View CVS/SVN repositories via a web browser
|
||||
#
|
||||
# -----------------------------------------------------------------------
|
||||
#
|
||||
# This is a wsgi entry point for the query ViewVC app. It's appropriate
|
||||
# for use with mod_wsgi. It defines a single application function that
|
||||
# is a valid wsgi entry point.
|
||||
#
|
||||
# -----------------------------------------------------------------------
|
||||
|
||||
import sys, os
|
||||
|
||||
LIBRARY_DIR = None
|
||||
CONF_PATHNAME = None
|
||||
|
||||
if LIBRARY_DIR:
|
||||
sys.path.insert(0, LIBRARY_DIR)
|
||||
else:
|
||||
sys.path.insert(0, os.path.abspath(os.path.join(sys.argv[0],
|
||||
"../../../lib")))
|
||||
|
||||
import sapi
|
||||
import viewvc
|
||||
import query
|
||||
|
||||
def application(environ, start_response):
|
||||
server = sapi.WsgiServer(environ, start_response)
|
||||
cfg = viewvc.load_config(CONF_PATHNAME, server)
|
||||
viewvc_base_url = cfg.query.viewvc_base_url
|
||||
if viewvc_base_url is None:
|
||||
viewvc_base_url = "viewvc.wsgi"
|
||||
query.main(server, cfg, viewvc_base_url)
|
||||
return []
|
@@ -1,50 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2010 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 ViewVC
|
||||
# distribution or at http://viewvc.org/license-1.html.
|
||||
#
|
||||
# For more information, visit http://viewvc.org/
|
||||
#
|
||||
# -----------------------------------------------------------------------
|
||||
#
|
||||
# viewvc: View CVS/SVN repositories via a web browser
|
||||
#
|
||||
# -----------------------------------------------------------------------
|
||||
#
|
||||
# This is a fcgi entry point for the main ViewVC app. It's appropriate
|
||||
# for use with mod_fcgid and flup. It defines a single application function
|
||||
# that is a valid fcgi entry point.
|
||||
#
|
||||
# mod_fcgid: http://httpd.apache.org/mod_fcgid/
|
||||
# flup:
|
||||
# http://pypi.python.org/pypi/flup
|
||||
# http://trac.saddi.com/flup
|
||||
#
|
||||
# -----------------------------------------------------------------------
|
||||
|
||||
import sys, os
|
||||
|
||||
LIBRARY_DIR = None
|
||||
CONF_PATHNAME = None
|
||||
|
||||
if LIBRARY_DIR:
|
||||
sys.path.insert(0, LIBRARY_DIR)
|
||||
else:
|
||||
sys.path.insert(0, os.path.abspath(os.path.join(sys.argv[0],
|
||||
"../../../lib")))
|
||||
|
||||
import sapi
|
||||
import viewvc
|
||||
from flup.server import fcgi
|
||||
|
||||
def application(environ, start_response):
|
||||
server = sapi.WsgiServer(environ, start_response)
|
||||
cfg = viewvc.load_config(CONF_PATHNAME, server)
|
||||
viewvc.main(server, cfg)
|
||||
return []
|
||||
|
||||
fcgi.WSGIServer(application).run()
|
@@ -1,41 +0,0 @@
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2009 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 ViewVC
|
||||
# distribution or at http://viewvc.org/license-1.html.
|
||||
#
|
||||
# For more information, visit http://viewvc.org/
|
||||
#
|
||||
# -----------------------------------------------------------------------
|
||||
#
|
||||
# viewvc: View CVS/SVN repositories via a web browser
|
||||
#
|
||||
# -----------------------------------------------------------------------
|
||||
#
|
||||
# This is a wsgi entry point for the main ViewVC app. It's appropriate
|
||||
# for use with mod_wsgi. It defines a single application function that
|
||||
# is a valid wsgi entry point.
|
||||
#
|
||||
# -----------------------------------------------------------------------
|
||||
|
||||
import sys, os
|
||||
|
||||
LIBRARY_DIR = None
|
||||
CONF_PATHNAME = None
|
||||
|
||||
if LIBRARY_DIR:
|
||||
sys.path.insert(0, LIBRARY_DIR)
|
||||
else:
|
||||
sys.path.insert(0, os.path.abspath(os.path.join(sys.argv[0],
|
||||
"../../../lib")))
|
||||
|
||||
import sapi
|
||||
import viewvc
|
||||
|
||||
def application(environ, start_response):
|
||||
server = sapi.WsgiServer(environ, start_response)
|
||||
cfg = viewvc.load_config(CONF_PATHNAME, server)
|
||||
viewvc.main(server, cfg)
|
||||
return []
|
@@ -1,32 +0,0 @@
|
||||
#---------------------------------------------------------------------------
|
||||
#
|
||||
# MIME type mapping file for ViewVC
|
||||
#
|
||||
# Information on ViewVC is located at the following web site:
|
||||
# http://viewvc.org/
|
||||
#
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# THE FORMAT OF THIS FILE
|
||||
#
|
||||
# This file contains records -- one per line -- of the following format:
|
||||
#
|
||||
# MIME_TYPE [EXTENSION [EXTENSION ...]]
|
||||
#
|
||||
# where whitespace separates the MIME_TYPE from the EXTENSION(s),
|
||||
# and the EXTENSIONs from each other.
|
||||
#
|
||||
# For example:
|
||||
#
|
||||
# text/x-csh csh
|
||||
# text/x-csrc c
|
||||
# text/x-diff diff patch
|
||||
# image/png png
|
||||
# image/jpeg jpeg jpg jpe
|
||||
#
|
||||
# By default, this file is left empty, allowing ViewVC to continue
|
||||
# consulting it first without overriding the MIME type mappings
|
||||
# found in more standard mapping files (such as those provided as
|
||||
# part of the operating system or web server software).
|
||||
#
|
||||
#
|
File diff suppressed because it is too large
Load Diff
@@ -161,6 +161,12 @@ td {
|
||||
resource. Valid only when <var>pathtype</var> is <tt>file</tt>
|
||||
or (for Subversion roots) <tt>dir</tt>.</td>
|
||||
</tr>
|
||||
<tr class="varlevel1">
|
||||
<td class="varname">log_rev_href</td>
|
||||
<td>String</td>
|
||||
<td>Revision number of the file-revision currently being viewed, or
|
||||
None.</td>
|
||||
</tr>
|
||||
<tr class="varlevel1">
|
||||
<td class="varname">nav_path</td>
|
||||
<td>List</td>
|
||||
@@ -315,7 +321,7 @@ td {
|
||||
<tr class="varlevel1">
|
||||
<td class="varname">pathrev_hidden_values</td>
|
||||
<td>List</td>
|
||||
<td>Hidden field name/value pairs for the revision/tag selection form.</td>
|
||||
<td>Hidden value name/value pairs for the revision/tag selection form.</td>
|
||||
</tr>
|
||||
<tr class="varlevel1">
|
||||
<td class="varname">pathrev_clear_action</td>
|
||||
@@ -325,7 +331,7 @@ td {
|
||||
<tr class="varlevel1">
|
||||
<td class="varname">pathrev_clear_hidden_values</td>
|
||||
<td>List</td>
|
||||
<td>Hidden field name/value pairs for the path revision clear button.</td>
|
||||
<td>Hidden value name/value pairs for the path revision clear button.</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
@@ -444,10 +450,10 @@ td {
|
||||
<tr class="varlevel1">
|
||||
<td class="varname">annotation</td>
|
||||
<td>String</td>
|
||||
<td>Valid values are "none" (no annotations were attempted),
|
||||
"annotated" (annotation was successful), "binary" (file contents
|
||||
are not line-based and human-readable), and "error" (something
|
||||
went wrong during annotation).</td>
|
||||
<td>If set, indicates that annotations were requested. Valid values
|
||||
are "annotated" (annotation was successful), "binary" (file contents
|
||||
are not line-based and human-readable), and "error" (something went
|
||||
wrong during annotation).</td>
|
||||
</tr>
|
||||
<tr class="varlevel1">
|
||||
<td class="varname">author</td>
|
||||
@@ -719,29 +725,19 @@ td {
|
||||
<tr class="varlevel1">
|
||||
<td class="varname">diff_format_hidden_values</td>
|
||||
<td>List</td>
|
||||
<td>Hidden field name/value pairs for the diff format selection form.</td>
|
||||
<td>Hidden value name/value pairs for the diff format selection form.</td>
|
||||
</tr>
|
||||
<tr class="varlevel1">
|
||||
<td class="varname">left</td>
|
||||
<td>Container</td>
|
||||
<td>Container object for grouping information about the left file.</td>
|
||||
</tr>
|
||||
<tr class="varlevel2">
|
||||
<td class="varname">left.ago</td>
|
||||
<td>String</td>
|
||||
<td>Text description of the time elapsed since <var>left.date</date>.</td>
|
||||
</tr>
|
||||
<tr class="varlevel2">
|
||||
<td class="varname">left.annotate_href</td>
|
||||
<td>String</td>
|
||||
<td>URL of the ViewVC annotation view for the left file.
|
||||
Valid only when <var>entries.pathtype</var> is <tt>file</tt>.</td>
|
||||
</tr>
|
||||
<tr class="varlevel2">
|
||||
<td class="varname">left.author</td>
|
||||
<td>String</td>
|
||||
<td>Author of the revision of the left file.</td>
|
||||
</tr>
|
||||
<tr class="varlevel2">
|
||||
<td class="varname">left.date</td>
|
||||
<td>String</td>
|
||||
@@ -759,11 +755,6 @@ td {
|
||||
<td>URL to download the HEAD revision of the left file as
|
||||
<tt>text/plain</tt>.</td>
|
||||
</tr>
|
||||
<tr class="varlevel2">
|
||||
<td class="varname">left.log</td>
|
||||
<td>String</td>
|
||||
<td>Log message of the left file revision.</td>
|
||||
</tr>
|
||||
<tr class="varlevel2">
|
||||
<td class="varname">left.path</td>
|
||||
<td>String</td>
|
||||
@@ -787,11 +778,6 @@ td {
|
||||
current revision. Valid only when <var>roottype</var> is
|
||||
<tt>svn</tt>.</td>
|
||||
</tr>
|
||||
<tr class="varlevel2">
|
||||
<td class="varname">left.size</td>
|
||||
<td>String</td>
|
||||
<td>Size of the left file revision, in bytes. Subversion only.</td>
|
||||
</tr>
|
||||
<tr class="varlevel2">
|
||||
<td class="varname">left.tag</td>
|
||||
<td>String</td>
|
||||
@@ -813,22 +799,12 @@ td {
|
||||
<td>Container</td>
|
||||
<td>Container object for grouping information about the right file.</td>
|
||||
</tr>
|
||||
<tr class="varlevel2">
|
||||
<td class="varname">right.author</td>
|
||||
<td>String</td>
|
||||
<td>Author of the revision of the right file.</td>
|
||||
</tr>
|
||||
<tr class="varlevel2">
|
||||
<td class="varname">right.annotate_href</td>
|
||||
<td>String</td>
|
||||
<td>URL of the ViewVC annotation view for the right file.
|
||||
Valid only when <var>entries.pathtype</var> is <tt>file</tt>.</td>
|
||||
</tr>
|
||||
<tr class="varlevel2">
|
||||
<td class="varname">right.author</td>
|
||||
<td>String</td>
|
||||
<td>Author of the revision of the right file.</td>
|
||||
</tr>
|
||||
<tr class="varlevel2">
|
||||
<td class="varname">right.date</td>
|
||||
<td>String</td>
|
||||
@@ -846,11 +822,6 @@ td {
|
||||
<td>URL to download the HEAD revision of the right file as
|
||||
<tt>text/plain</tt>.</td>
|
||||
</tr>
|
||||
<tr class="varlevel2">
|
||||
<td class="varname">right.log</td>
|
||||
<td>String</td>
|
||||
<td>Log message of the right file revision.</td>
|
||||
</tr>
|
||||
<tr class="varlevel2">
|
||||
<td class="varname">right.path</td>
|
||||
<td>String</td>
|
||||
@@ -874,11 +845,6 @@ td {
|
||||
current revision. Valid only when <var>roottype</var> is
|
||||
<tt>svn</tt>.</td>
|
||||
</tr>
|
||||
<tr class="varlevel2">
|
||||
<td class="varname">right.size</td>
|
||||
<td>String</td>
|
||||
<td>Size of the right file revision, in bytes. Subversion only.</td>
|
||||
</tr>
|
||||
<tr class="varlevel2">
|
||||
<td class="varname">right.tag</td>
|
||||
<td>String</td>
|
||||
@@ -939,7 +905,7 @@ td {
|
||||
<tr class="varlevel1">
|
||||
<td class="varname">dir_paging_hidden_values</td>
|
||||
<td>List</td>
|
||||
<td>Hidden field name/value pairs for the page selection form.</td>
|
||||
<td>Hidden value name/value pairs for the page selection form.</td>
|
||||
</tr>
|
||||
<tr class="varlevel1">
|
||||
<td class="varname">entries</td>
|
||||
@@ -1121,16 +1087,23 @@ td {
|
||||
<td>String</td>
|
||||
<td>Current search expression, if any.</td>
|
||||
</tr>
|
||||
<tr class="varlevel1">
|
||||
<td class="varname">search_re_form</td>
|
||||
<td>Boolean</td>
|
||||
<td>Indicates whether or not to display the regular expression search
|
||||
form. Value depends on the whether searching is enabled in the
|
||||
configuration and whether or not the current directory is
|
||||
empty.</td>
|
||||
</tr>
|
||||
<tr class="varlevel1">
|
||||
<td class="varname">search_re_action</td>
|
||||
<td>String</td>
|
||||
<td>Form action URL for the regular expression search form,
|
||||
if searching is available.</td>
|
||||
<td>Form action URL for the regular expression search form.</td>
|
||||
</tr>
|
||||
<tr class="varlevel1">
|
||||
<td class="varname">search_re_hidden_values</td>
|
||||
<td>List</td>
|
||||
<td>Hidden field name/value pairs for the regular expression search form.</td>
|
||||
<td>Hidden value name/value pairs for the regular expression search form.</td>
|
||||
</tr>
|
||||
<tr class="varlevel1">
|
||||
<td class="varname">show_attic_href</td>
|
||||
@@ -1276,7 +1249,7 @@ td {
|
||||
<tr class="varlevel1">
|
||||
<td class="varname">diff_select_hidden_values</td>
|
||||
<td>List</td>
|
||||
<td>Hidden field name/value pairs for the diff selection form.</td>
|
||||
<td>Hidden value name/value pairs for the diff selection form.</td>
|
||||
</tr>
|
||||
<tr class="varlevel1">
|
||||
<td class="varname">entries</td>
|
||||
@@ -1557,7 +1530,7 @@ td {
|
||||
<tr class="varlevel1">
|
||||
<td class="varname">log_paging_hidden_values</td>
|
||||
<td>List</td>
|
||||
<td>Hidden field name/value pairs for the page selection form.</td>
|
||||
<td>Hidden value name/value pairs for the page selection form.</td>
|
||||
</tr>
|
||||
<tr class="varlevel1">
|
||||
<td class="varname">logsort</td>
|
||||
@@ -1573,7 +1546,7 @@ td {
|
||||
<tr class="varlevel1">
|
||||
<td class="varname">logsort_hidden_values</td>
|
||||
<td>List</td>
|
||||
<td>Hidden field name/value pairs for the log sort drop down box</td>
|
||||
<td>Hidden value name/value pairs for the log sort drop down box</td>
|
||||
</tr>
|
||||
<tr class="varlevel1">
|
||||
<td class="varname">mime_type</td>
|
||||
@@ -1937,7 +1910,7 @@ td {
|
||||
<tr class="varlevel1">
|
||||
<td class="varname">query_hidden_values</td>
|
||||
<td>List</td>
|
||||
<td>Hidden field name/value pairs for query form.</td>
|
||||
<td>Hidden value name/value pairs for query form.</td>
|
||||
</tr>
|
||||
<tr class="varlevel1">
|
||||
<td class="varname">querysort</td>
|
||||
@@ -2077,7 +2050,7 @@ td {
|
||||
<tr class="varlevel1">
|
||||
<td class="varname">jump_rev_hidden_values</td>
|
||||
<td>List</td>
|
||||
<td>Hidden field name/value pairs for revision jump form.</td>
|
||||
<td>Hidden value name/value pairs for revision jump form.</td>
|
||||
</tr>
|
||||
<tr class="varlevel1">
|
||||
<td class="varname">limit_changes</td>
|
||||
@@ -2100,11 +2073,6 @@ td {
|
||||
<td>String</td>
|
||||
<td>URL for the current view but with <tt>limit_changes</tt> disabled.</td>
|
||||
</tr>
|
||||
<tr class="varlevel1">
|
||||
<td class="varname">num_changes</td>
|
||||
<td>String</td>
|
||||
<td>Number of paths changed in this revision.</td>
|
||||
</tr>
|
||||
<tr class="varlevel1">
|
||||
<td class="varname">next_href</td>
|
||||
<td>String</td>
|
||||
|
@@ -137,8 +137,9 @@ td {
|
||||
configuration's "general" section.</li>
|
||||
|
||||
<li>Finally, ensure that that the new <code>authorizer</code>
|
||||
option is set to either "forbidden" or "forbiddenre", depending
|
||||
on which of those you were using in ViewVC 1.0.x.</li>
|
||||
option is set to either "forbidden" (which is the default) or
|
||||
"forbiddenre", depending on which of those you were using in
|
||||
ViewVC 1.0.x.</li>
|
||||
|
||||
</ol>
|
||||
|
||||
@@ -214,9 +215,10 @@ td {
|
||||
<li>options/py2html_path</li>
|
||||
<li>options/use_enscript</li>
|
||||
<li>options/use_highlight</li>
|
||||
<li>options/use_pagesize</li>
|
||||
<li>options/use_php</li>
|
||||
<li>options/use_py2html</li>
|
||||
<li>options/use_pygments</li>
|
||||
<li>options/use_source_highlight</li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
@@ -224,23 +226,16 @@ td {
|
||||
<div class="h3">
|
||||
<h3>Checkin Database</h3>
|
||||
|
||||
<p>ViewVC 1.1 introduces to the <code>cvsdbadmin</code>
|
||||
and <code>svndbadmin</code> tools a new "purge" operation, which
|
||||
allows you to remove all the information related to a given root
|
||||
from your checkins database (without disturbing the information
|
||||
associated with other roots). Likewise, the "rebuild" command in
|
||||
those tools now implies a "purge" followed by an update.</p>
|
||||
|
||||
<p>As a related change, the <code>svndbadmin</code> program's
|
||||
"rebuild" subcommand has had its purpose become more defined. It
|
||||
no longer accepts a revision argument, and therefore can now only
|
||||
be used to completely rebuild the entirety of the checkin database
|
||||
information for a Subversion repository (instead of being able to
|
||||
only update the information related to single Subversion revision).
|
||||
For per-revision updating, use <code>svndbadmin update</code> and
|
||||
<p>In ViewVC 1.1, the <code>svndbadmin</code> program's "rebuild"
|
||||
subcommand has had its purpose become more defined. It no longer
|
||||
accepts a revision argument, and therefore can now only be used to
|
||||
completely rebuild the entirety of the checkin database information
|
||||
for a Subversion repository (instead of being able to only update
|
||||
the information related to single Subversion revision). For
|
||||
per-revision updating, use <code>svndbadmin update</code> and
|
||||
provide a revision (or revision range). And to get the previous
|
||||
rebuild-a-revision effect, pass the new <code>--force</code> option
|
||||
to <code>svndbadmin update</code>.</p>
|
||||
rebuild-a-revision effect, pass the new <code>--force</code>
|
||||
option to <code>svndbadmin update</code>.</p>
|
||||
|
||||
<p>In other words, where you once did this:</p>
|
||||
|
||||
@@ -254,19 +249,6 @@ td {
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<p>To enhance the performance of the new "purge" operation, ViewVC 1.1
|
||||
introduces some slight changes to the checkin database schema. If
|
||||
you use the <code>make-database</code> tool to (re)create your
|
||||
checkins database, it will by default employ the new database
|
||||
schema. This should cause the database to be virtually unusable by
|
||||
previous versions of ViewVC, and that's by design. If, however,
|
||||
you need to (re)create your checkins database and you require
|
||||
compatibility with previous versions of ViewVC or ViewCVS, simply
|
||||
pass the "--version=1.0" option to the <code>make-database</code>
|
||||
script. Note that your "purge" and "rebuild" operations could be
|
||||
abysmally slow, though, as that version of the database schema is
|
||||
not optimized for those operations.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="h3">
|
||||
@@ -314,22 +296,6 @@ td {
|
||||
<li>options/allow_tar</li>
|
||||
</ul>
|
||||
|
||||
<p>ViewVC now honors the "svn:mime-type" property stored on
|
||||
Subversion-versioned files as the primary source of MIME type
|
||||
determination (before falling back to name-based MIME mappings and
|
||||
such). However, this can negatively affect the viewability of
|
||||
certain files — especially images — whose
|
||||
"svn:mime-type" properties are set incorrectly, such as will happen
|
||||
if Subversion itself merely determines that the file isn't
|
||||
human-readable and uses the "application/octet-stream" MIME type to
|
||||
record this determination. To make ViewVC <em>not</em> honor the
|
||||
"svn:mime-type" property value, set the <code>svn_ignore_mimetype</code>
|
||||
configuration option.</p>
|
||||
|
||||
<p>Speaking of MIME types, the option <code>mime_types_file</code> is
|
||||
now <code>mime_types_files</code>, as it now carries multiple paths
|
||||
to MIME mappings files, ordered by preference.</p>
|
||||
|
||||
<p>The <code>use_rcsparse</code> option was moved from the "general"
|
||||
section to the "options" section.</p>
|
||||
|
||||
@@ -348,7 +314,7 @@ td {
|
||||
all = viewvc.*
|
||||
|
||||
[all-options]
|
||||
allowed_views = annotate, diff, markup, tar
|
||||
allow_tar = 1
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
@@ -358,7 +324,7 @@ allowed_views = annotate, diff, markup, tar
|
||||
all = viewvc.*
|
||||
|
||||
[vhost-all/options]
|
||||
allowed_views = annotate, diff, markup, tar
|
||||
allow_tar = 1
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
@@ -665,11 +631,6 @@ allowed_views = annotate, diff, markup, tar
|
||||
<td>revision.ezt</td>
|
||||
<td>now is an iterable list of objects with .name and .value attributes</td>
|
||||
</tr>
|
||||
<tr class="added">
|
||||
<td class="varname">num_changes</td>
|
||||
<td>revision.ezt</td>
|
||||
<td>added</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
@@ -698,7 +659,7 @@ allowed_views = annotate, diff, markup, tar
|
||||
<h3>Checkin Database</h3>
|
||||
|
||||
<p>ViewVC 1.0 reads and writes commit times in the MySQL database in
|
||||
UTC time rather than local time. This can cause times displayed on
|
||||
UTC time rather than local time. This can cause times displayed on
|
||||
the query page to be a few hours off if an old database is being
|
||||
used with a new version of ViewVC. The best way to fix this is to
|
||||
rebuild the database with the new version of cvsdbadmin, but it
|
||||
@@ -741,8 +702,7 @@ allowed_views = annotate, diff, markup, tar
|
||||
<li>options/root_as_url_component</li>
|
||||
<li>options/default_file_view</li>
|
||||
<li>options/sort_group_dirs</li>
|
||||
<li>options/dir_pagesize</li>
|
||||
<li>options/log_pagesize</li>
|
||||
<li>options/use_pagesize</li>
|
||||
<li>options/limit_changes</li>
|
||||
<li>options/use_localtime</li>
|
||||
<li>options/cross_copies</li>
|
||||
|
@@ -996,7 +996,7 @@ th.caption {
|
||||
<td>file query string</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>file_match=<var>FILE_MATCH</var></code></td>
|
||||
<td><code>file_match=FILE_MATCH</code></td>
|
||||
<td>optional</td>
|
||||
<td>"exact" "like" "glob" "regex" or "notregex" determining type
|
||||
of file match</td>
|
||||
@@ -1007,7 +1007,7 @@ th.caption {
|
||||
<td>author query string</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>who_match=<var>WHO_MATCH</var></code></td>
|
||||
<td><code>who_match=WHO_MATCH</code></td>
|
||||
<td>optional</td>
|
||||
<td>"exact" "like" "glob" "regex" or "notregex" determining type
|
||||
of author match</td>
|
||||
@@ -1024,36 +1024,36 @@ th.caption {
|
||||
of log message match</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>querysort=<var>SORT</var></code></td>
|
||||
<td><code>querysort=SORT</code></td>
|
||||
<td>optional</td>
|
||||
<td>"date" "author" or "file" determining order of query results</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>date=<var>DATE</var></code></td>
|
||||
<td><code>date=DATE</code></td>
|
||||
<td>optional</td>
|
||||
<td>"hours" "day" "week" "month" "all" or "explicit" to filter
|
||||
query results by date</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>hours=<var>HOURS</var></code></td>
|
||||
<td><code>hours=HOURS</code></td>
|
||||
<td>optional</td>
|
||||
<td>number of hours back to include results from when
|
||||
<code><var>DATE</var></code> is "hours"</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>mindate=<var>MINDATE</var></code></td>
|
||||
<td><code>mindate=MINDATE</code></td>
|
||||
<td>optional</td>
|
||||
<td>earliest date to include results from when
|
||||
<code><var>DATE</var></code> is "explicit"</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>maxdate=<var>MAXDATE</var></code></td>
|
||||
<td><code>maxdate=MAXDATE</code></td>
|
||||
<td>optional</td>
|
||||
<td>latest date to include results from when
|
||||
<code><var>DATE</var></code> is "explicit"</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>limit_changes=<var>LIMIT_CHANGES</var></code></td>
|
||||
<td><code>limit_changes=LIMIT_CHANGES</code></td>
|
||||
<td>optional</td>
|
||||
<td>maximum number of files to list per commit in query
|
||||
results. Default is value of <code>limit_changes</code>
|
||||
@@ -1113,7 +1113,7 @@ th.caption {
|
||||
<td>branch query string</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>branch_match=<var>BRANCH_MATCH</var></code></td>
|
||||
<td><code>branch_match=BRANCH_MATCH</code></td>
|
||||
<td>optional</td>
|
||||
<td>"exact" "like" "glob" "regex" or "notregex" determining type
|
||||
of branch match</td>
|
||||
@@ -1129,7 +1129,7 @@ th.caption {
|
||||
<td>file query string</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>file_match=<var>FILE_MATCH</var></code></td>
|
||||
<td><code>file_match=FILE_MATCH</code></td>
|
||||
<td>optional</td>
|
||||
<td>"exact" "like" "glob" "regex" or "notregex" determining type
|
||||
of file match</td>
|
||||
@@ -1140,7 +1140,7 @@ th.caption {
|
||||
<td>author query string</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>who_match=<var>WHO_MATCH</var></code></td>
|
||||
<td><code>who_match=WHO_MATCH</code></td>
|
||||
<td>optional</td>
|
||||
<td>"exact" "like" "glob" "regex" or "notregex" determining type
|
||||
of author match</td>
|
||||
@@ -1157,50 +1157,50 @@ th.caption {
|
||||
of log message match</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>querysort=<var>SORT</var></code></td>
|
||||
<td><code>querysort=SORT</code></td>
|
||||
<td>optional</td>
|
||||
<td>"date" "author" or "file" determining order of query results</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>date=<var>DATE</var></code></td>
|
||||
<td><code>date=DATE</code></td>
|
||||
<td>optional</td>
|
||||
<td>"hours" "day" "week" "month" "all" or "explicit" to filter
|
||||
query results by date</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>hours=<var>HOURS</var></code></td>
|
||||
<td><code>hours=HOURS</code></td>
|
||||
<td>optional</td>
|
||||
<td>number of hours back to include results from when
|
||||
<code><var>DATE</var></code> is "hours"</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>mindate=<var>MINDATE</var></code></td>
|
||||
<td><code>mindate=MINDATE</code></td>
|
||||
<td>optional</td>
|
||||
<td>earliest date to include results from when
|
||||
<code><var>DATE</var></code> is "explicit"</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>maxdate=<var>MAXDATE</var></code></td>
|
||||
<td><code>maxdate=MAXDATE</code></td>
|
||||
<td>optional</td>
|
||||
<td>latest date to include results from when
|
||||
<code><var>DATE</var></code> is "explicit"</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>format=<var>FORMAT</var></code></td>
|
||||
<td><code>format=FORMAT</code></td>
|
||||
<td>optional</td>
|
||||
<td>"rss" or "backout" values to generate an rss feed or list of
|
||||
commands to back out changes instead showing a normal query result
|
||||
page</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>limit=<var>LIMIT</var></code></td>
|
||||
<td><code>limit=LIMIT</code></td>
|
||||
<td>optional</td>
|
||||
<td>maximum number of file-revisions to process during a
|
||||
query. Default is value of <code>row_limit</code> configuration
|
||||
option</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>limit_changes=<var>LIMIT_CHANGES</var></code></td>
|
||||
<td><code>limit_changes=LIMIT_CHANGES</code></td>
|
||||
<td>optional</td>
|
||||
<td>maximum number of files to list per commit in query
|
||||
results. Default is value of <code>limit_changes</code>
|
||||
@@ -1254,7 +1254,7 @@ th.caption {
|
||||
<td><a href="#revision-param"><code>revision</code> parameter</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>limit_changes=<var>LIMIT_CHANGES</var></code></td>
|
||||
<td><code>limit_changes=LIMIT_CHANGES</code></td>
|
||||
<td>optional</td>
|
||||
<td>maximum number of files to list per commit. Default is value
|
||||
of <code>limit_changes</code> configuration option</td>
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2009 The ViewCVS Group. All Rights Reserved.
|
||||
# Copyright (C) 1999-2006 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 ViewVC
|
||||
@@ -39,7 +39,7 @@ def _parse(hdr, result):
|
||||
while pos < len(hdr):
|
||||
name = _re_token.match(hdr, pos)
|
||||
if not name:
|
||||
raise AcceptLanguageParseError()
|
||||
raise AcceptParseError()
|
||||
a = result.item_class(string.lower(name.group(1)))
|
||||
pos = name.end()
|
||||
while 1:
|
||||
@@ -210,7 +210,7 @@ class _LanguageSelector:
|
||||
def append(self, item):
|
||||
self.requested.append(item)
|
||||
|
||||
class AcceptLanguageParseError(Exception):
|
||||
class AcceptParseError(Exception):
|
||||
pass
|
||||
|
||||
def _test():
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2010 The ViewCVS Group. All Rights Reserved.
|
||||
# Copyright (C) 1999-2007 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
|
||||
@@ -32,8 +32,9 @@ import os
|
||||
import re
|
||||
import time
|
||||
import math
|
||||
import cgi
|
||||
import vclib
|
||||
import sapi
|
||||
|
||||
|
||||
re_includes = re.compile('\\#(\\s*)include(\\s*)"(.*?)"')
|
||||
|
||||
@@ -81,7 +82,7 @@ class HTMLBlameSource:
|
||||
diff_url = None
|
||||
if item.prev_rev:
|
||||
diff_url = '%sr1=%s&r2=%s' % (self.diff_url, item.prev_rev, item.rev)
|
||||
thisline = link_includes(sapi.escape(item.text), self.repos,
|
||||
thisline = link_includes(cgi.escape(item.text), self.repos,
|
||||
self.path_parts, self.include_url)
|
||||
return _item(text=thisline, line_number=item.line_number,
|
||||
rev=item.rev, prev_rev=item.prev_rev,
|
||||
|
303
lib/config.py
303
lib/config.py
@@ -1,6 +1,6 @@
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2010 The ViewCVS Group. All Rights Reserved.
|
||||
# Copyright (C) 1999-2008 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 ViewVC
|
||||
@@ -24,149 +24,45 @@ import fnmatch
|
||||
#########################################################################
|
||||
#
|
||||
# CONFIGURATION
|
||||
# -------------
|
||||
#
|
||||
# There are three forms of configuration:
|
||||
#
|
||||
# 1. edit the viewvc.conf created by the viewvc-install(er)
|
||||
# 2. as (1), but delete all unchanged entries from viewvc.conf
|
||||
# 3. do not use viewvc.conf and just edit the defaults in this file
|
||||
# 1) edit the viewvc.conf created by the viewvc-install(er)
|
||||
# 2) as (1), but delete all unchanged entries from viewvc.conf
|
||||
# 3) do not use viewvc.conf and just edit the defaults in this file
|
||||
#
|
||||
# Most users will want to use (1), but there are slight speed advantages
|
||||
# to the other two options. Note that viewvc.conf values are a bit easier
|
||||
# to work with since it is raw text, rather than python literal values.
|
||||
#
|
||||
#
|
||||
# A WORD ABOUT OPTION LAYERING/OVERRIDES
|
||||
# --------------------------------------
|
||||
#
|
||||
# ViewVC has three "layers" of configuration options:
|
||||
#
|
||||
# 1. base configuration options - very basic configuration bits
|
||||
# found in sections like 'general', 'options', etc.
|
||||
# 2. vhost overrides - these options overlay/override the base
|
||||
# configuration on a per-vhost basis.
|
||||
# 3. root overrides - these options overlay/override the base
|
||||
# configuration and vhost overrides on a per-root basis.
|
||||
#
|
||||
# Here's a diagram of the valid overlays/overrides:
|
||||
#
|
||||
# PER-ROOT PER-VHOST BASE
|
||||
#
|
||||
# ,-----------. ,-----------.
|
||||
# | vhost-*/ | | |
|
||||
# | general | --> | general |
|
||||
# | | | |
|
||||
# `-----------' `-----------'
|
||||
# ,-----------. ,-----------. ,-----------.
|
||||
# | root-*/ | | vhost-*/ | | |
|
||||
# | options | --> | options | --> | options |
|
||||
# | | | | | |
|
||||
# `-----------' `-----------' `-----------'
|
||||
# ,-----------. ,-----------. ,-----------.
|
||||
# | root-*/ | | vhost-*/ | | |
|
||||
# | templates | --> | templates | --> | templates |
|
||||
# | | | | | |
|
||||
# `-----------' `-----------' `-----------'
|
||||
# ,-----------. ,-----------. ,-----------.
|
||||
# | root-*/ | | vhost-*/ | | |
|
||||
# | utilities | --> | utilities | --> | utilities |
|
||||
# | | | | | |
|
||||
# `-----------' `-----------' `-----------'
|
||||
# ,-----------. ,-----------.
|
||||
# | vhost-*/ | | |
|
||||
# | cvsdb | --> | cvsdb |
|
||||
# | | | |
|
||||
# `-----------' `-----------'
|
||||
# ,-----------. ,-----------. ,-----------.
|
||||
# | root-*/ | | vhost-*/ | | |
|
||||
# | authz-* | --> | authz-* | --> | authz-* |
|
||||
# | | | | | |
|
||||
# `-----------' `-----------' `-----------'
|
||||
# ,-----------.
|
||||
# | |
|
||||
# | vhosts |
|
||||
# | |
|
||||
# `-----------'
|
||||
# ,-----------.
|
||||
# | |
|
||||
# | query |
|
||||
# | |
|
||||
# `-----------'
|
||||
#
|
||||
# ### TODO: Figure out what this all means for the 'kv' stuff.
|
||||
#
|
||||
#########################################################################
|
||||
|
||||
class Config:
|
||||
_base_sections = (
|
||||
# Base configuration sections.
|
||||
'authz-*',
|
||||
'cvsdb',
|
||||
'general',
|
||||
'options',
|
||||
'query',
|
||||
'templates',
|
||||
'utilities',
|
||||
)
|
||||
_force_multi_value = (
|
||||
# Configuration values with multiple, comma-separated values.
|
||||
'allowed_views',
|
||||
'cvs_roots',
|
||||
'kv_files',
|
||||
'languages',
|
||||
'mime_types_files',
|
||||
'root_parents',
|
||||
'svn_roots',
|
||||
)
|
||||
_allowed_overrides = {
|
||||
# Mapping of override types to allowed overridable sections.
|
||||
'vhost' : ('authz-*',
|
||||
'cvsdb',
|
||||
'general',
|
||||
'options',
|
||||
'templates',
|
||||
'utilities',
|
||||
),
|
||||
'root' : ('authz-*',
|
||||
'options',
|
||||
'templates',
|
||||
'utilities',
|
||||
)
|
||||
}
|
||||
_sections = ('general', 'utilities', 'options', 'cvsdb', 'templates')
|
||||
_force_multi_value = ('cvs_roots', 'svn_roots', 'languages', 'kv_files',
|
||||
'root_parents', 'allowed_views')
|
||||
|
||||
def __init__(self):
|
||||
self.root_options_overlayed = 0
|
||||
for section in self._base_sections:
|
||||
if section[-1] == '*':
|
||||
continue
|
||||
for section in self._sections:
|
||||
setattr(self, section, _sub_config())
|
||||
|
||||
def load_config(self, pathname, vhost=None):
|
||||
"""Load the configuration file at PATHNAME, applying configuration
|
||||
settings there as overrides to the built-in default values. If
|
||||
VHOST is provided, also process the configuration overrides
|
||||
specific to that virtual host."""
|
||||
|
||||
def load_config(self, pathname, vhost=None, rootname=None):
|
||||
self.conf_path = os.path.isfile(pathname) and pathname or None
|
||||
self.base = os.path.dirname(pathname)
|
||||
self.parser = ConfigParser.ConfigParser()
|
||||
self.parser.optionxform = lambda x: x # don't case-normalize option names.
|
||||
self.parser.read(self.conf_path or [])
|
||||
|
||||
for section in self.parser.sections():
|
||||
if self._is_allowed_section(self.parser, section,
|
||||
self._base_sections):
|
||||
|
||||
for section in self._sections:
|
||||
if self.parser.has_section(section):
|
||||
self._process_section(self.parser, section, section)
|
||||
|
||||
if vhost and self.parser.has_section('vhosts'):
|
||||
self._process_vhost(self.parser, vhost)
|
||||
|
||||
if rootname:
|
||||
self._process_root_options(self.parser, rootname)
|
||||
|
||||
def load_kv_files(self, language):
|
||||
"""Process the key/value (kv) files specified in the
|
||||
configuration, merging their values into the configuration as
|
||||
dotted heirarchical items."""
|
||||
|
||||
kv = _sub_config()
|
||||
|
||||
for fname in self.general.kv_files:
|
||||
@@ -179,7 +75,6 @@ class Config:
|
||||
fname = string.replace(fname, '%lang%', language)
|
||||
|
||||
parser = ConfigParser.ConfigParser()
|
||||
parser.optionxform = lambda x: x # don't case-normalize option names.
|
||||
parser.read(os.path.join(self.base, fname))
|
||||
for section in parser.sections():
|
||||
for option in parser.options(section):
|
||||
@@ -197,12 +92,10 @@ class Config:
|
||||
return kv
|
||||
|
||||
def path(self, path):
|
||||
"""Return PATH relative to the config file directory."""
|
||||
"""Return path relative to the config file directory"""
|
||||
return os.path.join(self.base, path)
|
||||
|
||||
def _process_section(self, parser, section, subcfg_name):
|
||||
if not hasattr(self, subcfg_name):
|
||||
setattr(self, subcfg_name, _sub_config())
|
||||
sc = getattr(self, subcfg_name)
|
||||
|
||||
for opt in parser.options(section):
|
||||
@@ -215,55 +108,25 @@ class Config:
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
### FIXME: This feels like unnecessary depth of knowledge for a
|
||||
### semi-generic configuration object.
|
||||
if opt == 'cvs_roots' or opt == 'svn_roots':
|
||||
value = _parse_roots(opt, value)
|
||||
|
||||
setattr(sc, opt, value)
|
||||
|
||||
def _is_allowed_section(self, parser, section, allowed_sections):
|
||||
"""Return 1 iff SECTION is an allowed section, defined as being
|
||||
explicitly present in the ALLOWED_SECTIONS list or present in the
|
||||
form 'someprefix-*' in that list."""
|
||||
|
||||
for allowed_section in allowed_sections:
|
||||
if allowed_section[-1] == '*':
|
||||
if _startswith(section, allowed_section[:-1]):
|
||||
return 1
|
||||
elif allowed_section == section:
|
||||
return 1
|
||||
return 0
|
||||
|
||||
def _is_allowed_override(self, parser, sectype, secspec, section):
|
||||
"""Test if SECTION is an allowed override section for sections of
|
||||
type SECTYPE ('vhosts' or 'root', currently) and type-specifier
|
||||
SECSPEC (a rootname or vhostname, currently). If it is, return
|
||||
the overridden base section name. If it's not an override section
|
||||
at all, return None. And if it's an override section but not an
|
||||
allowed one, raise IllegalOverrideSection."""
|
||||
|
||||
cv = '%s-%s/' % (sectype, secspec)
|
||||
lcv = len(cv)
|
||||
if section[:lcv] != cv:
|
||||
return None
|
||||
base_section = section[lcv:]
|
||||
if self._is_allowed_section(parser, base_section,
|
||||
self._allowed_overrides[sectype]):
|
||||
return base_section
|
||||
raise IllegalOverrideSection(sectype, section)
|
||||
|
||||
def _process_vhost(self, parser, vhost):
|
||||
# Find a vhost name for this VHOST, if any (else, we've nothing to do).
|
||||
# find a vhost name for this vhost, if any (if not, we've nothing to do)
|
||||
canon_vhost = self._find_canon_vhost(parser, vhost)
|
||||
if not canon_vhost:
|
||||
return
|
||||
|
||||
# Overlay any option sections associated with this vhost name.
|
||||
# overlay any option sections associated with this vhost name
|
||||
cv = 'vhost-%s/' % (canon_vhost)
|
||||
lcv = len(cv)
|
||||
for section in parser.sections():
|
||||
base_section = self._is_allowed_override(parser, 'vhost',
|
||||
canon_vhost, section)
|
||||
if base_section:
|
||||
if section[:lcv] == cv:
|
||||
base_section = section[lcv:]
|
||||
if base_section not in self._sections:
|
||||
raise IllegalOverrideSection('vhost', section)
|
||||
self._process_section(parser, section, base_section)
|
||||
|
||||
def _find_canon_vhost(self, parser, vhost):
|
||||
@@ -278,30 +141,26 @@ class Config:
|
||||
|
||||
return None
|
||||
|
||||
def _process_root_options(self, parser, rootname):
|
||||
rn = 'root-%s/' % (rootname)
|
||||
lrn = len(rn)
|
||||
for section in parser.sections():
|
||||
if section[:lrn] == rn:
|
||||
base_section = section[lrn:]
|
||||
if base_section in self._sections:
|
||||
if base_section == 'general':
|
||||
raise IllegalOverrideSection('root', section)
|
||||
self._process_section(parser, section, base_section)
|
||||
elif _startswith(base_section, 'authz-'):
|
||||
pass
|
||||
else:
|
||||
raise IllegalOverrideSection('root', section)
|
||||
|
||||
def overlay_root_options(self, rootname):
|
||||
"""Overlay per-root options for ROOTNAME atop the existing option
|
||||
set. This is a destructive change to the configuration."""
|
||||
|
||||
did_overlay = 0
|
||||
|
||||
"Overly per-root options atop the existing option set."
|
||||
if not self.conf_path:
|
||||
return
|
||||
|
||||
for section in self.parser.sections():
|
||||
base_section = self._is_allowed_override(self.parser, 'root',
|
||||
rootname, section)
|
||||
if base_section:
|
||||
# We can currently only deal with root overlays happening
|
||||
# once, so check that we've not yet done any overlaying of
|
||||
# per-root options.
|
||||
assert(self.root_options_overlayed == 0)
|
||||
self._process_section(self.parser, section, base_section)
|
||||
did_overlay = 1
|
||||
|
||||
# If we actually did any overlaying, remember this fact so we
|
||||
# don't do it again later.
|
||||
if did_overlay:
|
||||
self.root_options_overlayed = 1
|
||||
self._process_root_options(self.parser, rootname)
|
||||
|
||||
def _get_parser_items(self, parser, section):
|
||||
"""Basically implement ConfigParser.items() for pre-Python-2.3 versions."""
|
||||
@@ -312,67 +171,23 @@ class Config:
|
||||
for option in parser.options(section):
|
||||
d[option] = parser.get(section, option)
|
||||
return d.items()
|
||||
|
||||
def get_authorizer_and_params_hack(self, rootname):
|
||||
"""Return a 2-tuple containing the name and parameters of the
|
||||
authorizer configured for use with ROOTNAME.
|
||||
|
||||
### FIXME: This whole thing is a hack caused by our not being able
|
||||
### to non-destructively overlay root options when trying to do
|
||||
### something like a root listing (which might need to get
|
||||
### different authorizer bits for each and every root in the list).
|
||||
### Until we have a good way to do that, we expose this function,
|
||||
### which assumes that base and per-vhost configuration has been
|
||||
### absorbed into this object and that per-root options have *not*
|
||||
### been overlayed. See issue #371."""
|
||||
|
||||
# We assume that per-root options have *not* been overlayed.
|
||||
assert(self.root_options_overlayed == 0)
|
||||
|
||||
|
||||
def get_authorizer_params(self, authorizer, rootname=None):
|
||||
if not self.conf_path:
|
||||
return None, {}
|
||||
return {}
|
||||
|
||||
# Figure out the authorizer by searching first for a per-root
|
||||
# override, then falling back to the base/vhost configuration.
|
||||
authorizer = None
|
||||
root_options_section = 'root-%s/options' % (rootname)
|
||||
if self.parser.has_section(root_options_section) \
|
||||
and self.parser.has_option(root_options_section, 'authorizer'):
|
||||
authorizer = self.parser.get(root_options_section, 'authorizer')
|
||||
if not authorizer:
|
||||
authorizer = self.options.authorizer
|
||||
|
||||
# No authorizer? Get outta here.
|
||||
if not authorizer:
|
||||
return None, {}
|
||||
|
||||
# Dig up the parameters for the authorizer, starting with the
|
||||
# base/vhost items, then overlaying any root-specific ones we find.
|
||||
params = {}
|
||||
authz_section = 'authz-%s' % (authorizer)
|
||||
if hasattr(self, authz_section):
|
||||
sub_config = getattr(self, authz_section)
|
||||
for attr in dir(sub_config):
|
||||
params[attr] = getattr(sub_config, attr)
|
||||
root_authz_section = 'root-%s/authz-%s' % (rootname, authorizer)
|
||||
for section in self.parser.sections():
|
||||
if section == root_authz_section:
|
||||
if section == authz_section:
|
||||
for key, value in self._get_parser_items(self.parser, section):
|
||||
params[key] = value
|
||||
return authorizer, params
|
||||
|
||||
def get_authorizer_params(self, authorizer=None):
|
||||
"""Return a dictionary of parameter names and values which belong
|
||||
to the configured authorizer (or AUTHORIZER, if provided)."""
|
||||
params = {}
|
||||
if authorizer is None:
|
||||
authorizer = self.options.authorizer
|
||||
if authorizer:
|
||||
authz_section = 'authz-%s' % (self.options.authorizer)
|
||||
if hasattr(self, authz_section):
|
||||
sub_config = getattr(self, authz_section)
|
||||
for attr in dir(sub_config):
|
||||
params[attr] = getattr(sub_config, attr)
|
||||
if rootname:
|
||||
root_authz_section = 'root-%s/authz-%s' % (rootname, authorizer)
|
||||
for section in self.parser.sections():
|
||||
if section == root_authz_section:
|
||||
for key, value in self._get_parser_items(self.parser, section):
|
||||
params[key] = value
|
||||
return params
|
||||
|
||||
def set_defaults(self):
|
||||
@@ -382,7 +197,7 @@ class Config:
|
||||
self.general.svn_roots = { }
|
||||
self.general.root_parents = []
|
||||
self.general.default_root = ''
|
||||
self.general.mime_types_files = ["mimetypes.conf"]
|
||||
self.general.mime_types_file = ''
|
||||
self.general.address = ''
|
||||
self.general.kv_files = [ ]
|
||||
self.general.languages = ['en-us']
|
||||
@@ -398,13 +213,12 @@ class Config:
|
||||
|
||||
self.options.root_as_url_component = 1
|
||||
self.options.checkout_magic = 0
|
||||
self.options.allowed_views = ['annotate', 'diff', 'markup', 'roots']
|
||||
self.options.authorizer = None
|
||||
self.options.allowed_views = ['markup', 'annotate', 'roots']
|
||||
self.options.authorizer = 'forbidden'
|
||||
self.options.mangle_email_addresses = 0
|
||||
self.options.default_file_view = "log"
|
||||
self.options.http_expiration_time = 600
|
||||
self.options.generate_etags = 1
|
||||
self.options.svn_ignore_mimetype = 0
|
||||
self.options.svn_config_dir = None
|
||||
self.options.use_rcsparse = 0
|
||||
self.options.sort_by = 'file'
|
||||
@@ -425,17 +239,14 @@ class Config:
|
||||
self.options.show_subdir_lastmod = 0
|
||||
self.options.show_logs = 1
|
||||
self.options.show_log_in_markup = 1
|
||||
self.options.cross_copies = 1
|
||||
self.options.cross_copies = 0
|
||||
self.options.use_localtime = 0
|
||||
self.options.short_log_len = 80
|
||||
self.options.enable_syntax_coloration = 1
|
||||
self.options.tabsize = 8
|
||||
self.options.detect_encoding = 0
|
||||
self.options.use_cvsgraph = 0
|
||||
self.options.cvsgraph_conf = "cvsgraph.conf"
|
||||
self.options.use_re_search = 0
|
||||
self.options.dir_pagesize = 0
|
||||
self.options.log_pagesize = 0
|
||||
self.options.use_pagesize = 0
|
||||
self.options.limit_changes = 100
|
||||
|
||||
self.templates.diff = None
|
||||
@@ -461,8 +272,6 @@ class Config:
|
||||
self.cvsdb.rss_row_limit = 100
|
||||
self.cvsdb.check_database_for_root = 0
|
||||
|
||||
self.query.viewvc_base_url = None
|
||||
|
||||
def _startswith(somestr, substr):
|
||||
return somestr[:len(substr)] == substr
|
||||
|
||||
|
196
lib/cvsdb.py
196
lib/cvsdb.py
@@ -1,6 +1,6 @@
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2009 The ViewCVS Group. All Rights Reserved.
|
||||
# Copyright (C) 1999-2007 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 ViewVC
|
||||
@@ -20,14 +20,6 @@ import re
|
||||
import vclib
|
||||
import dbi
|
||||
|
||||
## Current commits database schema version number.
|
||||
##
|
||||
## Version 0 was the original Bonsai-compatible version.
|
||||
##
|
||||
## Version 1 added the 'metadata' table (which holds the 'version' key)
|
||||
## and renamed all the 'repository'-related stuff to be 'root'-
|
||||
##
|
||||
CURRENT_SCHEMA_VERSION = 1
|
||||
|
||||
## error
|
||||
error = "cvsdb error"
|
||||
@@ -45,7 +37,6 @@ class CheckinDatabase:
|
||||
self._passwd = passwd
|
||||
self._database = database
|
||||
self._row_limit = row_limit
|
||||
self._version = None
|
||||
|
||||
## database lookup caches
|
||||
self._get_cache = {}
|
||||
@@ -57,19 +48,6 @@ class CheckinDatabase:
|
||||
self._host, self._port, self._user, self._passwd, self._database)
|
||||
cursor = self.db.cursor()
|
||||
cursor.execute("SET AUTOCOMMIT=1")
|
||||
table_list = self.GetTableList()
|
||||
if 'metadata' in table_list:
|
||||
version = self.GetMetadataValue("version")
|
||||
if version is None:
|
||||
self._version = 0
|
||||
else:
|
||||
self._version = int(version)
|
||||
else:
|
||||
self._version = 0
|
||||
if self._version > CURRENT_SCHEMA_VERSION:
|
||||
raise DatabaseVersionError("Database version %d is newer than the "
|
||||
"last version supported by this "
|
||||
"software." % (self._version))
|
||||
|
||||
def sql_get_id(self, table, column, value, auto_set):
|
||||
sql = "SELECT id FROM %s WHERE %s=%%s" % (table, column)
|
||||
@@ -169,42 +147,6 @@ class CheckinDatabase:
|
||||
|
||||
return list
|
||||
|
||||
def GetTableList(self):
|
||||
sql = "SHOW TABLES"
|
||||
cursor = self.db.cursor()
|
||||
cursor.execute(sql)
|
||||
list = []
|
||||
while 1:
|
||||
row = cursor.fetchone()
|
||||
if row == None:
|
||||
break
|
||||
list.append(row[0])
|
||||
return list
|
||||
|
||||
def GetMetadataValue(self, name):
|
||||
sql = "SELECT value FROM metadata WHERE name=%s"
|
||||
sql_args = (name)
|
||||
cursor = self.db.cursor()
|
||||
cursor.execute(sql, sql_args)
|
||||
try:
|
||||
(value,) = cursor.fetchone()
|
||||
except TypeError:
|
||||
return None
|
||||
return value
|
||||
|
||||
def SetMetadataValue(self, name, value):
|
||||
assert(self._version > 0)
|
||||
sql = "REPLACE INTO metadata (name, value) VALUES (%s, %s)"
|
||||
sql_args = (name, value)
|
||||
cursor = self.db.cursor()
|
||||
try:
|
||||
cursor.execute(sql, sql_args)
|
||||
except Exception, e:
|
||||
raise Exception("Error setting metadata: '%s'\n"
|
||||
"\tname = %s\n"
|
||||
"\tvalue = %s\n"
|
||||
% (str(e), name, value))
|
||||
|
||||
def GetBranchID(self, branch, auto_set = 1):
|
||||
return self.get_id("branches", "branch", branch, auto_set)
|
||||
|
||||
@@ -309,9 +251,7 @@ class CheckinDatabase:
|
||||
minus_count = commit.GetMinusCount() or '0'
|
||||
description_id = self.GetDescriptionID(commit.GetDescription())
|
||||
|
||||
commits_table = self._version >= 1 and 'commits' or 'checkins'
|
||||
sql = "REPLACE INTO %s" % (commits_table)
|
||||
sql = sql + \
|
||||
sql = "REPLACE INTO checkins"\
|
||||
" (type,ci_when,whoid,repositoryid,dirid,fileid,revision,"\
|
||||
" stickytag,branchid,addedlines,removedlines,descid)"\
|
||||
"VALUES(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)"
|
||||
@@ -364,69 +304,58 @@ class CheckinDatabase:
|
||||
return "(%s)" % (string.join(sqlList, " OR "))
|
||||
|
||||
def CreateSQLQueryString(self, query):
|
||||
commits_table = self._version >= 1 and 'commits' or 'checkins'
|
||||
tableList = [(commits_table, None)]
|
||||
tableList = [("checkins", None)]
|
||||
condList = []
|
||||
|
||||
if len(query.repository_list):
|
||||
tableList.append(("repositories",
|
||||
"(%s.repositoryid=repositories.id)"
|
||||
% (commits_table)))
|
||||
"(checkins.repositoryid=repositories.id)"))
|
||||
temp = self.SQLQueryListString("repositories.repository",
|
||||
query.repository_list)
|
||||
condList.append(temp)
|
||||
|
||||
if len(query.branch_list):
|
||||
tableList.append(("branches",
|
||||
"(%s.branchid=branches.id)" % (commits_table)))
|
||||
tableList.append(("branches", "(checkins.branchid=branches.id)"))
|
||||
temp = self.SQLQueryListString("branches.branch",
|
||||
query.branch_list)
|
||||
condList.append(temp)
|
||||
|
||||
if len(query.directory_list):
|
||||
tableList.append(("dirs",
|
||||
"(%s.dirid=dirs.id)" % (commits_table)))
|
||||
tableList.append(("dirs", "(checkins.dirid=dirs.id)"))
|
||||
temp = self.SQLQueryListString("dirs.dir", query.directory_list)
|
||||
condList.append(temp)
|
||||
|
||||
if len(query.file_list):
|
||||
tableList.append(("files",
|
||||
"(%s.fileid=files.id)" % (commits_table)))
|
||||
tableList.append(("files", "(checkins.fileid=files.id)"))
|
||||
temp = self.SQLQueryListString("files.file", query.file_list)
|
||||
condList.append(temp)
|
||||
|
||||
if len(query.author_list):
|
||||
tableList.append(("people",
|
||||
"(%s.whoid=people.id)" % (commits_table)))
|
||||
tableList.append(("people", "(checkins.whoid=people.id)"))
|
||||
temp = self.SQLQueryListString("people.who", query.author_list)
|
||||
condList.append(temp)
|
||||
|
||||
if len(query.comment_list):
|
||||
tableList.append(("descs",
|
||||
"(%s.descid=descs.id)" % (commits_table)))
|
||||
tableList.append(("descs", "(checkins.descid=descs.id)"))
|
||||
temp = self.SQLQueryListString("descs.description",
|
||||
query.comment_list)
|
||||
condList.append(temp)
|
||||
|
||||
if query.from_date:
|
||||
temp = "(%s.ci_when>=\"%s\")" \
|
||||
% (commits_table, str(query.from_date))
|
||||
temp = "(checkins.ci_when>=\"%s\")" % (str(query.from_date))
|
||||
condList.append(temp)
|
||||
|
||||
if query.to_date:
|
||||
temp = "(%s.ci_when<=\"%s\")" \
|
||||
% (commits_table, str(query.to_date))
|
||||
temp = "(checkins.ci_when<=\"%s\")" % (str(query.to_date))
|
||||
condList.append(temp)
|
||||
|
||||
if query.sort == "date":
|
||||
order_by = "ORDER BY %s.ci_when DESC,descid" % (commits_table)
|
||||
order_by = "ORDER BY checkins.ci_when DESC,descid"
|
||||
elif query.sort == "author":
|
||||
tableList.append(("people",
|
||||
"(%s.whoid=people.id)" % (commits_table)))
|
||||
tableList.append(("people", "(checkins.whoid=people.id)"))
|
||||
order_by = "ORDER BY people.who,descid"
|
||||
elif query.sort == "file":
|
||||
tableList.append(("files",
|
||||
"(%s.fileid=files.id)" % (commits_table)))
|
||||
tableList.append(("files", "(checkins.fileid=files.id)"))
|
||||
order_by = "ORDER BY files.file,descid"
|
||||
|
||||
## exclude duplicates from the table list, and split out join
|
||||
@@ -452,8 +381,8 @@ class CheckinDatabase:
|
||||
elif self._row_limit:
|
||||
limit = "LIMIT %s" % (str(self._row_limit))
|
||||
|
||||
sql = "SELECT %s.* FROM %s %s %s %s" \
|
||||
% (commits_table, tables, conditions, order_by, limit)
|
||||
sql = "SELECT checkins.* FROM %s %s %s %s" % (
|
||||
tables, conditions, order_by, limit)
|
||||
|
||||
return sql
|
||||
|
||||
@@ -504,13 +433,8 @@ class CheckinDatabase:
|
||||
if file_id == None:
|
||||
return None
|
||||
|
||||
commits_table = self._version >= 1 and 'commits' or 'checkins'
|
||||
sql = "SELECT * FROM %s WHERE "\
|
||||
" repositoryid=%%s "\
|
||||
" AND dirid=%%s"\
|
||||
" AND fileid=%%s"\
|
||||
" AND revision=%%s"\
|
||||
% (commits_table)
|
||||
sql = "SELECT * FROM checkins WHERE "\
|
||||
" repositoryid=%s AND dirid=%s AND fileid=%s AND revision=%s"
|
||||
sql_args = (repository_id, dir_id, file_id, commit.GetRevision())
|
||||
|
||||
cursor = self.db.cursor()
|
||||
@@ -527,72 +451,40 @@ class CheckinDatabase:
|
||||
def sql_delete(self, table, key, value, keep_fkey = None):
|
||||
sql = "DELETE FROM %s WHERE %s=%%s" % (table, key)
|
||||
sql_args = (value, )
|
||||
commits_table = self._version >= 1 and 'commits' or 'checkins'
|
||||
if keep_fkey:
|
||||
sql += " AND %s NOT IN (SELECT %s FROM %s WHERE %s = %%s)" \
|
||||
% (key, keep_fkey, commits_table, keep_fkey)
|
||||
sql_args = (value, value)
|
||||
sql += " AND %s NOT IN (SELECT %s FROM checkins WHERE %s = %%s)" \
|
||||
% (key, keep_fkey, keep_fkey)
|
||||
sql_args = (value, value)
|
||||
cursor = self.db.cursor()
|
||||
cursor.execute(sql, sql_args)
|
||||
|
||||
def sql_purge(self, table, key, fkey, ftable):
|
||||
sql = "DELETE FROM %s WHERE %s NOT IN (SELECT %s FROM %s)" \
|
||||
% (table, key, fkey, ftable)
|
||||
cursor = self.db.cursor()
|
||||
cursor.execute(sql)
|
||||
|
||||
def PurgeRepository(self, repository):
|
||||
rep_id = self.GetRepositoryID(repository, auto_set=0)
|
||||
rep_id = self.GetRepositoryID(repository)
|
||||
if not rep_id:
|
||||
raise UnknownRepositoryError("Unknown repository '%s'"
|
||||
% (repository))
|
||||
|
||||
if (self._version >= 1):
|
||||
self.sql_delete('repositories', 'id', rep_id)
|
||||
self.sql_purge('commits', 'repositoryid', 'id', 'repositories')
|
||||
self.sql_purge('files', 'id', 'fileid', 'commits')
|
||||
self.sql_purge('dirs', 'id', 'dirid', 'commits')
|
||||
self.sql_purge('branches', 'id', 'branchid', 'commits')
|
||||
self.sql_purge('descs', 'id', 'descid', 'commits')
|
||||
self.sql_purge('people', 'id', 'whoid', 'commits')
|
||||
else:
|
||||
sql = "SELECT * FROM checkins WHERE repositoryid=%s"
|
||||
sql_args = (rep_id, )
|
||||
cursor = self.db.cursor()
|
||||
cursor.execute(sql, sql_args)
|
||||
checkins = []
|
||||
while 1:
|
||||
try:
|
||||
(ci_type, ci_when, who_id, repository_id,
|
||||
dir_id, file_id, revision, sticky_tag, branch_id,
|
||||
plus_count, minus_count, description_id) = \
|
||||
cursor.fetchone()
|
||||
except TypeError:
|
||||
break
|
||||
checkins.append([file_id, dir_id, branch_id,
|
||||
description_id, who_id])
|
||||
|
||||
#self.sql_delete('repositories', 'id', rep_id)
|
||||
self.sql_delete('checkins', 'repositoryid', rep_id)
|
||||
for checkin in checkins:
|
||||
self.sql_delete('files', 'id', checkin[0], 'fileid')
|
||||
self.sql_delete('dirs', 'id', checkin[1], 'dirid')
|
||||
self.sql_delete('branches', 'id', checkin[2], 'branchid')
|
||||
self.sql_delete('descs', 'id', checkin[3], 'descid')
|
||||
self.sql_delete('people', 'id', checkin[4], 'whoid')
|
||||
|
||||
# Reset all internal id caches. We could be choosier here,
|
||||
# but let's just be as safe as possible.
|
||||
self._get_cache = {}
|
||||
self._get_id_cache = {}
|
||||
self._desc_id_cache = {}
|
||||
raise Exception, "Unknown repository '%s'" % (repository)
|
||||
|
||||
sql = "SELECT * FROM checkins WHERE repositoryid=%s"
|
||||
sql_args = (rep_id, )
|
||||
cursor = self.db.cursor()
|
||||
cursor.execute(sql, sql_args)
|
||||
checkins = []
|
||||
while 1:
|
||||
try:
|
||||
(ci_type, ci_when, who_id, repository_id,
|
||||
dir_id, file_id, revision, sticky_tag, branch_id,
|
||||
plus_count, minus_count, description_id) = cursor.fetchone()
|
||||
except TypeError:
|
||||
break
|
||||
checkins.append([file_id, dir_id, branch_id, description_id, who_id])
|
||||
|
||||
class DatabaseVersionError(Exception):
|
||||
pass
|
||||
class UnknownRepositoryError(Exception):
|
||||
pass
|
||||
|
||||
#self.sql_delete('repositories', 'id', rep_id)
|
||||
self.sql_delete('checkins', 'repositoryid', rep_id)
|
||||
for checkin in checkins:
|
||||
self.sql_delete('files', 'id', checkin[0], 'fileid')
|
||||
self.sql_delete('dirs', 'id', checkin[1], 'dirid')
|
||||
self.sql_delete('branches', 'id', checkin[2], 'branchid')
|
||||
self.sql_delete('descs', 'id', checkin[3], 'descid')
|
||||
self.sql_delete('people', 'id', checkin[4], 'whoid')
|
||||
|
||||
## the Commit class holds data on one commit, the representation is as
|
||||
## close as possible to how it should be committed and retrieved to the
|
||||
|
14
lib/debug.py
14
lib/debug.py
@@ -1,6 +1,6 @@
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2008 The ViewCVS Group. All Rights Reserved.
|
||||
# Copyright (C) 1999-2007 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 ViewVC
|
||||
@@ -48,17 +48,13 @@ if SHOW_TIMES:
|
||||
else:
|
||||
_times[which] = t
|
||||
|
||||
def t_dump(out):
|
||||
out.write('<div>')
|
||||
names = _times.keys()
|
||||
names.sort()
|
||||
for name in names:
|
||||
out.write('%s: %.6fs<br/>\n' % (name, _times[name]))
|
||||
out.write('</div>')
|
||||
def dump():
|
||||
for name, value in _times.items():
|
||||
print '%s: %.6f<br />' % (name, value)
|
||||
|
||||
else:
|
||||
|
||||
t_start = t_end = t_dump = lambda *args: None
|
||||
t_start = t_end = dump = lambda *args: None
|
||||
|
||||
|
||||
class ViewVCException:
|
||||
|
120
lib/ezt.py
120
lib/ezt.py
@@ -347,7 +347,7 @@ class Template:
|
||||
for_names = [ ]
|
||||
|
||||
if base_format:
|
||||
program.append((self._cmd_format, _formatters[base_format]))
|
||||
program.append((self._cmd_format, _printers[base_format]))
|
||||
|
||||
for i in range(len(parts)):
|
||||
piece = parts[i]
|
||||
@@ -405,13 +405,13 @@ class Template:
|
||||
elif cmd == 'format':
|
||||
if args[1][0]:
|
||||
# argument is a variable reference
|
||||
formatter = args[1]
|
||||
printer = args[1]
|
||||
else:
|
||||
# argument is a string constant referring to built-in formatter
|
||||
formatter = _formatters.get(args[1][1])
|
||||
if not formatter:
|
||||
# argument is a string constant referring to built-in printer
|
||||
printer = _printers.get(args[1][1])
|
||||
if not printer:
|
||||
raise UnknownFormatConstantError(str(args[1:]))
|
||||
program.append((self._cmd_format, formatter))
|
||||
program.append((self._cmd_format, printer))
|
||||
|
||||
# remember the cmd, current pos, args, and a section placeholder
|
||||
stack.append([cmd, len(program), args[1:], None])
|
||||
@@ -460,18 +460,15 @@ class Template:
|
||||
def _cmd_print(self, valrefs, ctx):
|
||||
value = _get_value(valrefs[0], ctx)
|
||||
args = map(lambda valref, ctx=ctx: _get_value(valref, ctx), valrefs[1:])
|
||||
try:
|
||||
_write_value(value, args, ctx)
|
||||
except TypeError:
|
||||
raise Exception("Unprintable value type for '%s'" % (str(valrefs[0][0])))
|
||||
_write_value(value, args, ctx)
|
||||
|
||||
def _cmd_format(self, formatter, ctx):
|
||||
if type(formatter) is TupleType:
|
||||
formatter = _get_value(formatter, ctx)
|
||||
ctx.formatters.append(formatter)
|
||||
def _cmd_format(self, printer, ctx):
|
||||
if type(printer) is TupleType:
|
||||
printer = _get_value(printer, ctx)
|
||||
ctx.printers.append(printer)
|
||||
|
||||
def _cmd_end_format(self, valref, ctx):
|
||||
ctx.formatters.pop()
|
||||
ctx.printers.pop()
|
||||
|
||||
def _cmd_include(self, (valref, reader), ctx):
|
||||
fname = _get_value(valref, ctx)
|
||||
@@ -525,8 +522,7 @@ class Template:
|
||||
((valref,), unused, section) = args
|
||||
list = _get_value(valref, ctx)
|
||||
if isinstance(list, StringType):
|
||||
raise NeedSequenceError("The value of '%s' is not a sequence"
|
||||
% (valref[0]))
|
||||
raise NeedSequenceError()
|
||||
refname = valref[0]
|
||||
ctx.for_iterators[refname] = iterator = _iter(list)
|
||||
for unused in iterator:
|
||||
@@ -637,23 +633,14 @@ def _get_value((refname, start, rest), ctx):
|
||||
# string or a sequence
|
||||
return ob
|
||||
|
||||
def _print_formatted(formatters, ctx, chunk):
|
||||
# print chunk to ctx.fp after running it sequentially through formatters
|
||||
for formatter in formatters:
|
||||
chunk = formatter(chunk)
|
||||
ctx.fp.write(chunk)
|
||||
|
||||
def _write_value(value, args, ctx):
|
||||
# value is a callback function, generates its own output
|
||||
if callable(value):
|
||||
apply(value, [ctx] + list(args))
|
||||
return
|
||||
|
||||
# squirrel away formatters in case one of them recursively calls
|
||||
# _write_value() -- we'll use them (in reverse order) to format our
|
||||
# output.
|
||||
formatters = ctx.formatters[:]
|
||||
formatters.reverse()
|
||||
# pop printer in case it recursively calls _write_value
|
||||
printer = ctx.printers.pop()
|
||||
|
||||
try:
|
||||
# if the value has a 'read' attribute, then it is a stream: copy it
|
||||
@@ -662,7 +649,7 @@ def _write_value(value, args, ctx):
|
||||
chunk = value.read(16384)
|
||||
if not chunk:
|
||||
break
|
||||
_print_formatted(formatters, ctx, chunk)
|
||||
printer(ctx, chunk)
|
||||
|
||||
# value is a substitution pattern
|
||||
elif args:
|
||||
@@ -675,58 +662,21 @@ def _write_value(value, args, ctx):
|
||||
piece = args[idx]
|
||||
else:
|
||||
piece = '<undef>'
|
||||
_print_formatted(formatters, ctx, piece)
|
||||
printer(ctx, piece)
|
||||
|
||||
# plain old value, write to output
|
||||
else:
|
||||
_print_formatted(formatters, ctx, value)
|
||||
printer(ctx, value)
|
||||
|
||||
finally:
|
||||
# restore our formatters
|
||||
formatters.reverse()
|
||||
ctx.formatters = formatters
|
||||
|
||||
|
||||
class TemplateData:
|
||||
"""A custom dictionary-like object that allows one-time definition
|
||||
of keys, and only value fetches and changes, and key deletions,
|
||||
thereafter.
|
||||
|
||||
EZT doesn't require the use of this special class -- a normal
|
||||
dict-type data dictionary works fine. But use of this class will
|
||||
assist those who want the data sent to their templates to have a
|
||||
consistent set of keys."""
|
||||
|
||||
def __init__(self, initial_data={}):
|
||||
self._items = initial_data
|
||||
|
||||
def __getitem__(self, key):
|
||||
return self._items.__getitem__(key)
|
||||
|
||||
def __setitem__(self, key, item):
|
||||
assert self._items.has_key(key)
|
||||
return self._items.__setitem__(key, item)
|
||||
|
||||
def __delitem__(self, key):
|
||||
return self._items.__delitem__(key)
|
||||
|
||||
def keys(self):
|
||||
return self._items.keys()
|
||||
|
||||
def merge(self, template_data):
|
||||
"""Merge the data in TemplataData instance TEMPLATA_DATA into this
|
||||
instance. Avoid the temptation to use this conditionally in your
|
||||
code -- it rather defeats the purpose of this class."""
|
||||
|
||||
assert isinstance(template_data, TemplateData)
|
||||
self._items.update(template_data._items)
|
||||
ctx.printers.append(printer)
|
||||
|
||||
|
||||
class Context:
|
||||
"""A container for the execution context"""
|
||||
def __init__(self, fp):
|
||||
self.fp = fp
|
||||
self.formatters = []
|
||||
self.printers = []
|
||||
def write(self, value, args=()):
|
||||
_write_value(value, args, self)
|
||||
|
||||
@@ -839,26 +789,20 @@ class BaseUnavailableError(EZTException):
|
||||
class UnknownFormatConstantError(EZTException):
|
||||
"""The format specifier is an unknown value."""
|
||||
|
||||
def _raw_formatter(s):
|
||||
return s
|
||||
def _raw_printer(ctx, s):
|
||||
ctx.fp.write(s)
|
||||
|
||||
def _html_printer(ctx, s):
|
||||
ctx.fp.write(cgi.escape(s))
|
||||
|
||||
def _html_formatter(s):
|
||||
return cgi.escape(s)
|
||||
def _uri_printer(ctx, s):
|
||||
ctx.fp.write(urllib.quote(s))
|
||||
|
||||
def _xml_formatter(s):
|
||||
s = s.replace('&', '&')
|
||||
s = s.replace('<', '<')
|
||||
s = s.replace('>', '>')
|
||||
return s
|
||||
|
||||
def _uri_formatter(s):
|
||||
return urllib.quote(s)
|
||||
|
||||
_formatters = {
|
||||
FORMAT_RAW : _raw_formatter,
|
||||
FORMAT_HTML : _html_formatter,
|
||||
FORMAT_XML : _xml_formatter,
|
||||
FORMAT_URI : _uri_formatter,
|
||||
_printers = {
|
||||
FORMAT_RAW : _raw_printer,
|
||||
FORMAT_HTML : _html_printer,
|
||||
FORMAT_XML : _html_printer,
|
||||
FORMAT_URI : _uri_printer,
|
||||
}
|
||||
|
||||
# --- standard test environment ---
|
||||
|
20
lib/idiff.py
20
lib/idiff.py
@@ -1,6 +1,6 @@
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2010 The ViewCVS Group. All Rights Reserved.
|
||||
# Copyright (C) 1999-2006 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 ViewVC
|
||||
@@ -20,7 +20,7 @@ import difflib
|
||||
import sys
|
||||
import re
|
||||
import ezt
|
||||
import sapi
|
||||
import cgi
|
||||
|
||||
def sidebyside(fromlines, tolines, context):
|
||||
"""Generate side by side diff"""
|
||||
@@ -49,18 +49,18 @@ def _mdiff_split(flag, (line_number, text)):
|
||||
while True:
|
||||
m = _re_mdiff.search(text, pos)
|
||||
if not m:
|
||||
segments.append(_item(text=sapi.escape(text[pos:]), type=None))
|
||||
segments.append(_item(text=cgi.escape(text[pos:]), type=None))
|
||||
break
|
||||
|
||||
if m.start() > pos:
|
||||
segments.append(_item(text=sapi.escape(text[pos:m.start()]), type=None))
|
||||
segments.append(_item(text=cgi.escape(text[pos:m.start()]), type=None))
|
||||
|
||||
if m.group(1) == "+":
|
||||
segments.append(_item(text=sapi.escape(m.group(2)), type="add"))
|
||||
segments.append(_item(text=cgi.escape(m.group(2)), type="add"))
|
||||
elif m.group(1) == "-":
|
||||
segments.append(_item(text=sapi.escape(m.group(2)), type="remove"))
|
||||
segments.append(_item(text=cgi.escape(m.group(2)), type="remove"))
|
||||
elif m.group(1) == "^":
|
||||
segments.append(_item(text=sapi.escape(m.group(2)), type="change"))
|
||||
segments.append(_item(text=cgi.escape(m.group(2)), type="change"))
|
||||
|
||||
pos = m.end()
|
||||
|
||||
@@ -166,12 +166,12 @@ def _differ_split(row, guide):
|
||||
|
||||
for m in _re_differ.finditer(guide, pos):
|
||||
if m.start() > pos:
|
||||
segments.append(_item(text=sapi.escape(line[pos:m.start()]), type=None))
|
||||
segments.append(_item(text=sapi.escape(line[m.start():m.end()]),
|
||||
segments.append(_item(text=cgi.escape(line[pos:m.start()]), type=None))
|
||||
segments.append(_item(text=cgi.escape(line[m.start():m.end()]),
|
||||
type="change"))
|
||||
pos = m.end()
|
||||
|
||||
segments.append(_item(text=sapi.escape(line[pos:]), type=None))
|
||||
segments.append(_item(text=cgi.escape(line[pos:]), type=None))
|
||||
|
||||
return _item(gap=ezt.boolean(gap), type=type, segments=segments,
|
||||
left_number=left_number, right_number=right_number)
|
||||
|
190
lib/popen.py
190
lib/popen.py
@@ -1,6 +1,6 @@
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2009 The ViewCVS Group. All Rights Reserved.
|
||||
# Copyright (C) 1999-2007 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 ViewVC
|
||||
@@ -131,6 +131,194 @@ def popen(cmd, args, mode, capture_err=1):
|
||||
# crap. shouldn't be here.
|
||||
sys.exit(127)
|
||||
|
||||
def pipe_cmds(cmds, out=None):
|
||||
"""Executes a sequence of commands. The output of each command is directed to
|
||||
the input of the next command. A _pipe object is returned for writing to the
|
||||
first command's input. The output of the last command is directed to the
|
||||
"out" file object or the standard output if "out" is None. If "out" is not an
|
||||
OS file descriptor, a separate thread will be spawned to send data to its
|
||||
write() method."""
|
||||
|
||||
if out is None:
|
||||
out = sys.stdout
|
||||
|
||||
if sys.platform == "win32":
|
||||
### FIXME: windows implementation ignores "out" argument, always
|
||||
### writing last command's output to standard out
|
||||
|
||||
if debug.SHOW_CHILD_PROCESSES:
|
||||
dbgIn = StringIO.StringIO()
|
||||
hStdIn, handle = win32popen.MakeSpyPipe(1, 0, (dbgIn,))
|
||||
|
||||
i = 0
|
||||
for cmd in cmds:
|
||||
i = i + 1
|
||||
|
||||
dbgOut, dbgErr = StringIO.StringIO(), StringIO.StringIO()
|
||||
|
||||
if i < len(cmds):
|
||||
nextStdIn, hStdOut = win32popen.MakeSpyPipe(1, 1, (dbgOut,))
|
||||
x, hStdErr = win32popen.MakeSpyPipe(None, 1, (dbgErr,))
|
||||
else:
|
||||
ehandle = win32event.CreateEvent(None, 1, 0, None)
|
||||
nextStdIn, hStdOut = win32popen.MakeSpyPipe(None, 1, (dbgOut, sapi.server.file()), ehandle)
|
||||
x, hStdErr = win32popen.MakeSpyPipe(None, 1, (dbgErr,))
|
||||
|
||||
command = win32popen.CommandLine(cmd[0], cmd[1:])
|
||||
phandle, pid, thandle, tid = win32popen.CreateProcess(command, hStdIn, hStdOut, hStdErr)
|
||||
if debug.SHOW_CHILD_PROCESSES:
|
||||
debug.Process(command, dbgIn, dbgOut, dbgErr)
|
||||
|
||||
dbgIn = dbgOut
|
||||
hStdIn = nextStdIn
|
||||
|
||||
|
||||
else:
|
||||
|
||||
hStdIn, handle = win32popen.CreatePipe(1, 0)
|
||||
spool = None
|
||||
|
||||
i = 0
|
||||
for cmd in cmds:
|
||||
i = i + 1
|
||||
if i < len(cmds):
|
||||
nextStdIn, hStdOut = win32popen.CreatePipe(1, 1)
|
||||
else:
|
||||
# very last process
|
||||
nextStdIn = None
|
||||
|
||||
if sapi.server.inheritableOut:
|
||||
# send child output to standard out
|
||||
hStdOut = win32popen.MakeInheritedHandle(win32popen.FileObject2File(sys.stdout),0)
|
||||
ehandle = None
|
||||
else:
|
||||
ehandle = win32event.CreateEvent(None, 1, 0, None)
|
||||
x, hStdOut = win32popen.MakeSpyPipe(None, 1, (sapi.server.file(),), ehandle)
|
||||
|
||||
command = win32popen.CommandLine(cmd[0], cmd[1:])
|
||||
phandle, pid, thandle, tid = win32popen.CreateProcess(command, hStdIn, hStdOut, None)
|
||||
hStdIn = nextStdIn
|
||||
|
||||
return _pipe(win32popen.File2FileObject(handle, 'wb'), phandle, ehandle)
|
||||
|
||||
# flush the stdio buffers since we are about to change the FD under them
|
||||
sys.stdout.flush()
|
||||
sys.stderr.flush()
|
||||
|
||||
prev_r, parent_w = os.pipe()
|
||||
|
||||
null = os.open('/dev/null', os.O_RDWR)
|
||||
|
||||
child_pids = []
|
||||
|
||||
for cmd in cmds[:-1]:
|
||||
r, w = os.pipe()
|
||||
pid = os.fork()
|
||||
if not pid:
|
||||
# in the child
|
||||
|
||||
# hook up stdin to the "read" channel
|
||||
os.dup2(prev_r, 0)
|
||||
|
||||
# hook up stdout to the output channel
|
||||
os.dup2(w, 1)
|
||||
|
||||
# toss errors
|
||||
os.dup2(null, 2)
|
||||
|
||||
# close these extra descriptors
|
||||
os.close(prev_r)
|
||||
os.close(parent_w)
|
||||
os.close(null)
|
||||
os.close(r)
|
||||
os.close(w)
|
||||
|
||||
# time to run the command
|
||||
try:
|
||||
os.execvp(cmd[0], cmd)
|
||||
except:
|
||||
pass
|
||||
|
||||
sys.exit(127)
|
||||
|
||||
# in the parent
|
||||
child_pids.append(pid)
|
||||
|
||||
# we don't need these any more
|
||||
os.close(prev_r)
|
||||
os.close(w)
|
||||
|
||||
# the read channel of this pipe will feed into to the next command
|
||||
prev_r = r
|
||||
|
||||
# no longer needed
|
||||
os.close(null)
|
||||
|
||||
# done with most of the commands. set up the last command to write to "out"
|
||||
if not hasattr(out, 'fileno'):
|
||||
r, w = os.pipe()
|
||||
|
||||
pid = os.fork()
|
||||
if not pid:
|
||||
# in the child (the last command)
|
||||
|
||||
# hook up stdin to the "read" channel
|
||||
os.dup2(prev_r, 0)
|
||||
|
||||
# hook up stdout to "out"
|
||||
if hasattr(out, 'fileno'):
|
||||
if out.fileno() != 1:
|
||||
os.dup2(out.fileno(), 1)
|
||||
out.close()
|
||||
|
||||
else:
|
||||
# "out" can't be hooked up directly, so use a pipe and a thread
|
||||
os.dup2(w, 1)
|
||||
os.close(r)
|
||||
os.close(w)
|
||||
|
||||
# close these extra descriptors
|
||||
os.close(prev_r)
|
||||
os.close(parent_w)
|
||||
|
||||
# run the last command
|
||||
try:
|
||||
os.execvp(cmds[-1][0], cmds[-1])
|
||||
except:
|
||||
pass
|
||||
|
||||
sys.exit(127)
|
||||
|
||||
child_pids.append(pid)
|
||||
# not needed any more
|
||||
os.close(prev_r)
|
||||
|
||||
if not hasattr(out, 'fileno'):
|
||||
os.close(w)
|
||||
thread = _copy(r, out)
|
||||
thread.start()
|
||||
else:
|
||||
thread = None
|
||||
|
||||
# write into the first pipe, wait on the final process
|
||||
return _pipe(os.fdopen(parent_w, 'w'), child_pids, thread=thread)
|
||||
|
||||
class _copy(threading.Thread):
|
||||
def __init__(self, srcfd, destfile):
|
||||
self.srcfd = srcfd
|
||||
self.destfile = destfile
|
||||
threading.Thread.__init__(self)
|
||||
|
||||
def run(self):
|
||||
try:
|
||||
while 1:
|
||||
s = os.read(self.srcfd, 1024)
|
||||
if not s:
|
||||
break
|
||||
self.destfile.write(s)
|
||||
finally:
|
||||
os.close(self.srcfd)
|
||||
|
||||
class _pipe:
|
||||
"Wrapper for a file which can wait() on a child process at close time."
|
||||
|
||||
|
78
lib/query.py
78
lib/query.py
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2010 The ViewCVS Group. All Rights Reserved.
|
||||
# Copyright (C) 1999-2008 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 ViewVC
|
||||
@@ -275,30 +275,8 @@ def prev_rev(rev):
|
||||
return string.join(r, '.')
|
||||
|
||||
def is_forbidden(cfg, cvsroot_name, module):
|
||||
'''Return 1 if MODULE in CVSROOT_NAME is forbidden; return 0 otherwise.'''
|
||||
|
||||
# CVSROOT_NAME might be None here if the data comes from an
|
||||
# unconfigured root. This interfaces doesn't care that the root
|
||||
# isn't configured, but if that's the case, it will consult only
|
||||
# the base and per-vhost configuration for authorizer and
|
||||
# authorizer parameters.
|
||||
if cvsroot_name:
|
||||
authorizer, params = cfg.get_authorizer_and_params_hack(cvsroot_name)
|
||||
else:
|
||||
authorizer = cfg.options.authorizer
|
||||
params = cfg.get_authorizer_params()
|
||||
|
||||
# If CVSROOT_NAME isn't configured to use an authorizer, nothing
|
||||
# is forbidden. If it's configured to use something other than
|
||||
# the 'forbidden' authorizer, complain. Otherwise, check for
|
||||
# forbiddenness per the PARAMS as expected.
|
||||
if not authorizer:
|
||||
return 0
|
||||
if authorizer != 'forbidden':
|
||||
raise Exception("The 'forbidden' authorizer is the only one supported "
|
||||
"by this interface. The '%s' root is configured to "
|
||||
"use a different one." % (cvsroot_name))
|
||||
forbidden = params.get('forbidden', '')
|
||||
auth_params = cfg.get_authorizer_params('forbidden', cvsroot_name)
|
||||
forbidden = auth_params.get('forbidden', '')
|
||||
forbidden = map(string.strip, filter(None, string.split(forbidden, ',')))
|
||||
default = 0
|
||||
for pat in forbidden:
|
||||
@@ -312,7 +290,11 @@ def is_forbidden(cfg, cvsroot_name, module):
|
||||
|
||||
def build_commit(server, cfg, desc, files, cvsroots, viewvc_link):
|
||||
ob = _item(num_files=len(files), files=[])
|
||||
ob.log = desc and string.replace(server.escape(desc), '\n', '<br />') or ''
|
||||
|
||||
if desc:
|
||||
ob.log = string.replace(server.escape(desc), '\n', '<br />')
|
||||
else:
|
||||
ob.log = ' '
|
||||
|
||||
for commit in files:
|
||||
repository = commit.GetRepository()
|
||||
@@ -346,10 +328,9 @@ def build_commit(server, cfg, desc, files, cvsroots, viewvc_link):
|
||||
except:
|
||||
raise Exception, str([directory, commit.GetFile()])
|
||||
|
||||
## If we couldn't find the cvsroot path configured in the
|
||||
## viewvc.conf file, or we don't have a VIEWVC_LINK, then
|
||||
## don't make the link.
|
||||
if cvsroot_name and viewvc_link:
|
||||
## if we couldn't find the cvsroot path configured in the
|
||||
## viewvc.conf file, then don't make the link
|
||||
if cvsroot_name:
|
||||
flink = '[%s] <a href="%s/%s?root=%s">%s</a>' % (
|
||||
cvsroot_name, viewvc_link, urllib.quote(file),
|
||||
cvsroot_name, file)
|
||||
@@ -388,7 +369,6 @@ def run_query(server, cfg, form_data, viewvc_link):
|
||||
files = [ ]
|
||||
|
||||
cvsroots = {}
|
||||
viewvc.expand_root_parents(cfg)
|
||||
rootitems = cfg.general.svn_roots.items() + cfg.general.cvs_roots.items()
|
||||
for key, value in rootitems:
|
||||
cvsroots[cvsdb.CleanRepository(value)] = key
|
||||
@@ -432,31 +412,39 @@ def main(server, cfg, viewvc_link):
|
||||
commits = [ ]
|
||||
query = 'skipped'
|
||||
|
||||
docroot = cfg.options.docroot
|
||||
if docroot is None and viewvc_link:
|
||||
docroot = viewvc_link + '/' + viewvc.docroot_magic_path
|
||||
|
||||
data = ezt.TemplateData({
|
||||
script_name = server.getenv('SCRIPT_NAME', '')
|
||||
|
||||
data = {
|
||||
'cfg' : cfg,
|
||||
'address' : cfg.general.address,
|
||||
'vsn' : viewvc.__version__,
|
||||
'repository' : server.escape(form_data.repository),
|
||||
'branch' : server.escape(form_data.branch),
|
||||
'directory' : server.escape(form_data.directory),
|
||||
'file' : server.escape(form_data.file),
|
||||
'who' : server.escape(form_data.who),
|
||||
'docroot' : docroot,
|
||||
|
||||
'repository' : server.escape(form_data.repository, 1),
|
||||
'branch' : server.escape(form_data.branch, 1),
|
||||
'directory' : server.escape(form_data.directory, 1),
|
||||
'file' : server.escape(form_data.file, 1),
|
||||
'who' : server.escape(form_data.who, 1),
|
||||
'docroot' : cfg.options.docroot is None \
|
||||
and viewvc_link + '/' + viewvc.docroot_magic_path \
|
||||
or cfg.options.docroot,
|
||||
|
||||
'sortby' : form_data.sortby,
|
||||
'date' : form_data.date,
|
||||
|
||||
'query' : query,
|
||||
'commits' : commits,
|
||||
'num_commits' : len(commits),
|
||||
'rss_href' : None,
|
||||
'hours' : form_data.hours and form_data.hours or 2,
|
||||
})
|
||||
}
|
||||
|
||||
if form_data.hours:
|
||||
data['hours'] = form_data.hours
|
||||
else:
|
||||
data['hours'] = 2
|
||||
|
||||
server.header()
|
||||
|
||||
# generate the page
|
||||
server.header()
|
||||
template = viewvc.get_view_template(cfg, "query")
|
||||
template.generate(server.file(), data)
|
||||
|
||||
|
107
lib/sapi.py
107
lib/sapi.py
@@ -1,6 +1,6 @@
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2010 The ViewCVS Group. All Rights Reserved.
|
||||
# Copyright (C) 1999-2006 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 ViewVC
|
||||
@@ -20,27 +20,13 @@ import string
|
||||
import os
|
||||
import sys
|
||||
import re
|
||||
import cgi
|
||||
|
||||
|
||||
# global server object. It will be either a CgiServer, a WsgiServer,
|
||||
# or a proxy to an AspServer or ModPythonServer object.
|
||||
# global server object. It will be either a CgiServer or a proxy to
|
||||
# an AspServer or ModPythonServer object.
|
||||
server = None
|
||||
|
||||
|
||||
# Simple HTML string escaping. Note that we always escape the
|
||||
# double-quote character -- ViewVC shouldn't ever need to preserve
|
||||
# that character as-is, and sometimes needs to embed escaped values
|
||||
# into HTML attributes.
|
||||
def escape(s):
|
||||
s = str(s)
|
||||
s = string.replace(s, '&', '&')
|
||||
s = string.replace(s, '>', '>')
|
||||
s = string.replace(s, '<', '<')
|
||||
s = string.replace(s, '"', """)
|
||||
return s
|
||||
|
||||
|
||||
class Server:
|
||||
def __init__(self):
|
||||
self.pageGlobals = {}
|
||||
@@ -48,9 +34,6 @@ class Server:
|
||||
def self(self):
|
||||
return self
|
||||
|
||||
def escape(self, s):
|
||||
return escape(s)
|
||||
|
||||
def close(self):
|
||||
pass
|
||||
|
||||
@@ -146,6 +129,9 @@ class CgiServer(Server):
|
||||
global server
|
||||
server = self
|
||||
|
||||
global cgi
|
||||
import cgi
|
||||
|
||||
def addheader(self, name, value):
|
||||
self.headers.append((name, value))
|
||||
|
||||
@@ -172,7 +158,11 @@ class CgiServer(Server):
|
||||
if self.iis: url = fix_iis_url(self, url)
|
||||
self.addheader('Location', url)
|
||||
self.header(status='301 Moved')
|
||||
sys.stdout.write('This document is located <a href="%s">here</a>.\n' % url)
|
||||
print 'This document is located <a href="%s">here</a>.' % url
|
||||
sys.exit(0)
|
||||
|
||||
def escape(self, s, quote = None):
|
||||
return cgi.escape(s, quote)
|
||||
|
||||
def getenv(self, name, value=None):
|
||||
ret = os.environ.get(name, value)
|
||||
@@ -186,7 +176,7 @@ class CgiServer(Server):
|
||||
def FieldStorage(fp=None, headers=None, outerboundary="",
|
||||
environ=os.environ, keep_blank_values=0, strict_parsing=0):
|
||||
return cgi.FieldStorage(fp, headers, outerboundary, environ,
|
||||
keep_blank_values, strict_parsing)
|
||||
keep_blank_values, strict_parsing)
|
||||
|
||||
def write(self, s):
|
||||
sys.stdout.write(s)
|
||||
@@ -198,66 +188,6 @@ class CgiServer(Server):
|
||||
return sys.stdout
|
||||
|
||||
|
||||
class WsgiServer(Server):
|
||||
def __init__(self, environ, start_response):
|
||||
Server.__init__(self)
|
||||
|
||||
self._environ = environ
|
||||
self._start_response = start_response;
|
||||
self._headers = []
|
||||
self._wsgi_write = None
|
||||
self.headerSent = False
|
||||
|
||||
global server
|
||||
server = self
|
||||
|
||||
global cgi
|
||||
import cgi
|
||||
|
||||
def addheader(self, name, value):
|
||||
self._headers.append((name, value))
|
||||
|
||||
def header(self, content_type='text/html; charset=UTF-8', status=None):
|
||||
if not status:
|
||||
status = "200 OK"
|
||||
if not self.headerSent:
|
||||
self.headerSent = True
|
||||
self._headers.insert(0, ("Content-Type", content_type),)
|
||||
self._wsgi_write = self._start_response("%s" % status, self._headers)
|
||||
|
||||
def redirect(self, url):
|
||||
"""Redirect client to url. This discards any data that has been queued
|
||||
to be sent to the user. But there should never by any anyway.
|
||||
"""
|
||||
self.addheader('Location', url)
|
||||
self.header(status='301 Moved')
|
||||
self._wsgi_write('This document is located <a href="%s">here</a>.' % url)
|
||||
|
||||
def escape(self, s, quote = None):
|
||||
return cgi.escape(s, quote)
|
||||
|
||||
def getenv(self, name, value=None):
|
||||
return self._environ.get(name, value)
|
||||
|
||||
def params(self):
|
||||
return cgi.parse(environ=self._environ, fp=self._environ["wsgi.input"])
|
||||
|
||||
def FieldStorage(self, fp=None, headers=None, outerboundary="",
|
||||
environ=os.environ, keep_blank_values=0, strict_parsing=0):
|
||||
return cgi.FieldStorage(self._environ["wsgi.input"], headers,
|
||||
outerboundary, self._environ, keep_blank_values,
|
||||
strict_parsing)
|
||||
|
||||
def write(self, s):
|
||||
self._wsgi_write(s)
|
||||
|
||||
def flush(self):
|
||||
pass
|
||||
|
||||
def file(self):
|
||||
return File(self)
|
||||
|
||||
|
||||
class AspServer(ThreadedServer):
|
||||
def __init__(self, Server, Request, Response, Application):
|
||||
ThreadedServer.__init__(self)
|
||||
@@ -289,6 +219,10 @@ class AspServer(ThreadedServer):
|
||||
|
||||
def redirect(self, url):
|
||||
self.response.Redirect(url)
|
||||
sys.exit()
|
||||
|
||||
def escape(self, s, quote = None):
|
||||
return self.server.HTMLEncode(str(s))
|
||||
|
||||
def getenv(self, name, value = None):
|
||||
ret = self.request.ServerVariables(name)()
|
||||
@@ -351,6 +285,9 @@ class ModPythonServer(ThreadedServer):
|
||||
self.request = request
|
||||
self.headerSent = 0
|
||||
|
||||
global cgi
|
||||
import cgi
|
||||
|
||||
def addheader(self, name, value):
|
||||
self.request.headers_out.add(name, value)
|
||||
|
||||
@@ -371,7 +308,11 @@ class ModPythonServer(ThreadedServer):
|
||||
self.request.headers_out['Location'] = url
|
||||
self.request.status = mod_python.apache.HTTP_MOVED_TEMPORARILY
|
||||
self.request.write("You are being redirected to <a href=\"%s\">%s</a>"
|
||||
% (url, url))
|
||||
% (url, url))
|
||||
sys.exit()
|
||||
|
||||
def escape(self, s, quote = None):
|
||||
return cgi.escape(s, quote)
|
||||
|
||||
def getenv(self, name, value = None):
|
||||
try:
|
||||
|
@@ -22,6 +22,7 @@ class ViewVCAuthorizer(vcauth.GenericViewVCAuthorizer):
|
||||
"""Subversion authz authorizer module"""
|
||||
|
||||
def __init__(self, username, params={}):
|
||||
self.username = username
|
||||
self.rootpaths = { } # {root -> { paths -> access boolean for USERNAME }}
|
||||
|
||||
# Get the authz file location from a passed-in parameter.
|
||||
@@ -31,29 +32,14 @@ class ViewVCAuthorizer(vcauth.GenericViewVCAuthorizer):
|
||||
if not os.path.exists(self.authz_file):
|
||||
raise debug.ViewVCException("Configured authzfile file not found")
|
||||
|
||||
# See if the admin wants us to do case normalization of usernames.
|
||||
self.force_username_case = params.get('force_username_case')
|
||||
if self.force_username_case == "upper":
|
||||
self.username = username.upper()
|
||||
elif self.force_username_case == "lower":
|
||||
self.username = username.lower()
|
||||
elif not self.force_username_case:
|
||||
self.username = username
|
||||
else:
|
||||
raise debug.ViewVCException("Invalid value for force_username_case "
|
||||
"option")
|
||||
|
||||
def _get_paths_for_root(self, rootname):
|
||||
if self.rootpaths.has_key(rootname):
|
||||
return self.rootpaths[rootname]
|
||||
|
||||
paths_for_root = { }
|
||||
|
||||
# Parse the authz file, replacing ConfigParser's optionxform()
|
||||
# method with something that won't futz with the case of the
|
||||
# option names.
|
||||
# Parse the authz file.
|
||||
cp = ConfigParser()
|
||||
cp.optionxform = lambda x: x
|
||||
cp.read(self.authz_file)
|
||||
|
||||
# Figure out if there are any aliases for the current username
|
||||
|
@@ -180,10 +180,8 @@ class Repository:
|
||||
|
||||
rev is the revision of the item to return information about
|
||||
|
||||
Return value is a 5-tuple containing: the date, author, log
|
||||
message, a list of ChangedPath items representing paths changed,
|
||||
and a dictionary mapping property names to property values for
|
||||
properties stored on an item.
|
||||
Return value is a 4-tuple containing the date, author, log
|
||||
message, and a list of ChangedPath items representing paths changed
|
||||
|
||||
Raise vclib.UnsupportedFeature if the version control system
|
||||
doesn't support a global revision concept.
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2008 The ViewCVS Group. All Rights Reserved.
|
||||
# Copyright (C) 1999-2007 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
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2008 The ViewCVS Group. All Rights Reserved.
|
||||
# Copyright (C) 1999-2007 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 ViewVC
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2008 The ViewCVS Group. All Rights Reserved.
|
||||
# Copyright (C) 1999-2007 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 ViewVC
|
||||
@@ -19,11 +19,7 @@ import string
|
||||
import common
|
||||
|
||||
class _TokenStream:
|
||||
token_term = string.whitespace + ";:"
|
||||
try:
|
||||
token_term = frozenset(token_term)
|
||||
except NameError:
|
||||
pass
|
||||
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.
|
||||
@@ -48,17 +44,15 @@ class _TokenStream:
|
||||
# out more complex solutions.
|
||||
|
||||
buf = self.buf
|
||||
lbuf = len(buf)
|
||||
idx = self.idx
|
||||
|
||||
while 1:
|
||||
if idx == lbuf:
|
||||
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
|
||||
lbuf = len(buf)
|
||||
idx = 0
|
||||
|
||||
if buf[idx] not in string.whitespace:
|
||||
@@ -66,7 +60,7 @@ class _TokenStream:
|
||||
|
||||
idx = idx + 1
|
||||
|
||||
if buf[idx] in ';:':
|
||||
if buf[idx] == ';' or buf[idx] == ':':
|
||||
self.buf = buf
|
||||
self.idx = idx + 1
|
||||
return buf[idx]
|
||||
@@ -76,18 +70,17 @@ class _TokenStream:
|
||||
token = ''
|
||||
while 1:
|
||||
# find token characters in the current buffer
|
||||
while end < lbuf and buf[end] not in self.token_term:
|
||||
while end < len(buf) and buf[end] not in self.token_term:
|
||||
end = end + 1
|
||||
token = token + buf[idx:end]
|
||||
|
||||
if end < lbuf:
|
||||
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)
|
||||
lbuf = len(buf)
|
||||
idx = end = 0
|
||||
|
||||
self.buf = buf
|
||||
@@ -101,24 +94,22 @@ class _TokenStream:
|
||||
chunks = [ ]
|
||||
|
||||
while 1:
|
||||
if idx == lbuf:
|
||||
if idx == len(buf):
|
||||
idx = 0
|
||||
buf = self.rcsfile.read(self.CHUNK_SIZE)
|
||||
if buf == '':
|
||||
raise RuntimeError, 'EOF'
|
||||
lbuf = len(buf)
|
||||
i = string.find(buf, '@', idx)
|
||||
if i == -1:
|
||||
chunks.append(buf[idx:])
|
||||
idx = lbuf
|
||||
idx = len(buf)
|
||||
continue
|
||||
if i == lbuf - 1:
|
||||
if i == len(buf) - 1:
|
||||
chunks.append(buf[idx:i])
|
||||
idx = 0
|
||||
buf = '@' + self.rcsfile.read(self.CHUNK_SIZE)
|
||||
if buf == '@':
|
||||
raise RuntimeError, 'EOF'
|
||||
lbuf = len(buf)
|
||||
continue
|
||||
if buf[i + 1] == '@':
|
||||
chunks.append(buf[idx:i+1])
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2008 The ViewCVS Group. All Rights Reserved.
|
||||
# Copyright (C) 1999-2007 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 ViewVC
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2009 The ViewCVS Group. All Rights Reserved.
|
||||
# Copyright (C) 1999-2008 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 ViewVC
|
||||
@@ -18,9 +18,10 @@ import os
|
||||
import string
|
||||
import re
|
||||
import tempfile
|
||||
import popen2
|
||||
import time
|
||||
import urllib
|
||||
from svn_repos import Revision, SVNChangedPath, _datestr_to_date, _compare_paths, _path_parts, _cleanup_path, _rev2optrev, _fix_subversion_exception, _split_revprops
|
||||
from svn_repos import Revision, SVNChangedPath, _datestr_to_date, _compare_paths, _path_parts, _cleanup_path, _rev2optrev
|
||||
from svn import core, delta, client, wc, ra
|
||||
|
||||
|
||||
@@ -51,29 +52,6 @@ def get_directory_props(ra_session, path, rev):
|
||||
props = ra.svn_ra_get_dir(ra_session, path, rev)
|
||||
return props
|
||||
|
||||
def client_log(url, start_rev, end_rev, log_limit, cross_copies,
|
||||
cb_func, ctx):
|
||||
try:
|
||||
client.svn_client_log4([url], start_rev, start_rev, end_rev,
|
||||
log_limit, 1, not cross_copies, 0, None,
|
||||
cb_func, ctx)
|
||||
except NameError:
|
||||
# Wrap old svn_log_message_receiver_t interface with a
|
||||
# svn_log_entry_t one.
|
||||
def cb_convert(paths, revision, author, date, message, pool):
|
||||
class svn_log_entry_t:
|
||||
pass
|
||||
log_entry = svn_log_entry_t()
|
||||
log_entry.changed_paths = paths
|
||||
log_entry.revision = revision
|
||||
log_entry.revprops = { core.SVN_PROP_REVISION_LOG : message,
|
||||
core.SVN_PROP_REVISION_AUTHOR : author,
|
||||
core.SVN_PROP_REVISION_DATE : date,
|
||||
}
|
||||
cb_func(log_entry, pool)
|
||||
client.svn_client_log2([url], start_rev, end_rev, log_limit,
|
||||
1, not cross_copies, cb_convert, ctx)
|
||||
|
||||
### END COMPATABILITY CODE ###
|
||||
|
||||
|
||||
@@ -90,11 +68,7 @@ class LogCollector:
|
||||
self.show_all_logs = show_all_logs
|
||||
self.lockinfo = lockinfo
|
||||
|
||||
def add_log(self, log_entry, pool):
|
||||
paths = log_entry.changed_paths
|
||||
revision = log_entry.revision
|
||||
msg, author, date, revprops = _split_revprops(log_entry.revprops)
|
||||
|
||||
def add_log(self, paths, revision, author, date, message, pool):
|
||||
# Changed paths have leading slashes
|
||||
changed_paths = paths.keys()
|
||||
changed_paths.sort(lambda a, b: _compare_paths(a, b))
|
||||
@@ -114,8 +88,8 @@ class LogCollector:
|
||||
if change.copyfrom_path:
|
||||
this_path = change.copyfrom_path + self.path[len(changed_path):]
|
||||
if self.show_all_logs or this_path:
|
||||
entry = Revision(revision, date, author, msg, None, self.lockinfo,
|
||||
self.path[1:], None, None)
|
||||
entry = Revision(revision, _datestr_to_date(date), author, message, None,
|
||||
self.lockinfo, self.path[1:], None, None)
|
||||
self.logs.append(entry)
|
||||
if this_path:
|
||||
self.path = this_path
|
||||
@@ -183,7 +157,7 @@ class RemoteSubversionRepository(vclib.Repository):
|
||||
# Setup the client context baton, complete with non-prompting authstuffs.
|
||||
# TODO: svn_cmdline_setup_auth_baton() is mo' better (when available)
|
||||
core.svn_config_ensure(self.config_dir)
|
||||
self.ctx = client.svn_client_create_context()
|
||||
self.ctx = client.svn_client_ctx_t()
|
||||
self.ctx.auth_baton = core.svn_auth_open([
|
||||
client.svn_client_get_simple_provider(),
|
||||
client.svn_client_get_username_provider(),
|
||||
@@ -278,9 +252,9 @@ class RemoteSubversionRepository(vclib.Repository):
|
||||
if not vclib.check_path_access(self, entry_path_parts, entry.kind, rev):
|
||||
continue
|
||||
dirent = dirents[entry.name]
|
||||
entry.date, entry.author, entry.log, revprops, changes = \
|
||||
entry.date, entry.author, entry.log, changes = \
|
||||
self.revinfo(dirent.created_rev)
|
||||
entry.rev = str(dirent.created_rev)
|
||||
entry.rev = dirent.created_rev
|
||||
entry.size = dirent.size
|
||||
entry.lockinfo = None
|
||||
if locks.has_key(entry.name):
|
||||
@@ -309,8 +283,9 @@ class RemoteSubversionRepository(vclib.Repository):
|
||||
log_limit = 0
|
||||
if limit:
|
||||
log_limit = first + limit
|
||||
client_log(url, _rev2optrev(rev), _rev2optrev(1), log_limit,
|
||||
cross_copies, lc.add_log, self.ctx)
|
||||
client.svn_client_log2([url], _rev2optrev(rev), _rev2optrev(1),
|
||||
log_limit, 1, not cross_copies,
|
||||
lc.add_log, self.ctx)
|
||||
revs = lc.logs
|
||||
revs.sort()
|
||||
prev = None
|
||||
@@ -362,7 +337,7 @@ class RemoteSubversionRepository(vclib.Repository):
|
||||
if not cached_info:
|
||||
cached_info = self._revinfo_raw(rev)
|
||||
self._revinfo_cache[rev] = cached_info
|
||||
return tuple(cached_info)
|
||||
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)
|
||||
@@ -377,7 +352,7 @@ class RemoteSubversionRepository(vclib.Repository):
|
||||
args = vclib._diff_args(type, options)
|
||||
|
||||
def _date_from_rev(rev):
|
||||
date, author, msg, revprops, changes = self.revinfo(rev)
|
||||
date, author, msg, changes = self.revinfo(rev)
|
||||
return date
|
||||
|
||||
try:
|
||||
@@ -387,7 +362,6 @@ class RemoteSubversionRepository(vclib.Repository):
|
||||
info2 = p2, _date_from_rev(r2), r2
|
||||
return vclib._diff_fp(temp1, temp2, info1, info2, self.diff_cmd, args)
|
||||
except core.SubversionException, e:
|
||||
_fix_subversion_exception(e)
|
||||
if e.apr_err == vclib.svn.core.SVN_ERR_FS_NOT_FOUND:
|
||||
raise vclib.InvalidRevision
|
||||
raise
|
||||
@@ -442,54 +416,29 @@ class RemoteSubversionRepository(vclib.Repository):
|
||||
return revisions[0]
|
||||
|
||||
def _revinfo_raw(self, rev):
|
||||
# return 5-tuple (date, author, msg, revprops, changes)
|
||||
# return 5-tuple (date, author, message, changes)
|
||||
optrev = _rev2optrev(rev)
|
||||
revs = []
|
||||
|
||||
def _log_cb(log_entry, pool, retval=revs):
|
||||
### Subversion 1.5 and earlier didn't offer the 'changed_paths2'
|
||||
### hash, and in Subversion 1.6, it's offered but broken.
|
||||
try:
|
||||
changed_paths = log_entry.changed_paths2
|
||||
paths = (changed_paths or {}).keys()
|
||||
except:
|
||||
changed_paths = log_entry.changed_paths
|
||||
paths = (changed_paths or {}).keys()
|
||||
paths.sort(lambda a, b: _compare_paths(a, b))
|
||||
revision = log_entry.revision
|
||||
msg, author, date, revprops = _split_revprops(log_entry.revprops)
|
||||
def _log_cb(changed_paths, revision, author,
|
||||
datestr, message, pool, retval=revs):
|
||||
date = _datestr_to_date(datestr)
|
||||
action_map = { 'D' : vclib.DELETED,
|
||||
'A' : vclib.ADDED,
|
||||
'R' : vclib.REPLACED,
|
||||
'M' : vclib.MODIFIED,
|
||||
}
|
||||
paths = (changed_paths or {}).keys()
|
||||
paths.sort(lambda a, b: _compare_paths(a, b))
|
||||
changes = []
|
||||
found_readable = found_unreadable = 0
|
||||
for path in paths:
|
||||
change = changed_paths[path]
|
||||
### svn_log_changed_path_t (which we might get instead of the
|
||||
### svn_log_changed_path2_t we'd prefer) doesn't have the
|
||||
### 'node_kind' member.
|
||||
pathtype = None
|
||||
if hasattr(change, 'node_kind'):
|
||||
if change.node_kind == core.svn_node_dir:
|
||||
pathtype = vclib.DIR
|
||||
elif change.node_kind == core.svn_node_file:
|
||||
pathtype = vclib.FILE
|
||||
### svn_log_changed_path2_t only has the 'text_modified' and
|
||||
### 'props_modified' bits in Subversion 1.7 and beyond. And
|
||||
### svn_log_changed_path_t is without.
|
||||
text_modified = props_modified = 0
|
||||
if hasattr(change, 'text_modified'):
|
||||
if change.text_modified == core.svn_tristate_true:
|
||||
text_modified = 1
|
||||
if hasattr(change, 'props_modified'):
|
||||
if change.props_modified == core.svn_tristate_true:
|
||||
props_modified = 1
|
||||
change = changed_paths[path]
|
||||
action = action_map.get(change.action, vclib.MODIFIED)
|
||||
### Wrong, diddily wrong wrong wrong. Can you say,
|
||||
### "Manufacturing data left and right because it hurts to
|
||||
### figure out the right stuff?"
|
||||
action = action_map.get(change.action, vclib.MODIFIED)
|
||||
if change.copyfrom_path and change.copyfrom_rev:
|
||||
is_copy = 1
|
||||
base_path = change.copyfrom_path
|
||||
@@ -512,21 +461,21 @@ class RemoteSubversionRepository(vclib.Repository):
|
||||
base_path = None
|
||||
base_rev = None
|
||||
changes.append(SVNChangedPath(path, revision, pathtype, base_path,
|
||||
base_rev, action, is_copy,
|
||||
text_modified, props_modified))
|
||||
base_rev, action, is_copy, 0, 0))
|
||||
found_readable = 1
|
||||
else:
|
||||
found_unreadable = 1
|
||||
|
||||
if found_unreadable:
|
||||
msg = None
|
||||
message = None
|
||||
if not found_readable:
|
||||
author = None
|
||||
date = None
|
||||
revs.append([date, author, msg, revprops, changes])
|
||||
revs.append([date, author, message, changes])
|
||||
|
||||
client_log(self.rootpath, optrev, optrev, 1, 0, _log_cb, self.ctx)
|
||||
return tuple(revs[0])
|
||||
client.svn_client_log([self.rootpath], optrev, optrev,
|
||||
1, 0, _log_cb, self.ctx)
|
||||
return revs[0][0], revs[0][1], revs[0][2], revs[0][3]
|
||||
|
||||
##--- custom --##
|
||||
|
||||
@@ -537,7 +486,6 @@ class RemoteSubversionRepository(vclib.Repository):
|
||||
try:
|
||||
results = ra.get_locations(self.ra_session, path, rev, [old_rev])
|
||||
except core.SubversionException, e:
|
||||
_fix_subversion_exception(e)
|
||||
if e.apr_err == core.SVN_ERR_FS_NOT_FOUND:
|
||||
raise vclib.ItemNotFound(path)
|
||||
raise
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2010 The ViewCVS Group. All Rights Reserved.
|
||||
# Copyright (C) 1999-2008 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 ViewVC
|
||||
@@ -15,9 +15,11 @@
|
||||
import vclib
|
||||
import os
|
||||
import os.path
|
||||
import stat
|
||||
import string
|
||||
import cStringIO
|
||||
import signal
|
||||
import shutil
|
||||
import time
|
||||
import tempfile
|
||||
import popen
|
||||
@@ -29,19 +31,6 @@ from svn import fs, repos, core, client, delta
|
||||
if (core.SVN_VER_MAJOR, core.SVN_VER_MINOR, core.SVN_VER_PATCH) < (1, 3, 1):
|
||||
raise Exception, "Version requirement not met (needs 1.3.1 or better)"
|
||||
|
||||
|
||||
### Pre-1.5 Subversion doesn't have SVN_ERR_CEASE_INVOCATION
|
||||
try:
|
||||
_SVN_ERR_CEASE_INVOCATION = core.SVN_ERR_CEASE_INVOCATION
|
||||
except:
|
||||
_SVN_ERR_CEASE_INVOCATION = core.SVN_ERR_CANCELLED
|
||||
|
||||
### Pre-1.5 SubversionException's might not have the .msg and .apr_err members
|
||||
def _fix_subversion_exception(e):
|
||||
if not hasattr(e, 'apr_err'):
|
||||
e.apr_err = e[1]
|
||||
if not hasattr(e, 'message'):
|
||||
e.message = e[0]
|
||||
|
||||
def _allow_all(root, path, pool):
|
||||
"""Generic authz_read_func that permits access to all paths"""
|
||||
@@ -115,27 +104,6 @@ def _rootpath2url(rootpath, path):
|
||||
return 'file://' + string.join([rootpath, path], "/")
|
||||
|
||||
|
||||
# Given a dictionary REVPROPS of revision properties, pull special
|
||||
# ones out of them and return a 4-tuple containing the log message,
|
||||
# the author, the date (converted from the date string property), and
|
||||
# a dictionary of any/all other revprops.
|
||||
def _split_revprops(revprops):
|
||||
if not revprops:
|
||||
return None, None, None, {}
|
||||
special_props = []
|
||||
for prop in core.SVN_PROP_REVISION_LOG, \
|
||||
core.SVN_PROP_REVISION_AUTHOR, \
|
||||
core.SVN_PROP_REVISION_DATE:
|
||||
if revprops.has_key(prop):
|
||||
special_props.append(revprops[prop])
|
||||
del(revprops[prop])
|
||||
else:
|
||||
special_props.append(None)
|
||||
msg, author, datestr = tuple(special_props)
|
||||
date = _datestr_to_date(datestr)
|
||||
return msg, author, date, revprops
|
||||
|
||||
|
||||
def _datestr_to_date(datestr):
|
||||
try:
|
||||
return core.svn_time_from_cstring(datestr) / 1000000
|
||||
@@ -199,16 +167,13 @@ class NodeHistory:
|
||||
return
|
||||
self.histories.append([revision, _cleanup_path(path)])
|
||||
if self.limit and len(self.histories) == self.limit:
|
||||
raise core.SubversionException("", _SVN_ERR_CEASE_INVOCATION)
|
||||
raise core.SubversionException("", core.SVN_ERR_CEASE_INVOCATION)
|
||||
|
||||
def __getitem__(self, idx):
|
||||
return self.histories[idx]
|
||||
|
||||
|
||||
def _get_history(svnrepos, path, rev, path_type, limit=0, options={}):
|
||||
if svnrepos.youngest == 0:
|
||||
return []
|
||||
|
||||
rev_paths = []
|
||||
fsroot = svnrepos._getroot(rev)
|
||||
show_all_logs = options.get('svn_show_all_dir_logs', 0)
|
||||
@@ -225,8 +190,7 @@ def _get_history(svnrepos, path, rev, path_type, limit=0, options={}):
|
||||
repos.svn_repos_history(svnrepos.fs_ptr, path, history.add_history,
|
||||
1, rev, options.get('svn_cross_copies', 0))
|
||||
except core.SubversionException, e:
|
||||
_fix_subversion_exception(e)
|
||||
if e.apr_err != _SVN_ERR_CEASE_INVOCATION:
|
||||
if e.apr_err != core.SVN_ERR_CEASE_INVOCATION:
|
||||
raise
|
||||
|
||||
# Now, iterate over those history items, checking for changes of
|
||||
@@ -246,7 +210,7 @@ def _log_helper(svnrepos, path, rev, lockinfo):
|
||||
copyfrom_rev, copyfrom_path = fs.copied_from(rev_root, path)
|
||||
|
||||
# Assemble our LogEntry
|
||||
date, author, msg, revprops, changes = svnrepos._revinfo(rev)
|
||||
date, author, msg, changes = svnrepos.revinfo(rev)
|
||||
if fs.is_file(rev_root, path):
|
||||
size = fs.file_length(rev_root, path)
|
||||
else:
|
||||
@@ -335,14 +299,14 @@ class FileContentsPipe:
|
||||
|
||||
|
||||
class BlameSource:
|
||||
def __init__(self, local_url, rev, first_rev, config_dir):
|
||||
def __init__(self, local_url, rev, first_rev):
|
||||
self.idx = -1
|
||||
self.first_rev = first_rev
|
||||
self.blame_data = []
|
||||
|
||||
ctx = client.svn_client_create_context()
|
||||
core.svn_config_ensure(config_dir)
|
||||
ctx.config = core.svn_config_get_config(config_dir)
|
||||
ctx = client.ctx_t()
|
||||
core.svn_config_ensure(None)
|
||||
ctx.config = core.svn_config_get_config(None)
|
||||
ctx.auth_baton = core.svn_auth_open([])
|
||||
try:
|
||||
### TODO: Is this use of FIRST_REV always what we want? Should we
|
||||
@@ -350,7 +314,6 @@ class BlameSource:
|
||||
client.blame2(local_url, _rev2optrev(rev), _rev2optrev(first_rev),
|
||||
_rev2optrev(rev), self._blame_cb, ctx)
|
||||
except core.SubversionException, e:
|
||||
_fix_subversion_exception(e)
|
||||
if e.apr_err == core.SVN_ERR_CLIENT_IS_BINARY_FILE:
|
||||
raise vclib.NonTextualFileContents
|
||||
raise
|
||||
@@ -397,7 +360,7 @@ class LocalSubversionRepository(vclib.Repository):
|
||||
self.auth = authorizer
|
||||
self.svn_client_path = utilities.svn or 'svn'
|
||||
self.diff_cmd = utilities.diff or 'diff'
|
||||
self.config_dir = config_dir or None
|
||||
self.config_dir = config_dir
|
||||
|
||||
# See if this repository is even viewable, authz-wise.
|
||||
if not vclib.check_root_access(self):
|
||||
@@ -493,7 +456,7 @@ class LocalSubversionRepository(vclib.Repository):
|
||||
continue
|
||||
path = self._getpath(entry_path_parts)
|
||||
entry_rev = _get_last_history_rev(fsroot, path)
|
||||
date, author, msg, revprops, changes = self._revinfo(entry_rev)
|
||||
date, author, msg, changes = self.revinfo(entry_rev)
|
||||
entry.rev = str(entry_rev)
|
||||
entry.date = date
|
||||
entry.author = author
|
||||
@@ -588,124 +551,102 @@ class LocalSubversionRepository(vclib.Repository):
|
||||
youngest_rev, youngest_path = history[0]
|
||||
oldest_rev, oldest_path = history[-1]
|
||||
source = BlameSource(_rootpath2url(self.rootpath, path),
|
||||
youngest_rev, oldest_rev, self.config_dir)
|
||||
youngest_rev, oldest_rev)
|
||||
return source, youngest_rev
|
||||
|
||||
def _revinfo(self, rev, include_changed_paths=0):
|
||||
"""Internal-use, cache-friendly revision information harvester."""
|
||||
|
||||
def _revinfo_helper(rev, include_changed_paths):
|
||||
# Get the revision property info. (Would use
|
||||
# editor.get_root_props(), but something is broken there...)
|
||||
revprops = fs.revision_proplist(self.fs_ptr, rev)
|
||||
msg, author, date, revprops = _split_revprops(revprops)
|
||||
|
||||
# Optimization: If our caller doesn't care about the changed
|
||||
# paths, and we don't need them to do authz determinations, let's
|
||||
# get outta here.
|
||||
if self.auth is None and not include_changed_paths:
|
||||
return date, author, msg, revprops, None
|
||||
|
||||
# If we get here, then we either need the changed paths because we
|
||||
# were asked for them, or we need them to do authorization checks.
|
||||
# Either way, we need 'em, so let's get 'em.
|
||||
fsroot = self._getroot(rev)
|
||||
editor = repos.ChangeCollector(self.fs_ptr, fsroot)
|
||||
e_ptr, e_baton = delta.make_editor(editor)
|
||||
repos.svn_repos_replay(fsroot, e_ptr, e_baton)
|
||||
changedpaths = {}
|
||||
changes = editor.get_changes()
|
||||
|
||||
# Copy the Subversion changes into a new hash, checking
|
||||
# authorization and converting them into ChangedPath objects.
|
||||
found_readable = found_unreadable = 0
|
||||
for path in changes.keys():
|
||||
change = changes[path]
|
||||
if change.path:
|
||||
change.path = _cleanup_path(change.path)
|
||||
if change.base_path:
|
||||
change.base_path = _cleanup_path(change.base_path)
|
||||
is_copy = 0
|
||||
if not hasattr(change, 'action'): # new to subversion 1.4.0
|
||||
action = vclib.MODIFIED
|
||||
if not change.path:
|
||||
action = vclib.DELETED
|
||||
elif change.added:
|
||||
action = vclib.ADDED
|
||||
replace_check_path = path
|
||||
if change.base_path and change.base_rev:
|
||||
replace_check_path = change.base_path
|
||||
if changedpaths.has_key(replace_check_path) \
|
||||
and changedpaths[replace_check_path].action == vclib.DELETED:
|
||||
action = vclib.REPLACED
|
||||
else:
|
||||
if change.action == repos.CHANGE_ACTION_ADD:
|
||||
action = vclib.ADDED
|
||||
elif change.action == repos.CHANGE_ACTION_DELETE:
|
||||
action = vclib.DELETED
|
||||
elif change.action == repos.CHANGE_ACTION_REPLACE:
|
||||
action = vclib.REPLACED
|
||||
else:
|
||||
action = vclib.MODIFIED
|
||||
if (action == vclib.ADDED or action == vclib.REPLACED) \
|
||||
and change.base_path \
|
||||
and change.base_rev:
|
||||
is_copy = 1
|
||||
if change.item_kind == core.svn_node_dir:
|
||||
pathtype = vclib.DIR
|
||||
elif change.item_kind == core.svn_node_file:
|
||||
pathtype = vclib.FILE
|
||||
else:
|
||||
pathtype = None
|
||||
|
||||
parts = _path_parts(path)
|
||||
if vclib.check_path_access(self, parts, pathtype, rev):
|
||||
if is_copy and change.base_path and (change.base_path != path):
|
||||
parts = _path_parts(change.base_path)
|
||||
if not vclib.check_path_access(self, parts, pathtype, change.base_rev):
|
||||
is_copy = 0
|
||||
change.base_path = None
|
||||
change.base_rev = None
|
||||
changedpaths[path] = SVNChangedPath(path, rev, pathtype,
|
||||
change.base_path,
|
||||
change.base_rev, action,
|
||||
is_copy, change.text_changed,
|
||||
change.prop_changes)
|
||||
found_readable = 1
|
||||
else:
|
||||
found_unreadable = 1
|
||||
|
||||
# If our caller doesn't care about changed paths, we must be
|
||||
# here for authz reasons only. That means the minute we've
|
||||
# found both a readable and an unreadable path, we can bail out.
|
||||
if (not include_changed_paths) and found_readable and found_unreadable:
|
||||
return date, author, None, None, None
|
||||
|
||||
# Okay, we've process all our paths. Let's filter our metadata,
|
||||
# and return the requested data.
|
||||
if found_unreadable:
|
||||
msg = None
|
||||
if not found_readable:
|
||||
author = None
|
||||
date = None
|
||||
if include_changed_paths:
|
||||
return date, author, msg, revprops, changedpaths.values()
|
||||
else:
|
||||
return date, author, msg, revprops, None
|
||||
def _revinfo_raw(self, rev):
|
||||
fsroot = self._getroot(rev)
|
||||
|
||||
# Consult the revinfo cache first. If we don't have cached info,
|
||||
# or our caller wants changed paths and we don't have those for
|
||||
# this revision, go do the real work.
|
||||
# Get the changes for the revision
|
||||
editor = repos.ChangeCollector(self.fs_ptr, fsroot)
|
||||
e_ptr, e_baton = delta.make_editor(editor)
|
||||
repos.svn_repos_replay(fsroot, e_ptr, e_baton)
|
||||
changes = editor.get_changes()
|
||||
changedpaths = {}
|
||||
|
||||
# Now get the revision property info. Would use
|
||||
# editor.get_root_props(), but something is broken there...
|
||||
revprops = fs.revision_proplist(self.fs_ptr, rev)
|
||||
msg = revprops.get(core.SVN_PROP_REVISION_LOG)
|
||||
author = revprops.get(core.SVN_PROP_REVISION_AUTHOR)
|
||||
datestr = revprops.get(core.SVN_PROP_REVISION_DATE)
|
||||
|
||||
# Copy the Subversion changes into a new hash, converting them into
|
||||
# ChangedPath objects.
|
||||
found_readable = found_unreadable = 0
|
||||
for path in changes.keys():
|
||||
change = changes[path]
|
||||
if change.path:
|
||||
change.path = _cleanup_path(change.path)
|
||||
if change.base_path:
|
||||
change.base_path = _cleanup_path(change.base_path)
|
||||
is_copy = 0
|
||||
if not hasattr(change, 'action'): # new to subversion 1.4.0
|
||||
action = vclib.MODIFIED
|
||||
if not change.path:
|
||||
action = vclib.DELETED
|
||||
elif change.added:
|
||||
action = vclib.ADDED
|
||||
replace_check_path = path
|
||||
if change.base_path and change.base_rev:
|
||||
replace_check_path = change.base_path
|
||||
if changedpaths.has_key(replace_check_path) \
|
||||
and changedpaths[replace_check_path].action == vclib.DELETED:
|
||||
action = vclib.REPLACED
|
||||
else:
|
||||
if change.action == repos.CHANGE_ACTION_ADD:
|
||||
action = vclib.ADDED
|
||||
elif change.action == repos.CHANGE_ACTION_DELETE:
|
||||
action = vclib.DELETED
|
||||
elif change.action == repos.CHANGE_ACTION_REPLACE:
|
||||
action = vclib.REPLACED
|
||||
else:
|
||||
action = vclib.MODIFIED
|
||||
if (action == vclib.ADDED or action == vclib.REPLACED) \
|
||||
and change.base_path \
|
||||
and change.base_rev:
|
||||
is_copy = 1
|
||||
if change.item_kind == core.svn_node_dir:
|
||||
pathtype = vclib.DIR
|
||||
elif change.item_kind == core.svn_node_file:
|
||||
pathtype = vclib.FILE
|
||||
else:
|
||||
pathtype = None
|
||||
|
||||
parts = _path_parts(path)
|
||||
if vclib.check_path_access(self, parts, pathtype, rev):
|
||||
if is_copy and change.base_path and (change.base_path != path):
|
||||
parts = _path_parts(change.base_path)
|
||||
if not vclib.check_path_access(self, parts, pathtype, change.base_rev):
|
||||
is_copy = 0
|
||||
change.base_path = None
|
||||
change.base_rev = None
|
||||
changedpaths[path] = SVNChangedPath(path, rev, pathtype,
|
||||
change.base_path,
|
||||
change.base_rev, action,
|
||||
is_copy, change.text_changed,
|
||||
change.prop_changes)
|
||||
found_readable = 1
|
||||
else:
|
||||
found_unreadable = 1
|
||||
|
||||
# Return our tuple, auth-filtered: date, author, msg, changes
|
||||
if found_unreadable:
|
||||
msg = None
|
||||
if not found_readable:
|
||||
author = None
|
||||
datestr = None
|
||||
|
||||
date = _datestr_to_date(datestr)
|
||||
return date, author, msg, changedpaths.values()
|
||||
|
||||
def revinfo(self, rev):
|
||||
rev = self._getrev(rev)
|
||||
cached_info = self._revinfo_cache.get(rev)
|
||||
if not cached_info \
|
||||
or (include_changed_paths and cached_info[4] is None):
|
||||
cached_info = _revinfo_helper(rev, include_changed_paths)
|
||||
if not cached_info:
|
||||
cached_info = self._revinfo_raw(rev)
|
||||
self._revinfo_cache[rev] = cached_info
|
||||
return tuple(cached_info)
|
||||
|
||||
def revinfo(self, rev):
|
||||
return self._revinfo(rev, 1)
|
||||
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)
|
||||
@@ -720,7 +661,7 @@ class LocalSubversionRepository(vclib.Repository):
|
||||
args = vclib._diff_args(type, options)
|
||||
|
||||
def _date_from_rev(rev):
|
||||
date, author, msg, revprops, changes = self._revinfo(rev)
|
||||
date, author, msg, changes = self.revinfo(rev)
|
||||
return date
|
||||
|
||||
try:
|
||||
@@ -730,7 +671,6 @@ class LocalSubversionRepository(vclib.Repository):
|
||||
info2 = p2, _date_from_rev(r2), r2
|
||||
return vclib._diff_fp(temp1, temp2, info1, info2, self.diff_cmd, args)
|
||||
except core.SubversionException, e:
|
||||
_fix_subversion_exception(e)
|
||||
if e.apr_err == core.SVN_ERR_FS_NOT_FOUND:
|
||||
raise vclib.InvalidRevision
|
||||
raise
|
||||
@@ -770,7 +710,6 @@ class LocalSubversionRepository(vclib.Repository):
|
||||
results = repos.svn_repos_trace_node_locations(self.fs_ptr, path,
|
||||
rev, [old_rev], _allow_all)
|
||||
except core.SubversionException, e:
|
||||
_fix_subversion_exception(e)
|
||||
if e.apr_err == core.SVN_ERR_FS_NOT_FOUND:
|
||||
raise vclib.ItemNotFound(path)
|
||||
raise
|
||||
@@ -820,7 +759,6 @@ class LocalSubversionRepository(vclib.Repository):
|
||||
try:
|
||||
mid_id = fs.node_id(self._getroot(mid), path)
|
||||
except core.SubversionException, e:
|
||||
_fix_subversion_exception(e)
|
||||
if e.apr_err == core.SVN_ERR_FS_NOT_FOUND:
|
||||
cmp = -1
|
||||
else:
|
||||
|
1151
lib/viewvc.py
1151
lib/viewvc.py
File diff suppressed because it is too large
Load Diff
@@ -38,70 +38,50 @@ numbers, and not literal):
|
||||
should exactly reflect what you wish to distribute and dub "the
|
||||
release".
|
||||
|
||||
7. Update your release branch working copy to HEAD.
|
||||
|
||||
svn up
|
||||
|
||||
8. Edit the file 'lib/viewvc.py' and remove the "-dev" suffix from
|
||||
7. Edit the file 'lib/viewvc.py' and remove the "-dev" suffix from
|
||||
__version__. The remainder should be of the form "X.Y.Z", where X,
|
||||
Y, and Z are positive integers.
|
||||
Y, and Z are positive integers. Do NOT commit this change.
|
||||
|
||||
*** Do NOT commit this change. ***
|
||||
8. Update your working copy to HEAD, and tag the release:
|
||||
|
||||
9. "Peg" the contributed templates externals definition to the
|
||||
current HEAD revision:
|
||||
svn update
|
||||
svn cp -m "Tag the X.Y.Z final release." . \
|
||||
http://viewvc.tigris.org/svn/viewvc/tags/X.Y.Z
|
||||
|
||||
svn pedit svn:externals .
|
||||
|
||||
(squeeze "-rBASE_REV", where BASE_REV is the current HEAD revision
|
||||
number, between 'templates-contrib' and the target URL).
|
||||
9. Go into an empty directory and run the 'make-release' script:
|
||||
|
||||
*** Do NOT commit this change. ***
|
||||
tools/make-release viewvc-X.Y.Z X.Y.Z
|
||||
|
||||
10. Tag the release:
|
||||
|
||||
svn cp -m "Tag the X.Y.Z final release." . ^/tags/X.Y.Z
|
||||
|
||||
This will create a copy of the release branch, plus your local
|
||||
modifications to the svn:externals property and lib/viewvc.py
|
||||
file, to the tag location.
|
||||
|
||||
11. Revert the changes in your working copy.
|
||||
|
||||
svn revert -R .
|
||||
|
||||
12. Go into an empty directory and run the 'make-release' script:
|
||||
|
||||
tools/make-release viewvc-X.Y.Z tags/X.Y.Z
|
||||
|
||||
13. Verify the archive files:
|
||||
10. Verify the archive files:
|
||||
|
||||
- do they have a LICENSE.html file?
|
||||
- do they have necessary include documentation?
|
||||
- do they *not* have unnecessary stuff?
|
||||
- do they install and work correctly?
|
||||
|
||||
14. Upload the created archive files (tar.gz and zip) into the Files
|
||||
11. Upload the created archive files (tar.gz and zip) into the Files
|
||||
and Documents section of the Tigris.org project, and modify the
|
||||
CHECKSUMS document there accordingly. Also, drop a copy of the
|
||||
archive files into the root directory of the viewvc.org website
|
||||
(unversioned).
|
||||
|
||||
15. On trunk, update the websites (both the viewvc.org/ and www/ ones)
|
||||
12. On trunk, update the websites (both the viewvc.org/ and www/ ones)
|
||||
to refer to the new release files, and copy the CHANGES for the
|
||||
new release into trunk's CHANGES file.
|
||||
|
||||
16. Edit the file 'lib/viewvc.py' again, incrementing the patch number
|
||||
assigned to the __version__ variable. Add a new empty block in
|
||||
the branch's CHANGES file. Commit your changes:
|
||||
13. Edit the file 'lib/viewvc.py' again, re-adding the "-dev" suffix
|
||||
and incrementing the patch number assigned to the __version__
|
||||
variable, and add a new empty block in the branch's CHANGES file,
|
||||
and commit:
|
||||
|
||||
svn ci -m "Begin a new release cycle."
|
||||
|
||||
17. Edit the Issue Tracker configuration options, adding a new Version
|
||||
14. Edit the Issue Tracker configuration options, adding a new Version
|
||||
for the just-released one, and a new Milestone for the next patch
|
||||
(and possibly, minor or major) release. (For the Milestone sort
|
||||
key, use a packed integer XXYYZZ: 1.0.3 == 10003, 2.11.4 == 21104.)
|
||||
|
||||
18. Send to the announce@ list a message explaining all the cool new
|
||||
features, and post similar announcements to other places interested
|
||||
in this sort of stuff, such as Freshmeat (http://www.freshmeat.net).
|
||||
15. Write an announcement explaining all the cool new features and
|
||||
post it to the announce@ list, to the project's News area, and to
|
||||
other places interested in this sort of stuff, such as Freshmeat
|
||||
(http://www.freshmeat.net).
|
||||
|
@@ -21,13 +21,13 @@
|
||||
<th style="width:6%;"></th>
|
||||
<th style="width:47%; vertical-align:top;">
|
||||
[is left.path right.path][else][left.path][end]
|
||||
revision [if-any left_view_href]<a href="[left_view_href]">[end][left.rev][if-any left_view_href]</a>[end][if-any left.author] by <em>[left.author]</em>[end],
|
||||
revision [if-any left_view_href]<a href="[left_view_href]">[end][left.rev][if-any left_view_href]</a>[end],
|
||||
[left.date]
|
||||
[if-any left.tag]<br />Tag: [left.tag][end]
|
||||
</th>
|
||||
<th style="width:47%; vertical-align:top;">
|
||||
[is left.path right.path][else][right.path][end]
|
||||
revision [if-any right_view_href]<a href="[right_view_href]">[end][right.rev][if-any right_view_href]</a>[end][if-any right.author] by <em>[right.author]</em>[end],
|
||||
revision [if-any right_view_href]<a href="[right_view_href]">[end][right.rev][if-any right_view_href]</a>[end],
|
||||
[right.date]
|
||||
[if-any right.tag]<br />Tag: [right.tag][end]
|
||||
</th>
|
||||
@@ -49,7 +49,7 @@
|
||||
[else]
|
||||
[is changes.type "add"]
|
||||
<tr>
|
||||
<td class="vc_diff_line_number" id="l[changes.line_number]">[if-any right.annotate_href]<a href="[right.annotate_href]#l[changes.line_number]">[changes.line_number]</a>[else][changes.line_number][end]</td>
|
||||
<td id="l[changes.line_number]">[if-any right.annotate_href]<a href="[right.annotate_href]#l[changes.line_number]">[changes.line_number]</a>[else][changes.line_number][end]</td>
|
||||
<td class="vc_diff_empty"> </td>
|
||||
<td class="vc_diff_add"> [changes.right]</td>
|
||||
</tr>
|
||||
@@ -64,7 +64,7 @@
|
||||
[is changes.type "change"]
|
||||
<tr>
|
||||
[if-any changes.have_right]
|
||||
<td class="vc_diff_line_number" id="l[changes.line_number]">[if-any right.annotate_href]<a href="[right.annotate_href]#l[changes.line_number]">[changes.line_number]</a>[else][changes.line_number][end]</td>
|
||||
<td id="l[changes.line_number]">[if-any right.annotate_href]<a href="[right.annotate_href]#l[changes.line_number]">[changes.line_number]</a>[else][changes.line_number][end]</td>
|
||||
[else]
|
||||
<td></td>
|
||||
[end]
|
||||
@@ -112,7 +112,7 @@
|
||||
</tr>
|
||||
[else]
|
||||
<tr>
|
||||
<td class="vc_diff_line_number" id="l[changes.line_number]">[if-any right.annotate_href]<a href="[right.annotate_href]#l[changes.line_number]">[changes.line_number]</a>[else][changes.line_number][end]</td>
|
||||
<td id="l[changes.line_number]">[if-any right.annotate_href]<a href="[right.annotate_href]#l[changes.line_number]">[changes.line_number]</a>[else][changes.line_number][end]</td>
|
||||
<td class="vc_diff_nochange"> [changes.left]</td>
|
||||
<td class="vc_diff_nochange"> [changes.right]</td>
|
||||
</tr>
|
||||
|
@@ -4,31 +4,23 @@
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 200px" class="vc_header[is sortby "file"]_sort[end]">
|
||||
[if-any sortby_file_href]<a href="[sortby_file_href]#dirlist">File</a>[else]File[end]
|
||||
<a href="[sortby_file_href]#dirlist">File
|
||||
[is sortby "file"]
|
||||
<img class="vc_sortarrow" alt="[is sortdir "down"](rev)[end]"
|
||||
width="13" height="13"
|
||||
src="[docroot]/images/[is sortdir "up"]up[else]down[end].png" />
|
||||
[end]
|
||||
</a>
|
||||
</th>
|
||||
<th style="width: 96px" class="vc_header"></th>
|
||||
[if-any sortby_rev_href]
|
||||
<th class="vc_header[is sortby "rev"]_sort[end]">
|
||||
<a href="[sortby_rev_href]#dirlist">Last Change</a>
|
||||
<a href="[sortby_rev_href]#dirlist">Last Change
|
||||
[is sortby "rev"]
|
||||
<img class="vc_sortarrow" alt="[is sortdir "down"](rev)[end]"
|
||||
width="13" height="13"
|
||||
src="[docroot]/images/[is sortdir "up"]up[else]down[end].png" />
|
||||
[end]
|
||||
[else]
|
||||
<th class="vc_header[is sortby "date"]_sort[end]">
|
||||
[if-any sortby_date_href]<a href="[sortby_date_href]#dirlist">Last Change</a>[else]Last Change[end]
|
||||
[is sortby "date"]
|
||||
<img class="vc_sortarrow" alt="[is sortdir "down"](date)[end]"
|
||||
width="13" height="13"
|
||||
src="[docroot]/images/[is sortdir "up"]up[else]down[end].png" />
|
||||
[end]
|
||||
[end]
|
||||
</a>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
@@ -4,45 +4,50 @@
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="vc_header[is sortby "file"]_sort[end]" colspan="2">
|
||||
[if-any sortby_file_href]<a href="[sortby_file_href]#dirlist">File</a>[else]File[end]
|
||||
<a href="[sortby_file_href]#dirlist">File
|
||||
[is sortby "file"]
|
||||
<img class="vc_sortarrow" alt="[is sortdir "down"](rev)[end]"
|
||||
width="13" height="13"
|
||||
src="[docroot]/images/[is sortdir "up"]up[else]down[end].png" />
|
||||
[end]
|
||||
</a>
|
||||
</th>
|
||||
<th class="vc_header[is sortby "rev"]_sort[end]">
|
||||
[if-any sortby_rev_href]<a href="[sortby_rev_href]#dirlist">Rev.</a>[else]Rev.[end]
|
||||
<a href="[sortby_rev_href]#dirlist">Rev.
|
||||
[is sortby "rev"]
|
||||
<img class="vc_sortarrow" alt="[is sortdir "down"](rev)[end]"
|
||||
width="13" height="13"
|
||||
src="[docroot]/images/[is sortdir "up"]up[else]down[end].png" />
|
||||
[end]
|
||||
</a>
|
||||
</th>
|
||||
<th class="vc_header[is sortby "date"]_sort[end]">
|
||||
[if-any sortby_date_href]<a href="[sortby_date_href]#dirlist">Age</a>[else]Age[end]
|
||||
<a href="[sortby_date_href]#dirlist">Age
|
||||
[is sortby "date"]
|
||||
<img class="vc_sortarrow" alt="[is sortdir "down"](rev)[end]"
|
||||
width="13" height="13"
|
||||
src="[docroot]/images/[is sortdir "up"]up[else]down[end].png" />
|
||||
[end]
|
||||
</a>
|
||||
</th>
|
||||
<th class="vc_header[is sortby "author"]_sort[end]">
|
||||
[if-any sortby_author_href]<a href="[sortby_author_href]#dirlist">Author</a>[else]Author[end]
|
||||
<a href="[sortby_author_href]#dirlist">Author
|
||||
[is sortby "author"]
|
||||
<img class="vc_sortarrow" alt="[is sortdir "down"](rev)[end]"
|
||||
width="13" height="13"
|
||||
src="[docroot]/images/[is sortdir "up"]up[else]down[end].png" />
|
||||
[end]
|
||||
</a>
|
||||
</th>
|
||||
[is cfg.options.show_logs "1"]
|
||||
<th class="vc_header[is sortby "log"]_sort[end]">
|
||||
[if-any sortby_log_href]<a href="[sortby_log_href]#dirlist">Last log entry</a>[else]Last log entry[end]
|
||||
<a href="[sortby_log_href]#dirlist">Last log entry
|
||||
[is sortby "log"]
|
||||
<img class="vc_sortarrow" alt="[is sortdir "down"](rev)[end]"
|
||||
width="13" height="13"
|
||||
src="[docroot]/images/[is sortdir "up"]up[else]down[end].png" />
|
||||
[end]
|
||||
</a>
|
||||
</th>
|
||||
[end]
|
||||
</tr>
|
||||
|
@@ -94,6 +94,9 @@ form { margin: 0; }
|
||||
.vc_properties {
|
||||
margin: 1em 0;
|
||||
}
|
||||
.vc_properties h2 {
|
||||
font-size: 115%;
|
||||
}
|
||||
|
||||
|
||||
/*** File Content Markup Styles ***/
|
||||
@@ -226,8 +229,6 @@ form { margin: 0; }
|
||||
font-family: sans-serif;
|
||||
font-size: smaller;
|
||||
}
|
||||
.vc_diff_line_number {
|
||||
}
|
||||
.vc_raw_diff {
|
||||
background-color: #cccccc;
|
||||
font-size: smaller;
|
||||
|
@@ -1,15 +1,5 @@
|
||||
[# ------------------------------------------------------------------------- ]
|
||||
[# CUSTOMIZE ME: To avoid displaying "binary garbage" -- the contents of ]
|
||||
[# files with non-human-readable file formats -- change the value of the ]
|
||||
[# hide_binary_garbage variable below to 1. ]
|
||||
[# ------------------------------------------------------------------------- ]
|
||||
|
||||
[define hide_binary_garbage]0[end]
|
||||
|
||||
[# ------------------------------------------------------------------------- ]
|
||||
|
||||
[# setup page definitions]
|
||||
[define page_title]Contents of /[where][end]
|
||||
[define page_title]Annotate of /[where][end]
|
||||
[define help_href][docroot]/help_rootview.html[end]
|
||||
[# end]
|
||||
|
||||
@@ -18,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] -
|
||||
([is annotation "annotated"]<a href="[view_href]"><strong>hide annotations</strong></a>[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][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]
|
||||
|
||||
@@ -53,12 +43,14 @@ Revision [if-any revision_href]<a href="[revision_href]"><strong>[rev]</strong><
|
||||
[if-any lockinfo]
|
||||
<br />Lock status: <img src="[docroot]/images/lock.png" alt="Locked" width="16" height="16" /> [lockinfo]
|
||||
[end]
|
||||
[if-any annotation]
|
||||
[is annotation "binary"]
|
||||
<br /><strong>Unable to calculate annotation data on binary file contents.</strong>
|
||||
[end]
|
||||
[is annotation "error"]
|
||||
<br /><strong>Error occurred while calculating annotation data.</strong>
|
||||
[end]
|
||||
[end]
|
||||
[is state "dead"]
|
||||
<br /><strong><em>FILE REMOVED</em></strong>
|
||||
[end]
|
||||
@@ -67,14 +59,6 @@ Revision [if-any revision_href]<a href="[revision_href]"><strong>[rev]</strong><
|
||||
[end]
|
||||
</div>
|
||||
|
||||
[if-any prefer_markup][define hide_binary_garbage]0[end][end]
|
||||
[if-any image_src_href][define hide_binary_garbage]0[end][end]
|
||||
|
||||
[is hide_binary_garbage "1"]
|
||||
<p><strong>This file's contents are not viewable.
|
||||
[if-any download_href]Please <a href="[download_href]">download</a>
|
||||
this version of the file in order to view it.[end]</strong></p>
|
||||
[else]
|
||||
|
||||
[define last_rev]0[end]
|
||||
[define rowclass]vc_row_even[end]
|
||||
@@ -117,7 +101,6 @@ Revision [if-any revision_href]<a href="[revision_href]"><strong>[rev]</strong><
|
||||
</div>
|
||||
[end]
|
||||
[end]
|
||||
[end]
|
||||
|
||||
[include "include/props.ezt"]
|
||||
[include "include/footer.ezt"]
|
||||
|
@@ -32,7 +32,7 @@
|
||||
<td>[include "pathrev_form.ezt"]</td>
|
||||
</tr>
|
||||
|
||||
[if-any search_re_action]
|
||||
[if-any search_re_form]
|
||||
<tr>
|
||||
<td>Filter files by content:</td>
|
||||
<td><form method="get" action="[search_re_action]" style="display: inline;">
|
||||
@@ -63,7 +63,7 @@
|
||||
|
||||
</table>
|
||||
|
||||
[is picklist_len "0"]
|
||||
[is cfg.options.use_pagesize "0"]
|
||||
[else]
|
||||
[is picklist_len "1"]
|
||||
[else]
|
||||
|
@@ -2,7 +2,7 @@
|
||||
[is pathtype "file"]
|
||||
<a href="[up_href]"><img src="[docroot]/images/back_small.png" class="vc_icon" alt="Parent Directory" /> Parent Directory</a>
|
||||
[if-any log_href]
|
||||
| <a href="[log_href]"><img src="[docroot]/images/log.png" class="vc_icon" alt="Revision Log" /> Revision Log</a>
|
||||
| <a href="[log_href][if-any log_href_rev]#rev[log_href_rev][end]"><img src="[docroot]/images/log.png" class="vc_icon" alt="Revision Log" /> Revision Log</a>
|
||||
[end]
|
||||
[if-any graph_href]
|
||||
| <a href="[graph_href]"><img src="[docroot]/images/cvsgraph_16x16.png" class="vc_icon" alt="View Revision Graph" /> Revision Graph</a>
|
||||
|
@@ -5,7 +5,7 @@
|
||||
<table>
|
||||
<tr>
|
||||
<td>[if-any cfg.general.address]<address><a href="mailto:[cfg.general.address]">[cfg.general.address]</a></address>[else] [end]</td>
|
||||
<td style="text-align: right;">[if-any help_href]<strong><a href="[help_href]">ViewVC Help</a></strong>[else] [end]</td>
|
||||
<td style="text-align: right;"><strong><a href="[help_href]">ViewVC Help</a></strong></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Powered by <a href="http://viewvc.tigris.org/">ViewVC [vsn]</a></td>
|
||||
|
@@ -5,7 +5,7 @@
|
||||
<head>
|
||||
<title>[if-any rootname][[][rootname]][else]ViewVC[end] [page_title]</title>
|
||||
<meta name="generator" content="ViewVC [vsn]" />
|
||||
<link rel="shortcut icon" href="[docroot]/images/favicon.ico" />
|
||||
<link rel="shortcut icon" href="[docroot]/images/favicon.ico" type="image/x-icon" />
|
||||
<link rel="stylesheet" href="[docroot]/styles.css" type="text/css" />
|
||||
[if-any rss_href]<link rel="alternate" type="application/rss+xml" title="RSS [[][rootname]][where]" href="[rss_href]" />[end]
|
||||
</head>
|
||||
|
@@ -1,4 +1,4 @@
|
||||
[is picklist_len "0"]
|
||||
[is cfg.options.use_pagesize "0"]
|
||||
[else]
|
||||
[is picklist_len "1"]
|
||||
[else]
|
||||
@@ -17,4 +17,6 @@
|
||||
</select>
|
||||
</form>
|
||||
[end]
|
||||
[end]
|
||||
[end]
|
||||
|
||||
|
||||
|
@@ -4,13 +4,13 @@
|
||||
<!-- ViewVC :: http://www.viewvc.org/ -->
|
||||
<head>
|
||||
<title>Checkin Database Query</title>
|
||||
[if-any docroot]<link rel="stylesheet" href="[docroot]/styles.css" type="text/css" />[end]
|
||||
<link rel="stylesheet" href="[docroot]/styles.css" type="text/css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
[# setup page definitions]
|
||||
[define help_href][if-any docroot][docroot]/help_query.html[end][end]
|
||||
[define help_href][docroot]/help_query.html[end]
|
||||
[# end]
|
||||
|
||||
<p>
|
||||
@@ -202,21 +202,21 @@
|
||||
</td>
|
||||
|
||||
[# uncommment, if you want a separate Description column:
|
||||
{if-index commits.files first}
|
||||
{if-index commits.files first{
|
||||
<td style="vertical-align:top;" rowspan="{commits.num_files}">
|
||||
{if-any commits.log}{commits.log}{else} {end}
|
||||
{commits.log}
|
||||
</td>
|
||||
{end}
|
||||
|
||||
(substitute brackets for the braces)
|
||||
]
|
||||
</tr>
|
||||
[# and also take the following out in the "Description column" case:]
|
||||
[# and also take the following out in the "Description column"-case:]
|
||||
[if-index commits.files last]
|
||||
<tr class="vc_row_[if-index commits even]even[else]odd[end]">
|
||||
<td> </td>
|
||||
<td colspan="5"><strong>Log:</strong><br />
|
||||
<pre class="vc_log">[if-any commits.log][commits.log][else] [end]</pre></td>
|
||||
<pre class="vc_log">[commits.log]</pre></td>
|
||||
</tr>
|
||||
[end]
|
||||
[# ---]
|
||||
|
@@ -6,7 +6,6 @@
|
||||
[include "include/header.ezt" "revision"]
|
||||
|
||||
<hr />
|
||||
|
||||
<form method="get" action="[jump_rev_action]">
|
||||
<table cellspacing="1" cellpadding="2" style="width: auto;">
|
||||
<tr align="left">
|
||||
@@ -29,11 +28,6 @@
|
||||
<td>[if-any date][date][else]<em>(unknown date)</em>[end]
|
||||
[if-any ago]<em>([ago] ago)</em>[end]</td>
|
||||
</tr>
|
||||
<tr align="left">
|
||||
<th>Changed paths:</th>
|
||||
<td><strong>[num_changes]</strong>
|
||||
[if-any more_changes](showing only [limit_changes]; <a href="[more_changes_href]">show all</a>)[end][if-any first_changes](<a href="[first_changes_href]">show only first [first_changes]</a>)[end]</td>
|
||||
</tr>
|
||||
<tr align="left">
|
||||
<th>Log Message:</th>
|
||||
<td><pre class="vc_log">[log]</pre></td>
|
||||
@@ -43,7 +37,18 @@
|
||||
|
||||
<hr />
|
||||
|
||||
<h2>Changed paths</h2>
|
||||
<p><strong>Changed paths:</strong></p>
|
||||
|
||||
[if-any more_changes]
|
||||
<div>
|
||||
Only [limit_changes] changes shown,
|
||||
<a href="[more_changes_href]">display [more_changes] more changes...</a>
|
||||
</div>
|
||||
[end]
|
||||
|
||||
[if-any first_changes]
|
||||
<div><a href="[first_changes_href]">Show only first [first_changes] changes...</div>
|
||||
[end]
|
||||
|
||||
<table cellspacing="1" cellpadding="2">
|
||||
<thead>
|
||||
@@ -70,13 +75,7 @@
|
||||
<td colspan="5">No changed paths.</td>
|
||||
</tr>
|
||||
[end]
|
||||
[if-any more_changes]
|
||||
<tr>
|
||||
<td colspan="5">[[]<a href="[more_changes_href]">...</a>]</td>
|
||||
</tr>
|
||||
[end]
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
[include "include/props.ezt"]
|
||||
[include "include/footer.ezt"]
|
||||
|
@@ -7,11 +7,11 @@
|
||||
<description>[is roottype "svn"]Subversion[else]CVS[end] commits to the[if-any where] [where] directory of the[end] [rootname] repository</description>
|
||||
|
||||
[for commits]<item>
|
||||
<title>[if-any commits.rev][commits.rev]: [end][[commits.author]] [format "xml"][commits.short_log][end]</title>
|
||||
<title>[if-any commits.rev][commits.rev]: [end][[commits.author]] [commits.short_log]</title>
|
||||
[if-any commits.rss_url]<link>[commits.rss_url]</link>[end]
|
||||
<author>[commits.author]</author>
|
||||
<pubDate>[if-any commits.rss_date][commits.rss_date][else](unknown date)[end]</pubDate>
|
||||
<description><pre>[format "xml"][format "html"][commits.log][end][end]</pre></description>
|
||||
<description><pre>[format "xml"][commits.log][end]</pre></description>
|
||||
</item>[end]
|
||||
</channel>
|
||||
</rss>
|
||||
|
@@ -17,18 +17,17 @@
|
||||
|
||||
### Validate input
|
||||
if test $# != 2 && test $# != 1; then
|
||||
echo "Usage: $0 TARGET-DIRECTORY [BRANCH]"
|
||||
echo "Usage: $0 TARGET-DIRECTORY [TAGNAME]"
|
||||
echo ""
|
||||
echo "If BRANCH (i.e. \"tags/1.1.0\" or \"branches/1.0.x\") is not provided,"
|
||||
echo "the release will be rolled from trunk."
|
||||
echo "If TAGNAME is not provided, the release will be rolled from trunk."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
TARGET=${1}
|
||||
if test $# = 1; then
|
||||
if test $# == 1; then
|
||||
ROOT=trunk
|
||||
else
|
||||
ROOT=${2}
|
||||
ROOT=tags/${2}
|
||||
fi
|
||||
|
||||
if test -e ${TARGET}; then
|
||||
@@ -37,8 +36,7 @@ if test -e ${TARGET}; then
|
||||
fi
|
||||
|
||||
### Grab an export from the Subversion repository.
|
||||
EXPORT_URL="http://viewvc.tigris.org/svn/viewvc/${ROOT}"
|
||||
echo "Exporting '${EXPORT_URL}' into '${TARGET}'"
|
||||
echo "Exporting into:" ${TARGET}
|
||||
|
||||
for PLATFORM in unix windows; do
|
||||
if test ${PLATFORM} = windows; then
|
||||
@@ -50,7 +48,7 @@ for PLATFORM in unix windows; do
|
||||
echo "Beginning build for ${PLATFORM}:"
|
||||
|
||||
echo " Exporting source code..."
|
||||
svn export --quiet ${EOL} ${EXPORT_URL} ${TARGET}
|
||||
svn export --quiet ${EOL} http://viewvc.tigris.org/svn/viewvc/${ROOT} ${TARGET}
|
||||
|
||||
### Various shifting, cleanup.
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- Mode: python -*-
|
||||
#
|
||||
# Copyright (C) 1999-2009 The ViewCVS Group. All Rights Reserved.
|
||||
# Copyright (C) 1999-2007 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 ViewVC
|
||||
@@ -49,10 +49,6 @@ CLEAN_MODE = None
|
||||
FILE_INFO_LIST = [
|
||||
("bin/cgi/viewvc.cgi", "bin/cgi/viewvc.cgi", 0755, 1, 0, 0),
|
||||
("bin/cgi/query.cgi", "bin/cgi/query.cgi", 0755, 1, 0, 0),
|
||||
("bin/wsgi/viewvc.wsgi", "bin/wsgi/viewvc.wsgi", 0755, 1, 0, 0),
|
||||
("bin/wsgi/viewvc.fcgi", "bin/wsgi/viewvc.fcgi", 0755, 1, 0, 0),
|
||||
("bin/wsgi/query.wsgi", "bin/wsgi/query.wsgi", 0755, 1, 0, 0),
|
||||
("bin/wsgi/query.fcgi", "bin/wsgi/query.fcgi", 0755, 1, 0, 0),
|
||||
("bin/mod_python/viewvc.py", "bin/mod_python/viewvc.py", 0755, 1, 0, 0),
|
||||
("bin/mod_python/query.py", "bin/mod_python/query.py", 0755, 1, 0, 0),
|
||||
("bin/mod_python/handler.py", "bin/mod_python/handler.py", 0755, 1, 0, 0),
|
||||
@@ -62,12 +58,10 @@ FILE_INFO_LIST = [
|
||||
("bin/cvsdbadmin", "bin/cvsdbadmin", 0755, 1, 0, 0),
|
||||
("bin/svndbadmin", "bin/svndbadmin", 0755, 1, 0, 0),
|
||||
("bin/make-database", "bin/make-database", 0755, 1, 0, 0),
|
||||
("conf/viewvc.conf.dist", "viewvc.conf.dist", 0644, 0, 0, 0),
|
||||
("conf/viewvc.conf.dist", "viewvc.conf", 0644, 0, 1, 0),
|
||||
("conf/cvsgraph.conf.dist", "cvsgraph.conf.dist", 0644, 0, 0, 0),
|
||||
("conf/cvsgraph.conf.dist", "cvsgraph.conf", 0644, 0, 1, 0),
|
||||
("conf/mimetypes.conf.dist", "mimetypes.conf.dist", 0644, 0, 0, 0),
|
||||
("conf/mimetypes.conf.dist", "mimetypes.conf", 0644, 0, 1, 0),
|
||||
("viewvc.conf.dist", "viewvc.conf.dist", 0644, 0, 0, 0),
|
||||
("viewvc.conf.dist", "viewvc.conf", 0644, 0, 1, 0),
|
||||
("cvsgraph.conf.dist", "cvsgraph.conf.dist", 0644, 0, 0, 0),
|
||||
("cvsgraph.conf.dist", "cvsgraph.conf", 0644, 0, 1, 0),
|
||||
]
|
||||
if sys.platform == "win32":
|
||||
FILE_INFO_LIST.extend([
|
||||
@@ -79,12 +73,11 @@ if sys.platform == "win32":
|
||||
## List of directories for installation.
|
||||
## type (source path,
|
||||
## destination path,
|
||||
## boolean -- optional item?,
|
||||
## boolean -- prompt before replacing?)
|
||||
TREE_LIST = [
|
||||
("lib", "lib", 0, 0),
|
||||
("templates", "templates", 0, 1),
|
||||
("templates-contrib", "templates-contrib", 1, 1),
|
||||
("lib", "lib", 0),
|
||||
("templates", "templates", 1),
|
||||
("templates-contrib", "templates-contrib", 1),
|
||||
]
|
||||
|
||||
|
||||
@@ -280,22 +273,18 @@ LEGEND
|
||||
py_compile.compile(destdir_path, destdir_path + "c" , dst_path)
|
||||
|
||||
|
||||
def install_tree(src_path, dst_path, is_optional, prompt_replace):
|
||||
def install_tree(src_path, dst_path, prompt_replace):
|
||||
"""Install a tree whose source is at SRC_PATH (which is relative
|
||||
to the ViewVC source directory) into the location DST_PATH (which
|
||||
is relative both to the global ROOT_DIR and DESTDIR settings). If
|
||||
PROMPT_REPLACE is set (and is not overridden by global setting
|
||||
CLEAN_MODE), prompt the user for how to deal with already existing
|
||||
files that differ from the to-be-installed version. If
|
||||
IS_OPTIONAL is set, don't fuss about a missing source item."""
|
||||
files that differ from the to-be-installed version."""
|
||||
|
||||
orig_src_path = src_path
|
||||
orig_dst_path = dst_path
|
||||
src_path = _actual_src_path(src_path)
|
||||
dst_path = os.path.join(ROOT_DIR, string.replace(dst_path, '/', os.sep))
|
||||
if not os.path.isdir(src_path):
|
||||
print " skipping %s" % (dst_path)
|
||||
return
|
||||
destdir_path = os.path.join(DESTDIR + dst_path)
|
||||
|
||||
# Get a list of items in the directory.
|
||||
@@ -315,7 +304,7 @@ def install_tree(src_path, dst_path, is_optional, prompt_replace):
|
||||
|
||||
# If the item is a subdirectory, recurse. Otherwise, install the file.
|
||||
if os.path.isdir(os.path.join(src_path, fname)):
|
||||
install_tree(orig_src_child, orig_dst_child, 0, prompt_replace)
|
||||
install_tree(orig_src_child, orig_dst_child, prompt_replace)
|
||||
else:
|
||||
set_paths = 0
|
||||
compile_it = fname[-3:] == '.py'
|
||||
|
784
viewvc.conf.dist
Normal file
784
viewvc.conf.dist
Normal file
@@ -0,0 +1,784 @@
|
||||
#---------------------------------------------------------------------------
|
||||
#
|
||||
# Configuration file for ViewVC
|
||||
#
|
||||
# Information on ViewVC is located at the following web site:
|
||||
# http://viewvc.org/
|
||||
#
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# THE FORMAT OF THIS CONFIGURATION FILE
|
||||
#
|
||||
# This file is delineated by sections, specified in [brackets]. Within
|
||||
# each section, are a number of configuration settings. These settings
|
||||
# take the form of: name = value. Values may be continued on the
|
||||
# following line by indenting the continued line.
|
||||
#
|
||||
# WARNING: Indentation *always* means continuation. Name=value lines
|
||||
# should always start in column zero.
|
||||
#
|
||||
# Comments should always start in column zero, and are identified
|
||||
# with "#".
|
||||
#
|
||||
# Certain configuration settings may have multiple values. These should
|
||||
# be separated by a comma. The settings where this is allowed are noted
|
||||
# below. Any other setting that requires special syntax is noted at that
|
||||
# setting.
|
||||
#
|
||||
#
|
||||
# SOME TERMINOLOGY USED HEREIN
|
||||
#
|
||||
# "root" - This is a CVS or Subversion repository. For Subversion, the
|
||||
# meaning is pretty clear, as the virtual, versioned directory tree
|
||||
# stored inside a Subversion repository looks nothing like the actual
|
||||
# tree visible with shell utilities that holds the repository. For
|
||||
# CVS, this is more confusing, because CVS's repository layout mimics
|
||||
# (actually, defines) the layout of the stuff housed in the repository.
|
||||
# But a CVS repository can be identified by the presence of a CVSROOT
|
||||
# subdirectory in its root directory.
|
||||
#
|
||||
# "module" - A module is a top-level subdirectory of a root, usually
|
||||
# associated with the concept of a single "project" among many housed
|
||||
# within a single repository.
|
||||
#
|
||||
#
|
||||
# BASIC VIEWVC CONFIGURATION HINTS
|
||||
#
|
||||
# While ViewVC has quite a few configuration options, you generally
|
||||
# only need to change a small subset of them to get your ViewVC
|
||||
# installation working properly. Here are some options that we
|
||||
# recommend you pay attention to. Of course, don't try to change the
|
||||
# options here -- do so in the relevant section of the configuration
|
||||
# file below.
|
||||
#
|
||||
# For correct operation, you will probably need to change the following
|
||||
# configuration variables:
|
||||
#
|
||||
# cvs_roots (for CVS)
|
||||
# svn_roots (for Subversion)
|
||||
# root_parents (for CVS or Subversion)
|
||||
# default_root
|
||||
# root_as_url_component
|
||||
# rcs_dir
|
||||
# mime_types_file
|
||||
# the many options in the [utilities] section
|
||||
#
|
||||
# It is usually desirable to change the following variables:
|
||||
#
|
||||
# address
|
||||
# forbidden
|
||||
#
|
||||
# To optimize delivery of ViewVC static files:
|
||||
#
|
||||
# docroot
|
||||
#
|
||||
# To customize the display of ViewVC for your site:
|
||||
#
|
||||
# template_dir
|
||||
# the [templates] override section
|
||||
#
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
[general]
|
||||
|
||||
#
|
||||
# This setting specifies each of the CVS roots on your system and assigns
|
||||
# names to them. Each root should be given by a "name: path" value. Multiple
|
||||
# roots should be separated by commas and can be placed on separate lines.
|
||||
#
|
||||
cvs_roots = cvs: /home/cvsroot
|
||||
|
||||
#
|
||||
# This setting specifies each of the Subversion roots (repositories)
|
||||
# on your system and assigns names to them. Each root should be given
|
||||
# by a "name: path" value. Multiple roots should be separated by
|
||||
# commas and can be placed on separate lines.
|
||||
#
|
||||
#svn_roots = svn: /home/svnrepos
|
||||
|
||||
# The 'root_parents' setting specifies a list of directories in which
|
||||
# any number of repositories may reside. Rather than force you to add
|
||||
# a new entry to 'cvs_roots' or 'svn_roots' each time you create a new
|
||||
# repository, ViewVC rewards you for organising all your repositories
|
||||
# under a few parent directories by allowing you to simply specifiy
|
||||
# just those parent directories. ViewVC will then notice each
|
||||
# repository in that directory as a new root whose name is the
|
||||
# subdirectory of the parent path in which that repository lives.
|
||||
#
|
||||
# You can specify multiple parent paths separated by commas or new lines.
|
||||
#
|
||||
# Caution: these names can, of course, clash with names you have
|
||||
# defined in your cvs_roots or svn_roots configuration items. If this
|
||||
# occurs, you can either rename the offending repository on disk, or
|
||||
# grant new names to the clashing item in cvs_roots or svn_roots.
|
||||
# Each parent path is processed sequentially, so repositories under
|
||||
# later parent paths may override earlier ones.
|
||||
#
|
||||
#root_parents = /home/svn-repositories : svn,
|
||||
# /home/cvs-repositories : cvs
|
||||
|
||||
# This is the name of the default root. Valid names include those
|
||||
# explicitly listed in the cvs_roots and svn_roots configuration
|
||||
# options, as well as those implicitly indicated by virtue of being
|
||||
# the basenames of repositories found in the root_parents option
|
||||
# locations.
|
||||
#
|
||||
# Note: This setting is ignored when root_as_url_component is enabled.
|
||||
default_root = cvs
|
||||
|
||||
#
|
||||
# This is a pathname to a MIME types file to help viewvc to guess the
|
||||
# correct MIME type on checkout. If you are having problems with the
|
||||
# default guess on the MIME type, then uncomment this option and point
|
||||
# it at a MIME type file.
|
||||
#
|
||||
# For example, you can use the mime.types provided by Apache here:
|
||||
#mime_types_file = /usr/local/apache2/conf/mime.types
|
||||
|
||||
# The address of the local repository maintainer. (This option is
|
||||
# provided only as a convenience for ViewVC installations which are
|
||||
# using the default template set, where the value of this option will
|
||||
# be displayed in the footer of every ViewVC page.)
|
||||
address =
|
||||
|
||||
#
|
||||
# This option provides a mechanism for custom key/value pairs to be
|
||||
# available to templates. These are stored in key/value (KV) files.
|
||||
#
|
||||
# The paths of the KV files are listed here, specified either as
|
||||
# absolute paths or relative to this configuration file. The files
|
||||
# use the same format as this configuration file, containing one or
|
||||
# more user-defined sections, and user-defined options in those
|
||||
# sections. ViewVC makes these options available to template authors
|
||||
# as:
|
||||
#
|
||||
# kv.SECTION.OPTION
|
||||
#
|
||||
# Note that an option name can be dotted. For example:
|
||||
#
|
||||
# [my_images]
|
||||
# logos.small = /images/small-logo.png
|
||||
# logos.big = /images/big-logo.png
|
||||
#
|
||||
# Templates can use these with a directive like: [kv.my_images.logos.small]
|
||||
#
|
||||
# Note that section names which are common to multiple KV files will
|
||||
# be merged. If two files have a [my_images] section, then the
|
||||
# options in those two like-named sections will be merged together.
|
||||
# If two files have the same option name in a section, then one will
|
||||
# overwrite the other (and which one "wins" is unspecified).
|
||||
#
|
||||
# To further categorize the KV files, and how the values are provided to
|
||||
# the templates, a KV file name may be annotated with an additional level
|
||||
# of dotted naming. For example:
|
||||
#
|
||||
# kv_files = [asf]kv/images.conf
|
||||
#
|
||||
# Assuming the same section as above, the template would refer to an image
|
||||
# using [kv.asf.my_images.logos.small]
|
||||
#
|
||||
# Lastly, it is possible to use %lang% in the filenames to specify a
|
||||
# substitution of the selected language-tag.
|
||||
#
|
||||
# Example:
|
||||
# kv_files = kv/file1.conf, kv/file2.conf, [i18n]kv/%lang%_data.conf
|
||||
#
|
||||
kv_files =
|
||||
|
||||
#
|
||||
# This option is a comma-separated list of language-tag values
|
||||
# available to ViewVC. The first language-tag listed is the default
|
||||
# language, and will be used if an Accept-Language header is not
|
||||
# present in the request, or none of the user's requested languages
|
||||
# are available. If there are ties on the selection of a language,
|
||||
# then the first to appear in the list is chosen.
|
||||
#
|
||||
# Some examples:
|
||||
#
|
||||
# languages = en-us, de
|
||||
# languages = en-us, en-gb, de
|
||||
# languages = de, fr, en-us
|
||||
#
|
||||
languages = en-us
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
[utilities]
|
||||
|
||||
# ViewVC uses (sometimes optionally) various third-party programs to do some
|
||||
# of the heavy lifting. Generally, it will attempt to execute those utility
|
||||
# programs in such a way that if they are found in ViewVC's executable
|
||||
# search path ($PATH, %PATH%, etc.) all is well. But sometimes these tools
|
||||
# aren't installed in the executable search path, so here's where you can
|
||||
# tell ViewVC where to find them.
|
||||
#
|
||||
# NOTE: Options with a "_dir" suffix are for configuring the directories
|
||||
# in which certain programs live; otherwise, the option value should
|
||||
# point to the actual program.
|
||||
|
||||
# RCS utilities, used for viewing CVS repositories
|
||||
rcs_dir =
|
||||
# rcs_dir = /usr/bin/
|
||||
|
||||
# ViewVC can use CVSNT (www.cvsnt.org) instead of the RCS utilities to
|
||||
# retrieve information from CVS repositories. To enable use of CVSNT,
|
||||
# set the "cvsnt" value to the path of the CVSNT executable. (If CVSNT
|
||||
# is on the standard path, you can also set it to the name of the
|
||||
# CVSNT executable). By default "cvsnt" is set to "cvs" on Windows and
|
||||
# is not set on other platforms.
|
||||
cvsnt =
|
||||
# cvsnt =
|
||||
# cvsnt = cvs
|
||||
# cvsnt = K:\Program Files\cvsnt\cvs.exe
|
||||
# cvsnt = = /usr/bin/cvs
|
||||
|
||||
# Subversion command-line client, used for viewing Subversion repositories
|
||||
svn =
|
||||
# svn = /usr/bin/svn
|
||||
|
||||
# GNU diff, used for showing file version differences
|
||||
diff =
|
||||
# diff = /usr/bin/diff
|
||||
|
||||
# CvsGraph, a graphical CVS version graph generator (see options.use_cvsgraph)
|
||||
cvsgraph =
|
||||
# cvsgraph = /usr/local/bin/cvsgraph
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
[options]
|
||||
|
||||
# root_as_url_component: Interpret the first path component in the URL
|
||||
# after the script location as the root to use. This is an
|
||||
# alternative to using the "root=" query key. If ViewVC is configured
|
||||
# with multiple repositories, this results in more natural looking
|
||||
# ViewVC URLs.
|
||||
# Note: Enabling this option will break backwards compatibility with
|
||||
# any old ViewCVS URL which doesn't have an explicit "root" parameter.
|
||||
root_as_url_component = 1
|
||||
|
||||
# checkout_magic: Use checkout links with magic /*checkout*/ prefixes so
|
||||
# checked out HTML pages can have working links to other repository files
|
||||
# Note: This option is DEPRECATED and should not be used in new ViewVC
|
||||
# installations. Setting "default_file_view = co" achieves the same effect
|
||||
checkout_magic = 0
|
||||
|
||||
# allowed_views: List the ViewVC views which are enabled. Views not
|
||||
# in this comma-delited list will not be served (or, will return an
|
||||
# error on attempted access).
|
||||
# Possible values: "tar", "annotate", "co", "markup", "roots"
|
||||
allowed_views = markup, annotate, roots
|
||||
|
||||
# authorizer: The name of the ViewVC authorizer plugin to use when
|
||||
# authorizing access to repository contents. This value must be the
|
||||
# name of a Python module addressable as vcauth.MODULENAME (most
|
||||
# easily accomplished by placing it in ViewVC's lib/vcauth/ directory)
|
||||
# and which implements a ViewVCAuthorizer class (as a subclass of
|
||||
# vcauth.GenericViewVCAuthorizer). You can provide custom parameters
|
||||
# to the authorizer module by defining configuration sections named
|
||||
# authz-MODULENAME and adding the parameter keys and values there.
|
||||
#
|
||||
# ViewVC provides the following modules:
|
||||
# svnauthz - based on Subversion authz files
|
||||
# forbidden - simple path glob matches against top-level root directories
|
||||
# forbiddenre - root and path matches against regular expressions
|
||||
#
|
||||
# NOTE: Only one authorizer may be in use for a given ViewVC request.
|
||||
# It doesn't matter if you configure the parameters of multiple
|
||||
# authorizer plugins -- only the authorizer whose name is configured
|
||||
# here (or effectively configured here via vhost configuration) will
|
||||
# be activated.
|
||||
authorizer = forbidden
|
||||
|
||||
# hide_cvsroot: Don't show the CVSROOT directory
|
||||
# 1 Hide CVSROOT directory
|
||||
# 0 Show CVSROOT directory
|
||||
# NOTE: Someday this option may be removed in favor of letting
|
||||
# individual authorizer plugin hide the CVSROOT.
|
||||
hide_cvsroot = 1
|
||||
|
||||
# mangle_email_addresses: Mangle email addresses in marked-up output.
|
||||
# There are various levels of mangling available:
|
||||
# 0 - No mangling; markup un-mangled email addresses as hyperlinks
|
||||
# 1 - Obfuscation (using entity encoding); no hyperlinking
|
||||
# 2 - Data-dropping address truncation; no hyperlinking
|
||||
# Note: this will not effect the display of versioned file contents, only
|
||||
# addresses that appear in version control metadata (e.g. log messages).
|
||||
mangle_email_addresses = 0
|
||||
|
||||
# default_file_view: "log", "co", or "markup"
|
||||
# Controls whether the default view for file URLs is a checkout view or
|
||||
# a log view. "log" is the default for backwards compatibility with old
|
||||
# ViewCVS URLs, but "co" has the advantage that it allows ViewVC to serve
|
||||
# static HTML pages directly from a repository with working links
|
||||
# to other repository files
|
||||
# Note: Changing this option may break compatibility with existing
|
||||
# bookmarked URLs.
|
||||
# Also note: If you choose one of the "co" or "markup" views, be sure
|
||||
# to enable it (via the allowed_views option)
|
||||
default_file_view = log
|
||||
|
||||
# http_expiration_time: Expiration time (in seconds) for cacheable
|
||||
# pages served by ViewVC. Note that in most cases, a cache aware
|
||||
# client will only revalidate the page after it expires (using the
|
||||
# If-Modified-Since and/or If-None-Match headers) and that browsers
|
||||
# will also revalidate the page when the reload button is pressed.
|
||||
# Set to 0 to disable the transmission of these caching headers.
|
||||
http_expiration_time = 600
|
||||
|
||||
# generate_etags: Generate Etag headers for relevant pages to assist
|
||||
# in browser caching.
|
||||
# 1 Generate Etags
|
||||
# 0 Don't generate Etags
|
||||
generate_etags = 1
|
||||
|
||||
# svn_config_dir: Path of the Subversion runtime configuration
|
||||
# directory ViewVC should consult for various things, including cached
|
||||
# remote authentication credentials. If unset, Subversion will use
|
||||
# the default location(s) ($HOME/.subversion, etc.)
|
||||
svn_config_dir =
|
||||
|
||||
# use the rcsparse Python module to retrieve CVS repository
|
||||
# information instead of invoking rcs utilities [EXPERIMENTAL]
|
||||
use_rcsparse = 0
|
||||
|
||||
# sort_by: File sort order
|
||||
# file Sort by filename
|
||||
# rev Sort by revision number
|
||||
# date Sort by commit date
|
||||
# author Sort by author
|
||||
# log Sort by log message
|
||||
sort_by = file
|
||||
|
||||
# sort_group_dirs: Group directories when sorting
|
||||
# 1 Group directories together
|
||||
# 0 No grouping -- sort directories as any other item would be sorted
|
||||
sort_group_dirs = 1
|
||||
|
||||
# hide_attic: Hide or show the contents of the Attic subdirectory
|
||||
# 1 Hide dead files inside Attic subdir
|
||||
# 0 Show the files which are inside the Attic subdir
|
||||
hide_attic = 1
|
||||
|
||||
# hide_errorful_entries: Hide or show errorful directory entries
|
||||
# (perhaps due to not being readable, or some other rlog parsing
|
||||
# error, etc.)
|
||||
# 1 Hide errorful entries from the directory display
|
||||
# 0 Show errorful entries (with their errors) in the directory display
|
||||
hide_errorful_entries = 0
|
||||
|
||||
# log_sort: Sort order for log messages
|
||||
# date Sort revisions by date
|
||||
# rev Sort revision by revision number
|
||||
# none Use the version control system's ordering
|
||||
log_sort = date
|
||||
|
||||
# diff_format: Default diff format
|
||||
# h Human readable
|
||||
# u Unified diff
|
||||
# c Context diff
|
||||
# s Side by side
|
||||
# l Long human readable (more context)
|
||||
# f Full human readable (entire file)
|
||||
diff_format = h
|
||||
|
||||
# hr_breakable: Diff view line breaks
|
||||
# 1 lines break at spaces
|
||||
# 0 no line breaking
|
||||
# Or, use a positive integer > 1 to cut lines after that many characters
|
||||
hr_breakable = 1
|
||||
|
||||
# give out function names in human readable diffs
|
||||
# this just makes sense if we have C-files, otherwise
|
||||
# diff's heuristic doesn't work well ..
|
||||
# ( '-p' option to diff)
|
||||
hr_funout = 0
|
||||
|
||||
# ignore whitespaces for human readable diffs
|
||||
# (indendation and stuff ..)
|
||||
# ( '-w' option to diff)
|
||||
hr_ignore_white = 0
|
||||
|
||||
# ignore diffs which are caused by
|
||||
# keyword-substitution like $Id - Stuff
|
||||
# ( '-kk' option to rcsdiff)
|
||||
hr_ignore_keyword_subst = 1
|
||||
|
||||
# Enable highlighting of intraline changes in human readable diffs
|
||||
# this feature is experimental and currently requires python 2.4
|
||||
hr_intraline = 0
|
||||
|
||||
# allow compression with gzip of output if the Browser accepts it
|
||||
# (HTTP_ACCEPT_ENCODING contains "gzip")
|
||||
#allow_compress = 1
|
||||
|
||||
# The directory which contains the EZT templates used by ViewVC to
|
||||
# customize the display of the various output views. ViewVC looks in
|
||||
# this directory for files with names that match the name of the view
|
||||
# ("log", "directory", etc.) plus the ".ezt" extension. If specified
|
||||
# as a relative path, it is relative to the directory where this config
|
||||
# file resides; absolute paths may be used as well.
|
||||
#
|
||||
# If %lang% occurs in the pathname, then the selected language will be
|
||||
# substituted.
|
||||
#
|
||||
# See also the [templates] configuration section, where you can
|
||||
# override templates on a per-view basis.
|
||||
#
|
||||
template_dir = templates
|
||||
|
||||
# Web path to a directory that contains ViewVC static files
|
||||
# (stylesheets, images, etc.) If set, static files will get
|
||||
# downloaded directory from this location. If unset, static files
|
||||
# will be served by the ViewVC script (at a likely performance
|
||||
# penalty, and from the "docroot" subdirectory of the directory
|
||||
# specified by the "template_dir" option).
|
||||
#docroot = /docroot
|
||||
|
||||
# Show last changelog message for CVS subdirectories
|
||||
# NOTE: The current implementation makes many assumptions and may show
|
||||
# the incorrect file at some times. The main assumption is that the
|
||||
# last modified file has the newest filedate. But some CVS operations
|
||||
# touches the file without even when a new version is not checked in,
|
||||
# and TAG based browsing essentially puts this out of order, unless
|
||||
# the last checkin was on the same tag as you are viewing. Enable
|
||||
# this if you like the feature, but don't rely on correct results.
|
||||
#
|
||||
# ** WARNING: Enabling this will currently leak unauthorized path names **
|
||||
show_subdir_lastmod = 0
|
||||
|
||||
# Show the most recent log entry in directory listings.
|
||||
show_logs = 1
|
||||
|
||||
# Show log when viewing file contents
|
||||
show_log_in_markup = 1
|
||||
|
||||
# Cross filesystem copies when traversing Subversion file revision histories.
|
||||
cross_copies = 1
|
||||
|
||||
# Display dates as UTC or in local time zone
|
||||
use_localtime = 0
|
||||
#use_localtime = 1
|
||||
|
||||
### CONFIGURATION DEFAULTS ###
|
||||
###
|
||||
### Defaults for configuration variables that shouldn't need
|
||||
### to be configured..
|
||||
|
||||
# the length to which the most recent log entry should be truncated when
|
||||
# shown in the directory view
|
||||
short_log_len = 80
|
||||
|
||||
# should we colorize known file content syntaxes? (requires Pygments module)
|
||||
enable_syntax_coloration = 1
|
||||
|
||||
# Use CvsGraph. See http://www.akhphd.au.dk/~bertho/cvsgraph/ for
|
||||
# documentation and download.
|
||||
use_cvsgraph = 0
|
||||
#use_cvsgraph = 1
|
||||
|
||||
# Location of the customized cvsgraph configuration file.
|
||||
cvsgraph_conf = cvsgraph.conf
|
||||
|
||||
#
|
||||
# Set to enable regular expression search of all files in a directory
|
||||
#
|
||||
# WARNING:
|
||||
#
|
||||
# Enabling this option can consume HUGE amounts of server time. A
|
||||
# "checkout" must be performed on *each* file in a directory, and
|
||||
# the result needs to be searched for a match against the regular
|
||||
# expression.
|
||||
#
|
||||
#
|
||||
# SECURITY WARNING: Denial Of Service
|
||||
#
|
||||
# Since a user can enter the regular expression, it is possible for
|
||||
# them to enter an expression with many alternatives and a lot of
|
||||
# backtracking. Executing that search over thousands of lines over
|
||||
# dozens of files can easily tie up a server for a long period of
|
||||
# time.
|
||||
#
|
||||
# This option should only be used on sites with trusted users. It is
|
||||
# highly inadvisable to use this on a public site.
|
||||
#
|
||||
use_re_search = 0
|
||||
# use_re_search = 1
|
||||
|
||||
#
|
||||
# Split directories and logs into pages.
|
||||
# Allows ViewVC to present discrete pages to the users instead of the
|
||||
# entire log or directory.
|
||||
# Set use_pagesize to the number of entries you want displayed on a page.
|
||||
#
|
||||
use_pagesize = 0
|
||||
# use_pagesize = 20
|
||||
|
||||
# Limit number of changed paths shown per commit in the Subversion revision
|
||||
# view and in query results. This is not a hard limit (the UI provides
|
||||
# options to show all changed paths), but it prevents ViewVC from generating
|
||||
# enormous and hard to read pages by default when they happen to contain
|
||||
# import or merge commits affecting hundreds or thousands of files.
|
||||
# Set to 0 to disable the limit.
|
||||
limit_changes = 100
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
[templates]
|
||||
|
||||
# You can override the templates used by various ViewVC views in this
|
||||
# section. By default, ViewVC will look for templates in the
|
||||
# directory specified by the "template_dir" configuration option (see
|
||||
# the documentation for that option for details). But if you want to
|
||||
# use a different template for a particular view, simply uncomment the
|
||||
# appropriate option below and specify the currect location of the EZT
|
||||
# template file you wish to use for that view.
|
||||
#
|
||||
# Templates are specified relative to the configured template
|
||||
# directory (see the "template_dir" option), but absolute paths may
|
||||
# also be used as well.
|
||||
#
|
||||
# If %lang% occurs in the pathname, then the selected language will be
|
||||
# substituted.
|
||||
#
|
||||
# Note: the selected language is defined by the "languages" item in the
|
||||
# [general] section, and based on the request's Accept-Language
|
||||
# header.
|
||||
#
|
||||
#diff = diff.ezt
|
||||
#directory = directory.ezt
|
||||
### an alternative directory view
|
||||
#directory = dir_new.ezt
|
||||
#error = error.ezt
|
||||
#file = file.ezt
|
||||
#graph = graph.ezt
|
||||
#log = log.ezt
|
||||
### a table-based alternative log view
|
||||
#log = log_table.ezt
|
||||
#query = query.ezt
|
||||
#query_form = query_form.ezt
|
||||
#query_results = query_results.ezt
|
||||
#revision = revision.ezt
|
||||
#roots = roots.ezt
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
[cvsdb]
|
||||
|
||||
# Set to 1 to enable the database integration feature, 0 otherwise.
|
||||
enabled = 0
|
||||
|
||||
# Database hostname and port.
|
||||
#host = localhost
|
||||
#port = 3306
|
||||
|
||||
# ViewVC database name.
|
||||
#database_name = ViewVC
|
||||
|
||||
# Username and password of user with read/write privileges to the ViewVC
|
||||
# database.
|
||||
#user =
|
||||
#passwd =
|
||||
|
||||
# Username and password of user with read privileges to the ViewVC
|
||||
# database.
|
||||
#readonly_user =
|
||||
#readonly_passwd =
|
||||
|
||||
# Limit the number of rows returned by a given query to this number.
|
||||
#row_limit = 1000
|
||||
|
||||
# Limit the number of rows returned by a given query made as part an
|
||||
# RSS feed request to this number. (Keeping in mind that RSS readers
|
||||
# tend to poll regularly for new data, you might want to keep this set
|
||||
# to a conservative number.)
|
||||
#rss_row_limit = 100
|
||||
|
||||
# Check if the repository is found in the database before showing
|
||||
# the query link and RSS feeds. Set to 1 to enable check.
|
||||
#
|
||||
# WARNING: Enabling this check adds the cost of a database connection
|
||||
# and query to most ViewVC requests. If all your roots are represented
|
||||
# in the commits database, or if you don't care about the creation of
|
||||
# RSS and query links that might lead ultimately to error pages for
|
||||
# certain of your roots, or if you simply don't want to add this extra
|
||||
# cost to your ViewVC requests, leave this disabled.
|
||||
#check_database_for_root = 0
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
[vhosts]
|
||||
|
||||
# Virtual hosts are individual logical servers accessible via
|
||||
# different hostnames, but which are all really the same physical
|
||||
# computer. For example, you might have your web server configured to
|
||||
# accept incoming traffic for both http://www.yourdomain.com/ and
|
||||
# http://viewvc.yourdomain.com/. Users pointing their web browsers at
|
||||
# each of those two URLs might see entirely different content via one
|
||||
# URL versus the other, but all that content actually lives on the
|
||||
# same computer, is served up via the same web server, and so
|
||||
# on. It just *looks* like its coming from multiple servers.
|
||||
#
|
||||
# ViewVC allows you to customize its configuration options for
|
||||
# individual virtual hosts. You might, for example, wish to expose
|
||||
# all of your Subversion repositories at http://svn.yourdomain.com/viewvc/
|
||||
# and all your CVS ones at http://cvs.yourdomain.com/viewvc/, with no
|
||||
# cross-exposure. Using ViewVC's virtual host (vhost) configuration
|
||||
# support, you can do this. Simply create two vhost configurations
|
||||
# (one for each of your hostnames), then configure the cvs_roots
|
||||
# option only for the vhost associated with cvs.yourdomain.com, and
|
||||
# configure the svn_roots option only for the vhost associated with
|
||||
# svn.yourdomain.com.
|
||||
#
|
||||
# This section is a freeform configuration section, where you create
|
||||
# both the option names and their values. The names of the options
|
||||
# are then treated as canonical names of virtual hosts, and their
|
||||
# values are defined to be comma-delimited lists of hostname globs
|
||||
# against which incoming ViewVC requests will be matched to figure out
|
||||
# which vhost they apply to.
|
||||
#
|
||||
# After you've named and defined your vhosts, you may then create new
|
||||
# configuration sections whose names are of the form
|
||||
# vhost-VHOSTNAME/CONFIGSECTION. VHOSTNAME here is the canonical name
|
||||
# of one of the virtual hosts you defined under the [vhosts] section.
|
||||
# Inside those configuration sections, you override the standard
|
||||
# ViewVC options typically found in the base configuration section
|
||||
# named CONFIGSECTION ("general", "option", etc.)
|
||||
#
|
||||
# Here is an example:
|
||||
#
|
||||
# [vhosts]
|
||||
# libs = libs.yourdomain.*, *.yourlibs.*
|
||||
# gui = guiproject.yourdomain.*
|
||||
#
|
||||
# [vhost-libs/general]
|
||||
# cvs_roots =
|
||||
# svn_roots = svnroot: /var/svn/libs-repos
|
||||
# default_root = svnroot
|
||||
#
|
||||
# [vhost-libs/options]
|
||||
# show_logs = 1
|
||||
#
|
||||
# [vhost-gui/general]
|
||||
# cvs_roots = cvsroot: /var/cvs/guiproject
|
||||
# svn_roots =
|
||||
# default_root = cvsroot
|
||||
#
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# ViewVC recognizes per-root configuration overrides, too. To
|
||||
# override the value of a configuration parameter only for a single
|
||||
# root, create a configuration section whose names is of the form
|
||||
# root-ROOTNAME/CONFIGSECTION. ROOTNAME here is the name of the root
|
||||
# as defined explicitly in cvs_roots or svn_roots or implicitly as the
|
||||
# basename of a root path in root_parents. Options found in this new
|
||||
# configuration section override for this one root the corresponding
|
||||
# options found in the base configuration section CONFIGSECTION
|
||||
# ("options", "authz-*", etc.)
|
||||
#
|
||||
# Here is an example showing how to enable Subversion authz-based
|
||||
# authorization for only the single root named "svnroot":
|
||||
#
|
||||
# [root-svnroot/options]
|
||||
# authorizer = svnauthz
|
||||
#
|
||||
# [root-svnroot/authz-svnauthz]
|
||||
# authzfile = /path/to/authzfile
|
||||
#
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
[authz-forbidden]
|
||||
|
||||
# The "forbidden" authorizer forbids access to repository modules,
|
||||
# defined to be top-level subdirectories in a repository. You can use
|
||||
# a simple list of modules, or something more complex:
|
||||
#
|
||||
# *) The "!" can be used before a module to explicitly state that it
|
||||
# is NOT forbidden. Whenever this form is seen, then all modules will
|
||||
# be forbidden unless one of the "!" modules match.
|
||||
#
|
||||
# *) Shell-style "glob" expressions may be used. "*" will match any
|
||||
# sequence of zero or more characters, "?" will match any single
|
||||
# character, "[seq]" will match any character in seq, and "[!seq]"
|
||||
# will match any character not in seq.
|
||||
#
|
||||
# *) Tests are performed in sequence. The first match will terminate the
|
||||
# testing. This allows for more complex allow/deny patterns.
|
||||
#
|
||||
# Tests are case-sensitive.
|
||||
#
|
||||
# NOTE: Again, this is for the hiding of modules within repositories, *not*
|
||||
# for the hiding of repositories (roots) themselves.
|
||||
#
|
||||
# Some examples:
|
||||
#
|
||||
# Disallow "example" but allow all others:
|
||||
# forbidden = example
|
||||
#
|
||||
# Disallow "example1" and "example2" but allow all others:
|
||||
# forbidden = example1, example2
|
||||
#
|
||||
# Allow *only* "example1" and "example2":
|
||||
# forbidden = !example1, !example2
|
||||
#
|
||||
# Forbid modules starting with "x":
|
||||
# forbidden = x*
|
||||
#
|
||||
# Allow modules starting with "x" but no others:
|
||||
# forbidden = !x*
|
||||
#
|
||||
# Allow "xml", forbid other modules starting with "x", and allow the rest:
|
||||
# forbidden = !xml, x*, !*
|
||||
#
|
||||
forbidden =
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
[authz-forbiddenre]
|
||||
|
||||
# The "forbiddenre" authorizer forbids access to repositories and
|
||||
# repository paths by comparing a list of regular expressions
|
||||
# (separated by commas) against paths consisting of the repository (or
|
||||
# root) name plus the path of the versioned file or directory to be
|
||||
# tested. For example, to see if the user is authorized to see the
|
||||
# path "/trunk/www/index.html" in the repository whose root name is
|
||||
# "svnrepos", this authorizer will check the path
|
||||
# "svnrepos/trunk/www/index.html" against the list of forbidden
|
||||
# regular expressions. Directory paths will be terminated by a forward
|
||||
# slash.
|
||||
#
|
||||
# Like the "forbidden" authorizer...
|
||||
#
|
||||
# *) The "!" can be used before a module to explicitly state that it
|
||||
# is NOT forbidden. Whenever this form is seen, then all modules will
|
||||
# be forbidden unless one of the "!" modules match.
|
||||
#
|
||||
# *) Tests are performed in sequence. The first match will terminate the
|
||||
# testing. This allows for more complex allow/deny patterns.
|
||||
#
|
||||
# Unlike the "forbidden" authorizer, you can can use this to hide roots, too.
|
||||
#
|
||||
# Some examples:
|
||||
#
|
||||
# Disallow files named "PRIVATE", but allow all others:
|
||||
# forbiddenre = /PRIVATE$
|
||||
#
|
||||
# Disallow the "hidden" repository, allowing all others:
|
||||
# forbiddenre = ^hidden(/|$)
|
||||
#
|
||||
# Allow only the "example1" and "example2" roots and the paths inside them,
|
||||
# disallowing all others (which can be done in multiple ways):
|
||||
# forbiddenre = !^example1(/|$), !^example2(/|$)/
|
||||
# forbiddenre = !^example[12](/|$)
|
||||
#
|
||||
# Only allow visibility of HTML files and the directories that hold them:
|
||||
# forbiddenre = !^([^/]+|.*(/|\.html))$
|
||||
#
|
||||
forbiddenre =
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
[authz-svnauthz]
|
||||
|
||||
# The "svnauthz" authorizer uses a Subversion authz configuration file
|
||||
# to determine access to repository paths. This option specifies the
|
||||
# location of that file using an absolute path.
|
||||
#
|
||||
authzfile =
|
||||
|
||||
#---------------------------------------------------------------------------
|
9
viewvc.org/.htaccess
Normal file
9
viewvc.org/.htaccess
Normal file
@@ -0,0 +1,9 @@
|
||||
# Old documents.
|
||||
RedirectPermanent /upgrading.html http://viewvc.tigris.org/nonav/source/browse/*checkout*/viewvc/trunk/docs/upgrading-howto.html
|
||||
RedirectPermanent /template-authoring-guide.html http://viewvc.tigris.org/nonav/source/browse/*checkout*/viewvc/trunk/docs/template-authoring-guide.html
|
||||
RedirectPermanent /url-reference.html http://viewvc.tigris.org/nonav/source/browse/*checkout*/viewvc/trunk/docs/url-reference.html
|
||||
|
||||
# The license-1.html file.
|
||||
RedirectPermanent /license-1.html http://viewvc.tigris.org/nonav/source/browse/*checkout*/viewvc/trunk/LICENSE.html
|
||||
|
||||
|
93
viewvc.org/contact.html
Normal file
93
viewvc.org/contact.html
Normal file
@@ -0,0 +1,93 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>ViewVC: Contact</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||
<link rel="stylesheet" type="text/css" href="./styles.css"/>
|
||||
<link rel="shortcut icon" href="./favicon.ico" type="image/x-icon" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="title">
|
||||
<a href="http://www.viewvc.org/"><img
|
||||
src="./images/title.jpg" alt="ViewVC: Repository Browsing"/></a>
|
||||
</div>
|
||||
|
||||
<div id="menu">
|
||||
<p><a href="./index.html">Home</a> |
|
||||
<a href="http://viewvc.tigris.org/">Project Page</a> |
|
||||
<a href="./download.html">Download</a> |
|
||||
<a href="./contributing.html">Contributing</a> |
|
||||
<a href="./faq.html">FAQ</a> |
|
||||
<a href="http://viewvc.tigris.org/nonav/source/browse/*checkout*/viewvc/trunk/LICENSE.html">License</a> |
|
||||
<a href="./contact.html">Contact</a> |
|
||||
<a href="./who.html">About</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<table id="pagetable">
|
||||
<tr>
|
||||
<td id="pagecolumn1">
|
||||
|
||||
<h4>On this page:</h4>
|
||||
|
||||
<ul id="bookmarks">
|
||||
<li><a href="#sec-contacting-us">Contacting Us</a></li>
|
||||
</ul>
|
||||
|
||||
<p><a href="http://validator.w3.org/check?uri=referer"><img
|
||||
src="http://www.w3.org/Icons/valid-xhtml10"
|
||||
alt="Valid XHTML 1.0 Strict" height="31" width="88" /></a>
|
||||
</p>
|
||||
|
||||
</td>
|
||||
<td id="pagecolumn2">
|
||||
|
||||
<div class="section">
|
||||
|
||||
<h2 id="sec-contacting-us">Contacting Us</h2>
|
||||
|
||||
<div class="section-body">
|
||||
|
||||
<p>ViewVC is an <a href="http://www.opensource.org/">Open Source</a>
|
||||
project, and all <a href="./contributing.html">contributions</a>
|
||||
are welcome. Please send any comments, questions, or suggestions
|
||||
to the <a
|
||||
href="mailto:users@viewvc.tigris.org">ViewVC
|
||||
users mailing list</a>. There is also a <a
|
||||
href="mailto:dev@viewvc.tigris.org">mailing
|
||||
list specifically for ViewVC developers</a>. You can subscribe to
|
||||
these lists (and other project lists), as well view the list
|
||||
archives, <a
|
||||
href="http://viewvc.tigris.org/servlets/ProjectMailingListList"
|
||||
>here</a>. If you are having problems with ViewVC, consider
|
||||
checking our <a href="./faq.html">Frequently Asked Questions</a>
|
||||
page and list of <a
|
||||
href="http://viewvc.tigris.org/issues/buglist.cgi?component=viewvc&issue_status=UNCONFIRMED&issue_status=NEW&issue_status=STARTED&issue_status=REOPENED"
|
||||
>open issues</a> before mail our users@ list — perhaps the
|
||||
information you need is already available in one of those
|
||||
places.</p>
|
||||
|
||||
<p>If you prefer interaction that's a little more real-time, use your
|
||||
favorite IRC client to pop into <tt><a
|
||||
href="irc://irc.freenode.net/viewvc">#viewvc</a></tt> on
|
||||
irc.freenode.net.</p>
|
||||
|
||||
<p>So, to summarize:</p>
|
||||
|
||||
<ul>
|
||||
<li>To discuss ViewVC installation, configuration, and behavior: users@viewvc.tigris.org</li>
|
||||
<li>To discuss the development of ViewVC itself or submit patches: dev@viewvc.tigris.org</li>
|
||||
<li>To discussion anything ViewVC-related in real time: irc.freenode.net, #viewvc</li>
|
||||
</ul>
|
||||
|
||||
</div> <!-- section-body -->
|
||||
</div> <!-- section -->
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
241
viewvc.org/contributing.html
Normal file
241
viewvc.org/contributing.html
Normal file
@@ -0,0 +1,241 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>ViewVC: Contributing</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||
<link rel="stylesheet" type="text/css" href="./styles.css"/>
|
||||
<link rel="shortcut icon" href="./favicon.ico" type="image/x-icon" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="title">
|
||||
<a href="http://www.viewvc.org/"><img
|
||||
src="./images/title.jpg" alt="ViewVC: Repository Browsing"/></a>
|
||||
</div>
|
||||
|
||||
<div id="menu">
|
||||
<p><a href="./index.html">Home</a> |
|
||||
<a href="http://viewvc.tigris.org/">Project Page</a> |
|
||||
<a href="./download.html">Download</a> |
|
||||
<a href="./contributing.html">Contributing</a> |
|
||||
<a href="./faq.html">FAQ</a> |
|
||||
<a href="http://viewvc.tigris.org/nonav/source/browse/*checkout*/viewvc/trunk/LICENSE.html">License</a> |
|
||||
<a href="./contact.html">Contact</a> |
|
||||
<a href="./who.html">About</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<table id="pagetable">
|
||||
<tr>
|
||||
<td id="pagecolumn1">
|
||||
|
||||
<h4>On this page:</h4>
|
||||
|
||||
<ul id="bookmarks">
|
||||
<li><a href="#sec-getting-started">Getting Started</a></li>
|
||||
<li><a href="#sec-testing">Testing and Reporting</a></li>
|
||||
<li><a href="#sec-coding-style">Coding Style</a></li>
|
||||
<li><a href="#sec-patches">Submitting Patches</a></li>
|
||||
<li><a href="#sec-security">Security</a></li>
|
||||
<li><a href="#sec-adding-features">Adding Features</a></li>
|
||||
<li><a href="#sec-templates">Hacking on Templates</a></li>
|
||||
</ul>
|
||||
|
||||
<p><a href="http://validator.w3.org/check?uri=referer"><img
|
||||
src="http://www.w3.org/Icons/valid-xhtml10"
|
||||
alt="Valid XHTML 1.0 Strict" height="31" width="88" /></a>
|
||||
</p>
|
||||
|
||||
</td>
|
||||
<td id="pagecolumn2">
|
||||
|
||||
<div class="section">
|
||||
|
||||
<h2 id="sec-getting-started">Getting Started</h2>
|
||||
|
||||
<div class="section-body">
|
||||
|
||||
<p>Some basic knowledge about <a
|
||||
href="http://www.python.org">Python</a> and development tools like
|
||||
<code>diff</code> is required. Your best bet is to start with a
|
||||
fresh source code snapshot, which you may obtain from our
|
||||
Subversion repository (see instructions <a
|
||||
href="./download.html#sec-subversion">here</a>).</p>
|
||||
|
||||
<p>Version control history can be obtained using Subversion clients,
|
||||
but is also browsable using <a
|
||||
href="http://viewvc.tigris.org/source/browse/viewvc/trunk/"
|
||||
>tigris.org's integrated ViewVC tool</a>.</p>
|
||||
|
||||
</div> <!-- section-body -->
|
||||
</div> <!-- section -->
|
||||
|
||||
<div class="section">
|
||||
|
||||
<h2 id="sec-testing">Testing and Reporting</h2>
|
||||
|
||||
<div class="section-body">
|
||||
|
||||
<p>Testing usability and the installation process on different
|
||||
platforms is also a valuable contribution. Please report your
|
||||
results back to us developers. Bandwidth is getting cheaper daily,
|
||||
so don't be afraid — in fact, feel encouraged — to dump
|
||||
as much detail about the problems you are seeing as possible into
|
||||
your bug reports. Here are some things you definitely should
|
||||
try to include:</p>
|
||||
|
||||
<ul>
|
||||
|
||||
<li>What version of ViewVC you are using (if you are using a source
|
||||
snapshot, tell us the date of that snapshot).</li>
|
||||
|
||||
<li>What operating system your ViewVC is running on.</li>
|
||||
|
||||
<li>What version of Python you are using.</li>
|
||||
|
||||
<li>Whether you are running ViewVC standalone, or as a CGI program
|
||||
under a web server (and if so, what web server).</li>
|
||||
|
||||
<li>The URL of your ViewVC instantiation, if it is public.
|
||||
Sometimes, letting developers see the problem for themselves can
|
||||
save everyone alot of time.</li>
|
||||
|
||||
</ul>
|
||||
|
||||
</div> <!-- section-body -->
|
||||
</div> <!-- section -->
|
||||
|
||||
<div class="section">
|
||||
|
||||
<h2 id="sec-coding-style">Coding Style</h2>
|
||||
|
||||
<div class="section-body">
|
||||
|
||||
<p>Unlike its predecessor, CvsWeb, ViewVC is written in Python, so it
|
||||
doesn't suffer from the "unmaintainable code effect" that hits most
|
||||
Perl projects sooner or later:</p>
|
||||
|
||||
<blockquote>
|
||||
|
||||
<p>"[Perl] combines all the worst aspects of C and Lisp: a
|
||||
billion different sublanguages in one monolithic executable. It
|
||||
combines the power of C with the readability of
|
||||
PostScript." — Jamie Zawinski
|
||||
</p>
|
||||
|
||||
</blockquote>
|
||||
|
||||
<p>Of course, a symphony of insanity can be composed in any language,
|
||||
so we do try to stick to some basic guiding principles. Maintain
|
||||
whatever style is present in the code being modified. New code can
|
||||
use anything sane (which generally means <a
|
||||
href="http://www.python.org/dev/peps/pep-0008/">PEP 8</a>).
|
||||
Our only real peeve is if someone writes a function call as:
|
||||
<code>some_func (args)</code> — that space between the
|
||||
function name and opening parenthesis is Huge Badness. Oh, and we
|
||||
do <strong>not</strong> use Subversion keywords (such as
|
||||
<code>$</code><code>Id$</code>) within the source.</p>
|
||||
|
||||
<p>Otherwise… <em>shrug</em>.</p>
|
||||
|
||||
</div> <!-- section-body -->
|
||||
</div> <!-- section -->
|
||||
|
||||
<div class="section">
|
||||
|
||||
<h2 id="sec-patches">Submitting Patches</h2>
|
||||
|
||||
<div class="section-body">
|
||||
|
||||
<p>Nothing speaks more loudly when bugs or features are the topic than
|
||||
a patch. And quite frankly, sometimes if you want something done,
|
||||
you gotta do it yourself. So, patches are always welcome. If you
|
||||
aren't sure what exactly a "patch" is, or don't know how
|
||||
to generate one, but you've got code contributions to make, please
|
||||
don't hesitate to ask questions on the mailing lists. Patch
|
||||
generation and application are pretty easy thing to get the hang of,
|
||||
and drastically simplify code submission and review.</p>
|
||||
|
||||
<p>Please use the <a
|
||||
href="http://viewvc.tigris.org/servlets/ProjectIssues">Issue
|
||||
Tracker</a> to submit your patches. Unified contextual diffs
|
||||
against the latest development snapshot are preferred.</p>
|
||||
|
||||
<p>If you have commit access, then you should know what you're doing.
|
||||
Just make changes directly. Subscribing to the <a
|
||||
href="http://viewvc.tigris.org/servlets/ProjectMailingListList"
|
||||
><tt>dev@</tt> developer mailing list</a> is recommended in any
|
||||
case.</p>
|
||||
|
||||
</div> <!-- section-body -->
|
||||
</div> <!-- section -->
|
||||
|
||||
<div class="section">
|
||||
|
||||
<h2 id="sec-security">Security</h2>
|
||||
|
||||
<div class="section-body">
|
||||
|
||||
<p>Since ViewVC is used on the Internet, security is a major concern.
|
||||
If you need to pass data from the request into an external program,
|
||||
please don't use <code>os.system()</code> or
|
||||
<code>os.popen()</code>. Please use the module
|
||||
<code>lib/popen.py</code> that is included in the ViewVC
|
||||
distribution instead.</p>
|
||||
|
||||
</div> <!-- section-body -->
|
||||
</div> <!-- section -->
|
||||
|
||||
<div class="section">
|
||||
|
||||
<h2 id="sec-adding-features">Adding Features</h2>
|
||||
|
||||
<div class="section-body">
|
||||
|
||||
<p>If you need a new configuration option think carefully, into which
|
||||
section it belongs. Try to keep the content of
|
||||
<code>cgi/viewvc.conf.dist</code> file and the library module
|
||||
<code>lib/config.py</code> in sync.</p>
|
||||
|
||||
<p>Because ViewVC is a Web-based application, people will have ViewVC
|
||||
URLs hyperlinked from other sites, embedded in emails, bookmarked
|
||||
in their browsers, etc. It is very important to ensure that those
|
||||
URLs continue to retrieve the information they were intended to
|
||||
retrieve even if ViewVC is upgraded on the hosting server. In
|
||||
other words, as new features require modifications to the <a
|
||||
href="./url-reference.html">ViewVC URL schema</a>, make sure those
|
||||
modifications preserve the existing functionality of all ViewVC
|
||||
URLs.</p>
|
||||
|
||||
<p>The library subdirectory contains a module <code>debug.py</code>,
|
||||
which you may find useful for performance testing.</p>
|
||||
|
||||
<p>If a new file or module is added, a new line in the installer
|
||||
program <code>viewvc-install</code> is required.</p>
|
||||
|
||||
</div> <!-- section-body -->
|
||||
</div> <!-- section -->
|
||||
|
||||
<div class="section">
|
||||
|
||||
<h2 id="sec-templates">Hacking on Templates</h2>
|
||||
|
||||
<div class="section-body">
|
||||
|
||||
<p>The library module <code>ezt.py</code> contains a module docstring
|
||||
which describes the directives used in the HTML templates used by
|
||||
ViewVC. The templates themselves can be found in the
|
||||
<code>templates</code> subdirectory. We're currently developing a
|
||||
how-to guide for <a href="./template-authoring-guide.html">ViewVC
|
||||
template customization</a>.</p>
|
||||
|
||||
</div> <!-- section-body -->
|
||||
</div> <!-- section -->
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
90
viewvc.org/download.html
Normal file
90
viewvc.org/download.html
Normal file
@@ -0,0 +1,90 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>ViewVC: Download</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||
<link rel="stylesheet" type="text/css" href="./styles.css"/>
|
||||
<link rel="shortcut icon" href="./favicon.ico" type="image/x-icon" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="title">
|
||||
<a href="http://www.viewvc.org/"><img
|
||||
src="./images/title.jpg" alt="ViewVC: Repository Browsing"/></a>
|
||||
</div>
|
||||
|
||||
<div id="menu">
|
||||
<p><a href="./index.html">Home</a> |
|
||||
<a href="http://viewvc.tigris.org/">Project Page</a> |
|
||||
<a href="./download.html">Download</a> |
|
||||
<a href="./contributing.html">Contributing</a> |
|
||||
<a href="./faq.html">FAQ</a> |
|
||||
<a href="http://viewvc.tigris.org/nonav/source/browse/*checkout*/viewvc/trunk/LICENSE.html">License</a> |
|
||||
<a href="./contact.html">Contact</a> |
|
||||
<a href="./who.html">About</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<table id="pagetable">
|
||||
<tr>
|
||||
<td id="pagecolumn1">
|
||||
|
||||
<h4>On this page:</h4>
|
||||
|
||||
<ul id="bookmarks">
|
||||
<li><a href="#sec-download">Downloading</a></li>
|
||||
<li><a href="#sec-subversion">Subversion</a></li>
|
||||
</ul>
|
||||
|
||||
<p><a href="http://validator.w3.org/check?uri=referer"><img
|
||||
src="http://www.w3.org/Icons/valid-xhtml10"
|
||||
alt="Valid XHTML 1.0 Strict" height="31" width="88" /></a>
|
||||
</p>
|
||||
|
||||
</td>
|
||||
<td id="pagecolumn2">
|
||||
|
||||
<div class="section">
|
||||
|
||||
<h2 id="sec-download">Downloading</h2>
|
||||
|
||||
<div class="section-body">
|
||||
|
||||
<p>You can download the latest release of ViewVC (and the older ViewVC
|
||||
and ViewCVS releases, too) from our <a
|
||||
href="http://viewvc.tigris.org/servlets/ProjectDocumentList?folderID=6004"
|
||||
>Documents & Files</a> area. For information about what has
|
||||
changed in each release, see the <a
|
||||
href="http://viewvc.tigris.org/source/browse/viewvc/trunk/CHANGES?rev=HEAD"
|
||||
>CHANGES</a> file.</p>
|
||||
|
||||
<p>We are also making <a href="./nightly/">nightly snapshots</a>
|
||||
available in tar.gz and zip formats.</p>
|
||||
|
||||
</div> <!-- section-body -->
|
||||
</div> <!-- section -->
|
||||
|
||||
<div class="section">
|
||||
|
||||
<h2 id="sec-subversion">Subversion</h2>
|
||||
|
||||
<div class="section-body">
|
||||
|
||||
<p>The source code for ViewVC is maintained in a Subversion repository
|
||||
at Tigris.org. You can checkout the trunk of our development tree
|
||||
from <a href="http://viewvc.tigris.org/svn/viewvc/trunk/"
|
||||
>http://viewvc.tigris.org/svn/viewvc/trunk/</a>. You'll
|
||||
need to provide your Tigris.org username and password when so
|
||||
prompted, or, if you don't have a Tigris.org account, use "guest"
|
||||
as the username (with no, or an empty, password).</p>
|
||||
|
||||
</div> <!-- section-body -->
|
||||
</div> <!-- section -->
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
359
viewvc.org/faq.html
Normal file
359
viewvc.org/faq.html
Normal file
@@ -0,0 +1,359 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>ViewVC: Frequently Asked Questions (FAQ)</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||
<link rel="stylesheet" type="text/css" href="./styles.css"/>
|
||||
<link rel="shortcut icon" href="./favicon.ico" type="image/x-icon" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="title">
|
||||
<a href="http://www.viewvc.org/"><img
|
||||
src="./images/title.jpg" alt="ViewVC: Frequently Asked Questions (FAQ)"/></a>
|
||||
</div>
|
||||
|
||||
<div id="menu">
|
||||
<p><a href="./index.html">Home</a> |
|
||||
<a href="http://viewvc.tigris.org/">Project Page</a> |
|
||||
<a href="./download.html">Download</a> |
|
||||
<a href="./contributing.html">Contributing</a> |
|
||||
<a href="./faq.html">FAQ</a> |
|
||||
<a href="http://viewvc.tigris.org/nonav/source/browse/*checkout*/viewvc/trunk/LICENSE.html">License</a> |
|
||||
<a href="./contact.html">Contact</a> |
|
||||
<a href="./who.html">About</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<table id="pagetable">
|
||||
<tr>
|
||||
<td id="pagecolumn1">
|
||||
|
||||
<h4>On this page:</h4>
|
||||
|
||||
<ul id="bookmarks">
|
||||
<li><a href="#faq-q">Questions</a></li>
|
||||
<li><a href="#faq-a">Answers</a></li>
|
||||
</ul>
|
||||
|
||||
<p><a href="http://validator.w3.org/check?uri=referer"><img
|
||||
src="http://www.w3.org/Icons/valid-xhtml10"
|
||||
alt="Valid XHTML 1.0 Strict" height="31" width="88" /></a>
|
||||
</p>
|
||||
|
||||
</td>
|
||||
<td id="pagecolumn2">
|
||||
|
||||
<div class="section">
|
||||
|
||||
<!-- ##################################################################### -->
|
||||
<h2 id="faq-q">Questions</h2>
|
||||
<!-- ##################################################################### -->
|
||||
|
||||
<div class="section-body">
|
||||
|
||||
<!-- #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# -->
|
||||
<h3 class="faq-section" id="faq-q-general">General Usage</h3>
|
||||
<!-- #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# -->
|
||||
|
||||
<ul>
|
||||
|
||||
<li><a href="#installation">Where does the installation documentation,
|
||||
if any, live?</a></li>
|
||||
|
||||
<li><a href="#authz-support">Does ViewVC support path-based
|
||||
authorization, such as Subversion's authz-file mechanism?</a></li>
|
||||
|
||||
<li><a href="#missing-tmpdir">What causes "Error: OSError: [Errno 2] No such file
|
||||
or directory: '/tmp/tmpGc-Ztj'"?</a></li>
|
||||
|
||||
<li><a href="#standalone-only">Why does <em>SOME-FEATURE</em>
|
||||
work under standalone.py, but not under Apache (or IIS or
|
||||
…)?</a></li>
|
||||
|
||||
<li><a href="#rss-support">How do I enable ViewVC's RSS feed
|
||||
capabilities?</a></li>
|
||||
|
||||
</ul>
|
||||
|
||||
<!-- #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# -->
|
||||
<h3 class="faq-section" id="faq-q-cvs">CVS Browsing</h3>
|
||||
<!-- #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# -->
|
||||
|
||||
<ul>
|
||||
|
||||
<li><a href="#rlog-output-ended-early">What causes "Error: Rlog output ended
|
||||
early. Expected RCS file "/opt/cvs/project/file,v""?</a></li>
|
||||
|
||||
<li><a href="#comalformedoutput">What causes "Error: COMalformedOutput: Unable to
|
||||
find filename in co output stream"?</a></li>
|
||||
|
||||
<li><a href="#error-during-rlog">What causes "Error: error during
|
||||
rlog: 0x100"?</a></li>
|
||||
|
||||
<li><a href="#missing-files">Why do my directories have no files in them?</a></li>
|
||||
|
||||
<li><a href="#none-match">ViewVC doesn't show files I'm looking for,
|
||||
and instead displays the message "NOTE: There are N files, but
|
||||
none match the current selection criteria". How can I fix this?</a></li>
|
||||
|
||||
</ul>
|
||||
|
||||
<!-- #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# -->
|
||||
<h3 class="faq-section" id="faq-q-svn">Subversion Browsing</h3>
|
||||
<!-- #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# -->
|
||||
|
||||
<ul>
|
||||
|
||||
<li><a href="#no-module-named-svn">What causes "Error: ImportError: No module named
|
||||
svn"?</a></li>
|
||||
|
||||
<li><a href="#remote-svn-access">Can I use ViewVC with remote
|
||||
Subversion repositories?</a></li>
|
||||
|
||||
</ul>
|
||||
|
||||
<!-- #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="section">
|
||||
|
||||
<!-- ##################################################################### -->
|
||||
<h2 id="faq-a">Answers</h2>
|
||||
<!-- ##################################################################### -->
|
||||
|
||||
<div class="section-body">
|
||||
|
||||
<!-- #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# -->
|
||||
<h3 class="faq-section" id="faq-a-general">General Usage</h3>
|
||||
<!-- #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# -->
|
||||
|
||||
<div id="installation">
|
||||
<p class="faq-atitle">Where does the installation documentation, if
|
||||
any, live?</p>
|
||||
|
||||
<p>ViewVC's installation how-to documentation lives in the INSTALL
|
||||
file located in the root of the ViewVC source code distribution.
|
||||
The most recent version of this document (which may cover
|
||||
unreleased ViewVC versions) can be found
|
||||
at <a href="http://viewvc.tigris.org/source/browse/*checkout*/viewvc/trunk/INSTALL"
|
||||
>http://viewvc.tigris.org/source/browse/*checkout*/viewvc/trunk/INSTALL</a>.
|
||||
If you are upgrading an existing ViewVC instance, you'll also want
|
||||
to read the upgrade documentation, found
|
||||
at <a href="http://viewvc.tigris.org/source/browse/*checkout*/viewvc/trunk/docs/upgrading-howto.html"
|
||||
>http://viewvc.tigris.org/source/browse/*checkout*/viewvc/trunk/docs/upgrading-howto.html</a>.</p>
|
||||
</div>
|
||||
|
||||
<div id="authz-support">
|
||||
<p class="faq-atitle">Does ViewVC support path-based authorization,
|
||||
such as Subversion's authz-file mechanism?</p>
|
||||
|
||||
<p>There are no released versions of ViewVC which have this support
|
||||
built-in. The feature request is being tracking in <a
|
||||
href="http://viewvc.tigris.org/issues/show_bug.cgi?id=268">issue
|
||||
#268</a>, and we're working to complete it for release in ViewVC
|
||||
1.1.</p>
|
||||
|
||||
<p>In the meantime, there are some available workarounds. For
|
||||
example, if you are running ViewVC under Apache, you can use
|
||||
regular Apache configuration directives to authz-protect areas of
|
||||
your repository — see the <a
|
||||
href="http://httpd.apache.org/docs/2.2/mod/core.html#location"
|
||||
>Location</a> and <a
|
||||
href="http://httpd.apache.org/docs/2.2/mod/core.html#locationmatch"
|
||||
>LocationMatch</a> directives, as well as the <a
|
||||
href="http://httpd.apache.org/docs/2.2/howto/auth.html"
|
||||
>Authentication, Authorization and Access Control</a> portions of
|
||||
the Apache HTTP Server documentation. This works best when ViewVC
|
||||
is only serving up a single repository, or when the
|
||||
<code>root_as_url_component</code> option is enabled otherwise.
|
||||
And you might have to disable the checkout view, or at least turn
|
||||
off the use of <code>checkout_magic</code> (see
|
||||
<code>viewvc.conf</code> for details).</p>
|
||||
</div>
|
||||
|
||||
<div id="missing-tmpdir">
|
||||
<p class="faq-atitle">What causes "Error: OSError: [Errno 2] No such
|
||||
file or directory: '/tmp/tmpGc-Ztj'"?</p>
|
||||
|
||||
<p>This is tracked in <a
|
||||
href="http://viewvc.tigris.org/issues/show_bug.cgi?id=282">issue
|
||||
#282</a>. While we haven't figured out how to make the error
|
||||
message more graceful or helpful, the basic problem seems to
|
||||
generally boil down to a misconfiguration of ViewVC. Make sure
|
||||
your helper applications are in the program search path
|
||||
(<code>$PATH</code>, e.g.) on your ViewVC server, or accurately
|
||||
specified in <code>viewvc.conf</code>.</p>
|
||||
</div>
|
||||
|
||||
<div id="standalone-only">
|
||||
<p class="faq-atitle">Why does <em>SOME-FEATURE</em> work under
|
||||
standalone.py, but not under Apache (or IIS or …)?</p>
|
||||
|
||||
<p>Most of the time folks run standalone.py, they do so as a regular
|
||||
system user, from a shell running with any and all the
|
||||
environmental customizations present in their shell startup
|
||||
scripts. But most web server packages (like Apache) run as a
|
||||
different, often underprivileged, user, whose environment is
|
||||
stripped down to just the system-wide default state. This can
|
||||
cause problems for ViewVC's various helper applications, which
|
||||
might reside in a location that's included as part of your (and
|
||||
thus standalone.py's) <code>$PATH</code>, but not that of the user
|
||||
as whom the web server package runs. The solution might be as
|
||||
simple explicitly configuring the paths of the helper applications
|
||||
in <code>viewvc.conf</code>, or as complex as expanding the program
|
||||
search path used by your web server software.</p>
|
||||
</div>
|
||||
|
||||
<div id="rss-support">
|
||||
<p class="faq-atitle">How do I enable ViewVC's RSS feed capabilities?</p>
|
||||
|
||||
<p>ViewVC generates its RSS feeds from repository data mirrored in a
|
||||
database as part of its MySQL integration. Follow the steps in
|
||||
ViewVC's <code>INSTALL</code> file to setup and configure the MySQL
|
||||
integration and begin mirroring your commit metadata in the
|
||||
database — the RSS feed feature will then be enabled with no
|
||||
additional configuration.</p>
|
||||
</div>
|
||||
|
||||
<!-- #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# -->
|
||||
<h3 class="faq-section" id="faq-a-cvs">CVS Browsing</h3>
|
||||
<!-- #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# -->
|
||||
|
||||
<div id="rlog-output-ended-early">
|
||||
|
||||
<p class="faq-atitle">What causes "Error: Rlog output ended
|
||||
early. Expected RCS file "/opt/cvs/project/file,v""?</p>
|
||||
|
||||
<p>This error generally occurs when ViewVC is unable to locate the
|
||||
rlog tool, one of several in the RCS toolchain. If the system
|
||||
doesn't have the RCS toolchain installed, you'll need to install
|
||||
it. If the RCS toolchain is installed, but ViewVC simply can't
|
||||
locate the RCS programs, either ensure that the programs are
|
||||
in the system <code>$PATH</code>, or specify their location in
|
||||
the <code>viewvc.conf</code> file — the option is
|
||||
<code>utilities/rcs_dir</code> as of ViewVC 1.1,
|
||||
<code>general/rcs_path</code> in earlier versions.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="comalformedoutput">
|
||||
|
||||
<p class="faq-atitle">What causes "Error: COMalformedOutput: Unable to
|
||||
find filename in co output stream"?</p>
|
||||
|
||||
<p>This is another symptom of the basic problem described <a
|
||||
href="#rlog-output-ended-early">here</a>.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="error-during-rlog">
|
||||
<p class="faq-atitle">What causes "Error: error during rlog:
|
||||
0x100"?</p>
|
||||
|
||||
<p>### TODO ###</p>
|
||||
</div>
|
||||
|
||||
<div id="missing-files">
|
||||
<p class="faq-atitle">Why do my directories have no files in them?</p>
|
||||
|
||||
<p>There are a few reasons why this can happen. Here are some of the
|
||||
most common ones:</p>
|
||||
|
||||
<ul>
|
||||
<li>Some folks mistakenly point ViewVC's configuration bits to their
|
||||
CVS working copies. But ViewVC isn't a working copy browser
|
||||
— it's a <em>repository</em> browser. If you don't know
|
||||
the difference, here's a tip that might help: CVS repositories
|
||||
are directories trees filled with files that end with
|
||||
"<code>,v</code>". If your directory isn't filled with "comma
|
||||
vee" files, it probably is <em>not</em> a CVS repository.</li>
|
||||
<li>… <!-- TODO --></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div id="none-match">
|
||||
<p class="faq-atitle">ViewVC doesn't show files I'm looking for, and
|
||||
instead displays the message "NOTE: There are N files, but none
|
||||
match the current selection criteria". How can I fix this?</p>
|
||||
|
||||
<p>From time to time, CVS and CVSNT add support for new keywords to
|
||||
the RCS backend used to house repository data. If you're running a
|
||||
version of ViewVC or ViewCVS that hasn't yet learned to handle
|
||||
those new keywords, you might get the error you're seeing. The
|
||||
solution is to try to get versions of CVS/CVSNT and ViewVC which
|
||||
are better aligned, which generally means upgrading ViewVC (which
|
||||
is probably less disruptive than downgrading your version control
|
||||
system).</p>
|
||||
</div>
|
||||
|
||||
<!-- #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# -->
|
||||
<h3 class="faq-section" id="faq-a-svn">Subversion Browsing</h3>
|
||||
<!-- #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# -->
|
||||
|
||||
<div id="no-module-named-svn">
|
||||
<p class="faq-atitle">What causes "Error: ImportError: No module named
|
||||
svn"?</p>
|
||||
|
||||
<p>ViewVC uses Subversion's Python bindings to interact with and pull
|
||||
information out of your Subversion repositories. These bindings
|
||||
are not, however, generally provided as part of the ViewVC
|
||||
distribution — you have to install them yourself some other
|
||||
way. (For more information, contact the <a
|
||||
href="http://subversion.tigris.org">Subversion</a> community.) The
|
||||
error you see is Python being asked to import the Subversion Python
|
||||
bindings and being unable to do so, typically because the bindings
|
||||
modules aren't found in the Python library search path.</p>
|
||||
</div>
|
||||
|
||||
<div id="remote-svn-access">
|
||||
|
||||
<p class="faq-atitle">Can I use ViewVC with remote Subversion
|
||||
repositories?</p>
|
||||
|
||||
<p>ViewVC prefers to have direct access to the repository (and in
|
||||
fact, <em>must</em> have that for CVS repositories), but there does
|
||||
exist experimental support for remote Subversion repositories.
|
||||
Enabling this is a fairly simple — just use the URL of the
|
||||
repository where you would use its path in the
|
||||
<code>svn_roots</code> configuration options (sorry, you can't use
|
||||
<code>root_parents</code> for remote repositories because
|
||||
Subversion doesn't expose a repository-listing repository access
|
||||
API).</p>
|
||||
|
||||
<p>What you should expect:</p>
|
||||
|
||||
<ul>
|
||||
<li><p>Near parity with local-access Subversion in terms of
|
||||
functionality.</p></li>
|
||||
|
||||
<li><p>Known shortcomings:</p>
|
||||
<ul>
|
||||
<li>file sizes aren't reported everywhere</li>
|
||||
<li>the "revision" view lacks/botches some information</li>
|
||||
<li>she ain't the fastest horse on the track…</li>
|
||||
</ul>
|
||||
</li>
|
||||
|
||||
<li><p>Lack of configury for dealing with the intricacies of remote
|
||||
access. If the auth credentials and such you need to access
|
||||
the remote repository aren't cached in
|
||||
<code>~VIEWVC_USER/.subversion</code> (where
|
||||
<code>VIEWVC_USER</code> is the system user as whom ViewVC
|
||||
runs), stuff won't work.</p></li>
|
||||
</ul>
|
||||
|
||||
<!-- #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div> <!-- section -->
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
BIN
viewvc.org/favicon.ico
Normal file
BIN
viewvc.org/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
BIN
viewvc.org/images/bg-grad.jpg
Normal file
BIN
viewvc.org/images/bg-grad.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.9 KiB |
BIN
viewvc.org/images/title.jpg
Normal file
BIN
viewvc.org/images/title.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 16 KiB |
BIN
viewvc.org/images/title.xcf
Normal file
BIN
viewvc.org/images/title.xcf
Normal file
Binary file not shown.
204
viewvc.org/index.html
Normal file
204
viewvc.org/index.html
Normal file
@@ -0,0 +1,204 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>ViewVC: Repository Browsing</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||
<link rel="stylesheet" type="text/css" href="./styles.css"/>
|
||||
<link rel="shortcut icon" href="./favicon.ico" type="image/x-icon" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="title">
|
||||
<a href="http://www.viewvc.org/"><img
|
||||
src="./images/title.jpg" alt="ViewVC: Repository Browsing"/></a>
|
||||
</div>
|
||||
|
||||
<div id="menu">
|
||||
<p><a href="./index.html">Home</a> |
|
||||
<a href="http://viewvc.tigris.org/">Project Page</a> |
|
||||
<a href="./download.html">Download</a> |
|
||||
<a href="./contributing.html">Contributing</a> |
|
||||
<a href="./faq.html">FAQ</a> |
|
||||
<a href="http://viewvc.tigris.org/nonav/source/browse/*checkout*/viewvc/trunk/LICENSE.html">License</a> |
|
||||
<a href="./contact.html">Contact</a> |
|
||||
<a href="./who.html">About</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<table id="pagetable">
|
||||
<tr>
|
||||
<td id="pagecolumn1">
|
||||
|
||||
<h4>On this page:</h4>
|
||||
|
||||
<ul id="bookmarks">
|
||||
<li><a href="#sec-what-is-viewvc">What Is ViewVC?</a></li>
|
||||
<li><a href="#sec-requirements">Requirements</a></li>
|
||||
<li><a href="#sec-future">Future Plans</a></li>
|
||||
</ul>
|
||||
|
||||
<p><a href="http://validator.w3.org/check?uri=referer"><img
|
||||
src="http://www.w3.org/Icons/valid-xhtml10"
|
||||
alt="Valid XHTML 1.0 Strict" height="31" width="88" /></a>
|
||||
</p>
|
||||
|
||||
</td>
|
||||
<td id="pagecolumn2">
|
||||
|
||||
<div class="section">
|
||||
|
||||
<h2 id="sec-what-is-viewvc">What Is ViewVC?</h2>
|
||||
|
||||
<div class="section-body">
|
||||
|
||||
<p>ViewVC is a browser interface for CVS and Subversion version
|
||||
control repositories. It generates templatized HTML to present
|
||||
navigable directory, revision, and change log listings. It can
|
||||
display specific versions of files as well as diffs between those
|
||||
versions. Basically, ViewVC provides the bulk of the report-like
|
||||
functionality you expect out of your version control tool, but much
|
||||
more prettily than the average textual command-line program
|
||||
output.</p>
|
||||
|
||||
<p>Here are some of the additional features of ViewVC:</p>
|
||||
|
||||
<ul>
|
||||
|
||||
<li>Support for filesystem-accessible CVS and Subversion repositories.</li>
|
||||
|
||||
<li>Individually configurable virtual host support.</li>
|
||||
|
||||
<li>Line-based annotation/blame display.</li>
|
||||
|
||||
<li>Revision graph capabilities (via integration with <a
|
||||
href="http://www.akhphd.au.dk/~bertho/cvsgraph/">CvsGraph</a>)
|
||||
(<em>CVS only</em>).</li>
|
||||
|
||||
<li>Syntax highlighting support.</li>
|
||||
|
||||
<li><a href="http://www.mozilla.org/projects/bonsai/">Bonsai</a>-like
|
||||
repository query facilities.</li>
|
||||
|
||||
<li>Template-driven output generation.</li>
|
||||
|
||||
<li>Colorized, side-by-side differences.</li>
|
||||
|
||||
<li>Tarball generation (by tag/branch for CVS, by revision for
|
||||
Subversion).</li>
|
||||
|
||||
<li>I18N support based on the Accept-Language request header.</li>
|
||||
|
||||
<li>Ability to run either as CGI script or as a standalone
|
||||
server.</li>
|
||||
|
||||
<li>Regexp-based file searching.</li>
|
||||
|
||||
<li>INI-like configuration file (as opposed to requiring actual code
|
||||
tweaks).</li>
|
||||
|
||||
</ul>
|
||||
|
||||
<p>For a complete list of changes present in each release, see
|
||||
ViewVC's <a
|
||||
href="http://viewvc.tigris.org/source/browse/viewvc/trunk/CHANGES?rev=HEAD"
|
||||
>CHANGES</a> file.</p>
|
||||
|
||||
</div> <!-- section-body -->
|
||||
</div> <!-- section -->
|
||||
|
||||
<div class="section">
|
||||
|
||||
<h2 id="sec-requirements">Requirements</h2>
|
||||
|
||||
<div class="section-body">
|
||||
|
||||
<p>The only hard software requirement for running ViewVC is <a
|
||||
href="http://www.python.org/">Python 1.5.2</a> or later. All other
|
||||
requirements depend on what you want to do with the tool.</p>
|
||||
|
||||
<p>If you plan to use ViewVC with CVS repositories, you need the
|
||||
following things:</p>
|
||||
|
||||
<ul>
|
||||
|
||||
<li><a href="http://www.cs.purdue.edu/homes/trinkle/RCS/">RCS</a>
|
||||
(Revision Control System)</li>
|
||||
|
||||
<li><a href="http://www.gnu.org/software/diffutils/diffutils.html">GNU
|
||||
diff</a></li>
|
||||
|
||||
<li>Read-only, physical access to a CVS repository.</li>
|
||||
|
||||
</ul>
|
||||
|
||||
<p>For use with Subversion repositories, you need these things:</p>
|
||||
|
||||
<ul>
|
||||
|
||||
<li><a href="http://subversion.tigris.org/">Subversion</a> 1.2 or
|
||||
later and its SWIG Python bindings.</li>
|
||||
|
||||
<li><a href="http://www.gnu.org/software/diffutils/diffutils.html">GNU
|
||||
diff</a></li>
|
||||
|
||||
<li>Physical access to a Subversion repository (though there is
|
||||
limited, use-at-your-risk support for remote access, too).</li>
|
||||
|
||||
</ul>
|
||||
|
||||
<p>ViewVC integrates with additional pieces of software to provide
|
||||
certain bits of optional functionality:</p>
|
||||
|
||||
<ul>
|
||||
|
||||
<li><a href="http://www.mysql.com/">MySQL</a> — Needed to use
|
||||
the commit database query functionality.</li>
|
||||
|
||||
<li><a href="http://www.codento.com/people/mtr/genscript/">GNU
|
||||
enscript</a> — Needed for syntax highlighting in versioned
|
||||
file contents displays</li>
|
||||
|
||||
<li><a href="http://www.akhphd.au.dk/~bertho/cvsgraph/">CvsGraph</a>
|
||||
— Needed for version graph displays.</li>
|
||||
|
||||
<li><a href="http://httpd.apache.org/">Apache HTTP Server</a>, or
|
||||
another server capable of running CGI programs — unless
|
||||
you just want ViewVC to run in standalone server mode.</li>
|
||||
|
||||
</ul>
|
||||
|
||||
</div> <!-- section-body -->
|
||||
</div> <!-- section -->
|
||||
|
||||
<div class="section">
|
||||
|
||||
<h2 id="sec-future">Future Plans</h2>
|
||||
|
||||
<div class="section-body">
|
||||
|
||||
<p>ViewVC is an Open Source project. So any future development
|
||||
depends on the <a href="./contributing.html">contributions</a> that
|
||||
will be made by its user community. Certainly working patches have
|
||||
a greater chance to become realized quickly than feature requests,
|
||||
but please don't hesitate to submit your suggestions to our <a
|
||||
href="http://viewvc.tigris.org/servlets/ProjectIssues">issue
|
||||
tracker</a>.</p>
|
||||
|
||||
<p>Some things we're thinking about include:</p>
|
||||
|
||||
<ul>
|
||||
<li>UI streamlining/simplification.</li>
|
||||
<li>Integration with CVS and Subversion commit mail scripts.</li>
|
||||
<li>Integration with an indexer such as LXR.</li>
|
||||
</ul>
|
||||
|
||||
</div> <!-- section-body -->
|
||||
</div> <!-- section -->
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
219
viewvc.org/nightly/build-viewvc-snapshot
Executable file
219
viewvc.org/nightly/build-viewvc-snapshot
Executable file
@@ -0,0 +1,219 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import sys
|
||||
import os
|
||||
import time
|
||||
import urllib
|
||||
import shutil
|
||||
import getopt
|
||||
import tempfile
|
||||
|
||||
|
||||
class BuildError(Exception):
|
||||
def __init__(self, message):
|
||||
self.message = message
|
||||
def __str__(self):
|
||||
return self.message
|
||||
|
||||
|
||||
def make_release(branch, export_dir, publish_dir, root_url, username, password):
|
||||
|
||||
# Export the requested ViewVC source tree.
|
||||
cmd = "svn export --quiet '%s/%s' %s " \
|
||||
"--username '%s' --password '%s' --non-interactive --force" \
|
||||
% (root_url, urllib.quote(branch), export_dir, username, password)
|
||||
sys.stdout.write("Running: %s\n" % (cmd))
|
||||
os.system(cmd)
|
||||
|
||||
# Get the version number from ViewVC itself.
|
||||
sys.path.insert(0, os.path.join(export_dir, 'lib'))
|
||||
try:
|
||||
import viewvc
|
||||
except ImportError:
|
||||
raise BuildError("Unable to import viewvc module; export failed?")
|
||||
version = viewvc.__version__
|
||||
del sys.modules['viewvc']
|
||||
del viewvc
|
||||
del sys.path[0]
|
||||
|
||||
# Now, use ViewVC tools to make the distribution archives.
|
||||
localtime = time.localtime()
|
||||
date = "%4d%02d%02d" % (localtime[0], localtime[1], localtime[2])
|
||||
distversion = "viewvc-%s" % (version)
|
||||
distname = "%s-%s" % (distversion, date)
|
||||
gzip_name = distname + '.tar.gz'
|
||||
zip_name = distname + '.zip'
|
||||
curdir = os.getcwd()
|
||||
try:
|
||||
os.chdir(os.path.join(export_dir, 'tools'))
|
||||
os.system('./make-release %s' % (distname))
|
||||
finally:
|
||||
os.chdir(curdir)
|
||||
|
||||
# Finally, return the locations of the archive files we've built.
|
||||
gzip_file = os.path.join(export_dir, 'tools', gzip_name)
|
||||
if not os.path.exists(gzip_file):
|
||||
gzip_file = None
|
||||
zip_file = os.path.join(export_dir, 'tools', zip_name)
|
||||
if not os.path.exists(zip_file):
|
||||
zip_file = None
|
||||
|
||||
# Remove superceded archives.
|
||||
if gzip_file or zip_file:
|
||||
dirents = os.listdir(publish_dir)
|
||||
for dirent in dirents:
|
||||
if dirent.startswith(distversion) \
|
||||
and ((dirent.endswith('.tar.gz') and gzip_file) \
|
||||
or (dirent.endswith('.zip') and zip_file)):
|
||||
os.unlink(dirent)
|
||||
|
||||
# Install the new archives.
|
||||
if gzip_file:
|
||||
os.rename(gzip_file, os.path.join(publish_dir, gzip_name))
|
||||
if zip_file:
|
||||
os.rename(zip_file, os.path.join(publish_dir, zip_name))
|
||||
|
||||
# Return our archive names.
|
||||
return gzip_file and gzip_name or None, zip_file and zip_name or None
|
||||
|
||||
|
||||
def publish_releases(branches, publish_dir, root_url, username, password):
|
||||
new_index_contents = get_html_index_header()
|
||||
for branch in branches:
|
||||
sys.stdout.write("Beginning build for branch '%s'.\n" % (branch))
|
||||
export_dir = None
|
||||
try:
|
||||
export_dir = tempfile.mkdtemp("", "viewvc-nightly-")
|
||||
gzip_file, zip_file = make_release(branch, export_dir, publish_dir,
|
||||
root_url, username, password)
|
||||
new_index_contents = new_index_contents + """
|
||||
<p>Build of %s:</p>
|
||||
<ul>
|
||||
<li><a href="%s">%s</a></li>
|
||||
<li><a href="%s">%s</a></li>
|
||||
</ul>
|
||||
""" % (branch, urllib.quote(gzip_file), gzip_file,
|
||||
urllib.quote(zip_file), zip_file)
|
||||
finally:
|
||||
if export_dir:
|
||||
sys.stdout.write("Removing temporary directory '%s'.\n" % (export_dir))
|
||||
shutil.rmtree(export_dir)
|
||||
sys.stdout.write("Finished build for branch '%s'.\n" % (branch))
|
||||
|
||||
new_index_contents = new_index_contents + get_html_index_footer()
|
||||
open(os.path.join(publish_dir, 'index.html'), 'w').write(new_index_contents)
|
||||
|
||||
|
||||
def get_html_index_header():
|
||||
return """
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>ViewVC: Nightly Snapshots</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||
<link rel="stylesheet" type="text/css" href="../styles.css"/>
|
||||
<link rel="shortcut icon" href="../favicon.ico" type="image/x-icon" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="title">
|
||||
<a href="http://www.viewvc.org/"><img
|
||||
src="../images/title.jpg" alt="ViewVC: Repository Browsing"/></a>
|
||||
</div>
|
||||
|
||||
<div id="menu">
|
||||
<p><a href="../index.html">Home</a> |
|
||||
<a href="http://viewvc.tigris.org/">Project Page</a> |
|
||||
<a href="../download.html">Download</a> |
|
||||
<a href="../contributing.html">Contributing</a> |
|
||||
<a href="./faq.html">FAQ</a> |
|
||||
<a href="http://viewvc.tigris.org/nonav/source/browse/*checkout*/viewvc/trunk/LICENSE.html">License</a> |
|
||||
<a href="../contact.html">Contact</a> |
|
||||
<a href="../who.html">About</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<table id="pagetable">
|
||||
<tr>
|
||||
<td id="pagecolumn1">
|
||||
|
||||
<h4>On this page:</h4>
|
||||
|
||||
<ul id="bookmarks">
|
||||
<li><a href="%s">Snapshots</a></li>
|
||||
</ul>
|
||||
|
||||
<p><a href="http://validator.w3.org/check?uri=referer"><img
|
||||
src="http://www.w3.org/Icons/valid-xhtml10"
|
||||
alt="Valid XHTML 1.0 Strict" height="31" width="88" /></a>
|
||||
</p>
|
||||
|
||||
</td>
|
||||
<td id="pagecolumn2">
|
||||
|
||||
<div class="section">
|
||||
<h2 id="sec-snapshots">Snapshots</h2>
|
||||
<div class="section-body">
|
||||
""" % ("#sec-snapshots")
|
||||
|
||||
|
||||
def get_html_index_footer():
|
||||
return """
|
||||
</div> <!-- section-body -->
|
||||
</div> <!-- section -->
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
"""
|
||||
|
||||
|
||||
def usage_and_exit(errmsg=None):
|
||||
stream = errmsg and sys.stderr or sys.stdout
|
||||
progname = os.path.basename(sys.argv[0])
|
||||
stream.write("""%s -- nightly ViewVC build generation
|
||||
|
||||
Usage: %s [OPTIONS] PUBLISH-DIR BRANCH ...
|
||||
|
||||
Build an archive from one or more BRANCH in the ViewVC source
|
||||
repository, dropping them into PUBLISH-DIR alongside an index.html
|
||||
file that name and links to them.
|
||||
|
||||
Options:
|
||||
--help (-h, -?) : Show this usage message
|
||||
--username : Username used for source export
|
||||
--password : Password used for source export
|
||||
--root-url : Alternative source repository root URL
|
||||
|
||||
""" % (progname, progname))
|
||||
if errmsg:
|
||||
stream.write("ERROR: %s\n" % (errmsg))
|
||||
sys.exit(errmsg and 1 or 0)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
root_url = "http://viewvc.tigris.org/svn/viewvc"
|
||||
username = password = ""
|
||||
opts, args = getopt.getopt(sys.argv[1:], 'h?',
|
||||
['help', 'username=', 'password=', 'root-url='])
|
||||
for name, value in opts:
|
||||
if name == '-h' or name == '-?' or name == '--help':
|
||||
usage_and_exit()
|
||||
elif name == '--username':
|
||||
username = value
|
||||
elif name == '--password':
|
||||
password = value
|
||||
elif name == '--root-url':
|
||||
root_url = value
|
||||
argc = len(args)
|
||||
if argc < 2:
|
||||
usage_and_exit("Not enough arguments")
|
||||
try:
|
||||
publish_releases(args[1:], args[0], root_url, username, password)
|
||||
except BuildError, e:
|
||||
sys.stderr.write(str(e) + "\n")
|
||||
sys.exit(1)
|
169
viewvc.org/styles.css
Normal file
169
viewvc.org/styles.css
Normal file
@@ -0,0 +1,169 @@
|
||||
body {
|
||||
background-color: #b2d388;
|
||||
color: black;
|
||||
font-family: trebuchet ms, arial, sans-serif;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
#title {
|
||||
background-color: #739c3e;
|
||||
height: 70px;
|
||||
}
|
||||
|
||||
img {
|
||||
border: none;
|
||||
}
|
||||
|
||||
hr {
|
||||
width: 95%;
|
||||
height: 1px;
|
||||
}
|
||||
|
||||
address {
|
||||
font-size: 60%;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
h2 {
|
||||
background-color: #94bd5e;
|
||||
padding: 2px 0.5em 2px 0.5em;
|
||||
margin: 0;
|
||||
border-bottom: dotted 1px rgb(180,193,205);
|
||||
font-size: 110%;
|
||||
}
|
||||
|
||||
h3 {
|
||||
margin: 0;
|
||||
font-size: 100%;
|
||||
font-weight: bold;
|
||||
border-bottom: dotted 1px rgb(180,193,205);
|
||||
}
|
||||
|
||||
h4 {
|
||||
padding: 2px 0.5em 2px 0.5em;
|
||||
margin: 0;
|
||||
font-size: 90%;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
p, dl {
|
||||
padding: 0.5em;
|
||||
margin: 0;
|
||||
font-size: 90%;
|
||||
}
|
||||
|
||||
ul, ol {
|
||||
font-size: 90%;
|
||||
padding: 0.5em;
|
||||
margin: 0 0 0 0.25in;
|
||||
}
|
||||
|
||||
code {
|
||||
font-size: 105%;
|
||||
font-style: italic;
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
text-align: justify;
|
||||
font-style: italic;
|
||||
margin: 0 0.5in 0 0.5in;
|
||||
padding: 5px;
|
||||
border: 1px dotted black;
|
||||
}
|
||||
|
||||
.section {
|
||||
background: white;
|
||||
border-color: rgb(24,24,24);
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
padding: 0;
|
||||
margin-bottom: 0.5em;
|
||||
}
|
||||
|
||||
.section-body {
|
||||
padding: 0 1em;
|
||||
}
|
||||
|
||||
.section p, .section dl, .section ul, .section ol {
|
||||
padding: 0.5em 0;
|
||||
}
|
||||
|
||||
#menu {
|
||||
background: black;
|
||||
color: white;
|
||||
}
|
||||
|
||||
#menu a, #menu a:visited {
|
||||
background: black;
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#menu a:hover {
|
||||
background: black;
|
||||
color: white;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
#submenu {
|
||||
background: rgb(90%,97%,99%);
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
#pagetable tr {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
#pagetable {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#pagecolumn1 {
|
||||
width: 175px;
|
||||
padding: 1em 0 0 0;
|
||||
}
|
||||
|
||||
#pagecolumn1 a, #pagecolumn1 a:visited {
|
||||
color: rgb(0,0,164);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#pagecolumn1 a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
#pagecolumn2 {
|
||||
padding: 1em 2em;
|
||||
}
|
||||
|
||||
#pagecolumn2 a, #pagecolumn2 a:visited {
|
||||
color: rgb(0,0,164);
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
#pagecolumn2 a:hover {
|
||||
background-color: rgb(180,193,205);
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
#bookmarks {
|
||||
padding-left: 0.5em;
|
||||
font-size: 80%;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.notice {
|
||||
border: 1px solid black;
|
||||
margin-bottom: 0.5em;
|
||||
background: yellow;
|
||||
}
|
||||
|
||||
.faq-section {
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
.faq-atitle {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
181
viewvc.org/who.html
Normal file
181
viewvc.org/who.html
Normal file
@@ -0,0 +1,181 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||
<head>
|
||||
<title>ViewVC: About</title>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||
<link rel="stylesheet" type="text/css" href="./styles.css"/>
|
||||
<link rel="shortcut icon" href="./favicon.ico" type="image/x-icon" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="title">
|
||||
<a href="http://www.viewvc.org/"><img
|
||||
src="./images/title.jpg" alt="ViewVC: Repository Browsing"/></a>
|
||||
</div>
|
||||
|
||||
<div id="menu">
|
||||
<p><a href="./index.html">Home</a> |
|
||||
<a href="http://viewvc.tigris.org/">Project Page</a> |
|
||||
<a href="./download.html">Download</a> |
|
||||
<a href="./contributing.html">Contributing</a> |
|
||||
<a href="./faq.html">FAQ</a> |
|
||||
<a href="http://viewvc.tigris.org/nonav/source/browse/*checkout*/viewvc/trunk/LICENSE.html">License</a> |
|
||||
<a href="./contact.html">Contact</a> |
|
||||
<a href="./who.html">About</a>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<table id="pagetable">
|
||||
<tr>
|
||||
<td id="pagecolumn1">
|
||||
|
||||
<h4>On this page:</h4>
|
||||
|
||||
<ul id="bookmarks">
|
||||
<li><a href="#sec-history">The History of ViewVC</a></li>
|
||||
<li><a href="#sec-viewcvs-group">The ViewCVS Group</a></li>
|
||||
<li><a href="#sec-site-credits">About This Site</a></li>
|
||||
</ul>
|
||||
|
||||
<p><a href="http://validator.w3.org/check?uri=referer"><img
|
||||
src="http://www.w3.org/Icons/valid-xhtml10"
|
||||
alt="Valid XHTML 1.0 Strict" height="31" width="88" /></a>
|
||||
</p>
|
||||
|
||||
</td>
|
||||
<td id="pagecolumn2">
|
||||
|
||||
<div class="section">
|
||||
|
||||
<h2 id="sec-history">The History of ViewVC</h2>
|
||||
|
||||
<div class="section-body">
|
||||
|
||||
<p>The ViewVC software was inspired by early versions of cvsweb
|
||||
(originally written by Bill Fenner, further developed by Henner
|
||||
Zeller, and now maintained as <a
|
||||
href="http://www.freebsd.org/projects/cvsweb.html">CVSweb</a> by
|
||||
the FreeBSD community). Greg Stein wanted to make some changes and
|
||||
updates, but cvsweb was implemented in Perl. He wrote:</p>
|
||||
|
||||
<blockquote>
|
||||
|
||||
<p>"While I can manage some Perl, cvsweb was rather
|
||||
unmaintainable for me. So I undertook the task to convert the
|
||||
software to Python. As a result, I've actually been able to go
|
||||
<strong>way</strong> beyond the simple changes that I had
|
||||
envisioned."
|
||||
</p>
|
||||
|
||||
</blockquote>
|
||||
|
||||
<p>So ViewVC started out as just a port of the cvsweb script,
|
||||
originally called ViewCVS. Along the way, it has had numerous
|
||||
cleanups and other modifications, a process simplified by the
|
||||
elegance of the <a href="http://www.python.org/">Python</a>
|
||||
language.</p>
|
||||
|
||||
<p>In 2001, the ViewCVS project was moved to <a
|
||||
href="http://www.sourceforge.net">SourceForge</a>, a popular
|
||||
software collaboration environment. There the project continued to
|
||||
mature, releasing several stable-yet-pre-1.0 versions. In 2002,
|
||||
C. Michael Pilato began implementing support for Subversion in
|
||||
ViewCVS, taking advantage of a version control abstraction layer
|
||||
begun by Lucas Bruand. Along the way, Russell Yanofsky delivered
|
||||
large improvements to that abstraction, and to ViewCVS as whole.
|
||||
ViewCVS was well on its way to releasing a 1.0 version.</p>
|
||||
|
||||
<p>Of course, now that ViewCVS could browse Subversion repositories as
|
||||
easily as CVS ones, the ViewCVS name seemed inappropriate. Also,
|
||||
the active ViewCVS developers at the time were growing frustrated
|
||||
with SourceForge as a project hosting environment —
|
||||
Subversion wasn't yet available as an option for version control,
|
||||
the CVS service was always down at just the wrong moment, the bug
|
||||
trackers were painful to use, and so on. So in late 2005, the
|
||||
decision was made to rename the project to ViewVC, to convert the
|
||||
project's CVS data to Subversion, and to move the project and its
|
||||
version controlled and open issue data to <a
|
||||
href="http://www.tigris.org">Tigris.org</a>.</p>
|
||||
|
||||
<p>Today, ViewVC is being developed at <a
|
||||
href="http://viewvc.tigris.org">http://viewvc.tigris.org</a> by a
|
||||
small community of folks.</p>
|
||||
|
||||
</div> <!-- section-body -->
|
||||
</div> <!-- section -->
|
||||
|
||||
<div class="section">
|
||||
|
||||
<h2 id="sec-viewcvs-group">The ViewCVS Group</h2>
|
||||
|
||||
<div class="section-body">
|
||||
|
||||
<p>The ViewCVS Group is an informal group of people working on and
|
||||
developing the ViewVC package. The current set of members are
|
||||
listed below with some of their notable contributions:</p>
|
||||
|
||||
<dl>
|
||||
<dt><a href="http://www.lyra.org/greg/">Greg Stein</a></dt>
|
||||
<dd>original python port of Henner Zeller's cvsweb, secure popen
|
||||
implementation, configuration file implementation, rcsparse
|
||||
module, and EZT template engine</dd>
|
||||
|
||||
<dt>Jay Painter</dt>
|
||||
<dd>CVSdb query engine</dd>
|
||||
|
||||
<dt>Tanaka Akira</dt>
|
||||
<dd>enscript colorization and tarball generation</dd>
|
||||
|
||||
<dt>Tim Cera</dt>
|
||||
<dd>CvsGraph support, log_table template, regular expression search,
|
||||
and paging capability</dd>
|
||||
|
||||
<dt>Peter Funk</dt>
|
||||
<dd>standalone server, blimp logo, and numerous improvements to
|
||||
ViewVC's interfaces and documentation</dd>
|
||||
|
||||
<dt>Lucas Bruand</dt>
|
||||
<dd>C++ RCS parser (tparse) and vclib module for supporting new
|
||||
version control systems</dd>
|
||||
|
||||
<dt><a href="http://www.cmichaelpilato.com/">C. Michael Pilato</a></dt>
|
||||
<dd>Subversion support, root_as_url alternative URL scheme,
|
||||
templatization work, website design, documentation</dd>
|
||||
|
||||
<dt>Russell Yanofsky</dt>
|
||||
<dd>Windows support and the sapi module for supporting multiple web
|
||||
server interfaces, sweeping abstraction and UI improvements</dd>
|
||||
|
||||
<dt>James Henstridge</dt>
|
||||
<dd>integrated query interface, support for querying Subversion
|
||||
repositories, caching support, CSS formatting, and the EZT
|
||||
"define" directive</dd>
|
||||
|
||||
</dl>
|
||||
|
||||
</div> <!-- section-body -->
|
||||
</div> <!-- section -->
|
||||
|
||||
<div class="section">
|
||||
|
||||
<h2 id="sec-site-credits">About This Site</h2>
|
||||
|
||||
<div class="section-body">
|
||||
|
||||
<p>The ViewVC website was designed by <a
|
||||
href="http://www.cmichaelpilato.com/">C. Michael Pilato</a>. All
|
||||
HTML was hand-edited in Emacs, and the little splashes of graphical
|
||||
goodness owe their existence to Open Office and the Gimp. Textual
|
||||
content for the site is mostly the work of Greg Stein, but has been
|
||||
tweaked through the ages by various ViewVC contributors.</p>
|
||||
|
||||
</div> <!-- section-body -->
|
||||
</div> <!-- section -->
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
Reference in New Issue
Block a user