mirror of
https://github.com/vitalif/viewvc-4intranet
synced 2019-04-16 04:14:59 +03:00
Compare commits
1 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
1f399bbd6d |
58
CHANGES
58
CHANGES
@@ -1,58 +1,3 @@
|
||||
Version 1.1.18 (released 28-Feb-2013)
|
||||
|
||||
* fix exception raised by BDB-backed SVN repositories (issue #519)
|
||||
* hide revision-less files when rcsparse is in use
|
||||
* include branchpoints in branch views using rcsparse (issue #347)
|
||||
* miscellaneous cvsdb improvements:
|
||||
- add --port option to make-database (issue #521)
|
||||
- explicitly name columns in queries (issue #522)
|
||||
- update MySQL syntax to avoid discontinued "TYPE=" terms
|
||||
|
||||
Version 1.1.17 (released 25-Oct-2012)
|
||||
|
||||
* fix exception caused by uninitialized variable usage (issue #516)
|
||||
|
||||
Version 1.1.16 (released 24-Oct-2012)
|
||||
|
||||
* security fix: escape "extra" diff info to avoid XSS attack (issue #515)
|
||||
* add 'binary_mime_types' configuration option and handling (issue #510)
|
||||
* fix 'select for diffs' persistence across log pages (issue #512)
|
||||
* remove lock status and filesize check on directories in remote SVN views
|
||||
* fix bogus 'Annotation of' page title for non-annotated view (issue #514)
|
||||
|
||||
Version 1.1.15 (released 22-Jun-2012)
|
||||
|
||||
* security fix: complete authz support for remote SVN views (issue #353)
|
||||
* security fix: log msg leak in SVN revision view with unreadable copy source
|
||||
* fix several instances of incorrect information in remote SVN views
|
||||
* increase performance of some revision metadata lookups in remote SVN views
|
||||
* fix RSS feed regression introduced in 1.1.14
|
||||
|
||||
Version 1.1.14 (released 12-Jun-2012)
|
||||
|
||||
* fix annotation of svn files with non-URI-safe paths (issue #504)
|
||||
* handle file:/// Subversion rootpaths as local roots (issue #446)
|
||||
* fix bug caused by trying to case-normalize anon usernames (issue #505)
|
||||
* speed up log handling by reusing tokenization results (issue #506)
|
||||
* add support for custom revision log markup rules (issue #246)
|
||||
|
||||
Version 1.1.13 (released 23-Jan-2012)
|
||||
|
||||
* fix svndbadmin failure on deleted paths under Subversion 1.7 (issue #499)
|
||||
* fix annotation of files in svn roots with non-URI-safe paths
|
||||
* fix stray annotation warning in markup display of images
|
||||
* more gracefully handle attempts to display binary content (issue #501)
|
||||
|
||||
Version 1.1.12 (released 03-Nov-2011)
|
||||
|
||||
* fix path display in patch and certain diff views (issue #485)
|
||||
* fix broken cvsdb glob searching (issue 486)
|
||||
* allow svn revision specifiers to have leading r's (issue #441, #448)
|
||||
* allow environmental override of configuration location (issue #494)
|
||||
* fix exception HTML-escaping non-string data under WSGI (issue #454)
|
||||
* add links to root logs from roots view (issue #470)
|
||||
* use Pygments lexer-guessing functionality (issue #495)
|
||||
|
||||
Version 1.1.11 (released 17-May-2011)
|
||||
|
||||
* security fix: remove user-reachable override of cvsdb row limit
|
||||
@@ -61,7 +6,7 @@ Version 1.1.11 (released 17-May-2011)
|
||||
* fix stack trace when asked to checkout a directory (issue #478)
|
||||
* improve memory usage and speed of revision log markup (issue #477)
|
||||
* fix broken annotation view in CVS keyword-bearing files (issue #479)
|
||||
* warn users when query results are incomplete (issue #433)
|
||||
* warn users when query results are incomplete (issue #443)
|
||||
* avoid parsing errors on RCS newphrases in the admin section (issue #483)
|
||||
* make rlog parsing code more robust in certain error cases (issue #444)
|
||||
|
||||
@@ -76,6 +21,7 @@ Version 1.1.9 (released 18-Feb-2011)
|
||||
* make revision log "extra pages" count configurable
|
||||
* fix Subversion 1.4.x revision log compatibility code regression
|
||||
* display sanitized error when authzfile is malformed
|
||||
* handle file:/// Subversion rootpaths as local roots (issue #446)
|
||||
* restore markup of URLs in file contents (issue #455)
|
||||
* optionally display last-committed metadata in roots view (issue #457)
|
||||
|
||||
|
55
INSTALL
55
INSTALL
@@ -34,7 +34,7 @@ Congratulations on getting this far. :-)
|
||||
(http://www.python.org/)
|
||||
* Subversion, Version Control System, 1.3.1 or later
|
||||
(binary installation and Python bindings)
|
||||
(http://subversion.apache.org/)
|
||||
(http://subversion.tigris.org/)
|
||||
|
||||
Optional:
|
||||
|
||||
@@ -176,24 +176,7 @@ APACHE CONFIGURATION
|
||||
or /etc/local. Use the vendor documentation or the find utility if
|
||||
in doubt.
|
||||
|
||||
2) Depending on how your Apache configuration is setup by default, you
|
||||
might need to explicitly allow high-level access to the ViewVC
|
||||
install location.
|
||||
|
||||
<Directory <VIEWVC_INSTALLATION_DIRECTORY>>
|
||||
Order allow,deny
|
||||
Allow from all
|
||||
</Directory>
|
||||
|
||||
For example, if ViewVC is installed in /usr/local/viewvc-1.0 on
|
||||
your system:
|
||||
|
||||
<Directory /usr/local/viewvc-1.0>
|
||||
Order allow,deny
|
||||
Allow from all
|
||||
</Directory>
|
||||
|
||||
3) Configure Apache to expose ViewVC to users at the URL of your choice.
|
||||
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:
|
||||
@@ -204,13 +187,13 @@ APACHE CONFIGURATION
|
||||
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
|
||||
ScriptAlias /viewvc <VIEWVC_INSTALLATION_DIRECTORY>/bin/cgi/viewvc.cgi
|
||||
|
||||
into your httpd.conf file. Choose the location in httpd.conf where
|
||||
also the other ScriptAlias lines reside. Some examples:
|
||||
|
||||
ScriptAlias /viewvc /usr/local/viewvc-1.0/bin/cgi/viewvc.cgi
|
||||
ScriptAlias /query /usr/local/viewvc-1.0/bin/cgi/query.cgi
|
||||
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
|
||||
@@ -218,10 +201,6 @@ APACHE CONFIGURATION
|
||||
Copy the CGI scripts from
|
||||
<VIEWVC_INSTALLATION_DIRECTORY>/bin/cgi/*.cgi
|
||||
to the /cgi-bin/ directory configured in your httpd.conf file.
|
||||
|
||||
You can override configuration file location using:
|
||||
|
||||
SetEnv VIEWVC_CONF_PATHNAME /etc/viewvc.conf
|
||||
|
||||
------------------------------------------
|
||||
METHOD C: CGI mode in ExecCGI'd directory
|
||||
@@ -231,8 +210,8 @@ APACHE CONFIGURATION
|
||||
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:
|
||||
|
||||
Options +ExecCGI
|
||||
AddHandler cgi-script .cgi
|
||||
Options +ExecCGI
|
||||
AddHandler cgi-script .cgi
|
||||
|
||||
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"
|
||||
@@ -248,10 +227,6 @@ APACHE CONFIGURATION
|
||||
In httpd.conf, make sure that "AllowOverride All" or at least
|
||||
"AllowOverride FileInfo Options" are enabled for the directory
|
||||
you copied the files to.
|
||||
|
||||
You can override configuration file location using:
|
||||
|
||||
SetEnv VIEWVC_CONF_PATHNAME /etc/viewvc.conf
|
||||
|
||||
Note: If you are using Mod_Python under Apache 1.3 the tarball generation
|
||||
feature may not work because it uses multithreading. This works fine
|
||||
@@ -303,6 +278,13 @@ APACHE 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
|
||||
@@ -324,14 +306,7 @@ APACHE CONFIGURATION
|
||||
http://<server_name>/viewvc/~checkout~/<module_name>
|
||||
http://<server_name>/viewvc/<module_name>.tar.gz?view=tar
|
||||
|
||||
5) 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".
|
||||
|
||||
6) Optional: Protect your ViewVC instance from server-whacking webcrawlers.
|
||||
5) Optional: Protect your ViewVC instance from server-whacking webcrawlers.
|
||||
|
||||
As ViewVC is a web-based application which each page containing various
|
||||
links to other pages and views, you can expect your server's performance
|
||||
|
@@ -15,7 +15,7 @@
|
||||
|
||||
<blockquote>
|
||||
|
||||
<p><strong>Copyright © 1999-2013 The ViewCVS Group. All rights
|
||||
<p><strong>Copyright © 1999-2011 The ViewCVS Group. All rights
|
||||
reserved.</strong></p>
|
||||
|
||||
<p>By using ViewVC, you agree to the terms and conditions set forth
|
||||
@@ -62,8 +62,6 @@
|
||||
<li>March 18, 2009 — copyright years updated</li>
|
||||
<li>March 29, 2010 — copyright years updated</li>
|
||||
<li>February 18, 2011 — copyright years updated</li>
|
||||
<li>January 23, 2012 — copyright years updated</li>
|
||||
<li>January 04, 2013 — copyright years updated</li>
|
||||
</ul>
|
||||
|
||||
</body>
|
||||
|
@@ -3,7 +3,7 @@
|
||||
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2013 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
|
||||
|
@@ -3,7 +3,7 @@
|
||||
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2013 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
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2013 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
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2013 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
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2013 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
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2013 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
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2013 The ViewCVS Group. All Rights Reserved.
|
||||
# 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
|
||||
@@ -40,7 +40,7 @@ CREATE TABLE branches (
|
||||
branch varchar(64) binary DEFAULT '' NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE branch (branch)
|
||||
) ENGINE=MyISAM;
|
||||
) TYPE=MyISAM;
|
||||
|
||||
DROP TABLE IF EXISTS checkins;
|
||||
CREATE TABLE checkins (
|
||||
@@ -63,7 +63,7 @@ CREATE TABLE checkins (
|
||||
KEY dirid (dirid),
|
||||
KEY fileid (fileid),
|
||||
KEY branchid (branchid)
|
||||
) ENGINE=MyISAM;
|
||||
) TYPE=MyISAM;
|
||||
|
||||
DROP TABLE IF EXISTS descs;
|
||||
CREATE TABLE descs (
|
||||
@@ -72,7 +72,7 @@ CREATE TABLE descs (
|
||||
hash bigint(20) DEFAULT '0' NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
KEY hash (hash)
|
||||
) ENGINE=MyISAM;
|
||||
) TYPE=MyISAM;
|
||||
|
||||
DROP TABLE IF EXISTS dirs;
|
||||
CREATE TABLE dirs (
|
||||
@@ -80,7 +80,7 @@ CREATE TABLE dirs (
|
||||
dir varchar(255) binary DEFAULT '' NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE dir (dir)
|
||||
) ENGINE=MyISAM;
|
||||
) TYPE=MyISAM;
|
||||
|
||||
DROP TABLE IF EXISTS files;
|
||||
CREATE TABLE files (
|
||||
@@ -88,7 +88,7 @@ CREATE TABLE files (
|
||||
file varchar(255) binary DEFAULT '' NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE file (file)
|
||||
) ENGINE=MyISAM;
|
||||
) TYPE=MyISAM;
|
||||
|
||||
DROP TABLE IF EXISTS people;
|
||||
CREATE TABLE people (
|
||||
@@ -96,7 +96,7 @@ CREATE TABLE people (
|
||||
who varchar(128) binary DEFAULT '' NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE who (who)
|
||||
) ENGINE=MyISAM;
|
||||
) TYPE=MyISAM;
|
||||
|
||||
DROP TABLE IF EXISTS repositories;
|
||||
CREATE TABLE repositories (
|
||||
@@ -104,7 +104,7 @@ CREATE TABLE repositories (
|
||||
repository varchar(64) binary DEFAULT '' NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE repository (repository)
|
||||
) ENGINE=MyISAM;
|
||||
) TYPE=MyISAM;
|
||||
|
||||
DROP TABLE IF EXISTS tags;
|
||||
CREATE TABLE tags (
|
||||
@@ -118,7 +118,7 @@ CREATE TABLE tags (
|
||||
KEY dirid (dirid),
|
||||
KEY fileid (fileid),
|
||||
KEY branchid (branchid)
|
||||
) ENGINE=MyISAM;
|
||||
) TYPE=MyISAM;
|
||||
"""
|
||||
|
||||
## ------------------------------------------------------------------------
|
||||
@@ -132,7 +132,7 @@ CREATE TABLE branches (
|
||||
branch varchar(64) binary DEFAULT '' NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE branch (branch)
|
||||
) ENGINE=MyISAM;
|
||||
) TYPE=MyISAM;
|
||||
|
||||
DROP TABLE IF EXISTS commits;
|
||||
CREATE TABLE commits (
|
||||
@@ -156,7 +156,7 @@ CREATE TABLE commits (
|
||||
KEY fileid (fileid),
|
||||
KEY branchid (branchid),
|
||||
KEY descid (descid)
|
||||
) ENGINE=MyISAM;
|
||||
) TYPE=MyISAM;
|
||||
|
||||
DROP TABLE IF EXISTS descs;
|
||||
CREATE TABLE descs (
|
||||
@@ -165,7 +165,7 @@ CREATE TABLE descs (
|
||||
hash bigint(20) DEFAULT '0' NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
KEY hash (hash)
|
||||
) ENGINE=MyISAM;
|
||||
) TYPE=MyISAM;
|
||||
|
||||
DROP TABLE IF EXISTS dirs;
|
||||
CREATE TABLE dirs (
|
||||
@@ -173,7 +173,7 @@ CREATE TABLE dirs (
|
||||
dir varchar(255) binary DEFAULT '' NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE dir (dir)
|
||||
) ENGINE=MyISAM;
|
||||
) TYPE=MyISAM;
|
||||
|
||||
DROP TABLE IF EXISTS files;
|
||||
CREATE TABLE files (
|
||||
@@ -181,7 +181,7 @@ CREATE TABLE files (
|
||||
file varchar(255) binary DEFAULT '' NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE file (file)
|
||||
) ENGINE=MyISAM;
|
||||
) TYPE=MyISAM;
|
||||
|
||||
DROP TABLE IF EXISTS people;
|
||||
CREATE TABLE people (
|
||||
@@ -189,7 +189,7 @@ CREATE TABLE people (
|
||||
who varchar(128) binary DEFAULT '' NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE who (who)
|
||||
) ENGINE=MyISAM;
|
||||
) TYPE=MyISAM;
|
||||
|
||||
DROP TABLE IF EXISTS repositories;
|
||||
CREATE TABLE repositories (
|
||||
@@ -197,7 +197,7 @@ CREATE TABLE repositories (
|
||||
repository varchar(64) binary DEFAULT '' NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE repository (repository)
|
||||
) ENGINE=MyISAM;
|
||||
) TYPE=MyISAM;
|
||||
|
||||
DROP TABLE IF EXISTS tags;
|
||||
CREATE TABLE tags (
|
||||
@@ -211,7 +211,7 @@ CREATE TABLE tags (
|
||||
KEY dirid (dirid),
|
||||
KEY fileid (fileid),
|
||||
KEY branchid (branchid)
|
||||
) ENGINE=MyISAM;
|
||||
) TYPE=MyISAM;
|
||||
|
||||
DROP TABLE IF EXISTS metadata;
|
||||
CREATE TABLE metadata (
|
||||
@@ -219,7 +219,7 @@ CREATE TABLE metadata (
|
||||
value text,
|
||||
PRIMARY KEY (name),
|
||||
UNIQUE name (name)
|
||||
) ENGINE=MyISAM;
|
||||
) TYPE=MyISAM;
|
||||
INSERT INTO metadata (name, value) VALUES ('version', '1');
|
||||
"""
|
||||
|
||||
@@ -245,10 +245,6 @@ 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.
|
||||
|
||||
NOTE: If a hostname or port is supplied at the command line or during
|
||||
interactive prompting, this script will pass '--protocol=TCP' to
|
||||
'mysql'.
|
||||
|
||||
Options:
|
||||
|
||||
--dbname=ARG Use ARG as the ViewVC database name to create.
|
||||
@@ -257,8 +253,7 @@ Options:
|
||||
--help Show this usage message.
|
||||
|
||||
--hostname=ARG Use ARG as the hostname for the MySQL connection.
|
||||
|
||||
--port=ARG Use ARG as the port for the MySQL connection.
|
||||
[Default: localhost]
|
||||
|
||||
--password=ARG Use ARG as the password for the MySQL connection.
|
||||
|
||||
@@ -278,11 +273,10 @@ Options:
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
# Parse the command-line options, if any.
|
||||
dbname = version = hostname = port = username = password = None
|
||||
dbname = version = hostname = username = password = None
|
||||
opts, args = getopt.getopt(sys.argv[1:], '', [ 'dbname=',
|
||||
'help',
|
||||
'hostname=',
|
||||
'port=',
|
||||
'password=',
|
||||
'username=',
|
||||
'version=',
|
||||
@@ -296,8 +290,6 @@ if __name__ == "__main__":
|
||||
dbname = value
|
||||
elif name == '--hostname':
|
||||
hostname = value
|
||||
elif name == '--port':
|
||||
port = value
|
||||
elif name == '--username':
|
||||
username = value
|
||||
elif name == '--password':
|
||||
@@ -310,9 +302,7 @@ if __name__ == "__main__":
|
||||
|
||||
# Prompt for information not provided via command-line options.
|
||||
if hostname is None:
|
||||
hostname = raw_input("MySQL Hostname (leave blank for default): ")
|
||||
if port is None:
|
||||
port = raw_input("MySQL Port (leave blank for default): ")
|
||||
hostname = raw_input("MySQL Hostname [default: localhost]: ") or ""
|
||||
if username is None:
|
||||
username = raw_input("MySQL User: ")
|
||||
if password is None:
|
||||
@@ -320,7 +310,7 @@ if __name__ == "__main__":
|
||||
if dbname is None:
|
||||
dbname = raw_input("ViewVC Database Name [default: ViewVC]: ") or "ViewVC"
|
||||
|
||||
# Create the database.
|
||||
# Create the database
|
||||
dscript = string.replace(DATABASE_SCRIPT_COMMON, "<dbname>", dbname)
|
||||
if version == "1.0":
|
||||
print BONSAI_COMPAT
|
||||
@@ -328,22 +318,16 @@ if __name__ == "__main__":
|
||||
else:
|
||||
dscript = dscript + DATABASE_SCRIPT_VERSION_1
|
||||
|
||||
# Calculate command arguments.
|
||||
cmd_args = "--user=%s --password=%s" % (username, password)
|
||||
if hostname or port:
|
||||
cmd_args = cmd_args + " --protocol=TCP"
|
||||
if hostname:
|
||||
cmd_args = cmd_args + " --host=%s" % (hostname)
|
||||
if port:
|
||||
cmd_args = cmd_args + " --port=%s" % (port)
|
||||
|
||||
host_option = hostname and "--host=%s" % (hostname) or ""
|
||||
if sys.platform == "win32":
|
||||
cmd = "mysql %s" % (cmd_args)
|
||||
cmd = "mysql --user=%s --password=%s %s "\
|
||||
% (username, password, host_option)
|
||||
mysql = os.popen(cmd, "w") # popen2.Popen3 is not provided on windows
|
||||
mysql.write(dscript)
|
||||
status = mysql.close()
|
||||
else:
|
||||
cmd = "{ mysql %s ; } 2>&1" % (cmd_args)
|
||||
cmd = "{ mysql --user=%s --password=%s %s ; } 2>&1" \
|
||||
% (username, password, host_option)
|
||||
pipes = popen2.Popen3(cmd)
|
||||
pipes.tochild.write(dscript)
|
||||
pipes.tochild.close()
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2013 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
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2013 The ViewCVS Group. All Rights Reserved.
|
||||
# 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
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2013 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
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2013 The ViewCVS Group. All Rights Reserved.
|
||||
# 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
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 2004-2013 The ViewCVS Group. All Rights Reserved.
|
||||
# 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
|
||||
@@ -153,7 +153,7 @@ class SvnRev:
|
||||
fsroot = self._get_root_for_rev(rev)
|
||||
|
||||
# find changes in the revision
|
||||
editor = svn.repos.ChangeCollector(repo.fs, fsroot)
|
||||
editor = svn.repos.RevisionChangeCollector(repo.fs, rev)
|
||||
e_ptr, e_baton = svn.delta.make_editor(editor)
|
||||
svn.repos.svn_repos_replay(fsroot, e_ptr, e_baton)
|
||||
|
||||
@@ -164,33 +164,21 @@ class SvnRev:
|
||||
continue
|
||||
|
||||
# deal with the change types we handle
|
||||
action = None
|
||||
base_root = None
|
||||
base_path = change.base_path
|
||||
if change.base_path:
|
||||
base_root = self._get_root_for_rev(change.base_rev)
|
||||
|
||||
# figure out what kind of change this is, and get a diff
|
||||
# object for it. note that prior to 1.4 Subversion's
|
||||
# bindings didn't give us change.action, but that's okay
|
||||
# because back then deleted paths always had a change.path
|
||||
# of None.
|
||||
if hasattr(change, 'action') \
|
||||
and change.action == svn.repos.CHANGE_ACTION_DELETE:
|
||||
action = 'remove'
|
||||
elif not change.path:
|
||||
|
||||
if not change.path:
|
||||
action = 'remove'
|
||||
elif change.added:
|
||||
action = 'add'
|
||||
else:
|
||||
action = 'change'
|
||||
|
||||
if action == 'remove':
|
||||
diffobj = svn.fs.FileDiff(base_root, base_path, None, None)
|
||||
else:
|
||||
diffobj = svn.fs.FileDiff(base_root, base_path,
|
||||
fsroot, change.path)
|
||||
|
||||
diffobj = svn.fs.FileDiff(base_root and base_root or None,
|
||||
base_root and change.base_path or None,
|
||||
change.path and fsroot or None,
|
||||
change.path and change.path or None)
|
||||
diff_fp = diffobj.get_pipe()
|
||||
plus, minus = _get_diff_counts(diff_fp)
|
||||
self.changes.append((path, action, plus, minus))
|
||||
@@ -300,7 +288,7 @@ def usage():
|
||||
located at REPOS-PATH.
|
||||
|
||||
Usage: 1. %s [-v] rebuild REPOS-PATH
|
||||
2. %s [-v] update REPOS-PATH [REV[:REV2]] [--force]
|
||||
2. %s [-v] update REPOS-PATH [REV:[REV2]] [--force]
|
||||
3. %s [-v] purge REPOS-PATH
|
||||
|
||||
1. Rebuild the commit database information for the repository located
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/python
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2013 The ViewCVS Group. All Rights Reserved.
|
||||
# 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
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2013 The ViewCVS Group. All Rights Reserved.
|
||||
# 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
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/python
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2013 The ViewCVS Group. All Rights Reserved.
|
||||
# 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
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2013 The ViewCVS Group. All Rights Reserved.
|
||||
# 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
|
||||
|
@@ -86,8 +86,8 @@
|
||||
|
||||
## cvs_roots: Specifies each of the CVS roots on your system and
|
||||
## assigns names to them. Each root should be given by a "name: path"
|
||||
## value (where the path is an absolute filesystem path). Multiple roots
|
||||
## should be separated by commas and can be placed on separate lines.
|
||||
## value. Multiple roots should be separated by commas and can be
|
||||
## placed on separate lines.
|
||||
##
|
||||
## Example:
|
||||
## cvs_roots = cvsroot: /opt/cvs/repos1,
|
||||
@@ -97,13 +97,8 @@
|
||||
|
||||
## svn_roots: 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 (where the path is an absolute filesystem path).
|
||||
## Multiple roots should be separated by commas and can be placed on
|
||||
## separate lines.
|
||||
##
|
||||
## NOTE: ViewVC offers *experimental* support for displaying remote
|
||||
## Subversion repositories. Simply use the repository's URL instead
|
||||
## of a local filesystem path when defining the root.
|
||||
## a "name: path" value. Multiple roots should be separated by commas
|
||||
## and can be placed on separate lines.
|
||||
##
|
||||
## Example:
|
||||
## svn_roots = svnrepos: /opt/svn/,
|
||||
@@ -114,8 +109,7 @@
|
||||
## root_parents: Specifies a list of directories under which any
|
||||
## number of repositories may reside. You can specify multiple root
|
||||
## parents separated by commas or new lines, each of which is of the
|
||||
## form "path: type" (where the type is either "cvs" or "svn", and
|
||||
## the path is an absolute filesystem path).
|
||||
## form "path: type" (where type is either "cvs" or "svn").
|
||||
##
|
||||
## Rather than force you to add a new entry to 'cvs_roots' or
|
||||
## 'svn_roots' each time you create a new repository, ViewVC rewards
|
||||
@@ -351,64 +345,10 @@
|
||||
## 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).
|
||||
##
|
||||
## Valid items for this list include: "annotate", "co", "diff", "markup",
|
||||
## "roots", "tar".
|
||||
##
|
||||
## ----------+---------------------------------------------------------
|
||||
## VIEW | DESCRIPTION
|
||||
## ----------+---------------------------------------------------------
|
||||
## annotate | The 'annotate' view shows the contents of a single
|
||||
## | revision of a versioned file in exactly the same way as
|
||||
## | the markup view, but with additional line-by-line
|
||||
## | change attribution (the revision number, author, etc.
|
||||
## | the most recent edit to that line of text as of the
|
||||
## | displayed version).
|
||||
## ----------+---------------------------------------------------------
|
||||
## co | The 'co' (aka "checkout" or "download") view isn't
|
||||
## | really a branded view at all, but allows for direct
|
||||
## | downloading of the contents of a single revision of a
|
||||
## | versioned file.
|
||||
## ----------+---------------------------------------------------------
|
||||
## diff | The 'diff' view displays line-based differences between
|
||||
## | two revisions of a versioned file in a variety of
|
||||
## | different user-selectable formats.
|
||||
## ----------+---------------------------------------------------------
|
||||
## markup | The 'markup' view shows the contents of a single
|
||||
## | revision of a versioned file, with syntax highlighting
|
||||
## | where possible and enabled. It can also optionally
|
||||
## | show change log information for that revision of the
|
||||
## | file.
|
||||
## ----------+---------------------------------------------------------
|
||||
## roots | The 'roots' view is a simple listing of the various
|
||||
## | repositories which ViewVC has been configured to serve
|
||||
## | to users.
|
||||
## ----------+---------------------------------------------------------
|
||||
## tar | The 'tar' view isn't a branded view, but generates
|
||||
## | a GNU Tar archive file containing a single versioned
|
||||
## | directory and its contents (recursively).
|
||||
## ----------+---------------------------------------------------------
|
||||
## Possible values: "annotate", "co", "diff", "markup", "roots", "tar"
|
||||
##
|
||||
#allowed_views = annotate, diff, markup, roots
|
||||
|
||||
## Comma-delimited list of MIME content types (with support for fnmatch-
|
||||
## style glob characters) which are considered not-human-readable and for
|
||||
## which ViewVC will neither generate links to, nor support the direct
|
||||
## display of, non-checkout views which carry the file's content (the
|
||||
## 'markup', 'annotate', 'diff', and 'patch' views).
|
||||
##
|
||||
## NOTE: Handling of this option is given priority over ViewVC's
|
||||
## longstanding support for showing web-friendly file formats -- even
|
||||
## binary ones such as "image/jpeg" and "image/gif" -- in the 'markup'
|
||||
## view. Thus, if you add "image/*" to this list, 'markup'-view
|
||||
## display of JPEG, GIF, and PNG images will be disabled.
|
||||
##
|
||||
## Example:
|
||||
## binary_mime_types = application/octet-stream, image/*, application/pdf,
|
||||
## application/vnd*, application/msword, audio/*
|
||||
#
|
||||
#binary_mime_types =
|
||||
|
||||
## 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
|
||||
@@ -451,26 +391,6 @@
|
||||
##
|
||||
#mangle_email_addresses = 0
|
||||
|
||||
## custom_log_formatting: Specifies mappings of regular expressions to
|
||||
## substitution format strings used to URL-ize strings found in
|
||||
## revision log messages. Multiple mappings (specified as
|
||||
## REGEXP:FORMATSTRING) may be defined, separated by commas.
|
||||
##
|
||||
## NOTE: Due to a limitation of the configuration format, commas may
|
||||
## not be used in the regular expression portion of each mapping.
|
||||
## Commas "in the raw" may not be used in the format string portion,
|
||||
## either, but you can probably use the URI-encoded form of the comma
|
||||
## ("%2C") instead with no ill side-effects. If you must specify a
|
||||
## colon character in either the regular expression or the format
|
||||
## string, escape it with a preceding backslash ("\:").
|
||||
##
|
||||
## Example:
|
||||
## custom_log_formatting =
|
||||
## artf[0-9]+ : http://example.com/tracker?id=\0,
|
||||
## issue ([0-9]+) : http://example.com/bug?id=\1&opts=full%2csortby=id
|
||||
##
|
||||
#custom_log_formatting =
|
||||
|
||||
## 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
|
||||
@@ -579,7 +499,7 @@
|
||||
## (Only works well for C source files, otherwise diff's heuristic falls short.)
|
||||
## ('-p' option to diff)
|
||||
##
|
||||
#hr_funout = 1
|
||||
#hr_funout = 0
|
||||
|
||||
## hr_ignore_white: Ignore whitespace (indendation and stuff) for human
|
||||
## readable diffs.
|
||||
@@ -683,13 +603,7 @@
|
||||
#short_log_len = 80
|
||||
|
||||
## enable_syntax_coloration: Should we colorize known file content
|
||||
## syntaxes?
|
||||
##
|
||||
## NOTE: This feature requires the Pygments Python module
|
||||
## (http://pygments.org) and works only when ViewVC can determine the
|
||||
## MIME content type of the file whose contents it wishes to colorize.
|
||||
## Use the 'mime_types_files' configuration option to specify MIME
|
||||
## type mapping files useful for making that determination.
|
||||
## syntaxes? [Requires Pygments Python module]
|
||||
##
|
||||
#enable_syntax_coloration = 1
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
<html>
|
||||
<head>
|
||||
<title>ViewVC 1.1 Template Authoring Guide</title>
|
||||
<title>ViewVC 1.0 Template Authoring Guide</title>
|
||||
<style>
|
||||
body {
|
||||
background-color: rgb(180,193,205);
|
||||
@@ -38,13 +38,13 @@ td {
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<h1>ViewVC 1.1 Template Authoring Guide</h1>
|
||||
<h1>ViewVC 1.0 Template Authoring Guide</h1>
|
||||
|
||||
<div class="h2">
|
||||
<h2 id="introduction">Introduction</h2>
|
||||
|
||||
<p>This document represents an (unfinished) attempt at providing
|
||||
instructions for how to customize ViewVC's HTML output via
|
||||
documentation for how to customize ViewVC 1.0-dev's HTML output via
|
||||
modification of its templates.</p>
|
||||
|
||||
</div>
|
||||
@@ -802,11 +802,6 @@ td {
|
||||
<td>String</td>
|
||||
<td>This is a URL for the markup view of the left file.</td>
|
||||
</tr>
|
||||
<tr class="varlevel1">
|
||||
<td class="varname">patch_href</td>
|
||||
<td>String</td>
|
||||
<td>URL of the patch view for the file.</td>
|
||||
</tr>
|
||||
<tr class="varlevel1">
|
||||
<td class="varname">raw_diff</td>
|
||||
<td>String</td>
|
||||
@@ -2183,12 +2178,6 @@ td {
|
||||
<td>String</td>
|
||||
<td>Log message of last modification to the root.</td>
|
||||
</tr>
|
||||
<tr class="varlevel2">
|
||||
<td class="varname">roots.log_href</td>
|
||||
<td>String</td>
|
||||
<td>URL of log revision view for the top-most (root) directory of
|
||||
the root (repository).</td>
|
||||
</tr>
|
||||
<tr class="varlevel2">
|
||||
<td class="varname">roots.name</td>
|
||||
<td>String</td>
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2013 The ViewCVS Group. All Rights Reserved.
|
||||
# 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
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2013 The ViewCVS Group. All Rights Reserved.
|
||||
# Copyright (C) 1999-2010 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
|
||||
@@ -74,8 +74,7 @@ class HTMLBlameSource:
|
||||
self.path_parts = path_parts
|
||||
self.diff_url = diff_url
|
||||
self.include_url = include_url
|
||||
self.annotation, self.revision = self.repos.annotate(path_parts, opt_rev,
|
||||
True)
|
||||
self.annotation, self.revision = self.repos.annotate(path_parts, opt_rev)
|
||||
|
||||
def __getitem__(self, idx):
|
||||
item = self.annotation.__getitem__(idx)
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2013 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-2013 The ViewCVS Group. All Rights Reserved.
|
||||
# Copyright (C) 1999-2011 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
|
||||
@@ -112,8 +112,6 @@ class Config:
|
||||
_force_multi_value = (
|
||||
# Configuration values with multiple, comma-separated values.
|
||||
'allowed_views',
|
||||
'binary_mime_types',
|
||||
'custom_log_formatting',
|
||||
'cvs_roots',
|
||||
'kv_files',
|
||||
'languages',
|
||||
@@ -400,9 +398,7 @@ class Config:
|
||||
self.options.allowed_views = ['annotate', 'diff', 'markup', 'roots']
|
||||
self.options.authorizer = None
|
||||
self.options.mangle_email_addresses = 0
|
||||
self.options.custom_log_formatting = []
|
||||
self.options.default_file_view = "log"
|
||||
self.options.binary_mime_types = []
|
||||
self.options.http_expiration_time = 600
|
||||
self.options.generate_etags = 1
|
||||
self.options.svn_ignore_mimetype = 0
|
||||
|
24
lib/cvsdb.py
24
lib/cvsdb.py
@@ -1,6 +1,6 @@
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2013 The ViewCVS Group. All Rights Reserved.
|
||||
# Copyright (C) 1999-2011 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
|
||||
@@ -352,17 +352,9 @@ class CheckinDatabase:
|
||||
match = " LIKE "
|
||||
elif query_entry.match == "glob":
|
||||
match = " REGEXP "
|
||||
# Use fnmatch to translate the glob into a regular
|
||||
# expression. Sadly, we have to account for the fact
|
||||
# that in Python 2.6, fnmatch.translate() started
|
||||
# sticking '\Z(?ms)' at the end of the regular
|
||||
# expression instead of just '$', and doesn't prepend
|
||||
# the '^'.
|
||||
# use fnmatch to translate the glob into a regexp
|
||||
data = fnmatch.translate(data)
|
||||
if data[0] != '^':
|
||||
data = '^' + data
|
||||
if data[-7:] == '\Z(?ms)':
|
||||
data = data[:-7] + '$'
|
||||
if data[0] != '^': data = '^' + data
|
||||
elif query_entry.match == "regex":
|
||||
match = " REGEXP "
|
||||
elif query_entry.match == "notregex":
|
||||
@@ -520,10 +512,7 @@ class CheckinDatabase:
|
||||
if file_id == None:
|
||||
return None
|
||||
|
||||
sql = "SELECT type, ci_when, whoid, repositoryid, dirid, fileid, " \
|
||||
"revision, stickytag, branchid, addedlines, removedlines, " \
|
||||
"descid "\
|
||||
" FROM %s WHERE "\
|
||||
sql = "SELECT * FROM %s WHERE "\
|
||||
" repositoryid=%%s "\
|
||||
" AND dirid=%%s"\
|
||||
" AND fileid=%%s"\
|
||||
@@ -573,10 +562,7 @@ class CheckinDatabase:
|
||||
self.sql_purge('descs', 'id', 'descid', 'commits')
|
||||
self.sql_purge('people', 'id', 'whoid', 'commits')
|
||||
else:
|
||||
sql = "SELECT type, ci_when, whoid, repositoryid, dirid, " \
|
||||
"fileid, revision, stickytag, branchid, addedlines, " \
|
||||
"removedlines, descid "\
|
||||
" FROM checkins WHERE repositoryid=%s"
|
||||
sql = "SELECT * FROM checkins WHERE repositoryid=%s"
|
||||
sql_args = (rep_id, )
|
||||
cursor = self.db.cursor()
|
||||
cursor.execute(sql, sql_args)
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2013 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
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2013 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
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2013 The ViewCVS Group. All Rights Reserved.
|
||||
# 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
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2013 The ViewCVS Group. All Rights Reserved.
|
||||
# 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
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2013 The ViewCVS Group. All Rights Reserved.
|
||||
# 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
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2013 The ViewCVS Group. All Rights Reserved.
|
||||
# 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
|
||||
@@ -233,6 +233,9 @@ class WsgiServer(Server):
|
||||
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)
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 2006-2013 The ViewCVS Group. All Rights Reserved.
|
||||
# Copyright (C) 2006-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
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 2006-2013 The ViewCVS Group. All Rights Reserved.
|
||||
# Copyright (C) 2006-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
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 2008-2013 The ViewCVS Group. All Rights Reserved.
|
||||
# Copyright (C) 2008-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
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 2006-2013 The ViewCVS Group. All Rights Reserved.
|
||||
# Copyright (C) 2006-2011 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
|
||||
@@ -34,9 +34,9 @@ class ViewVCAuthorizer(vcauth.GenericViewVCAuthorizer):
|
||||
# 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 and string.upper(username) or username
|
||||
self.username = username.upper()
|
||||
elif self.force_username_case == "lower":
|
||||
self.username = username and string.lower(username) or username
|
||||
self.username = username.lower()
|
||||
elif not self.force_username_case:
|
||||
self.username = username
|
||||
else:
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2013 The ViewCVS Group. All Rights Reserved.
|
||||
# Copyright (C) 1999-2011 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
|
||||
@@ -170,19 +170,12 @@ class Repository:
|
||||
Return value is a python file object
|
||||
"""
|
||||
|
||||
def annotate(self, path_parts, rev, include_text=False):
|
||||
"""Return a list of Annotation object, sorted by their
|
||||
"line_number" components, which describe the lines of given
|
||||
version of a file.
|
||||
def annotate(self, path_parts, rev):
|
||||
"""Return a list of annotate file content lines and a revision.
|
||||
|
||||
The file path is specified as a list of components, relative to
|
||||
the root of the repository. e.g. ["subdir1", "subdir2", "filename"]
|
||||
|
||||
rev is the revision of the item to return information about.
|
||||
|
||||
If include_text is true, populate the Annotation objects' "text"
|
||||
members with the corresponding line of file content; otherwise,
|
||||
leave that member set to None."""
|
||||
The result is a list of Annotation objects, sorted by their
|
||||
line_number components.
|
||||
"""
|
||||
|
||||
def revinfo(self, rev):
|
||||
"""Return information about a global revision
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2013 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
|
||||
@@ -14,7 +14,6 @@ import os.path
|
||||
|
||||
|
||||
def canonicalize_rootpath(rootpath):
|
||||
assert os.path.isabs(rootpath)
|
||||
return os.path.normpath(rootpath)
|
||||
|
||||
|
||||
@@ -23,7 +22,6 @@ def expand_root_parent(parent_path):
|
||||
# "CVSROOT/config" is added the set of returned roots. Or, if the
|
||||
# PARENT_PATH itself contains a child "CVSROOT/config", then all its
|
||||
# subdirectories are returned as roots.
|
||||
assert os.path.isabs(parent_path)
|
||||
roots = {}
|
||||
subpaths = os.listdir(parent_path)
|
||||
cvsroot = os.path.exists(os.path.join(parent_path, "CVSROOT", "config"))
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2013 The ViewCVS Group. All Rights Reserved.
|
||||
# Copyright (C) 1999-2011 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
|
||||
@@ -332,13 +332,13 @@ class BinCVSRepository(BaseCVSRepository):
|
||||
args = rcs_args
|
||||
return popen.popen(cmd, args, mode, capture_err)
|
||||
|
||||
def annotate(self, path_parts, rev=None, include_text=False):
|
||||
def annotate(self, path_parts, rev=None):
|
||||
if self.itemtype(path_parts, rev) != vclib.FILE: # does auth-check
|
||||
raise vclib.Error("Path '%s' is not a file."
|
||||
% (string.join(path_parts, "/")))
|
||||
|
||||
from vclib.ccvs import blame
|
||||
source = blame.BlameSource(self.rcsfile(path_parts, 1), rev, include_text)
|
||||
source = blame.BlameSource(self.rcsfile(path_parts, 1), rev)
|
||||
return source, source.revision
|
||||
|
||||
def revinfo(self, rev):
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2013 The ViewCVS Group. All Rights Reserved.
|
||||
# Copyright (C) 1999-2011 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
|
||||
@@ -414,7 +414,7 @@ class CVSParser(rcsparse.Sink):
|
||||
|
||||
|
||||
class BlameSource:
|
||||
def __init__(self, rcs_file, opt_rev=None, include_text=False):
|
||||
def __init__(self, rcs_file, opt_rev=None):
|
||||
# Parse the CVS file
|
||||
parser = CVSParser()
|
||||
revision = parser.parse_cvs_file(rcs_file, opt_rev)
|
||||
@@ -428,7 +428,6 @@ class BlameSource:
|
||||
self.lines = lines
|
||||
self.num_lines = count
|
||||
self.parser = parser
|
||||
self.include_text = include_text
|
||||
|
||||
# keep track of where we are during an iteration
|
||||
self.idx = -1
|
||||
@@ -448,8 +447,6 @@ class BlameSource:
|
||||
line_number = idx + 1
|
||||
author = self.parser.revision_author[rev]
|
||||
thisline = self.lines[idx]
|
||||
if not self.include_text:
|
||||
thisline = None
|
||||
### TODO: Put a real date in here.
|
||||
item = vclib.Annotation(thisline, line_number, rev, prev_rev, author, None)
|
||||
self.last = item
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2013 The ViewCVS Group. All Rights Reserved.
|
||||
# Copyright (C) 1999-2011 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
|
||||
@@ -142,11 +142,11 @@ class CCVSRepository(BaseCVSRepository):
|
||||
return vclib._diff_fp(temp1, temp2, info1, info2,
|
||||
self.utilities.diff or 'diff', diff_args)
|
||||
|
||||
def annotate(self, path_parts, rev=None, include_text=False):
|
||||
def annotate(self, path_parts, rev=None):
|
||||
if self.itemtype(path_parts, rev) != vclib.FILE: # does auth-check
|
||||
raise vclib.Error("Path '%s' is not a file."
|
||||
% (string.join(path_parts, "/")))
|
||||
source = blame.BlameSource(self.rcsfile(path_parts, 1), rev, include_text)
|
||||
source = blame.BlameSource(self.rcsfile(path_parts, 1), rev)
|
||||
return source, source.revision
|
||||
|
||||
def revinfo(self, rev):
|
||||
@@ -200,7 +200,6 @@ class InfoSink(MatchingSink):
|
||||
self.matching_rev = None
|
||||
self.perfect_match = 0
|
||||
self.lockinfo = { }
|
||||
self.saw_revision = False
|
||||
|
||||
def define_tag(self, name, revision):
|
||||
MatchingSink.define_tag(self, name, revision)
|
||||
@@ -214,17 +213,10 @@ class InfoSink(MatchingSink):
|
||||
self.entry.absent = 1
|
||||
raise rcsparse.RCSStopParser
|
||||
|
||||
def parse_completed(self):
|
||||
if not self.saw_revision:
|
||||
#self.entry.errors.append("No revisions exist on %s" % (view_tag or "MAIN"))
|
||||
self.entry.absent = 1
|
||||
|
||||
def set_locker(self, rev, locker):
|
||||
self.lockinfo[rev] = locker
|
||||
|
||||
def define_revision(self, revision, date, author, state, branches, next):
|
||||
self.saw_revision = True
|
||||
|
||||
if self.perfect_match:
|
||||
return
|
||||
|
||||
@@ -232,18 +224,14 @@ class InfoSink(MatchingSink):
|
||||
rev = Revision(revision, date, author, state == "dead")
|
||||
rev.lockinfo = self.lockinfo.get(revision)
|
||||
|
||||
# perfect match if revision number matches tag number or if
|
||||
# revision is on trunk and tag points to trunk. imperfect match
|
||||
# if tag refers to a branch and either a) this revision is the
|
||||
# highest revision so far found on that branch, or b) this
|
||||
# revision is the branchpoint.
|
||||
# perfect match if revision number matches tag number or if revision is on
|
||||
# trunk and tag points to trunk. imperfect match if tag refers to a branch
|
||||
# and this revision is the highest revision so far found on that branch
|
||||
perfect = ((rev.number == tag.number) or
|
||||
(not tag.number and len(rev.number) == 2))
|
||||
if perfect or (tag.is_branch and \
|
||||
((tag.number == rev.number[:-1] and
|
||||
(not self.matching_rev or
|
||||
rev.number > self.matching_rev.number)) or
|
||||
(rev.number == tag.number[:-1]))):
|
||||
if perfect or (tag.is_branch and tag.number == rev.number[:-1] and
|
||||
(not self.matching_rev or
|
||||
rev.number > self.matching_rev.number)):
|
||||
self.matching_rev = rev
|
||||
self.perfect_match = perfect
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2013 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
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2013 The ViewCVS Group. All Rights Reserved.
|
||||
# Copyright (C) 1999-2011 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-2013 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
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2013 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
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2013 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
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2013 The ViewCVS Group. All Rights Reserved.
|
||||
# Copyright (C) 1999-2011 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,46 +19,26 @@ import urllib
|
||||
|
||||
_re_url = re.compile('^(http|https|file|svn|svn\+[^:]+)://')
|
||||
|
||||
def _canonicalize_path(path):
|
||||
import svn.core
|
||||
try:
|
||||
return svn.core.svn_path_canonicalize(path)
|
||||
except AttributeError: # svn_path_canonicalize() appeared in 1.4.0 bindings
|
||||
# There's so much more that we *could* do here, but if we're
|
||||
# here at all its because there's a really old Subversion in
|
||||
# place, and those older Subversion versions cared quite a bit
|
||||
# less about the specifics of path canonicalization.
|
||||
if re.search(_re_url, path):
|
||||
return path.rstrip('/')
|
||||
else:
|
||||
return os.path.normpath(path)
|
||||
|
||||
|
||||
def canonicalize_rootpath(rootpath):
|
||||
# Try to canonicalize the rootpath using Subversion semantics.
|
||||
rootpath = _canonicalize_path(rootpath)
|
||||
|
||||
# ViewVC's support for local repositories is more complete and more
|
||||
# performant than its support for remote ones, so if we're on a
|
||||
# Unix-y system and we have a file:/// URL, convert it to a local
|
||||
# path instead.
|
||||
if os.name == 'posix':
|
||||
rootpath_lower = rootpath.lower()
|
||||
if rootpath_lower in ['file://localhost',
|
||||
'file://localhost/',
|
||||
'file://',
|
||||
'file:///'
|
||||
]:
|
||||
return '/'
|
||||
if rootpath_lower.startswith('file://localhost/'):
|
||||
rootpath = os.path.normpath(urllib.unquote(rootpath[16:]))
|
||||
elif rootpath_lower.startswith('file:///'):
|
||||
rootpath = os.path.normpath(urllib.unquote(rootpath[7:]))
|
||||
|
||||
# Ensure that we have an absolute path (or URL), and return.
|
||||
if not re.search(_re_url, rootpath):
|
||||
assert os.path.isabs(rootpath)
|
||||
return rootpath
|
||||
try:
|
||||
import svn.core
|
||||
return svn.core.svn_path_canonicalize(rootpath)
|
||||
except:
|
||||
if os.name == 'posix':
|
||||
rootpath_lower = rootpath.lower()
|
||||
if rootpath_lower in ['file://localhost',
|
||||
'file://localhost/',
|
||||
'file://',
|
||||
'file:///'
|
||||
]:
|
||||
return '/'
|
||||
if rootpath_lower.startswith('file://localhost/'):
|
||||
return os.path.normpath(urllib.unquote(rootpath[16:]))
|
||||
elif rootpath_lower.startswith('file:///'):
|
||||
return os.path.normpath(urllib.unquote(rootpath[7:]))
|
||||
if re.search(_re_url, rootpath):
|
||||
return rootpath.rstrip('/')
|
||||
return os.path.normpath(rootpath)
|
||||
|
||||
|
||||
def expand_root_parent(parent_path):
|
||||
@@ -68,7 +48,6 @@ def expand_root_parent(parent_path):
|
||||
else:
|
||||
# Any subdirectories of PARENT_PATH which themselves have a child
|
||||
# "format" are returned as roots.
|
||||
assert os.path.isabs(parent_path)
|
||||
subpaths = os.listdir(parent_path)
|
||||
for rootname in subpaths:
|
||||
rootpath = os.path.join(parent_path, rootname)
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2013 The ViewCVS Group. All Rights Reserved.
|
||||
# Copyright (C) 1999-2011 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,10 +20,7 @@ import re
|
||||
import tempfile
|
||||
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, _canonicalize_path
|
||||
from svn_repos import Revision, SVNChangedPath, _datestr_to_date, _compare_paths, _path_parts, _cleanup_path, _rev2optrev, _fix_subversion_exception, _split_revprops
|
||||
from svn import core, delta, client, wc, ra
|
||||
|
||||
|
||||
@@ -54,14 +51,12 @@ 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, include_changes,
|
||||
cross_copies, cb_func, ctx):
|
||||
include_changes = include_changes and 1 or 0
|
||||
cross_copies = cross_copies and 1 or 0
|
||||
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, include_changes, not cross_copies,
|
||||
0, None, cb_func, ctx)
|
||||
log_limit, 1, not cross_copies, 0, None,
|
||||
cb_func, ctx)
|
||||
except AttributeError:
|
||||
# Wrap old svn_log_message_receiver_t interface with a
|
||||
# svn_log_entry_t one.
|
||||
@@ -77,14 +72,15 @@ def client_log(url, start_rev, end_rev, log_limit, include_changes,
|
||||
}
|
||||
cb_func(log_entry, pool)
|
||||
client.svn_client_log2([url], start_rev, end_rev, log_limit,
|
||||
include_changes, not cross_copies, cb_convert, ctx)
|
||||
1, not cross_copies, cb_convert, ctx)
|
||||
|
||||
### END COMPATABILITY CODE ###
|
||||
|
||||
|
||||
class LogCollector:
|
||||
### TODO: Make this thing authz-aware
|
||||
|
||||
def __init__(self, path, show_all_logs, lockinfo, access_check_func):
|
||||
def __init__(self, path, show_all_logs, lockinfo):
|
||||
# This class uses leading slashes for paths internally
|
||||
if not path:
|
||||
self.path = '/'
|
||||
@@ -93,12 +89,8 @@ class LogCollector:
|
||||
self.logs = []
|
||||
self.show_all_logs = show_all_logs
|
||||
self.lockinfo = lockinfo
|
||||
self.access_check_func = access_check_func
|
||||
self.done = False
|
||||
|
||||
def add_log(self, log_entry, pool):
|
||||
if self.done:
|
||||
return
|
||||
paths = log_entry.changed_paths
|
||||
revision = log_entry.revision
|
||||
msg, author, date, revprops = _split_revprops(log_entry.revprops)
|
||||
@@ -122,13 +114,9 @@ class LogCollector:
|
||||
if change.copyfrom_path:
|
||||
this_path = change.copyfrom_path + self.path[len(changed_path):]
|
||||
if self.show_all_logs or this_path:
|
||||
if self.access_check_func is None \
|
||||
or self.access_check_func(self.path[1:], revision):
|
||||
entry = Revision(revision, date, author, msg, None, self.lockinfo,
|
||||
self.path[1:], None, None)
|
||||
self.logs.append(entry)
|
||||
else:
|
||||
self.done = True
|
||||
entry = Revision(revision, date, author, msg, None, self.lockinfo,
|
||||
self.path[1:], None, None)
|
||||
self.logs.append(entry)
|
||||
if this_path:
|
||||
self.path = this_path
|
||||
|
||||
@@ -264,15 +252,14 @@ class RemoteSubversionRepository(vclib.Repository):
|
||||
### rev here should be the last history revision of the URL
|
||||
client.svn_client_cat(core.Stream(stream), url, _rev2optrev(rev), self.ctx)
|
||||
core.svn_stream_close(stream)
|
||||
lh_rev, c_rev = self._get_last_history_rev(path_parts, rev)
|
||||
return SelfCleanFP(tmp_file), lh_rev
|
||||
return SelfCleanFP(tmp_file), self._get_last_history_rev(path_parts, rev)
|
||||
|
||||
def listdir(self, path_parts, rev, options):
|
||||
path = self._getpath(path_parts)
|
||||
if self.itemtype(path_parts, rev) != vclib.DIR: # does auth-check
|
||||
raise vclib.Error("Path '%s' is not a directory." % path)
|
||||
rev = self._getrev(rev)
|
||||
entries = []
|
||||
entries = [ ]
|
||||
dirents, locks = self._get_dirents(path, rev)
|
||||
for name in dirents.keys():
|
||||
entry = dirents[name]
|
||||
@@ -280,9 +267,8 @@ class RemoteSubversionRepository(vclib.Repository):
|
||||
kind = vclib.DIR
|
||||
elif entry.kind == core.svn_node_file:
|
||||
kind = vclib.FILE
|
||||
else:
|
||||
kind = None
|
||||
entries.append(vclib.DirEntry(name, kind))
|
||||
if vclib.check_path_access(self, path_parts + [name], kind, rev):
|
||||
entries.append(vclib.DirEntry(name, kind))
|
||||
return entries
|
||||
|
||||
def dirlogs(self, path_parts, rev, entries, options):
|
||||
@@ -293,13 +279,11 @@ class RemoteSubversionRepository(vclib.Repository):
|
||||
dirents, locks = self._get_dirents(path, rev)
|
||||
for entry in entries:
|
||||
entry_path_parts = path_parts + [entry.name]
|
||||
dirent = dirents.get(entry.name, None)
|
||||
# dirents is authz-sanitized, so ensure the entry is found therein.
|
||||
if dirent is None:
|
||||
if not vclib.check_path_access(self, entry_path_parts, entry.kind, rev):
|
||||
continue
|
||||
# Get authz-sanitized revision metadata.
|
||||
dirent = dirents[entry.name]
|
||||
entry.date, entry.author, entry.log, revprops, changes = \
|
||||
self._revinfo(dirent.created_rev)
|
||||
self.revinfo(dirent.created_rev)
|
||||
entry.rev = str(dirent.created_rev)
|
||||
entry.size = dirent.size
|
||||
entry.lockinfo = None
|
||||
@@ -313,51 +297,28 @@ class RemoteSubversionRepository(vclib.Repository):
|
||||
rev = self._getrev(rev)
|
||||
url = self._geturl(path)
|
||||
|
||||
# If this is a file, fetch the lock status and size (as of REV)
|
||||
# for this item.
|
||||
lockinfo = size_in_rev = None
|
||||
if path_type == vclib.FILE:
|
||||
basename = path_parts[-1]
|
||||
list_url = self._geturl(self._getpath(path_parts[:-1]))
|
||||
dirents, locks = list_directory(list_url, _rev2optrev(rev),
|
||||
_rev2optrev(rev), 0, self.ctx)
|
||||
if locks.has_key(basename):
|
||||
lockinfo = locks[basename].owner
|
||||
if dirents.has_key(basename):
|
||||
size_in_rev = dirents[basename].size
|
||||
|
||||
# Special handling for the 'svn_latest_log' scenario.
|
||||
### FIXME: Don't like this hack. We should just introduce
|
||||
### something more direct in the vclib API.
|
||||
if options.get('svn_latest_log', 0):
|
||||
dir_lh_rev, dir_c_rev = self._get_last_history_rev(path_parts, rev)
|
||||
date, author, log, revprops, changes = self._revinfo(dir_lh_rev)
|
||||
return [vclib.Revision(dir_lh_rev, str(dir_lh_rev), date, author,
|
||||
None, log, size_in_rev, lockinfo)]
|
||||
# Use ls3 to fetch the lock status for this item.
|
||||
lockinfo = None
|
||||
basename = path_parts and path_parts[-1] or ""
|
||||
dirents, locks = list_directory(url, _rev2optrev(rev),
|
||||
_rev2optrev(rev), 0, self.ctx)
|
||||
if locks.has_key(basename):
|
||||
lockinfo = locks[basename].owner
|
||||
|
||||
def _access_checker(check_path, check_rev):
|
||||
return vclib.check_path_access(self, _path_parts(check_path),
|
||||
path_type, check_rev)
|
||||
|
||||
# It's okay if we're told to not show all logs on a file -- all
|
||||
# the revisions should match correctly anyway.
|
||||
lc = LogCollector(path, options.get('svn_show_all_dir_logs', 0),
|
||||
lockinfo, _access_checker)
|
||||
lc = LogCollector(path, options.get('svn_show_all_dir_logs', 0), lockinfo)
|
||||
|
||||
cross_copies = options.get('svn_cross_copies', 0)
|
||||
log_limit = 0
|
||||
if limit:
|
||||
log_limit = first + limit
|
||||
client_log(url, _rev2optrev(rev), _rev2optrev(1), log_limit, 1,
|
||||
client_log(url, _rev2optrev(rev), _rev2optrev(1), log_limit,
|
||||
cross_copies, lc.add_log, self.ctx)
|
||||
revs = lc.logs
|
||||
revs.sort()
|
||||
prev = None
|
||||
for rev in revs:
|
||||
# Swap out revision info with stuff from the cache (which is
|
||||
# authz-sanitized).
|
||||
rev.date, rev.author, rev.log, revprops, changes \
|
||||
= self._revinfo(rev.number)
|
||||
rev.prev = prev
|
||||
prev = rev
|
||||
revs.reverse()
|
||||
@@ -377,25 +338,13 @@ class RemoteSubversionRepository(vclib.Repository):
|
||||
_rev2optrev(rev), 0, self.ctx)
|
||||
return pairs and pairs[0][1] or {}
|
||||
|
||||
def annotate(self, path_parts, rev, include_text=False):
|
||||
def annotate(self, path_parts, rev):
|
||||
path = self._getpath(path_parts)
|
||||
if self.itemtype(path_parts, rev) != vclib.FILE: # does auth-check
|
||||
raise vclib.Error("Path '%s' is not a file." % path)
|
||||
rev = self._getrev(rev)
|
||||
url = self._geturl(path)
|
||||
|
||||
# Examine logs for the file to determine the oldest revision we are
|
||||
# permitted to see.
|
||||
log_options = {
|
||||
'svn_cross_copies' : 1,
|
||||
'svn_show_all_dir_logs' : 1,
|
||||
}
|
||||
revs = self.itemlog(path_parts, rev, vclib.SORTBY_REV, 0, 0, log_options)
|
||||
oldest_rev = revs[-1].number
|
||||
|
||||
# Now calculate the annotation data. Note that we'll not
|
||||
# inherently trust the provided author and date, because authz
|
||||
# rules might necessitate that we strip that information out.
|
||||
blame_data = []
|
||||
|
||||
def _blame_cb(line_no, revision, author, date,
|
||||
@@ -403,27 +352,21 @@ class RemoteSubversionRepository(vclib.Repository):
|
||||
prev_rev = None
|
||||
if revision > 1:
|
||||
prev_rev = revision - 1
|
||||
|
||||
# If we have an invalid revision, clear the date and author
|
||||
# values. Otherwise, if we have authz filtering to do, use the
|
||||
# revinfo cache to do so.
|
||||
if revision < 0:
|
||||
date = author = None
|
||||
elif self.auth:
|
||||
date, author, msg, revprops, changes = self._revinfo(revision)
|
||||
|
||||
# Strip text if the caller doesn't want it.
|
||||
if not include_text:
|
||||
line = None
|
||||
blame_data.append(vclib.Annotation(line, line_no + 1, revision, prev_rev,
|
||||
author, date))
|
||||
blame_data.append(vclib.Annotation(line, line_no+1, revision, prev_rev,
|
||||
author, None))
|
||||
|
||||
client.blame2(url, _rev2optrev(rev), _rev2optrev(oldest_rev),
|
||||
_rev2optrev(rev), _blame_cb, self.ctx)
|
||||
client.svn_client_blame(url, _rev2optrev(1), _rev2optrev(rev),
|
||||
_blame_cb, self.ctx)
|
||||
|
||||
return blame_data, rev
|
||||
|
||||
def revinfo(self, rev):
|
||||
return self._revinfo(rev, 1)
|
||||
rev = self._getrev(rev)
|
||||
cached_info = self._revinfo_cache.get(rev)
|
||||
if not cached_info:
|
||||
cached_info = self._revinfo_raw(rev)
|
||||
self._revinfo_cache[rev] = cached_info
|
||||
return tuple(cached_info)
|
||||
|
||||
def rawdiff(self, path_parts1, rev1, path_parts2, rev2, type, options={}):
|
||||
p1 = self._getpath(path_parts1)
|
||||
@@ -438,7 +381,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, revprops, changes = self.revinfo(rev)
|
||||
return date
|
||||
|
||||
try:
|
||||
@@ -464,11 +407,8 @@ class RemoteSubversionRepository(vclib.Repository):
|
||||
if rev is None or rev == 'HEAD':
|
||||
return self.youngest
|
||||
try:
|
||||
if type(rev) == type(''):
|
||||
while rev[0] == 'r':
|
||||
rev = rev[1:]
|
||||
rev = int(rev)
|
||||
except:
|
||||
except ValueError:
|
||||
raise vclib.InvalidRevision(rev)
|
||||
if (rev < 0) or (rev > self.youngest):
|
||||
raise vclib.InvalidRevision(rev)
|
||||
@@ -477,99 +417,42 @@ class RemoteSubversionRepository(vclib.Repository):
|
||||
def _geturl(self, path=None):
|
||||
if not path:
|
||||
return self.rootpath
|
||||
path = self.rootpath + '/' + urllib.quote(path)
|
||||
return _canonicalize_path(path)
|
||||
return self.rootpath + '/' + urllib.quote(path, "/*~")
|
||||
|
||||
def _get_dirents(self, path, rev):
|
||||
"""Return a 2-type of dirents and locks, possibly reading/writing
|
||||
from a local cache of that information. This functions performs
|
||||
authz checks, stripping out unreadable dirents."""
|
||||
from a local cache of that information."""
|
||||
|
||||
dir_url = self._geturl(path)
|
||||
path_parts = _path_parts(path)
|
||||
if path:
|
||||
key = str(rev) + '/' + path
|
||||
else:
|
||||
key = str(rev)
|
||||
|
||||
# Ensure that the cache gets filled...
|
||||
dirents_locks = self._dirent_cache.get(key)
|
||||
if not dirents_locks:
|
||||
tmp_dirents, locks = list_directory(dir_url, _rev2optrev(rev),
|
||||
_rev2optrev(rev), 0, self.ctx)
|
||||
dirents = {}
|
||||
for name, dirent in tmp_dirents.items():
|
||||
dirent_parts = path_parts + [name]
|
||||
kind = dirent.kind
|
||||
if (kind == core.svn_node_dir or kind == core.svn_node_file) \
|
||||
and vclib.check_path_access(self, dirent_parts,
|
||||
kind == core.svn_node_dir \
|
||||
and vclib.DIR or vclib.FILE, rev):
|
||||
lh_rev, c_rev = self._get_last_history_rev(dirent_parts, rev)
|
||||
dirent.created_rev = lh_rev
|
||||
dirents[name] = dirent
|
||||
dirents, locks = list_directory(dir_url, _rev2optrev(rev),
|
||||
_rev2optrev(rev), 0, self.ctx)
|
||||
dirents_locks = [dirents, locks]
|
||||
self._dirent_cache[key] = dirents_locks
|
||||
|
||||
# ...then return the goodies from the cache.
|
||||
return dirents_locks[0], dirents_locks[1]
|
||||
|
||||
def _get_last_history_rev(self, path_parts, rev):
|
||||
"""Return the a 2-tuple which contains:
|
||||
- the last interesting revision equal to or older than REV in
|
||||
the history of PATH_PARTS.
|
||||
- the created_rev of of PATH_PARTS as of REV."""
|
||||
|
||||
path = self._getpath(path_parts)
|
||||
url = self._geturl(self._getpath(path_parts))
|
||||
optrev = _rev2optrev(rev)
|
||||
|
||||
# Get the last-changed-rev.
|
||||
revisions = []
|
||||
def _info_cb(path, info, pool, retval=revisions):
|
||||
revisions.append(info.last_changed_rev)
|
||||
client.svn_client_info(url, optrev, optrev, _info_cb, 0, self.ctx)
|
||||
last_changed_rev = revisions[0]
|
||||
|
||||
# Now, this object might not have been directly edited since the
|
||||
# last-changed-rev, but it might have been the child of a copy.
|
||||
# To determine this, we'll run a potentially no-op log between
|
||||
# LAST_CHANGED_REV and REV.
|
||||
lc = LogCollector(path, 1, None, None)
|
||||
client_log(url, optrev, _rev2optrev(last_changed_rev), 1, 1, 0,
|
||||
lc.add_log, self.ctx)
|
||||
revs = lc.logs
|
||||
if revs:
|
||||
revs.sort()
|
||||
return revs[0].number, last_changed_rev
|
||||
else:
|
||||
return last_changed_rev, last_changed_rev
|
||||
return revisions[0]
|
||||
|
||||
def _revinfo_fetch(self, rev, include_changed_paths=0):
|
||||
need_changes = include_changed_paths or self.auth
|
||||
def _revinfo_raw(self, rev):
|
||||
# return 5-tuple (date, author, msg, revprops, changes)
|
||||
optrev = _rev2optrev(rev)
|
||||
revs = []
|
||||
|
||||
|
||||
def _log_cb(log_entry, pool, retval=revs):
|
||||
# If Subversion happens to call us more than once, we choose not
|
||||
# to care.
|
||||
if retval:
|
||||
return
|
||||
|
||||
revision = log_entry.revision
|
||||
msg, author, date, revprops = _split_revprops(log_entry.revprops)
|
||||
action_map = { 'D' : vclib.DELETED,
|
||||
'A' : vclib.ADDED,
|
||||
'R' : vclib.REPLACED,
|
||||
'M' : vclib.MODIFIED,
|
||||
}
|
||||
|
||||
# Easy out: if we won't use the changed-path info, just return a
|
||||
# changes-less tuple.
|
||||
if not need_changes:
|
||||
return revs.append([date, author, msg, revprops, None])
|
||||
|
||||
# Subversion 1.5 and earlier didn't offer the 'changed_paths2'
|
||||
# hash, and in Subversion 1.6, it's offered but broken.
|
||||
### 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()
|
||||
@@ -577,27 +460,29 @@ class RemoteSubversionRepository(vclib.Repository):
|
||||
changed_paths = log_entry.changed_paths
|
||||
paths = (changed_paths or {}).keys()
|
||||
paths.sort(lambda a, b: _compare_paths(a, b))
|
||||
|
||||
# If we get this far, our caller needs changed-paths, or we need
|
||||
# them for authz-related sanitization.
|
||||
revision = log_entry.revision
|
||||
msg, author, date, revprops = _split_revprops(log_entry.revprops)
|
||||
action_map = { 'D' : vclib.DELETED,
|
||||
'A' : vclib.ADDED,
|
||||
'R' : vclib.REPLACED,
|
||||
'M' : vclib.MODIFIED,
|
||||
}
|
||||
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.
|
||||
### 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.
|
||||
### 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:
|
||||
@@ -605,10 +490,9 @@ class RemoteSubversionRepository(vclib.Repository):
|
||||
if hasattr(change, 'props_modified'):
|
||||
if change.props_modified == core.svn_tristate_true:
|
||||
props_modified = 1
|
||||
|
||||
# Wrong, diddily wrong wrong wrong. Can you say,
|
||||
# "Manufacturing data left and right because it hurts to
|
||||
# figure out the right stuff?"
|
||||
### 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
|
||||
@@ -622,16 +506,15 @@ class RemoteSubversionRepository(vclib.Repository):
|
||||
base_path = path
|
||||
base_rev = revision - 1
|
||||
|
||||
# Check authz rules (sadly, we have to lie about the path type)
|
||||
### Check authz rules (we lie about the path type)
|
||||
parts = _path_parts(path)
|
||||
if vclib.check_path_access(self, parts, vclib.FILE, revision):
|
||||
if is_copy and base_path and (base_path != path):
|
||||
parts = _path_parts(base_path)
|
||||
if not vclib.check_path_access(self, parts, vclib.FILE, base_rev):
|
||||
if vclib.check_path_access(self, parts, vclib.FILE, base_rev):
|
||||
is_copy = 0
|
||||
base_path = None
|
||||
base_rev = None
|
||||
found_unreadable = 1
|
||||
changes.append(SVNChangedPath(path, revision, pathtype, base_path,
|
||||
base_rev, action, is_copy,
|
||||
text_modified, props_modified))
|
||||
@@ -639,45 +522,16 @@ class RemoteSubversionRepository(vclib.Repository):
|
||||
else:
|
||||
found_unreadable = 1
|
||||
|
||||
# If our caller doesn't want changed-path stuff, and we have
|
||||
# the info we need to make an authz determination already,
|
||||
# quit this loop and get on with it.
|
||||
if (not include_changed_paths) and found_unreadable and found_readable:
|
||||
break
|
||||
|
||||
# Filter unreadable information.
|
||||
if found_unreadable:
|
||||
msg = None
|
||||
if not found_readable:
|
||||
author = None
|
||||
date = None
|
||||
revs.append([date, author, msg, revprops, changes])
|
||||
|
||||
# Drop unrequested changes.
|
||||
if not include_changed_paths:
|
||||
changes = None
|
||||
|
||||
# Add this revision information to the "return" array.
|
||||
retval.append([date, author, msg, revprops, changes])
|
||||
|
||||
optrev = _rev2optrev(rev)
|
||||
client_log(self.rootpath, optrev, optrev, 1, need_changes, 0,
|
||||
_log_cb, self.ctx)
|
||||
client_log(self.rootpath, optrev, optrev, 1, 0, _log_cb, self.ctx)
|
||||
return tuple(revs[0])
|
||||
|
||||
def _revinfo(self, rev, include_changed_paths=0):
|
||||
"""Internal-use, cache-friendly revision information harvester."""
|
||||
|
||||
# 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.
|
||||
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 = self._revinfo_fetch(rev, include_changed_paths)
|
||||
self._revinfo_cache[rev] = cached_info
|
||||
return cached_info
|
||||
|
||||
##--- custom --##
|
||||
|
||||
def get_youngest_revision(self):
|
||||
@@ -695,16 +549,23 @@ class RemoteSubversionRepository(vclib.Repository):
|
||||
old_path = results[old_rev]
|
||||
except KeyError:
|
||||
raise vclib.ItemNotFound(path)
|
||||
old_path = _cleanup_path(old_path)
|
||||
old_path_parts = _path_parts(old_path)
|
||||
# Check access (lying about path types)
|
||||
if not vclib.check_path_access(self, old_path_parts, vclib.FILE, old_rev):
|
||||
raise vclib.ItemNotFound(path)
|
||||
return old_path
|
||||
|
||||
return _cleanup_path(old_path)
|
||||
|
||||
def created_rev(self, path, rev):
|
||||
lh_rev, c_rev = self._get_last_history_rev(_path_parts(path), rev)
|
||||
return lh_rev
|
||||
# NOTE: We can't use svn_client_propget here because the
|
||||
# interfaces in that layer strip out the properties not meant for
|
||||
# human consumption (such as svn:entry:committed-rev, which we are
|
||||
# using here to get the created revision of PATH@REV).
|
||||
kind = ra.svn_ra_check_path(self.ra_session, path, rev)
|
||||
if kind == core.svn_node_none:
|
||||
raise vclib.ItemNotFound(_path_parts(path))
|
||||
elif kind == core.svn_node_dir:
|
||||
props = get_directory_props(self.ra_session, path, rev)
|
||||
elif kind == core.svn_node_file:
|
||||
fetched_rev, props = ra.svn_ra_get_file(self.ra_session, path, rev, None)
|
||||
return int(props.get(core.SVN_PROP_ENTRY_COMMITTED_REV,
|
||||
SVN_INVALID_REVNUM))
|
||||
|
||||
def last_rev(self, path, peg_revision, limit_revision=None):
|
||||
"""Given PATH, known to exist in PEG_REVISION, find the youngest
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2013 The ViewCVS Group. All Rights Reserved.
|
||||
# Copyright (C) 1999-2011 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
|
||||
@@ -22,7 +22,6 @@ import time
|
||||
import tempfile
|
||||
import popen
|
||||
import re
|
||||
import urllib
|
||||
from svn import fs, repos, core, client, delta
|
||||
|
||||
|
||||
@@ -43,14 +42,7 @@ def _fix_subversion_exception(e):
|
||||
e.apr_err = e[1]
|
||||
if not hasattr(e, 'message'):
|
||||
e.message = e[0]
|
||||
|
||||
### Pre-1.4 Subversion doesn't have svn_path_canonicalize()
|
||||
def _canonicalize_path(path):
|
||||
try:
|
||||
return core.svn_path_canonicalize(path)
|
||||
except AttributeError:
|
||||
return path
|
||||
|
||||
|
||||
def _allow_all(root, path, pool):
|
||||
"""Generic authz_read_func that permits access to all paths"""
|
||||
return 1
|
||||
@@ -116,16 +108,11 @@ def _rev2optrev(rev):
|
||||
|
||||
def _rootpath2url(rootpath, path):
|
||||
rootpath = os.path.abspath(rootpath)
|
||||
drive, rootpath = os.path.splitdrive(rootpath)
|
||||
if rootpath and rootpath[0] != '/':
|
||||
rootpath = '/' + rootpath
|
||||
if os.sep != '/':
|
||||
rootpath = string.replace(rootpath, os.sep, '/')
|
||||
rootpath = urllib.quote(rootpath)
|
||||
path = urllib.quote(path)
|
||||
if drive:
|
||||
url = 'file:///' + drive + rootpath + '/' + path
|
||||
else:
|
||||
url = 'file://' + rootpath + '/' + path
|
||||
return _canonicalize_path(url)
|
||||
return 'file://' + string.join([rootpath, path], "/")
|
||||
|
||||
|
||||
# Given a dictionary REVPROPS of revision properties, pull special
|
||||
@@ -295,11 +282,10 @@ class FileContentsPipe:
|
||||
|
||||
|
||||
class BlameSource:
|
||||
def __init__(self, local_url, rev, first_rev, include_text, config_dir):
|
||||
def __init__(self, local_url, rev, first_rev, config_dir):
|
||||
self.idx = -1
|
||||
self.first_rev = first_rev
|
||||
self.blame_data = []
|
||||
self.include_text = include_text
|
||||
|
||||
ctx = client.svn_client_create_context()
|
||||
core.svn_config_ensure(config_dir)
|
||||
@@ -320,8 +306,6 @@ class BlameSource:
|
||||
prev_rev = None
|
||||
if rev > self.first_rev:
|
||||
prev_rev = rev - 1
|
||||
if not self.include_text:
|
||||
text = None
|
||||
self.blame_data.append(vclib.Annotation(text, line_no + 1, rev,
|
||||
prev_rev, author, None))
|
||||
|
||||
@@ -537,7 +521,7 @@ class LocalSubversionRepository(vclib.Repository):
|
||||
fsroot = self._getroot(rev)
|
||||
return fs.node_proplist(fsroot, path)
|
||||
|
||||
def annotate(self, path_parts, rev, include_text=False):
|
||||
def annotate(self, path_parts, rev):
|
||||
path = self._getpath(path_parts)
|
||||
path_type = self.itemtype(path_parts, rev) # does auth-check
|
||||
if path_type != vclib.FILE:
|
||||
@@ -548,8 +532,8 @@ class LocalSubversionRepository(vclib.Repository):
|
||||
{'svn_cross_copies': 1})
|
||||
youngest_rev, youngest_path = history[0]
|
||||
oldest_rev, oldest_path = history[-1]
|
||||
source = BlameSource(_rootpath2url(self.rootpath, path), youngest_rev,
|
||||
oldest_rev, include_text, self.config_dir)
|
||||
source = BlameSource(_rootpath2url(self.rootpath, path),
|
||||
youngest_rev, oldest_rev, self.config_dir)
|
||||
return source, youngest_rev
|
||||
|
||||
def revinfo(self, rev):
|
||||
@@ -651,7 +635,6 @@ class LocalSubversionRepository(vclib.Repository):
|
||||
is_copy = 0
|
||||
change.base_path = None
|
||||
change.base_rev = None
|
||||
found_unreadable = 1
|
||||
changedpaths[path] = SVNChangedPath(path, rev, pathtype,
|
||||
change.base_path,
|
||||
change.base_rev, action,
|
||||
@@ -663,19 +646,11 @@ class LocalSubversionRepository(vclib.Repository):
|
||||
return found_readable, found_unreadable, changedpaths.values()
|
||||
|
||||
def _get_change_copyinfo(fsroot, path, change):
|
||||
# If we know the copyfrom info, return it...
|
||||
if hasattr(change, 'copyfrom_known') and change.copyfrom_known:
|
||||
copyfrom_path = change.copyfrom_path
|
||||
copyfrom_rev = change.copyfrom_rev
|
||||
# ...otherwise, if this change could be a copy (that is, it
|
||||
# contains an add action), query the copyfrom info ...
|
||||
elif (change.change_kind == fs.path_change_add or
|
||||
change.change_kind == fs.path_change_replace):
|
||||
copyfrom_rev, copyfrom_path = fs.copied_from(fsroot, path)
|
||||
# ...else, there's no copyfrom info.
|
||||
else:
|
||||
copyfrom_rev = core.SVN_INVALID_REVNUM
|
||||
copyfrom_path = None
|
||||
copyfrom_rev, copyfrom_path = fs.copied_from(fsroot, path)
|
||||
return copyfrom_path, copyfrom_rev
|
||||
|
||||
def _simple_auth_check(fsroot):
|
||||
@@ -834,11 +809,8 @@ class LocalSubversionRepository(vclib.Repository):
|
||||
if rev is None or rev == 'HEAD':
|
||||
return self.youngest
|
||||
try:
|
||||
if type(rev) == type(''):
|
||||
while rev[0] == 'r':
|
||||
rev = rev[1:]
|
||||
rev = int(rev)
|
||||
except:
|
||||
except ValueError:
|
||||
raise vclib.InvalidRevision(rev)
|
||||
if (rev < 0) or (rev > self.youngest):
|
||||
raise vclib.InvalidRevision(rev)
|
||||
|
517
lib/viewvc.py
517
lib/viewvc.py
@@ -1,6 +1,6 @@
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2013 The ViewCVS Group. All Rights Reserved.
|
||||
# Copyright (C) 1999-2011 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
|
||||
@@ -14,7 +14,7 @@
|
||||
#
|
||||
# -----------------------------------------------------------------------
|
||||
|
||||
__version__ = '1.1.18'
|
||||
__version__ = '1.1.11'
|
||||
|
||||
# this comes from our library; measure the startup time
|
||||
import debug
|
||||
@@ -24,7 +24,6 @@ debug.t_start('imports')
|
||||
# standard modules that we know are in the path or builtin
|
||||
import sys
|
||||
import os
|
||||
import fnmatch
|
||||
import gzip
|
||||
import mimetypes
|
||||
import re
|
||||
@@ -1018,15 +1017,6 @@ def default_view(mime_type, cfg):
|
||||
return view_markup
|
||||
return view_checkout
|
||||
|
||||
def is_binary_file_mime_type(mime_type, cfg):
|
||||
"""Return True iff MIME_TYPE is set and matches one of the binary
|
||||
file mime type patterns in CFG."""
|
||||
if mime_type:
|
||||
for pattern in cfg.options.binary_mime_types:
|
||||
if fnmatch.fnmatch(mime_type, pattern):
|
||||
return True
|
||||
return False
|
||||
|
||||
def get_file_view_info(request, where, rev=None, mime_type=None, pathrev=-1):
|
||||
"""Return an object holding common hrefs and a viewability flag used
|
||||
for various views of FILENAME at revision REV whose MIME type is
|
||||
@@ -1087,12 +1077,7 @@ def get_file_view_info(request, where, rev=None, mime_type=None, pathrev=-1):
|
||||
params={'revision': rev},
|
||||
escape=1)
|
||||
|
||||
is_binary_file = is_binary_file_mime_type(mime_type, request.cfg)
|
||||
if is_binary_file:
|
||||
download_text_href = annotate_href = view_href = None
|
||||
prefer_markup = False
|
||||
else:
|
||||
prefer_markup = default_view(mime_type, request.cfg) == view_markup
|
||||
prefer_markup = default_view(mime_type, request.cfg) == view_markup
|
||||
|
||||
return _item(view_href=view_href,
|
||||
download_href=download_href,
|
||||
@@ -1114,29 +1099,6 @@ _re_rewrite_email = re.compile('([-a-zA-Z0-9_.\+]+)@'
|
||||
# Matches revision references
|
||||
_re_rewrite_svnrevref = re.compile(r'\b(r|rev #?|revision #?)([0-9]+)\b')
|
||||
|
||||
class ViewVCHtmlFormatterTokens:
|
||||
def __init__(self, tokens):
|
||||
self.tokens = tokens
|
||||
|
||||
def get_result(self, maxlen=0):
|
||||
"""Format the tokens per the registered set of formatters, and
|
||||
limited to MAXLEN visible characters (or unlimited if MAXLEN is
|
||||
0). Return a 3-tuple containing the formatted result string, the
|
||||
number of visible characters in the result string, and a boolean
|
||||
flag indicating whether or not S was truncated."""
|
||||
out = ''
|
||||
out_len = 0
|
||||
for token in self.tokens:
|
||||
chunk, chunk_len = token.converter(token.match, token.userdata, maxlen)
|
||||
out = out + chunk
|
||||
out_len = out_len + chunk_len
|
||||
if maxlen:
|
||||
maxlen = maxlen - chunk_len
|
||||
if maxlen <= 0:
|
||||
return out, out_len, 1
|
||||
return out, out_len, 0
|
||||
|
||||
|
||||
class ViewVCHtmlFormatter:
|
||||
"""Format a string as HTML-encoded output with customizable markup
|
||||
rules, for example turning strings that look like URLs into anchor links.
|
||||
@@ -1222,30 +1184,6 @@ class ViewVCHtmlFormatter:
|
||||
sapi.escape(trunc_s)), \
|
||||
len(trunc_s)
|
||||
|
||||
def format_custom_url(self, mobj, userdata, maxlen=0):
|
||||
"""Return a 2-tuple containing:
|
||||
- the text represented by MatchObject MOBJ, formatted as an
|
||||
linkified URL created by substituting match groups 0-9 into
|
||||
USERDATA (which is a format string that uses \N to
|
||||
represent the substitution locations) and with no more than
|
||||
MAXLEN characters in the non-HTML-tag portions. If MAXLEN
|
||||
is 0, there is no maximum.
|
||||
- the number of characters returned.
|
||||
"""
|
||||
format = userdata
|
||||
text = mobj.group(0)
|
||||
url = format
|
||||
for i in range(9):
|
||||
try:
|
||||
repl = mobj.group(i)
|
||||
except:
|
||||
repl = ''
|
||||
url = url.replace('\%d' % (i), repl)
|
||||
trunc_s = maxlen and text[:maxlen] or text
|
||||
return '<a href="%s">%s</a>' % (sapi.escape(url),
|
||||
sapi.escape(trunc_s)), \
|
||||
len(trunc_s)
|
||||
|
||||
def format_text(self, s, unused, maxlen=0):
|
||||
"""Return a 2-tuple containing:
|
||||
- the text S, HTML-escaped, containing no more than MAXLEN
|
||||
@@ -1278,14 +1216,20 @@ class ViewVCHtmlFormatter:
|
||||
"""
|
||||
out = ''
|
||||
out_len = 0
|
||||
tokens = self.tokenize_text(s)
|
||||
return tokens.get_result()
|
||||
for token in self._tokenize_text(s):
|
||||
chunk, chunk_len = token.converter(token.match, token.userdata, maxlen)
|
||||
out = out + chunk
|
||||
out_len = out_len + chunk_len
|
||||
if maxlen:
|
||||
maxlen = maxlen - chunk_len
|
||||
if maxlen <= 0:
|
||||
return out, out_len, 1
|
||||
return out, out_len, 0
|
||||
|
||||
def tokenize_text(self, s):
|
||||
"""Return a ViewVCHtmlFormatterTokens object containing the tokens
|
||||
created when parsing the string S. Callers can use that object's
|
||||
get_result() function to retrieve HTML-formatted text.
|
||||
"""
|
||||
def _entity_encode(self, s):
|
||||
return string.join(map(lambda x: '&#%d;' % (ord(x)), s), '')
|
||||
|
||||
def _tokenize_text(self, s):
|
||||
tokens = []
|
||||
# We could just have a "while s:" here instead of "for line: while
|
||||
# line:", but for really large log messages with heavy
|
||||
@@ -1332,80 +1276,36 @@ class ViewVCHtmlFormatter:
|
||||
converter=self.format_text,
|
||||
userdata=None))
|
||||
line = ''
|
||||
return ViewVCHtmlFormatterTokens(tokens)
|
||||
|
||||
def _entity_encode(self, s):
|
||||
return string.join(map(lambda x: '&#%d;' % (ord(x)), s), '')
|
||||
return tokens
|
||||
|
||||
|
||||
class LogFormatter:
|
||||
def __init__(self, request, log):
|
||||
self.request = request
|
||||
self.log = log or ''
|
||||
self.tokens = None
|
||||
self.cache = {} # (maxlen, htmlize) => resulting_log
|
||||
def format_log(request, log, maxlen=0, htmlize=1):
|
||||
if not log:
|
||||
return log
|
||||
|
||||
def get(self, maxlen=0, htmlize=1):
|
||||
cfg = self.request.cfg
|
||||
|
||||
# Prefer the cache.
|
||||
if self.cache.has_key((maxlen, htmlize)):
|
||||
return self.cache[(maxlen, htmlize)]
|
||||
|
||||
# If we are HTML-izing...
|
||||
if htmlize:
|
||||
# ...and we don't yet have ViewVCHtmlFormatter() object tokens...
|
||||
if not self.tokens:
|
||||
# ... then get them.
|
||||
lf = ViewVCHtmlFormatter()
|
||||
|
||||
# Rewrite URLs.
|
||||
lf.add_formatter(_re_rewrite_url, lf.format_url)
|
||||
|
||||
# Rewrite Subversion revision references.
|
||||
if self.request.roottype == 'svn':
|
||||
def revision_to_url(rev):
|
||||
return self.request.get_url(view_func=view_revision,
|
||||
params={'revision': rev},
|
||||
escape=1)
|
||||
lf.add_formatter(_re_rewrite_svnrevref, lf.format_svnrevref,
|
||||
revision_to_url)
|
||||
|
||||
# Rewrite email addresses.
|
||||
if cfg.options.mangle_email_addresses == 2:
|
||||
lf.add_formatter(_re_rewrite_email, lf.format_email_truncated)
|
||||
elif cfg.options.mangle_email_addresses == 1:
|
||||
lf.add_formatter(_re_rewrite_email, lf.format_email_obfuscated)
|
||||
else:
|
||||
lf.add_formatter(_re_rewrite_email, lf.format_email)
|
||||
|
||||
# Add custom rewrite handling per configuration.
|
||||
for rule in cfg.options.custom_log_formatting:
|
||||
rule = rule.replace('\\:', '\x01')
|
||||
regexp, format = map(lambda x: x.strip(), rule.split(':', 1))
|
||||
regexp = regexp.replace('\x01', ':')
|
||||
format = format.replace('\x01', ':')
|
||||
lf.add_formatter(re.compile(regexp), lf.format_custom_url, format)
|
||||
|
||||
# Tokenize the log message.
|
||||
self.tokens = lf.tokenize_text(self.log)
|
||||
|
||||
# Use our formatter to ... you know ... format.
|
||||
log, log_len, truncated = self.tokens.get_result(maxlen)
|
||||
result_log = log + (truncated and '…' or '')
|
||||
|
||||
# But if we're not HTML-izing...
|
||||
cfg = request.cfg
|
||||
if htmlize:
|
||||
lf = ViewVCHtmlFormatter()
|
||||
lf.add_formatter(_re_rewrite_url, lf.format_url)
|
||||
if request.roottype == 'svn':
|
||||
def revision_to_url(rev):
|
||||
return request.get_url(view_func=view_revision,
|
||||
params={'revision': rev},
|
||||
escape=1)
|
||||
lf.add_formatter(_re_rewrite_svnrevref, lf.format_svnrevref,
|
||||
revision_to_url)
|
||||
if cfg.options.mangle_email_addresses == 2:
|
||||
lf.add_formatter(_re_rewrite_email, lf.format_email_truncated)
|
||||
elif cfg.options.mangle_email_addresses == 1:
|
||||
lf.add_formatter(_re_rewrite_email, lf.format_email_obfuscated)
|
||||
else:
|
||||
# ...then do much more simplistic transformations as necessary.
|
||||
log = self.log
|
||||
if cfg.options.mangle_email_addresses == 2:
|
||||
log = re.sub(_re_rewrite_email, r'\1@...', log)
|
||||
result_log = maxlen and log[:maxlen] or log
|
||||
|
||||
# In either case, populate the cache and return the results.
|
||||
self.cache[(maxlen, htmlize)] = result_log
|
||||
return result_log
|
||||
|
||||
lf.add_formatter(_re_rewrite_email, lf.format_email)
|
||||
log, log_len, truncated = lf.get_result(log, maxlen)
|
||||
return log + (truncated and '…' or '')
|
||||
else:
|
||||
if cfg.options.mangle_email_addresses == 2:
|
||||
log = re.sub(_re_rewrite_email, r'\1@...', log)
|
||||
return maxlen and log[:maxlen] or log
|
||||
|
||||
_time_desc = {
|
||||
1 : 'second',
|
||||
@@ -1647,36 +1547,33 @@ def markup_escaped_urls(s):
|
||||
return "<a href=\"%s\">%s</a>" % (unescaped_url, url)
|
||||
return re.sub(_re_rewrite_escaped_url, _url_repl, s)
|
||||
|
||||
|
||||
def markup_stream(request, cfg, blame_data, file_lines, filename,
|
||||
mime_type, encoding, colorize):
|
||||
"""Return the contents of a versioned file as a list of
|
||||
vclib.Annotation objects, each representing one line of the file's
|
||||
contents. Use BLAME_DATA as the annotation information for the file
|
||||
if provided. Use FILE_LINES as the lines of file content text
|
||||
themselves. MIME_TYPE is the MIME content type of the file;
|
||||
ENCODING is its character encoding. If COLORIZE is true, attempt to
|
||||
apply syntax coloration to the file contents, and use the
|
||||
HTML-marked-up results as the text in the return vclib.Annotation
|
||||
objects."""
|
||||
|
||||
# Nothing to mark up? So be it.
|
||||
if not file_lines:
|
||||
return []
|
||||
|
||||
# Determine if we should (and can) use Pygments to highlight our
|
||||
# output. Reasons not to include a) being told not to by the
|
||||
# configuration, b) not being able to import the Pygments modules,
|
||||
# and c) Pygments not having a lexer for our file's format.
|
||||
pygments_lexer = None
|
||||
if colorize:
|
||||
def markup_stream_pygments(request, cfg, blame_data, fp, filename,
|
||||
mime_type, encoding):
|
||||
# Determine if we should use Pygments to highlight our output.
|
||||
# Reasons not to include a) being told not to by the configuration,
|
||||
# b) not being able to import the Pygments modules, and c) Pygments
|
||||
# not having a lexer for our file's format.
|
||||
blame_source = []
|
||||
if blame_data:
|
||||
for i in blame_data:
|
||||
i.text = sapi.escape(i.text)
|
||||
i.diff_href = None
|
||||
if i.prev_rev:
|
||||
i.diff_href = request.get_url(view_func=view_diff,
|
||||
params={'r1': i.prev_rev,
|
||||
'r2': i.rev},
|
||||
escape=1, partial=1)
|
||||
blame_source.append(i)
|
||||
blame_data = blame_source
|
||||
lexer = None
|
||||
use_pygments = cfg.options.enable_syntax_coloration
|
||||
try:
|
||||
from pygments import highlight
|
||||
from pygments.formatters import HtmlFormatter
|
||||
from pygments.lexers import ClassNotFound, \
|
||||
get_lexer_by_name, \
|
||||
get_lexer_for_mimetype, \
|
||||
get_lexer_for_filename, \
|
||||
guess_lexer
|
||||
get_lexer_for_filename
|
||||
if not encoding:
|
||||
encoding = 'guess'
|
||||
if cfg.options.detect_encoding:
|
||||
@@ -1685,50 +1582,50 @@ def markup_stream(request, cfg, blame_data, file_lines, filename,
|
||||
encoding = 'chardet'
|
||||
except (SyntaxError, ImportError):
|
||||
pass
|
||||
|
||||
# First, see if there's a Pygments lexer associated with MIME_TYPE.
|
||||
if mime_type:
|
||||
try:
|
||||
lexer = get_lexer_for_mimetype(mime_type,
|
||||
encoding=encoding,
|
||||
tabsize=cfg.options.tabsize,
|
||||
stripnl=False)
|
||||
except ClassNotFound:
|
||||
try:
|
||||
pygments_lexer = get_lexer_for_mimetype(mime_type,
|
||||
encoding=encoding,
|
||||
tabsize=cfg.options.tabsize,
|
||||
stripnl=False)
|
||||
lexer = get_lexer_for_filename(filename,
|
||||
encoding=encoding,
|
||||
tabsize=cfg.options.tabsize,
|
||||
stripnl=False)
|
||||
except ClassNotFound:
|
||||
pygments_lexer = None
|
||||
use_pygments = 0
|
||||
except ImportError:
|
||||
use_pygments = 0
|
||||
|
||||
# If we've no lexer thus far, try to find one based on the FILENAME.
|
||||
if not pygments_lexer:
|
||||
try:
|
||||
pygments_lexer = get_lexer_for_filename(filename,
|
||||
encoding=encoding,
|
||||
tabsize=cfg.options.tabsize,
|
||||
stripnl=False)
|
||||
except ClassNotFound:
|
||||
pygments_lexer = None
|
||||
|
||||
# Still no lexer? If we've reason to believe this is a text
|
||||
# file, try to guess the lexer based on the file's content.
|
||||
if not pygments_lexer and is_text(mime_type) and file_lines:
|
||||
try:
|
||||
pygments_lexer = guess_lexer(file_lines[0])
|
||||
except ClassNotFound:
|
||||
pygments_lexer = None
|
||||
|
||||
# If we aren't highlighting, just return an amalgamation of the
|
||||
# BLAME_DATA (if any) and the FILE_LINES.
|
||||
if not pygments_lexer:
|
||||
lines = []
|
||||
for i in range(len(file_lines)):
|
||||
line = file_lines[i].rstrip('\n\r')
|
||||
line = sapi.escape(string.expandtabs(line, cfg.options.tabsize))
|
||||
line = markup_escaped_urls(line)
|
||||
if blame_data:
|
||||
blame_item = blame_data[i]
|
||||
blame_item.text = line
|
||||
else:
|
||||
blame_item = vclib.Annotation(line, i + 1, None, None, None, None)
|
||||
blame_item.diff_href = None
|
||||
lines.append(blame_item)
|
||||
# If we aren't going to be highlighting anything, just return the
|
||||
# BLAME_SOURCE. If there's no blame_source, we'll generate a fake
|
||||
# one from the file contents we fetch with PATH and REV.
|
||||
if not use_pygments:
|
||||
if blame_source:
|
||||
class BlameSourceTabsizeWrapper:
|
||||
def __init__(self, blame_source, tabsize):
|
||||
self.blame_source = blame_source
|
||||
self.tabsize = cfg.options.tabsize
|
||||
def __getitem__(self, idx):
|
||||
item = self.blame_source.__getitem__(idx)
|
||||
item.text = string.expandtabs(item.text, self.tabsize)
|
||||
item.text = markup_escaped_urls(item.text)
|
||||
return item
|
||||
return BlameSourceTabsizeWrapper(blame_source, cfg.options.tabsize)
|
||||
else:
|
||||
lines = []
|
||||
line_no = 0
|
||||
while 1:
|
||||
line = fp.readline()
|
||||
if not line:
|
||||
break
|
||||
line_no = line_no + 1
|
||||
line = sapi.escape(string.expandtabs(line, cfg.options.tabsize))
|
||||
line = markup_escaped_urls(line)
|
||||
item = vclib.Annotation(line, line_no, None, None, None, None)
|
||||
item.diff_href = None
|
||||
lines.append(item)
|
||||
return lines
|
||||
|
||||
# If we get here, we're highlighting something.
|
||||
@@ -1743,7 +1640,7 @@ def markup_stream(request, cfg, blame_data, file_lines, filename,
|
||||
self.line_no = 0
|
||||
def write(self, buf):
|
||||
### FIXME: Don't bank on write() being called once per line
|
||||
buf = markup_escaped_urls(buf.rstrip('\n\r'))
|
||||
buf = markup_escaped_urls(buf)
|
||||
if self.has_blame_data:
|
||||
self.blame_data[self.line_no].text = buf
|
||||
else:
|
||||
@@ -1752,9 +1649,8 @@ def markup_stream(request, cfg, blame_data, file_lines, filename,
|
||||
item.diff_href = None
|
||||
self.blame_data.append(item)
|
||||
self.line_no = self.line_no + 1
|
||||
|
||||
ps = PygmentsSink(blame_data)
|
||||
highlight(string.join(file_lines, ''), pygments_lexer,
|
||||
ps = PygmentsSink(blame_source)
|
||||
highlight(fp.read(), lexer,
|
||||
HtmlFormatter(nowrap=True,
|
||||
classprefix="pygments-",
|
||||
encoding='utf-8'), ps)
|
||||
@@ -1793,8 +1689,7 @@ def get_itemprops(request, path_parts, rev):
|
||||
propnames.sort()
|
||||
props = []
|
||||
for name in propnames:
|
||||
lf = LogFormatter(request, itemprops[name])
|
||||
value = lf.get(maxlen=0, htmlize=1)
|
||||
value = format_log(request, itemprops[name])
|
||||
undisplayable = ezt.boolean(0)
|
||||
# skip non-utf8 property names
|
||||
try:
|
||||
@@ -1846,11 +1741,6 @@ def markup_or_annotate(request, is_annotate):
|
||||
revision = None
|
||||
mime_type, encoding = calculate_mime_type(request, path, rev)
|
||||
|
||||
# Is this display blocked by 'binary_mime_types' configuration?
|
||||
if is_binary_file_mime_type(mime_type, cfg):
|
||||
raise debug.ViewVCException('Display of binary file content disabled '
|
||||
'by configuration', '403 Forbidden')
|
||||
|
||||
# Is this a viewable image type?
|
||||
if is_viewable_image(mime_type) \
|
||||
and 'co' in cfg.options.allowed_views:
|
||||
@@ -1858,71 +1748,34 @@ def markup_or_annotate(request, is_annotate):
|
||||
fp.close()
|
||||
if check_freshness(request, None, revision, weak=1):
|
||||
return
|
||||
if is_annotate:
|
||||
annotation = 'binary'
|
||||
annotation = 'binary'
|
||||
image_src_href = request.get_url(view_func=view_checkout,
|
||||
params={'revision': rev}, escape=1)
|
||||
|
||||
# Not a viewable image.
|
||||
else:
|
||||
blame_data = None
|
||||
|
||||
# If this was an annotation request, try to annotate this file.
|
||||
# If something goes wrong, that's okay -- we'll gracefully revert
|
||||
# to a plain markup display.
|
||||
blame_source = None
|
||||
if is_annotate:
|
||||
# Try to annotate this file, but don't croak if we fail.
|
||||
try:
|
||||
blame_source, revision = request.repos.annotate(path, rev, False)
|
||||
blame_source, revision = request.repos.annotate(path, rev)
|
||||
annotation = 'annotated'
|
||||
if check_freshness(request, None, revision, weak=1):
|
||||
return
|
||||
# Create BLAME_DATA list from BLAME_SOURCE, adding diff_href
|
||||
# items to each relevant "line".
|
||||
blame_data = []
|
||||
for item in blame_source:
|
||||
item.diff_href = None
|
||||
if item.prev_rev:
|
||||
item.diff_href = request.get_url(view_func=view_diff,
|
||||
params={'r1': item.prev_rev,
|
||||
'r2': item.rev},
|
||||
escape=1, partial=1)
|
||||
blame_data.append(item)
|
||||
annotation = 'annotated'
|
||||
except vclib.NonTextualFileContents:
|
||||
annotation = 'binary'
|
||||
except:
|
||||
annotation = 'error'
|
||||
|
||||
# Grab the file contents.
|
||||
fp, revision = request.repos.openfile(path, rev, {'cvs_oldkeywords' : 1})
|
||||
if check_freshness(request, None, revision, weak=1):
|
||||
fp.close()
|
||||
return
|
||||
file_lines = fp.readlines()
|
||||
lines = markup_stream_pygments(request, cfg, blame_source, fp,
|
||||
path[-1], mime_type, encoding)
|
||||
fp.close()
|
||||
|
||||
# Do we have a differing number of file content lines and
|
||||
# annotation items? That's no good. Call it an error and don't
|
||||
# bother attempting the annotation display.
|
||||
if blame_data and (len(file_lines) != len(blame_data)):
|
||||
annotation = 'error'
|
||||
blame_data = None
|
||||
|
||||
# Try to markup the file contents/annotation. If we get an error
|
||||
# and we were colorizing the stream, try once more without the
|
||||
# colorization enabled.
|
||||
colorize = cfg.options.enable_syntax_coloration
|
||||
try:
|
||||
lines = markup_stream(request, cfg, blame_data, file_lines,
|
||||
path[-1], mime_type, encoding, colorize)
|
||||
except:
|
||||
if colorize:
|
||||
lines = markup_stream(request, cfg, blame_data, file_lines,
|
||||
path[-1], mime_type, encoding, False)
|
||||
else:
|
||||
raise debug.ViewVCException('Error displaying file contents',
|
||||
'500 Internal Server Error')
|
||||
|
||||
data = common_template_data(request, revision, mime_type)
|
||||
data = common_template_data(request, revision)
|
||||
data.merge(ezt.TemplateData({
|
||||
'mime_type' : mime_type,
|
||||
'log' : None,
|
||||
@@ -1946,19 +1799,14 @@ def markup_or_annotate(request, is_annotate):
|
||||
}))
|
||||
|
||||
if cfg.options.show_log_in_markup:
|
||||
options = {
|
||||
'svn_latest_log': 1, ### FIXME: Use of this magical value is uncool.
|
||||
'svn_cross_copies': 1,
|
||||
}
|
||||
options = {'svn_latest_log': 1} ### FIXME: No longer needed?
|
||||
revs = request.repos.itemlog(path, revision, vclib.SORTBY_REV,
|
||||
0, 1, options)
|
||||
entry = revs[-1]
|
||||
lf = LogFormatter(request, entry.log)
|
||||
|
||||
data['date'] = make_time_string(entry.date, cfg)
|
||||
data['author'] = entry.author
|
||||
data['changed'] = entry.changed
|
||||
data['log'] = lf.get(maxlen=0, htmlize=1)
|
||||
data['log'] = format_log(request, entry.log)
|
||||
data['size'] = entry.size
|
||||
|
||||
if entry.date is not None:
|
||||
@@ -2074,27 +1922,20 @@ def view_roots(request):
|
||||
rootnames = allroots.keys()
|
||||
rootnames.sort(icmp)
|
||||
for rootname in rootnames:
|
||||
root_path, root_type, lastmod = allroots[rootname]
|
||||
href = request.get_url(view_func=view_directory,
|
||||
where='', pathtype=vclib.DIR,
|
||||
params={'root': rootname}, escape=1)
|
||||
if root_type == vclib.SVN:
|
||||
log_href = request.get_url(view_func=view_log,
|
||||
where='', pathtype=vclib.DIR,
|
||||
params={'root': rootname}, escape=1)
|
||||
else:
|
||||
log_href = None
|
||||
lastmod = allroots[rootname][2]
|
||||
roots.append(_item(name=request.server.escape(rootname),
|
||||
type=root_type,
|
||||
path=root_path,
|
||||
type=allroots[rootname][1],
|
||||
path=allroots[rootname][0],
|
||||
author=lastmod and lastmod.author or None,
|
||||
ago=lastmod and lastmod.ago or None,
|
||||
date=lastmod and lastmod.date or None,
|
||||
log=lastmod and lastmod.log or None,
|
||||
short_log=lastmod and lastmod.short_log or None,
|
||||
rev=lastmod and lastmod.rev or None,
|
||||
href=href,
|
||||
log_href=log_href))
|
||||
href=href))
|
||||
|
||||
data = common_template_data(request)
|
||||
data.merge(ezt.TemplateData({
|
||||
@@ -2194,11 +2035,9 @@ def view_directory(request):
|
||||
row.date = make_time_string(file.date, cfg)
|
||||
row.ago = html_time(request, file.date)
|
||||
if cfg.options.show_logs:
|
||||
debug.t_start("dirview_logformat")
|
||||
lf = LogFormatter(request, file.log)
|
||||
row.log = lf.get(maxlen=0, htmlize=1)
|
||||
row.short_log = lf.get(maxlen=cfg.options.short_log_len, htmlize=1)
|
||||
debug.t_end("dirview_logformat")
|
||||
row.log = format_log(request, file.log)
|
||||
row.short_log = format_log(request, file.log,
|
||||
maxlen=cfg.options.short_log_len)
|
||||
row.lockinfo = file.lockinfo
|
||||
row.anchor = request.server.escape(file.name)
|
||||
row.name = request.server.escape(file.name)
|
||||
@@ -2551,7 +2390,6 @@ def view_log(request):
|
||||
sortby = vclib.SORTBY_DEFAULT
|
||||
|
||||
first = last = 0
|
||||
log_pagestart = None
|
||||
if cfg.options.log_pagesize:
|
||||
log_pagestart = int(request.query_dict.get('log_pagestart', 0))
|
||||
total = cfg.options.log_pagesextra * cfg.options.log_pagesize
|
||||
@@ -2576,6 +2414,7 @@ def view_log(request):
|
||||
entry.ago = None
|
||||
if rev.date is not None:
|
||||
entry.ago = html_time(request, rev.date, 1)
|
||||
entry.log = format_log(request, rev.log or '')
|
||||
entry.size = rev.size
|
||||
entry.lockinfo = rev.lockinfo
|
||||
entry.branch_point = None
|
||||
@@ -2583,9 +2422,6 @@ def view_log(request):
|
||||
entry.orig_path = None
|
||||
entry.copy_path = None
|
||||
|
||||
lf = LogFormatter(request, rev.log or '')
|
||||
entry.log = lf.get(maxlen=0, htmlize=1)
|
||||
|
||||
entry.view_href = None
|
||||
entry.download_href = None
|
||||
entry.download_text_href = None
|
||||
@@ -2675,8 +2511,7 @@ def view_log(request):
|
||||
if selected_rev != entry.rev:
|
||||
entry.sel_for_diff_href = \
|
||||
request.get_url(view_func=view_log,
|
||||
params={'r1': entry.rev,
|
||||
'log_pagestart': log_pagestart},
|
||||
params={'r1': entry.rev},
|
||||
escape=1)
|
||||
if entry.prev is not None:
|
||||
entry.diff_to_prev_href = \
|
||||
@@ -2817,9 +2652,7 @@ def view_log(request):
|
||||
|
||||
if cfg.options.log_pagesize:
|
||||
data['log_paging_action'], data['log_paging_hidden_values'] = \
|
||||
request.get_form(params={'log_pagestart': None,
|
||||
'r1': selected_rev,
|
||||
})
|
||||
request.get_form(params={'log_pagestart': None})
|
||||
data['log_pagestart'] = int(request.query_dict.get('log_pagestart',0))
|
||||
data['entries'] = paging_sws(data, 'entries', data['log_pagestart'],
|
||||
'rev', cfg.options.log_pagesize,
|
||||
@@ -3085,7 +2918,7 @@ class DiffSource:
|
||||
return _item(type='header',
|
||||
line_info_left=match.group(1),
|
||||
line_info_right=match.group(2),
|
||||
line_info_extra=self._format_text(match.group(3)))
|
||||
line_info_extra=match.group(3))
|
||||
|
||||
if line[0] == '\\':
|
||||
# \ No newline at end of file
|
||||
@@ -3153,8 +2986,7 @@ class DiffSource:
|
||||
class DiffSequencingError(Exception):
|
||||
pass
|
||||
|
||||
def diff_parse_headers(fp, diff_type, path1, path2, rev1, rev2,
|
||||
sym1=None, sym2=None):
|
||||
def diff_parse_headers(fp, diff_type, rev1, rev2, sym1=None, sym2=None):
|
||||
date1 = date2 = log_rev1 = log_rev2 = flag = None
|
||||
header_lines = []
|
||||
|
||||
@@ -3183,15 +3015,15 @@ def diff_parse_headers(fp, diff_type, path1, path2, rev1, rev2,
|
||||
if match:
|
||||
date1 = match.group(1)
|
||||
log_rev1 = match.group(2)
|
||||
line = '%s%s\t%s\t%s%s\n' % (f1, path1, date1, log_rev1,
|
||||
sym1 and ' ' + sym1 or '')
|
||||
if sym1:
|
||||
line = line[:-1] + ' %s\n' % sym1
|
||||
elif line[:len(f2)] == f2:
|
||||
match = _re_extract_rev.match(line)
|
||||
if match:
|
||||
date2 = match.group(1)
|
||||
log_rev2 = match.group(2)
|
||||
line = '%s%s\t%s\t%s%s\n' % (f2, path2, date2, log_rev2,
|
||||
sym2 and ' ' + sym2 or '')
|
||||
if sym2:
|
||||
line = line[:-1] + ' %s\n' % sym2
|
||||
parsing = 0
|
||||
elif line[:3] == 'Bin':
|
||||
flag = _RCSDIFF_IS_BINARY
|
||||
@@ -3300,13 +3132,6 @@ def view_patch(request):
|
||||
query_dict = request.query_dict
|
||||
p1, p2, rev1, rev2, sym1, sym2 = setup_diff(request)
|
||||
|
||||
mime_type1, encoding1 = calculate_mime_type(request, p1, rev1)
|
||||
mime_type2, encoding2 = calculate_mime_type(request, p2, rev2)
|
||||
if is_binary_file_mime_type(mime_type1, cfg) or \
|
||||
is_binary_file_mime_type(mime_type2, cfg):
|
||||
raise debug.ViewVCException('Display of binary file content disabled '
|
||||
'by configuration', '403 Forbidden')
|
||||
|
||||
# In the absence of a format dictation in the CGI params, we'll let
|
||||
# use the configured diff format, allowing 'c' to mean 'c' and
|
||||
# anything else to mean 'u'.
|
||||
@@ -3326,11 +3151,8 @@ def view_patch(request):
|
||||
raise debug.ViewVCException('Invalid path(s) or revision(s) passed '
|
||||
'to diff', '400 Bad Request')
|
||||
|
||||
path_left = _path_join(p1)
|
||||
path_right = _path_join(p2)
|
||||
date1, date2, flag, headers = diff_parse_headers(fp, diff_type,
|
||||
path_left, path_right,
|
||||
rev1, rev2, sym1, sym2)
|
||||
date1, date2, flag, headers = diff_parse_headers(fp, diff_type, rev1, rev2,
|
||||
sym1, sym2)
|
||||
|
||||
server_fp = get_writeready_server_file(request, 'text/plain')
|
||||
server_fp.write(headers)
|
||||
@@ -3347,13 +3169,6 @@ def view_diff(request):
|
||||
query_dict = request.query_dict
|
||||
p1, p2, rev1, rev2, sym1, sym2 = setup_diff(request)
|
||||
|
||||
mime_type1, encoding1 = calculate_mime_type(request, p1, rev1)
|
||||
mime_type2, encoding2 = calculate_mime_type(request, p2, rev2)
|
||||
if is_binary_file_mime_type(mime_type1, cfg) or \
|
||||
is_binary_file_mime_type(mime_type2, cfg):
|
||||
raise debug.ViewVCException('Display of binary file content disabled '
|
||||
'by configuration', '403 Forbidden')
|
||||
|
||||
# since templates are in use and subversion allows changes to the dates,
|
||||
# we can't provide a strong etag
|
||||
if check_freshness(request, None, '%s-%s' % (rev1, rev2), weak=1):
|
||||
@@ -3433,7 +3248,6 @@ def view_diff(request):
|
||||
changes = []
|
||||
if fp:
|
||||
date1, date2, flag, headers = diff_parse_headers(fp, diff_type,
|
||||
path_left, path_right,
|
||||
rev1, rev2, sym1, sym2)
|
||||
if human_readable:
|
||||
if flag is not None:
|
||||
@@ -3451,8 +3265,7 @@ def view_diff(request):
|
||||
fvi = get_file_view_info(request, path_left, rev1)
|
||||
left = _item(date=make_time_string(log_entry1.date, cfg),
|
||||
author=log_entry1.author,
|
||||
log=LogFormatter(request,
|
||||
log_entry1.log).get(maxlen=0, htmlize=1),
|
||||
log=format_log(request, log_entry1.log),
|
||||
size=log_entry1.size,
|
||||
ago=ago1,
|
||||
path=path_left,
|
||||
@@ -3468,8 +3281,7 @@ def view_diff(request):
|
||||
fvi = get_file_view_info(request, path_right, rev2)
|
||||
right = _item(date=make_time_string(log_entry2.date, cfg),
|
||||
author=log_entry2.author,
|
||||
log=LogFormatter(request,
|
||||
log_entry2.log).get(maxlen=0, htmlize=1),
|
||||
log=format_log(request, log_entry2.log),
|
||||
size=log_entry2.size,
|
||||
ago=ago2,
|
||||
path=path_right,
|
||||
@@ -3717,8 +3529,7 @@ def view_revision(request):
|
||||
propnames.sort()
|
||||
props = []
|
||||
for name in propnames:
|
||||
lf = LogFormatter(request, revprops[name])
|
||||
value = lf.get(maxlen=0, htmlize=1)
|
||||
value = format_log(request, revprops[name])
|
||||
undisplayable = ezt.boolean(0)
|
||||
# skip non-utf8 property names
|
||||
try:
|
||||
@@ -3841,14 +3652,13 @@ def view_revision(request):
|
||||
escape=1)
|
||||
jump_rev_action, jump_rev_hidden_values = \
|
||||
request.get_form(params={'revision': None})
|
||||
|
||||
lf = LogFormatter(request, msg)
|
||||
|
||||
data = common_template_data(request)
|
||||
data.merge(ezt.TemplateData({
|
||||
'rev' : str(rev),
|
||||
'author' : author,
|
||||
'date' : date_str,
|
||||
'log' : lf.get(maxlen=0, htmlize=1),
|
||||
'log' : format_log(request, msg),
|
||||
'properties' : props,
|
||||
'ago' : date is not None and html_time(request, date, 1) or None,
|
||||
'changes' : changes,
|
||||
@@ -4206,10 +4016,9 @@ def build_commit(request, files, max_files, dir_strip, format):
|
||||
commit.log = None
|
||||
commit.short_log = None
|
||||
else:
|
||||
lf = LogFormatter(request, desc)
|
||||
htmlize = (format != 'rss')
|
||||
commit.log = lf.get(maxlen=0, htmlize=htmlize)
|
||||
commit.short_log = lf.get(maxlen=cfg.options.short_log_len, htmlize=htmlize)
|
||||
commit.log = format_log(request, desc, 0, format != 'rss')
|
||||
commit.short_log = format_log(request, desc, cfg.options.short_log_len,
|
||||
format != 'rss')
|
||||
commit.author = request.server.escape(author)
|
||||
commit.rss_date = make_rss_time_string(date, request.cfg)
|
||||
if request.roottype == 'svn':
|
||||
@@ -4503,9 +4312,8 @@ def list_roots(request):
|
||||
date, author, msg, revprops, changes = repos.revinfo(youngest_rev)
|
||||
date_str = make_time_string(date, cfg)
|
||||
ago = html_time(request, date)
|
||||
lf = LogFormatter(request, msg)
|
||||
log = lf.get(maxlen=0, htmlize=1)
|
||||
short_log = lf.get(maxlen=cfg.options.short_log_len, htmlize=1)
|
||||
log = format_log(request, msg)
|
||||
short_log = format_log(request, msg, maxlen=cfg.options.short_log_len)
|
||||
lastmod = _item(ago=ago, author=author, date=date_str, log=log,
|
||||
short_log=short_log, rev=str(youngest_rev))
|
||||
except:
|
||||
@@ -4597,35 +4405,14 @@ def locate_root(cfg, rootname):
|
||||
return None, None
|
||||
|
||||
def load_config(pathname=None, server=None):
|
||||
"""Load the ViewVC configuration file. SERVER is the server object
|
||||
that will be using this configuration. Consult the environment for
|
||||
the variable VIEWVC_CONF_PATHNAME and VIEWCVS_CONF_PATHNAME (its
|
||||
legacy name) and, if set, use its value as the path of the
|
||||
configuration file; otherwise, use PATHNAME (if provided). Failing
|
||||
all else, use a hardcoded default configuration path."""
|
||||
|
||||
debug.t_start('load-config')
|
||||
|
||||
# See if the environment contains overrides to the configuration
|
||||
# path. If we have a SERVER object, consult its environment; use
|
||||
# the OS environment otherwise.
|
||||
env_pathname = None
|
||||
if server is not None:
|
||||
env_pathname = (server.getenv("VIEWVC_CONF_PATHNAME")
|
||||
or server.getenv("VIEWCVS_CONF_PATHNAME"))
|
||||
else:
|
||||
env_pathname = (os.environ.get("VIEWVC_CONF_PATHNAME")
|
||||
or os.environ.get("VIEWCVS_CONF_PATHNAME"))
|
||||
if pathname is None:
|
||||
pathname = (os.environ.get("VIEWVC_CONF_PATHNAME")
|
||||
or os.environ.get("VIEWCVS_CONF_PATHNAME")
|
||||
or os.path.join(os.path.dirname(os.path.dirname(__file__)),
|
||||
"viewvc.conf"))
|
||||
|
||||
# Try to find the configuration pathname by searching these ordered
|
||||
# locations: the environment, the passed-in PATHNAME, the hard-coded
|
||||
# default.
|
||||
pathname = (env_pathname
|
||||
or pathname
|
||||
or os.path.join(os.path.dirname(os.path.dirname(__file__)),
|
||||
"viewvc.conf"))
|
||||
|
||||
# Load the configuration!
|
||||
cfg = config.Config()
|
||||
cfg.set_defaults()
|
||||
cfg.load_config(pathname, server and server.getenv("HTTP_HOST"))
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2013 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
|
||||
|
@@ -92,15 +92,13 @@ numbers, and not literal):
|
||||
Also, drop a copy of the archive files into the root directory of
|
||||
the viewvc.org website (unversioned).
|
||||
|
||||
15. Update the Tigris.org website (^/trunk/www/index.html) to refer to
|
||||
the new release files and commit.
|
||||
15. 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.
|
||||
|
||||
svn ci -m "Bump latest advertised release."
|
||||
|
||||
16. Back on the release branch, 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:
|
||||
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:
|
||||
|
||||
svn ci -m "Begin a new release cycle."
|
||||
|
||||
@@ -113,13 +111,5 @@ numbers, and not literal):
|
||||
http://viewvc.tigris.org/issues/editmilestones.cgi?component=viewvc&action=add
|
||||
|
||||
18. Send to the announce@ list a message explaining all the cool new
|
||||
features.
|
||||
|
||||
http://viewvc.tigris.org/ds/viewForumSummary.do?dsForumId=4253
|
||||
|
||||
19. Post a new release notification at Freecode.
|
||||
|
||||
https://freecode.com/projects/viewvc/releases/new
|
||||
|
||||
20. Merge CHANGES for this release into the CHANGES file for newer
|
||||
release lines and commit.
|
||||
features, and post similar announcements to other places interested
|
||||
in this sort of stuff, such as Freshmeat (http://www.freshmeat.net).
|
||||
|
@@ -9,11 +9,7 @@
|
||||
[# ------------------------------------------------------------------------- ]
|
||||
|
||||
[# setup page definitions]
|
||||
[is annotation "annotated"]
|
||||
[define page_title]Annotation of /[where][end]
|
||||
[else]
|
||||
[define page_title]Contents of /[where][end]
|
||||
[end]
|
||||
[define page_title]Contents of /[where][end]
|
||||
[define help_href][docroot]/help_rootview.html[end]
|
||||
[# end]
|
||||
|
||||
|
@@ -27,7 +27,7 @@
|
||||
[roots.name]</a>
|
||||
</td>
|
||||
[is cfg.options.show_roots_lastmod "1"]
|
||||
<td style="width:20"> [if-any roots.log_href]<a href="[roots.log_href]">[roots.rev]</a>[else][roots.rev][end]</td>
|
||||
<td style="width:20"> [roots.rev]</td>
|
||||
<td style="width:20"> [roots.ago]</td>
|
||||
<td style="width:20"> [roots.author]</td>
|
||||
<td style="width:20"> [roots.short_log]</td>
|
||||
|
@@ -1,6 +1,6 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (C) 1999-2013 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,5 +1,5 @@
|
||||
/*
|
||||
# Copyright (C) 1999-2013 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
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
# Copyright (C) 1999-2013 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,5 +1,5 @@
|
||||
/*
|
||||
# Copyright (C) 1999-2013 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
|
||||
|
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
# Copyright (C) 1999-2013 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
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- Mode: python -*-
|
||||
#
|
||||
# Copyright (C) 1999-2013 The ViewCVS Group. All Rights Reserved.
|
||||
# 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
|
||||
@@ -209,8 +209,6 @@ def install_file(src_path, dst_path, mode, subst_path_vars,
|
||||
temp = raw_input("Do you want to [O]verwrite, [D]o "
|
||||
"not overwrite, or [V]iew "
|
||||
"differences? ")
|
||||
if len(temp) == 0:
|
||||
continue
|
||||
temp = string.lower(temp[0])
|
||||
if temp == "v" and ext not in BINARY_FILE_EXTS:
|
||||
print """
|
||||
|
Reference in New Issue
Block a user