mirror of
https://github.com/vitalif/viewvc-4intranet
synced 2019-04-16 04:14:59 +03:00
Compare commits
41 Commits
orig-r2243
...
1.1.0
Author | SHA1 | Date | |
---|---|---|---|
![]() |
6956afae73 | ||
![]() |
80a5efb953 | ||
![]() |
8843044571 | ||
![]() |
8b426f6fb3 | ||
![]() |
19ee8b32df | ||
![]() |
a5389019fa | ||
![]() |
7f272fbe04 | ||
![]() |
89edf0ac04 | ||
![]() |
71fbec8871 | ||
![]() |
504b1e1a8a | ||
![]() |
cf9381e0ee | ||
![]() |
3907172131 | ||
![]() |
c34752ce92 | ||
![]() |
40cc23f12a | ||
![]() |
9b7fea99d4 | ||
![]() |
85949a6464 | ||
![]() |
d5291a6b98 | ||
![]() |
9e41d171c9 | ||
![]() |
da54e91dea | ||
![]() |
41b2ae2c7a | ||
![]() |
1815220abe | ||
![]() |
a080d8eef4 | ||
![]() |
8c4af42d56 | ||
![]() |
7f1d0952fc | ||
![]() |
222aa4ec1f | ||
![]() |
c03bfd4b89 | ||
![]() |
6fa8cdf117 | ||
![]() |
c4c777ffe6 | ||
![]() |
3680903ed4 | ||
![]() |
6fe61a11bb | ||
![]() |
437975652f | ||
![]() |
7ff75bec7b | ||
![]() |
ea03f20f46 | ||
![]() |
a5df515d79 | ||
![]() |
fabe8e8a66 | ||
![]() |
f01fcc4ec4 | ||
![]() |
05e99f4c7b | ||
![]() |
d8aff4e58f | ||
![]() |
e8d3d6ad89 | ||
![]() |
1317088e3c | ||
![]() |
fe81ee5969 |
20
CHANGES
20
CHANGES
@@ -1,4 +1,4 @@
|
||||
Version 1.1.0 (released ??-???-????)
|
||||
Version 1.1.0 (released 13-May-2009)
|
||||
|
||||
* add support for full content diffs (issue #153)
|
||||
* make many more data dictionary items available to all views
|
||||
@@ -12,9 +12,7 @@ Version 1.1.0 (released ??-???-????)
|
||||
* add support for query by log message (issues #22, #121)
|
||||
* fix bug parsing 'svn blame' output with too-long author names (issue #221)
|
||||
* fix default standalone.py port to be within private IANA range (issue #234)
|
||||
* add support for integration with GNU source-highlight (issue #285)
|
||||
* add unified configury of allowed views
|
||||
* add support for disabling the checkout view (now the default state)
|
||||
* add unified configury of allowed views; checkout view disabled by default
|
||||
* add support for ranges of revisions to svndbadmin (issue #224)
|
||||
* make the query handling more forgiving of malformatted subdirs (issue #244)
|
||||
* add support for per-root configuration overrides (issue #371)
|
||||
@@ -36,7 +34,19 @@ Version 1.1.0 (released ??-???-????)
|
||||
* show RSS/query links only for roots found in commits database (issue #357)
|
||||
* recognize Subversion svn:mime-type property values (issue #364)
|
||||
* hide CVS files when viewing tags/branches on which they don't exist
|
||||
* add support for hiding errorful entries from the directory view (issue #105)
|
||||
* allow hiding of errorful entries from the directory view (issue #105)
|
||||
* fix directory view sorting UI
|
||||
* tolerate malformed Accept-Language headers (issue #396)
|
||||
* allow MIME type mapping overrides in ViewVC configuration (issue #401)
|
||||
* fix exception in rev-sorted remote Subversion directory views (issue #409)
|
||||
* allow setting of page sizes for log and dir views individually (issue #402)
|
||||
|
||||
Version 1.0.8 (released 05-May-2009)
|
||||
|
||||
* fix directory view sorting UI
|
||||
* tolerate malformed Accept-Language headers (issue #396)
|
||||
* fix directory log views in revision-less Subversion repositories
|
||||
* fix exception in rev-sorted remote Subversion directory views (issue #409)
|
||||
|
||||
Version 1.0.7 (released 14-Oct-2008)
|
||||
|
||||
|
2
INSTALL
2
INSTALL
@@ -139,7 +139,7 @@ installation instructions.
|
||||
default_root
|
||||
root_as_url_component
|
||||
rcs_dir
|
||||
mime_types_file
|
||||
mime_types_files
|
||||
|
||||
There are some other options that are usually nice to change. See
|
||||
viewvc.conf for more information. ViewVC provides a working,
|
||||
|
@@ -15,7 +15,7 @@
|
||||
|
||||
<blockquote>
|
||||
|
||||
<p><strong>Copyright © 1999-2008 The ViewCVS Group. All rights
|
||||
<p><strong>Copyright © 1999-2009 The ViewCVS Group. All rights
|
||||
reserved.</strong></p>
|
||||
|
||||
<p>By using ViewVC, you agree to the terms and conditions set forth
|
||||
@@ -59,6 +59,7 @@
|
||||
<li>March 17, 2006 — software renamed from "ViewCVS"</li>
|
||||
<li>April 10, 2007 — copyright years updated</li>
|
||||
<li>February 22, 2008 — copyright years updated</li>
|
||||
<li>March 18, 2009 — copyright years updated</li>
|
||||
</ul>
|
||||
|
||||
</body>
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2007 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
|
||||
@@ -18,22 +18,22 @@
|
||||
|
||||
import os, sys, string
|
||||
import popen2
|
||||
import getopt
|
||||
|
||||
INTRO_TEXT = """\
|
||||
This script creates the database and tables in MySQL used by the
|
||||
ViewVC checkin database. You will be prompted for: database server
|
||||
hostname, database user, database user password, and database name.
|
||||
This script will use the 'mysql' program to create the database for
|
||||
you. You will then need to set the appropriate parameters in the
|
||||
[cvsdb] section of your viewvc.conf file.
|
||||
"""
|
||||
|
||||
DATABASE_SCRIPT="""\
|
||||
## ------------------------------------------------------------------------
|
||||
## Stuff common to all schemas
|
||||
##
|
||||
DATABASE_SCRIPT_COMMON="""\
|
||||
DROP DATABASE IF EXISTS <dbname>;
|
||||
CREATE DATABASE <dbname>;
|
||||
|
||||
USE <dbname>;
|
||||
"""
|
||||
|
||||
## ------------------------------------------------------------------------
|
||||
## Version 0: The original, Bonsai-compatible schema.
|
||||
##
|
||||
DATABASE_SCRIPT_VERSION_0="""\
|
||||
DROP TABLE IF EXISTS branches;
|
||||
CREATE TABLE branches (
|
||||
id mediumint(9) NOT NULL auto_increment,
|
||||
@@ -121,28 +121,213 @@ CREATE TABLE tags (
|
||||
) TYPE=MyISAM;
|
||||
"""
|
||||
|
||||
## ------------------------------------------------------------------------
|
||||
## Version 1: Adds the 'metadata' table. Adds 'descid' index to
|
||||
## 'checkins' table, and renames that table to 'commits'.
|
||||
##
|
||||
DATABASE_SCRIPT_VERSION_1="""\
|
||||
DROP TABLE IF EXISTS branches;
|
||||
CREATE TABLE branches (
|
||||
id mediumint(9) NOT NULL auto_increment,
|
||||
branch varchar(64) binary DEFAULT '' NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE branch (branch)
|
||||
) TYPE=MyISAM;
|
||||
|
||||
DROP TABLE IF EXISTS commits;
|
||||
CREATE TABLE commits (
|
||||
type enum('Change','Add','Remove'),
|
||||
ci_when datetime DEFAULT '0000-00-00 00:00:00' NOT NULL,
|
||||
whoid mediumint(9) DEFAULT '0' NOT NULL,
|
||||
repositoryid mediumint(9) DEFAULT '0' NOT NULL,
|
||||
dirid mediumint(9) DEFAULT '0' NOT NULL,
|
||||
fileid mediumint(9) DEFAULT '0' NOT NULL,
|
||||
revision varchar(32) binary DEFAULT '' NOT NULL,
|
||||
stickytag varchar(255) binary DEFAULT '' NOT NULL,
|
||||
branchid mediumint(9) DEFAULT '0' NOT NULL,
|
||||
addedlines int(11) DEFAULT '0' NOT NULL,
|
||||
removedlines int(11) DEFAULT '0' NOT NULL,
|
||||
descid mediumint(9),
|
||||
UNIQUE repositoryid (repositoryid,dirid,fileid,revision),
|
||||
KEY ci_when (ci_when),
|
||||
KEY whoid (whoid),
|
||||
KEY repositoryid_2 (repositoryid),
|
||||
KEY dirid (dirid),
|
||||
KEY fileid (fileid),
|
||||
KEY branchid (branchid),
|
||||
KEY descid (descid)
|
||||
) TYPE=MyISAM;
|
||||
|
||||
DROP TABLE IF EXISTS descs;
|
||||
CREATE TABLE descs (
|
||||
id mediumint(9) NOT NULL auto_increment,
|
||||
description text,
|
||||
hash bigint(20) DEFAULT '0' NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
KEY hash (hash)
|
||||
) TYPE=MyISAM;
|
||||
|
||||
DROP TABLE IF EXISTS dirs;
|
||||
CREATE TABLE dirs (
|
||||
id mediumint(9) NOT NULL auto_increment,
|
||||
dir varchar(255) binary DEFAULT '' NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE dir (dir)
|
||||
) TYPE=MyISAM;
|
||||
|
||||
DROP TABLE IF EXISTS files;
|
||||
CREATE TABLE files (
|
||||
id mediumint(9) NOT NULL auto_increment,
|
||||
file varchar(255) binary DEFAULT '' NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE file (file)
|
||||
) TYPE=MyISAM;
|
||||
|
||||
DROP TABLE IF EXISTS people;
|
||||
CREATE TABLE people (
|
||||
id mediumint(9) NOT NULL auto_increment,
|
||||
who varchar(128) binary DEFAULT '' NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE who (who)
|
||||
) TYPE=MyISAM;
|
||||
|
||||
DROP TABLE IF EXISTS repositories;
|
||||
CREATE TABLE repositories (
|
||||
id mediumint(9) NOT NULL auto_increment,
|
||||
repository varchar(64) binary DEFAULT '' NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE repository (repository)
|
||||
) TYPE=MyISAM;
|
||||
|
||||
DROP TABLE IF EXISTS tags;
|
||||
CREATE TABLE tags (
|
||||
repositoryid mediumint(9) DEFAULT '0' NOT NULL,
|
||||
branchid mediumint(9) DEFAULT '0' NOT NULL,
|
||||
dirid mediumint(9) DEFAULT '0' NOT NULL,
|
||||
fileid mediumint(9) DEFAULT '0' NOT NULL,
|
||||
revision varchar(32) binary DEFAULT '' NOT NULL,
|
||||
UNIQUE repositoryid (repositoryid,dirid,fileid,branchid,revision),
|
||||
KEY repositoryid_2 (repositoryid),
|
||||
KEY dirid (dirid),
|
||||
KEY fileid (fileid),
|
||||
KEY branchid (branchid)
|
||||
) TYPE=MyISAM;
|
||||
|
||||
DROP TABLE IF EXISTS metadata;
|
||||
CREATE TABLE metadata (
|
||||
name varchar(255) binary DEFAULT '' NOT NULL,
|
||||
value text,
|
||||
PRIMARY KEY (name),
|
||||
UNIQUE name (name)
|
||||
) TYPE=MyISAM;
|
||||
INSERT INTO metadata (name, value) VALUES ('version', '1');
|
||||
"""
|
||||
|
||||
BONSAI_COMPAT="""
|
||||
WARNING: Creating Bonsai-compatible legacy database version. Some ViewVC
|
||||
features may not be available, or may not perform especially well.
|
||||
|
||||
"""
|
||||
|
||||
## ------------------------------------------------------------------------
|
||||
|
||||
def usage_and_exit(errmsg=None):
|
||||
stream = errmsg is None and sys.stdout or sys.stderr
|
||||
stream.write("""\
|
||||
Usage: %s [OPTIONS]
|
||||
|
||||
This script creates the database and tables in MySQL used by the
|
||||
ViewVC checkin database. In order to operate correctly, it needs to
|
||||
know the following: your database server hostname, database user,
|
||||
database user password, and database name. (You will be prompted for
|
||||
any of this information that you do not provide via command-line
|
||||
options.) This script will use the 'mysql' program to create the
|
||||
database for you. You will then need to set the appropriate
|
||||
parameters in the [cvsdb] section of your viewvc.conf file.
|
||||
|
||||
Options:
|
||||
|
||||
--dbname=ARG Use ARG as the ViewVC database name to create.
|
||||
[Default: ViewVC]
|
||||
|
||||
--help Show this usage message.
|
||||
|
||||
--hostname=ARG Use ARG as the hostname for the MySQL connection.
|
||||
[Default: localhost]
|
||||
|
||||
--password=ARG Use ARG as the password for the MySQL connection.
|
||||
|
||||
--username=ARG Use ARG as the username for the MySQL connection.
|
||||
|
||||
--version=ARG Create the database using the schema employed by
|
||||
version ARG of ViewVC. Valid values are:
|
||||
[ "1.0" ]
|
||||
|
||||
""" % (os.path.basename(sys.argv[0])))
|
||||
if errmsg is not None:
|
||||
stream.write("[ERROR] %s.\n" % (errmsg))
|
||||
sys.exit(1)
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
print INTRO_TEXT
|
||||
# Parse the command-line options, if any.
|
||||
dbname = version = hostname = username = password = None
|
||||
opts, args = getopt.getopt(sys.argv[1:], '', [ 'dbname=',
|
||||
'help',
|
||||
'hostname=',
|
||||
'password=',
|
||||
'username=',
|
||||
'version=',
|
||||
])
|
||||
if len(args) > 0:
|
||||
usage_and_exit("Unexpected command-line parameters")
|
||||
for name, value in opts:
|
||||
if name == '--help':
|
||||
usage_and_exit(0)
|
||||
elif name == '--dbname':
|
||||
dbname = value
|
||||
elif name == '--hostname':
|
||||
hostname = value
|
||||
elif name == '--username':
|
||||
username = value
|
||||
elif name == '--password':
|
||||
password = value
|
||||
elif name == '--version':
|
||||
if value in ["1.0"]:
|
||||
version = value
|
||||
else:
|
||||
usage_and_exit("Invalid version specified")
|
||||
|
||||
# Prompt for necessary information
|
||||
host = raw_input("MySQL Hostname [default: localhost]: ") or ""
|
||||
user = raw_input("MySQL User: ")
|
||||
passwd = raw_input("MySQL Password: ")
|
||||
dbase = raw_input("ViewVC Database Name [default: ViewVC]: ") or "ViewVC"
|
||||
# Prompt for information not provided via command-line options.
|
||||
if hostname is None:
|
||||
hostname = raw_input("MySQL Hostname [default: localhost]: ") or ""
|
||||
if username is None:
|
||||
username = raw_input("MySQL User: ")
|
||||
if password is None:
|
||||
password = raw_input("MySQL Password: ")
|
||||
if dbname is None:
|
||||
dbname = raw_input("ViewVC Database Name [default: ViewVC]: ") or "ViewVC"
|
||||
|
||||
# Create the database
|
||||
dscript = string.replace(DATABASE_SCRIPT, "<dbname>", dbase)
|
||||
host_option = host and "--host=%s" % (host) or ""
|
||||
dscript = string.replace(DATABASE_SCRIPT_COMMON, "<dbname>", dbname)
|
||||
if version == "1.0":
|
||||
print BONSAI_COMPAT
|
||||
dscript = dscript + DATABASE_SCRIPT_VERSION_0
|
||||
else:
|
||||
dscript = dscript + DATABASE_SCRIPT_VERSION_1
|
||||
|
||||
host_option = hostname and "--host=%s" % (hostname) or ""
|
||||
if sys.platform == "win32":
|
||||
cmd = "mysql --user=%s --password=%s %s "\
|
||||
% (user, passwd, host_option)
|
||||
% (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 --user=%s --password=%s %s ; } 2>&1" \
|
||||
% (user, passwd, host_option)
|
||||
% (username, password, host_option)
|
||||
pipes = popen2.Popen3(cmd)
|
||||
pipes.tochild.write(dscript)
|
||||
pipes.tochild.close()
|
||||
@@ -150,10 +335,11 @@ if __name__ == "__main__":
|
||||
status = pipes.wait()
|
||||
|
||||
if status:
|
||||
print "[ERROR] the database did not create sucessfully."
|
||||
print "[ERROR] The database did not create sucessfully."
|
||||
sys.exit(1)
|
||||
|
||||
print "Database created successfully."
|
||||
print "Database created successfully. Don't forget to configure the "
|
||||
print "[cvsdb] section of your viewvc.conf file."
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
sys.exit(0)
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2006 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-2006 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-2007 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
|
||||
@@ -226,9 +226,16 @@ If this doesn't work, please click on the link above.
|
||||
save_stdout = sys.stdout
|
||||
save_stderr = sys.stderr
|
||||
# For external tools like enscript we also need to redirect
|
||||
# the real stdout file descriptor. (On windows, reassigning the
|
||||
# sys.stdout variable is sufficient because pipe_cmds makes it
|
||||
# the standard output for child processes.)
|
||||
# the real stdout file descriptor.
|
||||
#
|
||||
# FIXME: This code used to carry the following comment:
|
||||
#
|
||||
# (On windows, reassigning the sys.stdout variable is sufficient
|
||||
# because pipe_cmds makes it the standard output for child
|
||||
# processes.)
|
||||
#
|
||||
# But we no longer use pipe_cmds. So at the very least, the
|
||||
# comment is stale. Is the code okay, though?
|
||||
if sys.platform != "win32": save_realstdout = os.dup(1)
|
||||
try:
|
||||
try:
|
||||
@@ -375,7 +382,7 @@ def gui(host, port):
|
||||
|
||||
# Early loading of configuration here. Used to
|
||||
# allow tinkering with configuration settings through the gui:
|
||||
handle_config()
|
||||
handle_config(options.config_file)
|
||||
if not LIBRARY_DIR:
|
||||
cfg.options.cvsgraph_conf = "../cgi/cvsgraph.conf.dist"
|
||||
|
||||
@@ -389,14 +396,6 @@ def gui(host, port):
|
||||
command=self.toggle_use_cvsgraph)
|
||||
self.cvsgraph_toggle.pack(side='top', anchor='w')
|
||||
|
||||
# enscript toggle:
|
||||
self.enscript_ivar = Tkinter.IntVar()
|
||||
self.enscript_ivar.set(cfg.options.use_enscript)
|
||||
self.enscript_toggle = Tkinter.Checkbutton(self.options_frm,
|
||||
text="enable enscript (needs binary)", var=self.enscript_ivar,
|
||||
command=self.toggle_use_enscript)
|
||||
self.enscript_toggle.pack(side='top', anchor='w')
|
||||
|
||||
# show_subdir_lastmod toggle:
|
||||
self.subdirmod_ivar = Tkinter.IntVar()
|
||||
self.subdirmod_ivar.set(cfg.options.show_subdir_lastmod)
|
||||
@@ -422,16 +421,27 @@ def gui(host, port):
|
||||
command=self.toggle_use_localtime)
|
||||
self.use_localtime_toggle.pack(side='top', anchor='w')
|
||||
|
||||
# use_pagesize integer var:
|
||||
self.usepagesize_lbl = Tkinter.Label(self.options_frm,
|
||||
text='Paging (number of items per page, 0 disables):')
|
||||
self.usepagesize_lbl.pack(side='top', anchor='w')
|
||||
self.use_pagesize_ivar = Tkinter.IntVar()
|
||||
self.use_pagesize_ivar.set(cfg.options.use_pagesize)
|
||||
self.use_pagesize_entry = Tkinter.Entry(self.options_frm,
|
||||
width=10, textvariable=self.use_pagesize_ivar)
|
||||
self.use_pagesize_entry.bind('<Return>', self.set_use_pagesize)
|
||||
self.use_pagesize_entry.pack(side='top', anchor='w')
|
||||
# log_pagesize integer var:
|
||||
self.log_pagesize_lbl = Tkinter.Label(self.options_frm,
|
||||
text='Paging (number of items per log page, 0 disables):')
|
||||
self.log_pagesize_lbl.pack(side='top', anchor='w')
|
||||
self.log_pagesize_ivar = Tkinter.IntVar()
|
||||
self.log_pagesize_ivar.set(cfg.options.log_pagesize)
|
||||
self.log_pagesize_entry = Tkinter.Entry(self.options_frm,
|
||||
width=10, textvariable=self.log_pagesize_ivar)
|
||||
self.log_pagesize_entry.bind('<Return>', self.set_log_pagesize)
|
||||
self.log_pagesize_entry.pack(side='top', anchor='w')
|
||||
|
||||
# dir_pagesize integer var:
|
||||
self.dir_pagesize_lbl = Tkinter.Label(self.options_frm,
|
||||
text='Paging (number of items per dir page, 0 disables):')
|
||||
self.dir_pagesize_lbl.pack(side='top', anchor='w')
|
||||
self.dir_pagesize_ivar = Tkinter.IntVar()
|
||||
self.dir_pagesize_ivar.set(cfg.options.dir_pagesize)
|
||||
self.dir_pagesize_entry = Tkinter.Entry(self.options_frm,
|
||||
width=10, textvariable=self.dir_pagesize_ivar)
|
||||
self.dir_pagesize_entry.bind('<Return>', self.set_dir_pagesize)
|
||||
self.dir_pagesize_entry.pack(side='top', anchor='w')
|
||||
|
||||
# directory view template:
|
||||
self.dirtemplate_lbl = Tkinter.Label(self.options_frm,
|
||||
@@ -507,9 +517,6 @@ def gui(host, port):
|
||||
def toggle_use_cvsgraph(self, event=None):
|
||||
cfg.options.use_cvsgraph = self.cvsgraph_ivar.get()
|
||||
|
||||
def toggle_use_enscript(self, event=None):
|
||||
cfg.options.use_enscript = self.enscript_ivar.get()
|
||||
|
||||
def toggle_use_localtime(self, event=None):
|
||||
cfg.options.use_localtime = self.use_localtime_ivar.get()
|
||||
|
||||
@@ -519,8 +526,11 @@ def gui(host, port):
|
||||
def toggle_useresearch(self, event=None):
|
||||
cfg.options.use_re_search = self.useresearch_ivar.get()
|
||||
|
||||
def set_use_pagesize(self, event=None):
|
||||
cfg.options.use_pagesize = self.use_pagesize_ivar.get()
|
||||
def set_log_pagesize(self, event=None):
|
||||
cfg.options.log_pagesize = self.log_pagesize_ivar.get()
|
||||
|
||||
def set_dir_pagesize(self, event=None):
|
||||
cfg.options.dir_pagesize = self.dir_pagesize_ivar.get()
|
||||
|
||||
def set_templates_log(self, event=None):
|
||||
cfg.templates.log = self.logtemplate_svar.get()
|
||||
@@ -614,7 +624,7 @@ def cli(argv):
|
||||
if pid != 0:
|
||||
sys.exit()
|
||||
if options.start_gui:
|
||||
gui(options.host, options.port, options.config_file)
|
||||
gui(options.host, options.port)
|
||||
return
|
||||
elif options.port:
|
||||
def ready(server):
|
||||
|
@@ -1,6 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 2004-2008 The ViewCVS Group. All Rights Reserved.
|
||||
# Copyright (C) 2004-2007 James Henstridge
|
||||
#
|
||||
# By using this file, you agree to the terms and conditions set forth in
|
||||
|
32
conf/mimetypes.conf.dist
Normal file
32
conf/mimetypes.conf.dist
Normal file
@@ -0,0 +1,32 @@
|
||||
#---------------------------------------------------------------------------
|
||||
#
|
||||
# MIME type mapping file for ViewVC
|
||||
#
|
||||
# Information on ViewVC is located at the following web site:
|
||||
# http://viewvc.org/
|
||||
#
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
# THE FORMAT OF THIS FILE
|
||||
#
|
||||
# This file contains records -- one per line -- of the following format:
|
||||
#
|
||||
# MIME_TYPE [EXTENSION [EXTENSION ...]]
|
||||
#
|
||||
# where whitespace separates the MIME_TYPE from the EXTENSION(s),
|
||||
# and the EXTENSIONs from each other.
|
||||
#
|
||||
# For example:
|
||||
#
|
||||
# text/x-csh csh
|
||||
# text/x-csrc c
|
||||
# text/x-diff diff patch
|
||||
# image/png png
|
||||
# image/jpeg jpeg jpg jpe
|
||||
#
|
||||
# By default, this file is left empty, allowing ViewVC to continue
|
||||
# consulting it first without overriding the MIME type mappings
|
||||
# found in more standard mapping files (such as those provided as
|
||||
# part of the operating system or web server software).
|
||||
#
|
||||
#
|
@@ -60,7 +60,7 @@
|
||||
# default_root
|
||||
# root_as_url_component
|
||||
# rcs_dir
|
||||
# mime_types_file
|
||||
# mime_types_files
|
||||
# the many options in the [utilities] section
|
||||
#
|
||||
# It is usually desirable to change the following variables:
|
||||
@@ -127,13 +127,26 @@ cvs_roots = cvs: /home/cvsroot
|
||||
default_root = cvs
|
||||
|
||||
#
|
||||
# This is a pathname to a MIME types file to help viewvc to guess the
|
||||
# correct MIME type on checkout. If you are having problems with the
|
||||
# default guess on the MIME type, then uncomment this option and point
|
||||
# it at a MIME type file.
|
||||
# This is a list of pathnames to a set of MIME type mapping files to
|
||||
# help ViewVC guess the correct MIME type of a versioned file. The
|
||||
# pathnames listed here are specified in order of authoritativeness
|
||||
# either as absolute paths or relative to this configuration file.
|
||||
#
|
||||
# For example, you can use the mime.types provided by Apache here:
|
||||
#mime_types_file = /usr/local/apache2/conf/mime.types
|
||||
# As a convenience, ViewVC provides a MIME type mapping file
|
||||
# (mimetypes.conf) which is, by default, the preferred provider of
|
||||
# MIME type mapping answers, but which is also empty. If you find
|
||||
# that ViewVC is unable to accurately guess MIME types based on the
|
||||
# extensions of some of your versioned files, you can add records of
|
||||
# your preferred mappings to the provided mimetypes.conf file (or to
|
||||
# your system's mapping files, if you wish).
|
||||
#
|
||||
# You might, for example, wish to have ViewVC also consult the mapping
|
||||
# files provided by your operating system and Apache.
|
||||
#
|
||||
# mime_types_files = mimetypes.conf,
|
||||
# /etc/mime.types,
|
||||
# /usr/local/apache2/conf/mime.types
|
||||
mime_types_files = mimetypes.conf
|
||||
|
||||
# The address of the local repository maintainer. (This option is
|
||||
# provided only as a convenience for ViewVC installations which are
|
||||
@@ -266,8 +279,8 @@ checkout_magic = 0
|
||||
# allowed_views: List the ViewVC views which are enabled. Views not
|
||||
# in this comma-delited list will not be served (or, will return an
|
||||
# error on attempted access).
|
||||
# Possible values: "tar", "annotate", "co", "markup", "roots"
|
||||
allowed_views = markup, annotate, roots
|
||||
# Possible values: "annotate", "co", "diff", "markup", "roots", "tar"
|
||||
allowed_views = annotate, diff, markup, roots
|
||||
|
||||
# authorizer: The name of the ViewVC authorizer plugin to use when
|
||||
# authorizing access to repository contents. This value must be the
|
||||
@@ -286,9 +299,9 @@ allowed_views = markup, annotate, roots
|
||||
# NOTE: Only one authorizer may be in use for a given ViewVC request.
|
||||
# It doesn't matter if you configure the parameters of multiple
|
||||
# authorizer plugins -- only the authorizer whose name is configured
|
||||
# here (or effectively configured here via vhost configuration) will
|
||||
# be activated.
|
||||
authorizer = forbidden
|
||||
# here (or effectively configured here via per-vhost or per-root
|
||||
# configuration) will be activated.
|
||||
authorizer =
|
||||
|
||||
# hide_cvsroot: Don't show the CVSROOT directory
|
||||
# 1 Hide CVSROOT directory
|
||||
@@ -332,6 +345,13 @@ http_expiration_time = 600
|
||||
# 0 Don't generate Etags
|
||||
generate_etags = 1
|
||||
|
||||
# Don't use the svn:mime-type property to determine how to display a
|
||||
# file in the markup view. This is especially helpful when versioned
|
||||
# images carry the default Subversion-calculated MIME type of
|
||||
# "application/octet-stream" (which isn't recognized as viewable type
|
||||
# by browsers).
|
||||
svn_ignore_mimetype = 0
|
||||
|
||||
# svn_config_dir: Path of the Subversion runtime configuration
|
||||
# directory ViewVC should consult for various things, including cached
|
||||
# remote authentication credentials. If unset, Subversion will use
|
||||
@@ -506,13 +526,22 @@ use_re_search = 0
|
||||
# use_re_search = 1
|
||||
|
||||
#
|
||||
# Split directories and logs into pages.
|
||||
# Allows ViewVC to present discrete pages to the users instead of the
|
||||
# entire log or directory.
|
||||
# Set use_pagesize to the number of entries you want displayed on a page.
|
||||
# Split directory listings across pages as needed. Allows ViewVC to
|
||||
# present discrete pages to the users instead of the entire directory.
|
||||
# Set dir_pagesize to the number of entries you want displayed on a page,
|
||||
# or 0 to disable pagination.
|
||||
#
|
||||
use_pagesize = 0
|
||||
# use_pagesize = 20
|
||||
dir_pagesize = 0
|
||||
# dir_pagesize = 20
|
||||
|
||||
#
|
||||
# Split revision log listings across multiple pages as needed. Allows
|
||||
# ViewVC to present discrete pages to the users instead of the entire log.
|
||||
# Set log_pagesize to the number of entries you want displayed on a page,
|
||||
# or 0 to disable pagination.
|
||||
#
|
||||
log_pagesize = 0
|
||||
# log_pagesize = 20
|
||||
|
||||
# Limit number of changed paths shown per commit in the Subversion revision
|
||||
# view and in query results. This is not a hard limit (the UI provides
|
@@ -161,12 +161,6 @@ td {
|
||||
resource. Valid only when <var>pathtype</var> is <tt>file</tt>
|
||||
or (for Subversion roots) <tt>dir</tt>.</td>
|
||||
</tr>
|
||||
<tr class="varlevel1">
|
||||
<td class="varname">log_rev_href</td>
|
||||
<td>String</td>
|
||||
<td>Revision number of the file-revision currently being viewed, or
|
||||
None.</td>
|
||||
</tr>
|
||||
<tr class="varlevel1">
|
||||
<td class="varname">nav_path</td>
|
||||
<td>List</td>
|
||||
@@ -450,10 +444,10 @@ td {
|
||||
<tr class="varlevel1">
|
||||
<td class="varname">annotation</td>
|
||||
<td>String</td>
|
||||
<td>If set, indicates that annotations were requested. Valid values
|
||||
are "annotated" (annotation was successful), "binary" (file contents
|
||||
are not line-based and human-readable), and "error" (something went
|
||||
wrong during annotation).</td>
|
||||
<td>Valid values are "none" (no annotations were attempted),
|
||||
"annotated" (annotation was successful), "binary" (file contents
|
||||
are not line-based and human-readable), and "error" (something
|
||||
went wrong during annotation).</td>
|
||||
</tr>
|
||||
<tr class="varlevel1">
|
||||
<td class="varname">author</td>
|
||||
@@ -1087,18 +1081,11 @@ td {
|
||||
<td>String</td>
|
||||
<td>Current search expression, if any.</td>
|
||||
</tr>
|
||||
<tr class="varlevel1">
|
||||
<td class="varname">search_re_form</td>
|
||||
<td>Boolean</td>
|
||||
<td>Indicates whether or not to display the regular expression search
|
||||
form. Value depends on the whether searching is enabled in the
|
||||
configuration and whether or not the current directory is
|
||||
empty.</td>
|
||||
</tr>
|
||||
<tr class="varlevel1">
|
||||
<td class="varname">search_re_action</td>
|
||||
<td>String</td>
|
||||
<td>Form action URL for the regular expression search form.</td>
|
||||
<td>Form action URL for the regular expression search form,
|
||||
if searching is available.</td>
|
||||
</tr>
|
||||
<tr class="varlevel1">
|
||||
<td class="varname">search_re_hidden_values</td>
|
||||
@@ -2073,6 +2060,11 @@ td {
|
||||
<td>String</td>
|
||||
<td>URL for the current view but with <tt>limit_changes</tt> disabled.</td>
|
||||
</tr>
|
||||
<tr class="varlevel1">
|
||||
<td class="varname">num_changes</td>
|
||||
<td>String</td>
|
||||
<td>Number of paths changed in this revision.</td>
|
||||
</tr>
|
||||
<tr class="varlevel1">
|
||||
<td class="varname">next_href</td>
|
||||
<td>String</td>
|
||||
|
@@ -137,9 +137,8 @@ td {
|
||||
configuration's "general" section.</li>
|
||||
|
||||
<li>Finally, ensure that that the new <code>authorizer</code>
|
||||
option is set to either "forbidden" (which is the default) or
|
||||
"forbiddenre", depending on which of those you were using in
|
||||
ViewVC 1.0.x.</li>
|
||||
option is set to either "forbidden" or "forbiddenre", depending
|
||||
on which of those you were using in ViewVC 1.0.x.</li>
|
||||
|
||||
</ol>
|
||||
|
||||
@@ -215,10 +214,9 @@ td {
|
||||
<li>options/py2html_path</li>
|
||||
<li>options/use_enscript</li>
|
||||
<li>options/use_highlight</li>
|
||||
<li>options/use_pagesize</li>
|
||||
<li>options/use_php</li>
|
||||
<li>options/use_py2html</li>
|
||||
<li>options/use_pygments</li>
|
||||
<li>options/use_source_highlight</li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
@@ -226,16 +224,23 @@ td {
|
||||
<div class="h3">
|
||||
<h3>Checkin Database</h3>
|
||||
|
||||
<p>In ViewVC 1.1, the <code>svndbadmin</code> program's "rebuild"
|
||||
subcommand has had its purpose become more defined. It no longer
|
||||
accepts a revision argument, and therefore can now only be used to
|
||||
completely rebuild the entirety of the checkin database information
|
||||
for a Subversion repository (instead of being able to only update
|
||||
the information related to single Subversion revision). For
|
||||
per-revision updating, use <code>svndbadmin update</code> and
|
||||
<p>ViewVC 1.1 introduces to the <code>cvsdbadmin</code>
|
||||
and <code>svndbadmin</code> tools a new "purge" operation, which
|
||||
allows you to remove all the information related to a given root
|
||||
from your checkins database (without disturbing the information
|
||||
associated with other roots). Likewise, the "rebuild" command in
|
||||
those tools now implies a "purge" followed by an update.</p>
|
||||
|
||||
<p>As a related change, the <code>svndbadmin</code> program's
|
||||
"rebuild" subcommand has had its purpose become more defined. It
|
||||
no longer accepts a revision argument, and therefore can now only
|
||||
be used to completely rebuild the entirety of the checkin database
|
||||
information for a Subversion repository (instead of being able to
|
||||
only update the information related to single Subversion revision).
|
||||
For per-revision updating, use <code>svndbadmin update</code> and
|
||||
provide a revision (or revision range). And to get the previous
|
||||
rebuild-a-revision effect, pass the new <code>--force</code>
|
||||
option to <code>svndbadmin update</code>.</p>
|
||||
rebuild-a-revision effect, pass the new <code>--force</code> option
|
||||
to <code>svndbadmin update</code>.</p>
|
||||
|
||||
<p>In other words, where you once did this:</p>
|
||||
|
||||
@@ -249,6 +254,19 @@ td {
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<p>To enhance the performance of the new "purge" operation, ViewVC 1.1
|
||||
introduces some slight changes to the checkin database schema. If
|
||||
you use the <code>make-database</code> tool to (re)create your
|
||||
checkins database, it will by default employ the new database
|
||||
schema. This should cause the database to be virtually unusable by
|
||||
previous versions of ViewVC, and that's by design. If, however,
|
||||
you need to (re)create your checkins database and you require
|
||||
compatibility with previous versions of ViewVC or ViewCVS, simply
|
||||
pass the "--version=1.0" option to the <code>make-database</code>
|
||||
script. Note that your "purge" and "rebuild" operations could be
|
||||
abysmally slow, though, as that version of the database schema is
|
||||
not optimized for those operations.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="h3">
|
||||
@@ -296,6 +314,22 @@ td {
|
||||
<li>options/allow_tar</li>
|
||||
</ul>
|
||||
|
||||
<p>ViewVC now honors the "svn:mime-type" property stored on
|
||||
Subversion-versioned files as the primary source of MIME type
|
||||
determination (before falling back to name-based MIME mappings and
|
||||
such). However, this can negatively affect the viewability of
|
||||
certain files — especially images — whose
|
||||
"svn:mime-type" properties are set incorrectly, such as will happen
|
||||
if Subversion itself merely determines that the file isn't
|
||||
human-readable and uses the "application/octet-stream" MIME type to
|
||||
record this determination. To make ViewVC <em>not</em> honor the
|
||||
"svn:mime-type" property value, set the <code>svn_ignore_mimetype</code>
|
||||
configuration option.</p>
|
||||
|
||||
<p>Speaking of MIME types, the option <code>mime_types_file</code> is
|
||||
now <code>mime_types_files</code>, as it now carries multiple paths
|
||||
to MIME mappings files, ordered by preference.</p>
|
||||
|
||||
<p>The <code>use_rcsparse</code> option was moved from the "general"
|
||||
section to the "options" section.</p>
|
||||
|
||||
@@ -631,6 +665,11 @@ allow_tar = 1
|
||||
<td>revision.ezt</td>
|
||||
<td>now is an iterable list of objects with .name and .value attributes</td>
|
||||
</tr>
|
||||
<tr class="added">
|
||||
<td class="varname">num_changes</td>
|
||||
<td>revision.ezt</td>
|
||||
<td>added</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
@@ -659,7 +698,7 @@ allow_tar = 1
|
||||
<h3>Checkin Database</h3>
|
||||
|
||||
<p>ViewVC 1.0 reads and writes commit times in the MySQL database in
|
||||
UTC time rather than local time. This can cause times displayed on
|
||||
UTC time rather than local time. This can cause times displayed on
|
||||
the query page to be a few hours off if an old database is being
|
||||
used with a new version of ViewVC. The best way to fix this is to
|
||||
rebuild the database with the new version of cvsdbadmin, but it
|
||||
@@ -702,7 +741,8 @@ allow_tar = 1
|
||||
<li>options/root_as_url_component</li>
|
||||
<li>options/default_file_view</li>
|
||||
<li>options/sort_group_dirs</li>
|
||||
<li>options/use_pagesize</li>
|
||||
<li>options/dir_pagesize</li>
|
||||
<li>options/log_pagesize</li>
|
||||
<li>options/limit_changes</li>
|
||||
<li>options/use_localtime</li>
|
||||
<li>options/cross_copies</li>
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2006 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
|
||||
@@ -39,7 +39,7 @@ def _parse(hdr, result):
|
||||
while pos < len(hdr):
|
||||
name = _re_token.match(hdr, pos)
|
||||
if not name:
|
||||
raise AcceptParseError()
|
||||
raise AcceptLanguageParseError()
|
||||
a = result.item_class(string.lower(name.group(1)))
|
||||
pos = name.end()
|
||||
while 1:
|
||||
@@ -210,7 +210,7 @@ class _LanguageSelector:
|
||||
def append(self, item):
|
||||
self.requested.append(item)
|
||||
|
||||
class AcceptParseError(Exception):
|
||||
class AcceptLanguageParseError(Exception):
|
||||
pass
|
||||
|
||||
def _test():
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2007 The ViewCVS Group. All Rights Reserved.
|
||||
# Copyright (C) 1999-2008 The ViewCVS Group. All Rights Reserved.
|
||||
# Copyright (C) 2000 Curt Hagenlocher <curt@hagenlocher.org>
|
||||
#
|
||||
# By using this file, you agree to the terms and conditions set forth in
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2008 The ViewCVS Group. All Rights Reserved.
|
||||
# Copyright (C) 1999-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 @@ import fnmatch
|
||||
class Config:
|
||||
_sections = ('general', 'utilities', 'options', 'cvsdb', 'templates')
|
||||
_force_multi_value = ('cvs_roots', 'svn_roots', 'languages', 'kv_files',
|
||||
'root_parents', 'allowed_views')
|
||||
'root_parents', 'allowed_views', 'mime_types_files')
|
||||
|
||||
def __init__(self):
|
||||
for section in self._sections:
|
||||
@@ -197,7 +197,7 @@ class Config:
|
||||
self.general.svn_roots = { }
|
||||
self.general.root_parents = []
|
||||
self.general.default_root = ''
|
||||
self.general.mime_types_file = ''
|
||||
self.general.mime_types_files = ["mimetypes.conf"]
|
||||
self.general.address = ''
|
||||
self.general.kv_files = [ ]
|
||||
self.general.languages = ['en-us']
|
||||
@@ -213,12 +213,13 @@ class Config:
|
||||
|
||||
self.options.root_as_url_component = 1
|
||||
self.options.checkout_magic = 0
|
||||
self.options.allowed_views = ['markup', 'annotate', 'roots']
|
||||
self.options.authorizer = 'forbidden'
|
||||
self.options.allowed_views = ['annotate', 'diff', 'markup', 'roots']
|
||||
self.options.authorizer = None
|
||||
self.options.mangle_email_addresses = 0
|
||||
self.options.default_file_view = "log"
|
||||
self.options.http_expiration_time = 600
|
||||
self.options.generate_etags = 1
|
||||
self.options.svn_ignore_mimetype = 0
|
||||
self.options.svn_config_dir = None
|
||||
self.options.use_rcsparse = 0
|
||||
self.options.sort_by = 'file'
|
||||
@@ -246,7 +247,8 @@ class Config:
|
||||
self.options.use_cvsgraph = 0
|
||||
self.options.cvsgraph_conf = "cvsgraph.conf"
|
||||
self.options.use_re_search = 0
|
||||
self.options.use_pagesize = 0
|
||||
self.options.dir_pagesize = 0
|
||||
self.options.log_pagesize = 0
|
||||
self.options.limit_changes = 100
|
||||
|
||||
self.templates.diff = None
|
||||
|
180
lib/cvsdb.py
180
lib/cvsdb.py
@@ -1,6 +1,6 @@
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2007 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
|
||||
@@ -20,6 +20,14 @@ import re
|
||||
import vclib
|
||||
import dbi
|
||||
|
||||
## Current commits database schema version number.
|
||||
##
|
||||
## Version 0 was the original Bonsai-compatible version.
|
||||
##
|
||||
## Version 1 added the 'metadata' table (which holds the 'version' key)
|
||||
## and renamed all the 'repository'-related stuff to be 'root'-
|
||||
##
|
||||
CURRENT_SCHEMA_VERSION = 1
|
||||
|
||||
## error
|
||||
error = "cvsdb error"
|
||||
@@ -37,6 +45,7 @@ class CheckinDatabase:
|
||||
self._passwd = passwd
|
||||
self._database = database
|
||||
self._row_limit = row_limit
|
||||
self._version = None
|
||||
|
||||
## database lookup caches
|
||||
self._get_cache = {}
|
||||
@@ -48,6 +57,19 @@ class CheckinDatabase:
|
||||
self._host, self._port, self._user, self._passwd, self._database)
|
||||
cursor = self.db.cursor()
|
||||
cursor.execute("SET AUTOCOMMIT=1")
|
||||
table_list = self.GetTableList()
|
||||
if 'metadata' in table_list:
|
||||
version = self.GetMetadataValue("version")
|
||||
if version is None:
|
||||
self._version = 0
|
||||
else:
|
||||
self._version = int(version)
|
||||
else:
|
||||
self._version = 0
|
||||
if self._version > CURRENT_SCHEMA_VERSION:
|
||||
raise Exception("Database version %d is newer than the last "
|
||||
"version supported by this software."
|
||||
% (self._version))
|
||||
|
||||
def sql_get_id(self, table, column, value, auto_set):
|
||||
sql = "SELECT id FROM %s WHERE %s=%%s" % (table, column)
|
||||
@@ -147,6 +169,42 @@ class CheckinDatabase:
|
||||
|
||||
return list
|
||||
|
||||
def GetTableList(self):
|
||||
sql = "SHOW TABLES"
|
||||
cursor = self.db.cursor()
|
||||
cursor.execute(sql)
|
||||
list = []
|
||||
while 1:
|
||||
row = cursor.fetchone()
|
||||
if row == None:
|
||||
break
|
||||
list.append(row[0])
|
||||
return list
|
||||
|
||||
def GetMetadataValue(self, name):
|
||||
sql = "SELECT value FROM metadata WHERE name=%s"
|
||||
sql_args = (name)
|
||||
cursor = self.db.cursor()
|
||||
cursor.execute(sql, sql_args)
|
||||
try:
|
||||
(value,) = cursor.fetchone()
|
||||
except TypeError:
|
||||
return None
|
||||
return value
|
||||
|
||||
def SetMetadataValue(self, name, value):
|
||||
assert(self._version > 0)
|
||||
sql = "REPLACE INTO metadata (name, value) VALUES (%s, %s)"
|
||||
sql_args = (name, value)
|
||||
cursor = self.db.cursor()
|
||||
try:
|
||||
cursor.execute(sql, sql_args)
|
||||
except Exception, e:
|
||||
raise Exception("Error setting metadata: '%s'\n"
|
||||
"\tname = %s\n"
|
||||
"\tvalue = %s\n"
|
||||
% (str(e), name, value))
|
||||
|
||||
def GetBranchID(self, branch, auto_set = 1):
|
||||
return self.get_id("branches", "branch", branch, auto_set)
|
||||
|
||||
@@ -251,7 +309,9 @@ class CheckinDatabase:
|
||||
minus_count = commit.GetMinusCount() or '0'
|
||||
description_id = self.GetDescriptionID(commit.GetDescription())
|
||||
|
||||
sql = "REPLACE INTO checkins"\
|
||||
commits_table = self._version >= 1 and 'commits' or 'checkins'
|
||||
sql = "REPLACE INTO %s" % (commits_table)
|
||||
sql = sql + \
|
||||
" (type,ci_when,whoid,repositoryid,dirid,fileid,revision,"\
|
||||
" stickytag,branchid,addedlines,removedlines,descid)"\
|
||||
"VALUES(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)"
|
||||
@@ -304,58 +364,69 @@ class CheckinDatabase:
|
||||
return "(%s)" % (string.join(sqlList, " OR "))
|
||||
|
||||
def CreateSQLQueryString(self, query):
|
||||
tableList = [("checkins", None)]
|
||||
commits_table = self._version >= 1 and 'commits' or 'checkins'
|
||||
tableList = [(commits_table, None)]
|
||||
condList = []
|
||||
|
||||
if len(query.repository_list):
|
||||
tableList.append(("repositories",
|
||||
"(checkins.repositoryid=repositories.id)"))
|
||||
"(%s.repositoryid=repositories.id)"
|
||||
% (commits_table)))
|
||||
temp = self.SQLQueryListString("repositories.repository",
|
||||
query.repository_list)
|
||||
condList.append(temp)
|
||||
|
||||
if len(query.branch_list):
|
||||
tableList.append(("branches", "(checkins.branchid=branches.id)"))
|
||||
tableList.append(("branches",
|
||||
"(%s.branchid=branches.id)" % (commits_table)))
|
||||
temp = self.SQLQueryListString("branches.branch",
|
||||
query.branch_list)
|
||||
condList.append(temp)
|
||||
|
||||
if len(query.directory_list):
|
||||
tableList.append(("dirs", "(checkins.dirid=dirs.id)"))
|
||||
tableList.append(("dirs",
|
||||
"(%s.dirid=dirs.id)" % (commits_table)))
|
||||
temp = self.SQLQueryListString("dirs.dir", query.directory_list)
|
||||
condList.append(temp)
|
||||
|
||||
if len(query.file_list):
|
||||
tableList.append(("files", "(checkins.fileid=files.id)"))
|
||||
tableList.append(("files",
|
||||
"(%s.fileid=files.id)" % (commits_table)))
|
||||
temp = self.SQLQueryListString("files.file", query.file_list)
|
||||
condList.append(temp)
|
||||
|
||||
if len(query.author_list):
|
||||
tableList.append(("people", "(checkins.whoid=people.id)"))
|
||||
tableList.append(("people",
|
||||
"(%s.whoid=people.id)" % (commits_table)))
|
||||
temp = self.SQLQueryListString("people.who", query.author_list)
|
||||
condList.append(temp)
|
||||
|
||||
if len(query.comment_list):
|
||||
tableList.append(("descs", "(checkins.descid=descs.id)"))
|
||||
tableList.append(("descs",
|
||||
"(%s.descid=descs.id)" % (commits_table)))
|
||||
temp = self.SQLQueryListString("descs.description",
|
||||
query.comment_list)
|
||||
condList.append(temp)
|
||||
|
||||
if query.from_date:
|
||||
temp = "(checkins.ci_when>=\"%s\")" % (str(query.from_date))
|
||||
temp = "(%s.ci_when>=\"%s\")" \
|
||||
% (commits_table, str(query.from_date))
|
||||
condList.append(temp)
|
||||
|
||||
if query.to_date:
|
||||
temp = "(checkins.ci_when<=\"%s\")" % (str(query.to_date))
|
||||
temp = "(%s.ci_when<=\"%s\")" \
|
||||
% (commits_table, str(query.to_date))
|
||||
condList.append(temp)
|
||||
|
||||
if query.sort == "date":
|
||||
order_by = "ORDER BY checkins.ci_when DESC,descid"
|
||||
order_by = "ORDER BY %s.ci_when DESC,descid" % (commits_table)
|
||||
elif query.sort == "author":
|
||||
tableList.append(("people", "(checkins.whoid=people.id)"))
|
||||
tableList.append(("people",
|
||||
"(%s.whoid=people.id)" % (commits_table)))
|
||||
order_by = "ORDER BY people.who,descid"
|
||||
elif query.sort == "file":
|
||||
tableList.append(("files", "(checkins.fileid=files.id)"))
|
||||
tableList.append(("files",
|
||||
"(%s.fileid=files.id)" % (commits_table)))
|
||||
order_by = "ORDER BY files.file,descid"
|
||||
|
||||
## exclude duplicates from the table list, and split out join
|
||||
@@ -381,8 +452,8 @@ class CheckinDatabase:
|
||||
elif self._row_limit:
|
||||
limit = "LIMIT %s" % (str(self._row_limit))
|
||||
|
||||
sql = "SELECT checkins.* FROM %s %s %s %s" % (
|
||||
tables, conditions, order_by, limit)
|
||||
sql = "SELECT %s.* FROM %s %s %s %s" \
|
||||
% (commits_table, tables, conditions, order_by, limit)
|
||||
|
||||
return sql
|
||||
|
||||
@@ -433,8 +504,13 @@ class CheckinDatabase:
|
||||
if file_id == None:
|
||||
return None
|
||||
|
||||
sql = "SELECT * FROM checkins WHERE "\
|
||||
" repositoryid=%s AND dirid=%s AND fileid=%s AND revision=%s"
|
||||
commits_table = self._version >= 1 and 'commits' or 'checkins'
|
||||
sql = "SELECT * FROM %s WHERE "\
|
||||
" repositoryid=%%s "\
|
||||
" AND dirid=%%s"\
|
||||
" AND fileid=%%s"\
|
||||
" AND revision=%%s"\
|
||||
% (commits_table)
|
||||
sql_args = (repository_id, dir_id, file_id, commit.GetRevision())
|
||||
|
||||
cursor = self.db.cursor()
|
||||
@@ -451,40 +527,58 @@ class CheckinDatabase:
|
||||
def sql_delete(self, table, key, value, keep_fkey = None):
|
||||
sql = "DELETE FROM %s WHERE %s=%%s" % (table, key)
|
||||
sql_args = (value, )
|
||||
commits_table = self._version >= 1 and 'commits' or 'checkins'
|
||||
if keep_fkey:
|
||||
sql += " AND %s NOT IN (SELECT %s FROM checkins WHERE %s = %%s)" \
|
||||
% (key, keep_fkey, keep_fkey)
|
||||
sql_args = (value, value)
|
||||
sql += " AND %s NOT IN (SELECT %s FROM %s WHERE %s = %%s)" \
|
||||
% (key, keep_fkey, commits_table, keep_fkey)
|
||||
sql_args = (value, value)
|
||||
cursor = self.db.cursor()
|
||||
cursor.execute(sql, sql_args)
|
||||
|
||||
def sql_purge(self, table, key, fkey, ftable):
|
||||
sql = "DELETE FROM %s WHERE %s NOT IN (SELECT %s FROM %s)" \
|
||||
% (table, key, fkey, ftable)
|
||||
cursor = self.db.cursor()
|
||||
cursor.execute(sql)
|
||||
|
||||
def PurgeRepository(self, repository):
|
||||
rep_id = self.GetRepositoryID(repository)
|
||||
if not rep_id:
|
||||
raise Exception, "Unknown repository '%s'" % (repository)
|
||||
|
||||
sql = "SELECT * FROM checkins WHERE repositoryid=%s"
|
||||
sql_args = (rep_id, )
|
||||
cursor = self.db.cursor()
|
||||
cursor.execute(sql, sql_args)
|
||||
checkins = []
|
||||
while 1:
|
||||
try:
|
||||
(ci_type, ci_when, who_id, repository_id,
|
||||
dir_id, file_id, revision, sticky_tag, branch_id,
|
||||
plus_count, minus_count, description_id) = cursor.fetchone()
|
||||
except TypeError:
|
||||
break
|
||||
checkins.append([file_id, dir_id, branch_id, description_id, who_id])
|
||||
|
||||
#self.sql_delete('repositories', 'id', rep_id)
|
||||
self.sql_delete('checkins', 'repositoryid', rep_id)
|
||||
for checkin in checkins:
|
||||
self.sql_delete('files', 'id', checkin[0], 'fileid')
|
||||
self.sql_delete('dirs', 'id', checkin[1], 'dirid')
|
||||
self.sql_delete('branches', 'id', checkin[2], 'branchid')
|
||||
self.sql_delete('descs', 'id', checkin[3], 'descid')
|
||||
self.sql_delete('people', 'id', checkin[4], 'whoid')
|
||||
if (self._version >= 1):
|
||||
self.sql_delete('repositories', 'id', rep_id)
|
||||
self.sql_purge('commits', 'repositoryid', 'id', 'repositories')
|
||||
self.sql_purge('files', 'id', 'fileid', 'commits')
|
||||
self.sql_purge('dirs', 'id', 'dirid', 'commits')
|
||||
self.sql_purge('branches', 'id', 'branchid', 'commits')
|
||||
self.sql_purge('descs', 'id', 'descid', 'commits')
|
||||
self.sql_purge('people', 'id', 'whoid', 'commits')
|
||||
else:
|
||||
sql = "SELECT * FROM checkins WHERE repositoryid=%s"
|
||||
sql_args = (rep_id, )
|
||||
cursor = self.db.cursor()
|
||||
cursor.execute(sql, sql_args)
|
||||
checkins = []
|
||||
while 1:
|
||||
try:
|
||||
(ci_type, ci_when, who_id, repository_id,
|
||||
dir_id, file_id, revision, sticky_tag, branch_id,
|
||||
plus_count, minus_count, description_id) = \
|
||||
cursor.fetchone()
|
||||
except TypeError:
|
||||
break
|
||||
checkins.append([file_id, dir_id, branch_id,
|
||||
description_id, who_id])
|
||||
|
||||
#self.sql_delete('repositories', 'id', rep_id)
|
||||
self.sql_delete('checkins', 'repositoryid', rep_id)
|
||||
for checkin in checkins:
|
||||
self.sql_delete('files', 'id', checkin[0], 'fileid')
|
||||
self.sql_delete('dirs', 'id', checkin[1], 'dirid')
|
||||
self.sql_delete('branches', 'id', checkin[2], 'branchid')
|
||||
self.sql_delete('descs', 'id', checkin[3], 'descid')
|
||||
self.sql_delete('people', 'id', checkin[4], 'whoid')
|
||||
|
||||
## the Commit class holds data on one commit, the representation is as
|
||||
## close as possible to how it should be committed and retrieved to the
|
||||
|
14
lib/debug.py
14
lib/debug.py
@@ -1,6 +1,6 @@
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2007 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
|
||||
@@ -48,13 +48,17 @@ if SHOW_TIMES:
|
||||
else:
|
||||
_times[which] = t
|
||||
|
||||
def dump():
|
||||
for name, value in _times.items():
|
||||
print '%s: %.6f<br />' % (name, value)
|
||||
def t_dump(out):
|
||||
out.write('<div>')
|
||||
names = _times.keys()
|
||||
names.sort()
|
||||
for name in names:
|
||||
out.write('%s: %.6fs<br/>\n' % (name, _times[name]))
|
||||
out.write('</div>')
|
||||
|
||||
else:
|
||||
|
||||
t_start = t_end = dump = lambda *args: None
|
||||
t_start = t_end = t_dump = lambda *args: None
|
||||
|
||||
|
||||
class ViewVCException:
|
||||
|
43
lib/ezt.py
43
lib/ezt.py
@@ -460,7 +460,10 @@ class Template:
|
||||
def _cmd_print(self, valrefs, ctx):
|
||||
value = _get_value(valrefs[0], ctx)
|
||||
args = map(lambda valref, ctx=ctx: _get_value(valref, ctx), valrefs[1:])
|
||||
_write_value(value, args, ctx)
|
||||
try:
|
||||
_write_value(value, args, ctx)
|
||||
except TypeError:
|
||||
raise Exception("Unprintable value type for '%s'" % (str(valrefs[0][0])))
|
||||
|
||||
def _cmd_format(self, printer, ctx):
|
||||
if type(printer) is TupleType:
|
||||
@@ -522,7 +525,8 @@ class Template:
|
||||
((valref,), unused, section) = args
|
||||
list = _get_value(valref, ctx)
|
||||
if isinstance(list, StringType):
|
||||
raise NeedSequenceError()
|
||||
raise NeedSequenceError("The value of '%s' is not a sequence"
|
||||
% (valref[0]))
|
||||
refname = valref[0]
|
||||
ctx.for_iterators[refname] = iterator = _iter(list)
|
||||
for unused in iterator:
|
||||
@@ -672,6 +676,41 @@ def _write_value(value, args, ctx):
|
||||
ctx.printers.append(printer)
|
||||
|
||||
|
||||
class TemplateData:
|
||||
"""A custom dictionary-like object that allows one-time definition
|
||||
of keys, and only value fetches and changes, and key deletions,
|
||||
thereafter.
|
||||
|
||||
EZT doesn't require the use of this special class -- a normal
|
||||
dict-type data dictionary works fine. But use of this class will
|
||||
assist those who want the data sent to their templates to have a
|
||||
consistent set of keys."""
|
||||
|
||||
def __init__(self, initial_data={}):
|
||||
self._items = initial_data
|
||||
|
||||
def __getitem__(self, key):
|
||||
return self._items.__getitem__(key)
|
||||
|
||||
def __setitem__(self, key, item):
|
||||
assert self._items.has_key(key)
|
||||
return self._items.__setitem__(key, item)
|
||||
|
||||
def __delitem__(self, key):
|
||||
return self._items.__delitem__(key)
|
||||
|
||||
def keys(self):
|
||||
return self._items.keys()
|
||||
|
||||
def merge(self, template_data):
|
||||
"""Merge the data in TemplataData instance TEMPLATA_DATA into this
|
||||
instance. Avoid the temptation to use this conditionally in your
|
||||
code -- it rather defeats the purpose of this class."""
|
||||
|
||||
assert isinstance(template_data, TemplateData)
|
||||
self._items.update(template_data._items)
|
||||
|
||||
|
||||
class Context:
|
||||
"""A container for the execution context"""
|
||||
def __init__(self, fp):
|
||||
|
190
lib/popen.py
190
lib/popen.py
@@ -1,6 +1,6 @@
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2007 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
|
||||
@@ -131,194 +131,6 @@ def popen(cmd, args, mode, capture_err=1):
|
||||
# crap. shouldn't be here.
|
||||
sys.exit(127)
|
||||
|
||||
def pipe_cmds(cmds, out=None):
|
||||
"""Executes a sequence of commands. The output of each command is directed to
|
||||
the input of the next command. A _pipe object is returned for writing to the
|
||||
first command's input. The output of the last command is directed to the
|
||||
"out" file object or the standard output if "out" is None. If "out" is not an
|
||||
OS file descriptor, a separate thread will be spawned to send data to its
|
||||
write() method."""
|
||||
|
||||
if out is None:
|
||||
out = sys.stdout
|
||||
|
||||
if sys.platform == "win32":
|
||||
### FIXME: windows implementation ignores "out" argument, always
|
||||
### writing last command's output to standard out
|
||||
|
||||
if debug.SHOW_CHILD_PROCESSES:
|
||||
dbgIn = StringIO.StringIO()
|
||||
hStdIn, handle = win32popen.MakeSpyPipe(1, 0, (dbgIn,))
|
||||
|
||||
i = 0
|
||||
for cmd in cmds:
|
||||
i = i + 1
|
||||
|
||||
dbgOut, dbgErr = StringIO.StringIO(), StringIO.StringIO()
|
||||
|
||||
if i < len(cmds):
|
||||
nextStdIn, hStdOut = win32popen.MakeSpyPipe(1, 1, (dbgOut,))
|
||||
x, hStdErr = win32popen.MakeSpyPipe(None, 1, (dbgErr,))
|
||||
else:
|
||||
ehandle = win32event.CreateEvent(None, 1, 0, None)
|
||||
nextStdIn, hStdOut = win32popen.MakeSpyPipe(None, 1, (dbgOut, sapi.server.file()), ehandle)
|
||||
x, hStdErr = win32popen.MakeSpyPipe(None, 1, (dbgErr,))
|
||||
|
||||
command = win32popen.CommandLine(cmd[0], cmd[1:])
|
||||
phandle, pid, thandle, tid = win32popen.CreateProcess(command, hStdIn, hStdOut, hStdErr)
|
||||
if debug.SHOW_CHILD_PROCESSES:
|
||||
debug.Process(command, dbgIn, dbgOut, dbgErr)
|
||||
|
||||
dbgIn = dbgOut
|
||||
hStdIn = nextStdIn
|
||||
|
||||
|
||||
else:
|
||||
|
||||
hStdIn, handle = win32popen.CreatePipe(1, 0)
|
||||
spool = None
|
||||
|
||||
i = 0
|
||||
for cmd in cmds:
|
||||
i = i + 1
|
||||
if i < len(cmds):
|
||||
nextStdIn, hStdOut = win32popen.CreatePipe(1, 1)
|
||||
else:
|
||||
# very last process
|
||||
nextStdIn = None
|
||||
|
||||
if sapi.server.inheritableOut:
|
||||
# send child output to standard out
|
||||
hStdOut = win32popen.MakeInheritedHandle(win32popen.FileObject2File(sys.stdout),0)
|
||||
ehandle = None
|
||||
else:
|
||||
ehandle = win32event.CreateEvent(None, 1, 0, None)
|
||||
x, hStdOut = win32popen.MakeSpyPipe(None, 1, (sapi.server.file(),), ehandle)
|
||||
|
||||
command = win32popen.CommandLine(cmd[0], cmd[1:])
|
||||
phandle, pid, thandle, tid = win32popen.CreateProcess(command, hStdIn, hStdOut, None)
|
||||
hStdIn = nextStdIn
|
||||
|
||||
return _pipe(win32popen.File2FileObject(handle, 'wb'), phandle, ehandle)
|
||||
|
||||
# flush the stdio buffers since we are about to change the FD under them
|
||||
sys.stdout.flush()
|
||||
sys.stderr.flush()
|
||||
|
||||
prev_r, parent_w = os.pipe()
|
||||
|
||||
null = os.open('/dev/null', os.O_RDWR)
|
||||
|
||||
child_pids = []
|
||||
|
||||
for cmd in cmds[:-1]:
|
||||
r, w = os.pipe()
|
||||
pid = os.fork()
|
||||
if not pid:
|
||||
# in the child
|
||||
|
||||
# hook up stdin to the "read" channel
|
||||
os.dup2(prev_r, 0)
|
||||
|
||||
# hook up stdout to the output channel
|
||||
os.dup2(w, 1)
|
||||
|
||||
# toss errors
|
||||
os.dup2(null, 2)
|
||||
|
||||
# close these extra descriptors
|
||||
os.close(prev_r)
|
||||
os.close(parent_w)
|
||||
os.close(null)
|
||||
os.close(r)
|
||||
os.close(w)
|
||||
|
||||
# time to run the command
|
||||
try:
|
||||
os.execvp(cmd[0], cmd)
|
||||
except:
|
||||
pass
|
||||
|
||||
sys.exit(127)
|
||||
|
||||
# in the parent
|
||||
child_pids.append(pid)
|
||||
|
||||
# we don't need these any more
|
||||
os.close(prev_r)
|
||||
os.close(w)
|
||||
|
||||
# the read channel of this pipe will feed into to the next command
|
||||
prev_r = r
|
||||
|
||||
# no longer needed
|
||||
os.close(null)
|
||||
|
||||
# done with most of the commands. set up the last command to write to "out"
|
||||
if not hasattr(out, 'fileno'):
|
||||
r, w = os.pipe()
|
||||
|
||||
pid = os.fork()
|
||||
if not pid:
|
||||
# in the child (the last command)
|
||||
|
||||
# hook up stdin to the "read" channel
|
||||
os.dup2(prev_r, 0)
|
||||
|
||||
# hook up stdout to "out"
|
||||
if hasattr(out, 'fileno'):
|
||||
if out.fileno() != 1:
|
||||
os.dup2(out.fileno(), 1)
|
||||
out.close()
|
||||
|
||||
else:
|
||||
# "out" can't be hooked up directly, so use a pipe and a thread
|
||||
os.dup2(w, 1)
|
||||
os.close(r)
|
||||
os.close(w)
|
||||
|
||||
# close these extra descriptors
|
||||
os.close(prev_r)
|
||||
os.close(parent_w)
|
||||
|
||||
# run the last command
|
||||
try:
|
||||
os.execvp(cmds[-1][0], cmds[-1])
|
||||
except:
|
||||
pass
|
||||
|
||||
sys.exit(127)
|
||||
|
||||
child_pids.append(pid)
|
||||
# not needed any more
|
||||
os.close(prev_r)
|
||||
|
||||
if not hasattr(out, 'fileno'):
|
||||
os.close(w)
|
||||
thread = _copy(r, out)
|
||||
thread.start()
|
||||
else:
|
||||
thread = None
|
||||
|
||||
# write into the first pipe, wait on the final process
|
||||
return _pipe(os.fdopen(parent_w, 'w'), child_pids, thread=thread)
|
||||
|
||||
class _copy(threading.Thread):
|
||||
def __init__(self, srcfd, destfile):
|
||||
self.srcfd = srcfd
|
||||
self.destfile = destfile
|
||||
threading.Thread.__init__(self)
|
||||
|
||||
def run(self):
|
||||
try:
|
||||
while 1:
|
||||
s = os.read(self.srcfd, 1024)
|
||||
if not s:
|
||||
break
|
||||
self.destfile.write(s)
|
||||
finally:
|
||||
os.close(self.srcfd)
|
||||
|
||||
class _pipe:
|
||||
"Wrapper for a file which can wait() on a child process at close time."
|
||||
|
||||
|
18
lib/query.py
18
lib/query.py
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2008 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
|
||||
@@ -412,13 +412,10 @@ def main(server, cfg, viewvc_link):
|
||||
commits = [ ]
|
||||
query = 'skipped'
|
||||
|
||||
script_name = server.getenv('SCRIPT_NAME', '')
|
||||
|
||||
data = {
|
||||
data = ezt.TemplateData({
|
||||
'cfg' : cfg,
|
||||
'address' : cfg.general.address,
|
||||
'vsn' : viewvc.__version__,
|
||||
|
||||
'repository' : server.escape(form_data.repository, 1),
|
||||
'branch' : server.escape(form_data.branch, 1),
|
||||
'directory' : server.escape(form_data.directory, 1),
|
||||
@@ -435,16 +432,11 @@ def main(server, cfg, viewvc_link):
|
||||
'commits' : commits,
|
||||
'num_commits' : len(commits),
|
||||
'rss_href' : None,
|
||||
}
|
||||
|
||||
if form_data.hours:
|
||||
data['hours'] = form_data.hours
|
||||
else:
|
||||
data['hours'] = 2
|
||||
|
||||
server.header()
|
||||
'hours' : form_data.hours and form_data.hours or 2,
|
||||
})
|
||||
|
||||
# generate the page
|
||||
server.header()
|
||||
template = viewvc.get_view_template(cfg, "query")
|
||||
template.generate(server.file(), data)
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2007 The ViewCVS Group. All Rights Reserved.
|
||||
# Copyright (C) 1999-2008 The ViewCVS Group. All Rights Reserved.
|
||||
# Copyright (C) 2000 Curt Hagenlocher <curt@hagenlocher.org>
|
||||
#
|
||||
# By using this file, you agree to the terms and conditions set forth in
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2007 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-2007 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-2007 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-2008 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
|
||||
@@ -21,7 +21,7 @@ import tempfile
|
||||
import popen2
|
||||
import time
|
||||
import urllib
|
||||
from svn_repos import Revision, SVNChangedPath, _datestr_to_date, _compare_paths, _path_parts, _cleanup_path, _rev2optrev
|
||||
from svn_repos import Revision, SVNChangedPath, _datestr_to_date, _compare_paths, _path_parts, _cleanup_path, _rev2optrev, _fix_subversion_exception
|
||||
from svn import core, delta, client, wc, ra
|
||||
|
||||
|
||||
@@ -254,7 +254,7 @@ class RemoteSubversionRepository(vclib.Repository):
|
||||
dirent = dirents[entry.name]
|
||||
entry.date, entry.author, entry.log, changes = \
|
||||
self.revinfo(dirent.created_rev)
|
||||
entry.rev = dirent.created_rev
|
||||
entry.rev = str(dirent.created_rev)
|
||||
entry.size = dirent.size
|
||||
entry.lockinfo = None
|
||||
if locks.has_key(entry.name):
|
||||
@@ -362,6 +362,7 @@ class RemoteSubversionRepository(vclib.Repository):
|
||||
info2 = p2, _date_from_rev(r2), r2
|
||||
return vclib._diff_fp(temp1, temp2, info1, info2, self.diff_cmd, args)
|
||||
except core.SubversionException, e:
|
||||
_fix_subversion_exception(e)
|
||||
if e.apr_err == vclib.svn.core.SVN_ERR_FS_NOT_FOUND:
|
||||
raise vclib.InvalidRevision
|
||||
raise
|
||||
@@ -486,6 +487,7 @@ class RemoteSubversionRepository(vclib.Repository):
|
||||
try:
|
||||
results = ra.get_locations(self.ra_session, path, rev, [old_rev])
|
||||
except core.SubversionException, e:
|
||||
_fix_subversion_exception(e)
|
||||
if e.apr_err == core.SVN_ERR_FS_NOT_FOUND:
|
||||
raise vclib.ItemNotFound(path)
|
||||
raise
|
||||
|
@@ -1,6 +1,6 @@
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2008 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
|
||||
@@ -15,11 +15,9 @@
|
||||
import vclib
|
||||
import os
|
||||
import os.path
|
||||
import stat
|
||||
import string
|
||||
import cStringIO
|
||||
import signal
|
||||
import shutil
|
||||
import time
|
||||
import tempfile
|
||||
import popen
|
||||
@@ -31,6 +29,19 @@ from svn import fs, repos, core, client, delta
|
||||
if (core.SVN_VER_MAJOR, core.SVN_VER_MINOR, core.SVN_VER_PATCH) < (1, 3, 1):
|
||||
raise Exception, "Version requirement not met (needs 1.3.1 or better)"
|
||||
|
||||
|
||||
### Pre-1.5 Subversion doesn't have SVN_ERR_CEASE_INVOCATION
|
||||
try:
|
||||
_SVN_ERR_CEASE_INVOCATION = core.SVN_ERR_CEASE_INVOCATION
|
||||
except:
|
||||
_SVN_ERR_CEASE_INVOCATION = core.SVN_ERR_CANCELLED
|
||||
|
||||
### Pre-1.5 SubversionException's might not have the .msg and .apr_err members
|
||||
def _fix_subversion_exception(e):
|
||||
if not hasattr(e, 'apr_err'):
|
||||
e.apr_err = e[1]
|
||||
if not hasattr(e, 'message'):
|
||||
e.message = e[0]
|
||||
|
||||
def _allow_all(root, path, pool):
|
||||
"""Generic authz_read_func that permits access to all paths"""
|
||||
@@ -167,13 +178,16 @@ class NodeHistory:
|
||||
return
|
||||
self.histories.append([revision, _cleanup_path(path)])
|
||||
if self.limit and len(self.histories) == self.limit:
|
||||
raise core.SubversionException("", core.SVN_ERR_CEASE_INVOCATION)
|
||||
raise core.SubversionException("", _SVN_ERR_CEASE_INVOCATION)
|
||||
|
||||
def __getitem__(self, idx):
|
||||
return self.histories[idx]
|
||||
|
||||
|
||||
def _get_history(svnrepos, path, rev, path_type, limit=0, options={}):
|
||||
if svnrepos.youngest == 0:
|
||||
return []
|
||||
|
||||
rev_paths = []
|
||||
fsroot = svnrepos._getroot(rev)
|
||||
show_all_logs = options.get('svn_show_all_dir_logs', 0)
|
||||
@@ -190,7 +204,8 @@ def _get_history(svnrepos, path, rev, path_type, limit=0, options={}):
|
||||
repos.svn_repos_history(svnrepos.fs_ptr, path, history.add_history,
|
||||
1, rev, options.get('svn_cross_copies', 0))
|
||||
except core.SubversionException, e:
|
||||
if e.apr_err != core.SVN_ERR_CEASE_INVOCATION:
|
||||
_fix_subversion_exception(e)
|
||||
if e.apr_err != _SVN_ERR_CEASE_INVOCATION:
|
||||
raise
|
||||
|
||||
# Now, iterate over those history items, checking for changes of
|
||||
@@ -210,7 +225,7 @@ def _log_helper(svnrepos, path, rev, lockinfo):
|
||||
copyfrom_rev, copyfrom_path = fs.copied_from(rev_root, path)
|
||||
|
||||
# Assemble our LogEntry
|
||||
date, author, msg, changes = svnrepos.revinfo(rev)
|
||||
date, author, msg, changes = svnrepos._revinfo(rev)
|
||||
if fs.is_file(rev_root, path):
|
||||
size = fs.file_length(rev_root, path)
|
||||
else:
|
||||
@@ -314,6 +329,7 @@ class BlameSource:
|
||||
client.blame2(local_url, _rev2optrev(rev), _rev2optrev(first_rev),
|
||||
_rev2optrev(rev), self._blame_cb, ctx)
|
||||
except core.SubversionException, e:
|
||||
_fix_subversion_exception(e)
|
||||
if e.apr_err == core.SVN_ERR_CLIENT_IS_BINARY_FILE:
|
||||
raise vclib.NonTextualFileContents
|
||||
raise
|
||||
@@ -456,7 +472,7 @@ class LocalSubversionRepository(vclib.Repository):
|
||||
continue
|
||||
path = self._getpath(entry_path_parts)
|
||||
entry_rev = _get_last_history_rev(fsroot, path)
|
||||
date, author, msg, changes = self.revinfo(entry_rev)
|
||||
date, author, msg, changes = self._revinfo(entry_rev)
|
||||
entry.rev = str(entry_rev)
|
||||
entry.date = date
|
||||
entry.author = author
|
||||
@@ -554,100 +570,125 @@ class LocalSubversionRepository(vclib.Repository):
|
||||
youngest_rev, oldest_rev)
|
||||
return source, youngest_rev
|
||||
|
||||
def _revinfo_raw(self, rev):
|
||||
fsroot = self._getroot(rev)
|
||||
|
||||
# Get the changes for the revision
|
||||
editor = repos.ChangeCollector(self.fs_ptr, fsroot)
|
||||
e_ptr, e_baton = delta.make_editor(editor)
|
||||
repos.svn_repos_replay(fsroot, e_ptr, e_baton)
|
||||
changes = editor.get_changes()
|
||||
changedpaths = {}
|
||||
def _revinfo(self, rev, include_changed_paths=0):
|
||||
"""Internal-use, cache-friendly revision information harvester."""
|
||||
|
||||
# Now get the revision property info. Would use
|
||||
# editor.get_root_props(), but something is broken there...
|
||||
revprops = fs.revision_proplist(self.fs_ptr, rev)
|
||||
msg = revprops.get(core.SVN_PROP_REVISION_LOG)
|
||||
author = revprops.get(core.SVN_PROP_REVISION_AUTHOR)
|
||||
datestr = revprops.get(core.SVN_PROP_REVISION_DATE)
|
||||
|
||||
# Copy the Subversion changes into a new hash, converting them into
|
||||
# ChangedPath objects.
|
||||
found_readable = found_unreadable = 0
|
||||
for path in changes.keys():
|
||||
change = changes[path]
|
||||
if change.path:
|
||||
change.path = _cleanup_path(change.path)
|
||||
if change.base_path:
|
||||
change.base_path = _cleanup_path(change.base_path)
|
||||
is_copy = 0
|
||||
if not hasattr(change, 'action'): # new to subversion 1.4.0
|
||||
action = vclib.MODIFIED
|
||||
if not change.path:
|
||||
action = vclib.DELETED
|
||||
elif change.added:
|
||||
action = vclib.ADDED
|
||||
replace_check_path = path
|
||||
if change.base_path and change.base_rev:
|
||||
replace_check_path = change.base_path
|
||||
if changedpaths.has_key(replace_check_path) \
|
||||
and changedpaths[replace_check_path].action == vclib.DELETED:
|
||||
action = vclib.REPLACED
|
||||
else:
|
||||
if change.action == repos.CHANGE_ACTION_ADD:
|
||||
action = vclib.ADDED
|
||||
elif change.action == repos.CHANGE_ACTION_DELETE:
|
||||
action = vclib.DELETED
|
||||
elif change.action == repos.CHANGE_ACTION_REPLACE:
|
||||
action = vclib.REPLACED
|
||||
else:
|
||||
def _revinfo_helper(rev, include_changed_paths):
|
||||
# Get the revision property info. (Would use
|
||||
# editor.get_root_props(), but something is broken there...)
|
||||
revprops = fs.revision_proplist(self.fs_ptr, rev)
|
||||
msg = revprops.get(core.SVN_PROP_REVISION_LOG)
|
||||
author = revprops.get(core.SVN_PROP_REVISION_AUTHOR)
|
||||
datestr = revprops.get(core.SVN_PROP_REVISION_DATE)
|
||||
date = _datestr_to_date(datestr)
|
||||
|
||||
# Optimization: If our caller doesn't care about the changed
|
||||
# paths, and we don't need them to do authz determinations, let's
|
||||
# get outta here.
|
||||
if self.auth is None and not include_changed_paths:
|
||||
return date, author, msg, None
|
||||
|
||||
# If we get here, then we either need the changed paths because we
|
||||
# were asked for them, or we need them to do authorization checks.
|
||||
# Either way, we need 'em, so let's get 'em.
|
||||
fsroot = self._getroot(rev)
|
||||
editor = repos.ChangeCollector(self.fs_ptr, fsroot)
|
||||
e_ptr, e_baton = delta.make_editor(editor)
|
||||
repos.svn_repos_replay(fsroot, e_ptr, e_baton)
|
||||
changedpaths = {}
|
||||
changes = editor.get_changes()
|
||||
|
||||
# Copy the Subversion changes into a new hash, checking
|
||||
# authorization and converting them into ChangedPath objects.
|
||||
found_readable = found_unreadable = 0
|
||||
for path in changes.keys():
|
||||
change = changes[path]
|
||||
if change.path:
|
||||
change.path = _cleanup_path(change.path)
|
||||
if change.base_path:
|
||||
change.base_path = _cleanup_path(change.base_path)
|
||||
is_copy = 0
|
||||
if not hasattr(change, 'action'): # new to subversion 1.4.0
|
||||
action = vclib.MODIFIED
|
||||
if (action == vclib.ADDED or action == vclib.REPLACED) \
|
||||
and change.base_path \
|
||||
and change.base_rev:
|
||||
is_copy = 1
|
||||
if change.item_kind == core.svn_node_dir:
|
||||
pathtype = vclib.DIR
|
||||
elif change.item_kind == core.svn_node_file:
|
||||
pathtype = vclib.FILE
|
||||
if not change.path:
|
||||
action = vclib.DELETED
|
||||
elif change.added:
|
||||
action = vclib.ADDED
|
||||
replace_check_path = path
|
||||
if change.base_path and change.base_rev:
|
||||
replace_check_path = change.base_path
|
||||
if changedpaths.has_key(replace_check_path) \
|
||||
and changedpaths[replace_check_path].action == vclib.DELETED:
|
||||
action = vclib.REPLACED
|
||||
else:
|
||||
if change.action == repos.CHANGE_ACTION_ADD:
|
||||
action = vclib.ADDED
|
||||
elif change.action == repos.CHANGE_ACTION_DELETE:
|
||||
action = vclib.DELETED
|
||||
elif change.action == repos.CHANGE_ACTION_REPLACE:
|
||||
action = vclib.REPLACED
|
||||
else:
|
||||
action = vclib.MODIFIED
|
||||
if (action == vclib.ADDED or action == vclib.REPLACED) \
|
||||
and change.base_path \
|
||||
and change.base_rev:
|
||||
is_copy = 1
|
||||
if change.item_kind == core.svn_node_dir:
|
||||
pathtype = vclib.DIR
|
||||
elif change.item_kind == core.svn_node_file:
|
||||
pathtype = vclib.FILE
|
||||
else:
|
||||
pathtype = None
|
||||
|
||||
parts = _path_parts(path)
|
||||
if vclib.check_path_access(self, parts, pathtype, rev):
|
||||
if is_copy and change.base_path and (change.base_path != path):
|
||||
parts = _path_parts(change.base_path)
|
||||
if not vclib.check_path_access(self, parts, pathtype, change.base_rev):
|
||||
is_copy = 0
|
||||
change.base_path = None
|
||||
change.base_rev = None
|
||||
changedpaths[path] = SVNChangedPath(path, rev, pathtype,
|
||||
change.base_path,
|
||||
change.base_rev, action,
|
||||
is_copy, change.text_changed,
|
||||
change.prop_changes)
|
||||
found_readable = 1
|
||||
else:
|
||||
found_unreadable = 1
|
||||
|
||||
# If our caller doesn't care about changed paths, we must be
|
||||
# here for authz reasons only. That means the minute we've
|
||||
# found both a readable and an unreadable path, we can bail out.
|
||||
if (not include_changed_paths) and found_readable and found_unreadable:
|
||||
return date, author, None, None
|
||||
|
||||
# Okay, we've process all our paths. Let's filter our metadata,
|
||||
# and return the requested data.
|
||||
if found_unreadable:
|
||||
msg = None
|
||||
if not found_readable:
|
||||
author = None
|
||||
date = None
|
||||
if include_changed_paths:
|
||||
return date, author, msg, changedpaths.values()
|
||||
else:
|
||||
pathtype = None
|
||||
return date, author, msg, None
|
||||
|
||||
parts = _path_parts(path)
|
||||
if vclib.check_path_access(self, parts, pathtype, rev):
|
||||
if is_copy and change.base_path and (change.base_path != path):
|
||||
parts = _path_parts(change.base_path)
|
||||
if not vclib.check_path_access(self, parts, pathtype, change.base_rev):
|
||||
is_copy = 0
|
||||
change.base_path = None
|
||||
change.base_rev = None
|
||||
changedpaths[path] = SVNChangedPath(path, rev, pathtype,
|
||||
change.base_path,
|
||||
change.base_rev, action,
|
||||
is_copy, change.text_changed,
|
||||
change.prop_changes)
|
||||
found_readable = 1
|
||||
else:
|
||||
found_unreadable = 1
|
||||
|
||||
# Return our tuple, auth-filtered: date, author, msg, changes
|
||||
if found_unreadable:
|
||||
msg = None
|
||||
if not found_readable:
|
||||
author = None
|
||||
datestr = None
|
||||
|
||||
date = _datestr_to_date(datestr)
|
||||
return date, author, msg, changedpaths.values()
|
||||
|
||||
def revinfo(self, rev):
|
||||
# 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:
|
||||
cached_info = self._revinfo_raw(rev)
|
||||
if not cached_info \
|
||||
or (include_changed_paths and cached_info[3] is None):
|
||||
cached_info = _revinfo_helper(rev, include_changed_paths)
|
||||
self._revinfo_cache[rev] = cached_info
|
||||
return cached_info[0], cached_info[1], cached_info[2], cached_info[3]
|
||||
|
||||
def revinfo(self, rev):
|
||||
return self._revinfo(rev, 1)
|
||||
|
||||
def rawdiff(self, path_parts1, rev1, path_parts2, rev2, type, options={}):
|
||||
p1 = self._getpath(path_parts1)
|
||||
p2 = self._getpath(path_parts2)
|
||||
@@ -661,7 +702,7 @@ class LocalSubversionRepository(vclib.Repository):
|
||||
args = vclib._diff_args(type, options)
|
||||
|
||||
def _date_from_rev(rev):
|
||||
date, author, msg, changes = self.revinfo(rev)
|
||||
date, author, msg, changes = self._revinfo(rev)
|
||||
return date
|
||||
|
||||
try:
|
||||
@@ -671,6 +712,7 @@ class LocalSubversionRepository(vclib.Repository):
|
||||
info2 = p2, _date_from_rev(r2), r2
|
||||
return vclib._diff_fp(temp1, temp2, info1, info2, self.diff_cmd, args)
|
||||
except core.SubversionException, e:
|
||||
_fix_subversion_exception(e)
|
||||
if e.apr_err == core.SVN_ERR_FS_NOT_FOUND:
|
||||
raise vclib.InvalidRevision
|
||||
raise
|
||||
@@ -710,6 +752,7 @@ class LocalSubversionRepository(vclib.Repository):
|
||||
results = repos.svn_repos_trace_node_locations(self.fs_ptr, path,
|
||||
rev, [old_rev], _allow_all)
|
||||
except core.SubversionException, e:
|
||||
_fix_subversion_exception(e)
|
||||
if e.apr_err == core.SVN_ERR_FS_NOT_FOUND:
|
||||
raise vclib.ItemNotFound(path)
|
||||
raise
|
||||
@@ -759,6 +802,7 @@ class LocalSubversionRepository(vclib.Repository):
|
||||
try:
|
||||
mid_id = fs.node_id(self._getroot(mid), path)
|
||||
except core.SubversionException, e:
|
||||
_fix_subversion_exception(e)
|
||||
if e.apr_err == core.SVN_ERR_FS_NOT_FOUND:
|
||||
cmp = -1
|
||||
else:
|
||||
|
477
lib/viewvc.py
477
lib/viewvc.py
@@ -1,6 +1,6 @@
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2008 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
|
||||
@@ -14,7 +14,7 @@
|
||||
#
|
||||
# -----------------------------------------------------------------------
|
||||
|
||||
__version__ = '1.1-dev'
|
||||
__version__ = '1.1.0'
|
||||
|
||||
# this comes from our library; measure the startup time
|
||||
import debug
|
||||
@@ -81,7 +81,7 @@ _sticky_vars = [
|
||||
]
|
||||
|
||||
# number of extra pages of information on either side of the current
|
||||
# page to fetch (see use_pagesize configuration option)
|
||||
# page to fetch (see dir_pagesize/log_pagesize configuration option)
|
||||
EXTRA_PAGES = 3
|
||||
|
||||
# for reading/writing between a couple descriptors
|
||||
@@ -106,7 +106,10 @@ class Request:
|
||||
# process the Accept-Language: header, and load the key/value
|
||||
# files, given the selected language
|
||||
hal = server.getenv('HTTP_ACCEPT_LANGUAGE','')
|
||||
self.lang_selector = accept.language(hal)
|
||||
try:
|
||||
self.lang_selector = accept.language(hal)
|
||||
except accept.AcceptLanguageParseError:
|
||||
self.lang_selector = accept.language('en')
|
||||
self.language = self.lang_selector.select_from(cfg.general.languages)
|
||||
self.kv = cfg.load_kv_files(self.language)
|
||||
|
||||
@@ -993,8 +996,20 @@ def default_view(mime_type, cfg):
|
||||
return view_checkout
|
||||
|
||||
def get_file_view_info(request, where, rev=None, mime_type=None, pathrev=-1):
|
||||
"""Return common hrefs and a viewability flag used for various views
|
||||
of FILENAME at revision REV whose MIME type is MIME_TYPE."""
|
||||
"""Return an object holding common hrefs and a viewability flag used
|
||||
for various views of FILENAME at revision REV whose MIME type is
|
||||
MIME_TYPE.
|
||||
|
||||
The object's members include:
|
||||
view_href
|
||||
download_href
|
||||
download_text_href
|
||||
annotate_href
|
||||
revision_href
|
||||
prefer_markup
|
||||
|
||||
"""
|
||||
|
||||
rev = rev and str(rev) or None
|
||||
mime_type = mime_type or guess_mime(where)
|
||||
if pathrev == -1: # cheesy default value, since we need to preserve None
|
||||
@@ -1042,8 +1057,12 @@ def get_file_view_info(request, where, rev=None, mime_type=None, pathrev=-1):
|
||||
|
||||
prefer_markup = default_view(mime_type, request.cfg) == view_markup
|
||||
|
||||
return view_href, download_href, download_text_href, \
|
||||
annotate_href, revision_href, ezt.boolean(prefer_markup)
|
||||
return _item(view_href=view_href,
|
||||
download_href=download_href,
|
||||
download_text_href=download_text_href,
|
||||
annotate_href=annotate_href,
|
||||
revision_href=revision_href,
|
||||
prefer_markup=ezt.boolean(prefer_markup))
|
||||
|
||||
|
||||
# Regular expressions for location text that looks like URLs and email
|
||||
@@ -1154,40 +1173,44 @@ def html_time(request, secs, extended=0):
|
||||
return s
|
||||
|
||||
def common_template_data(request, revision=None, mime_type=None):
|
||||
"""Return a ezt.TemplateData instance with data dictionary items
|
||||
common to most ViewVC views."""
|
||||
|
||||
cfg = request.cfg
|
||||
data = {
|
||||
|
||||
# Initialize data dictionary members (sorted alphanumerically)
|
||||
data = ezt.TemplateData({
|
||||
'annotate_href' : None,
|
||||
'cfg' : cfg,
|
||||
'vsn' : __version__,
|
||||
'kv' : request.kv,
|
||||
'docroot' : cfg.options.docroot is None \
|
||||
'docroot' : cfg.options.docroot is None \
|
||||
and request.script_name + '/' + docroot_magic_path \
|
||||
or cfg.options.docroot,
|
||||
'username' : request.username,
|
||||
'where' : request.server.escape(request.where),
|
||||
'roottype' : request.roottype,
|
||||
'download_href' : None,
|
||||
'download_text_href' : None,
|
||||
'graph_href': None,
|
||||
'kv' : request.kv,
|
||||
'lockinfo' : None,
|
||||
'log_href' : None,
|
||||
'nav_path' : nav_path(request),
|
||||
'pathtype' : None,
|
||||
'prefer_markup' : ezt.boolean(0),
|
||||
'queryform_href' : None,
|
||||
'rev' : None,
|
||||
'revision_href' : None,
|
||||
'rootname' : request.rootname \
|
||||
and request.server.escape(request.rootname) or None,
|
||||
'rootpath' : request.rootpath,
|
||||
'pathtype' : None,
|
||||
'nav_path' : nav_path(request),
|
||||
'view' : _view_codes[request.view_func],
|
||||
'rev' : None,
|
||||
'lockinfo' : None,
|
||||
'view_href' : None,
|
||||
'annotate_href' : None,
|
||||
'download_href' : None,
|
||||
'download_text_href' : None,
|
||||
'revision_href' : None,
|
||||
'queryform_href' : None,
|
||||
'roots_href' : request.get_url(view_func=view_roots, escape=1, params={}),
|
||||
'roottype' : request.roottype,
|
||||
'rss_href' : None,
|
||||
'tarball_href' : None,
|
||||
'up_href' : None,
|
||||
'log_href' : None,
|
||||
'log_href_rev': None,
|
||||
'graph_href': None,
|
||||
'rss_href' : None,
|
||||
'roots_href' : request.get_url(view_func=view_roots, escape=1, params={}),
|
||||
'prefer_markup' : ezt.boolean(0),
|
||||
}
|
||||
'username' : request.username,
|
||||
'view' : _view_codes[request.view_func],
|
||||
'view_href' : None,
|
||||
'vsn' : __version__,
|
||||
'where' : request.server.escape(request.where),
|
||||
})
|
||||
|
||||
rev = revision
|
||||
if not rev:
|
||||
@@ -1214,11 +1237,14 @@ def common_template_data(request, revision=None, mime_type=None):
|
||||
params={}, escape=1)
|
||||
|
||||
if request.pathtype == vclib.FILE:
|
||||
data['view_href'], data['download_href'], data['download_text_href'], \
|
||||
data['annotate_href'], data['revision_href'], data['prefer_markup'] \
|
||||
= get_file_view_info(request, request.where, data['rev'], mime_type)
|
||||
data['log_href'] = request.get_url(view_func=view_log,
|
||||
params={}, escape=1)
|
||||
fvi = get_file_view_info(request, request.where, data['rev'], mime_type)
|
||||
data['view_href'] = fvi.view_href
|
||||
data['download_href'] = fvi.download_href
|
||||
data['download_text_href'] = fvi.download_text_href
|
||||
data['annotate_href'] = fvi.annotate_href
|
||||
data['revision_href'] = fvi.revision_href
|
||||
data['prefer_markup'] = fvi.prefer_markup
|
||||
data['log_href'] = request.get_url(view_func=view_log, params={}, escape=1)
|
||||
if request.roottype == 'cvs' and cfg.options.use_cvsgraph:
|
||||
data['graph_href'] = request.get_url(view_func=view_cvsgraph,
|
||||
params={}, escape=1)
|
||||
@@ -1417,6 +1443,9 @@ def make_rss_time_string(date, cfg):
|
||||
return None
|
||||
return time.strftime("%a, %d %b %Y %H:%M:%S", time.gmtime(date)) + ' UTC'
|
||||
|
||||
def make_comma_sep_list_string(items):
|
||||
return string.join(map(lambda x: x.name, items), ', ')
|
||||
|
||||
def get_itemprops(request, path_parts, rev):
|
||||
itemprops = request.repos.itemprops(path_parts, rev)
|
||||
propnames = itemprops.keys()
|
||||
@@ -1444,7 +1473,8 @@ def calculate_mime_type(request, path_parts, rev):
|
||||
mime_type = None
|
||||
if not path_parts:
|
||||
return None
|
||||
if request.roottype == 'svn':
|
||||
if request.roottype == 'svn' \
|
||||
and (not request.cfg.options.svn_ignore_mimetype):
|
||||
try:
|
||||
itemprops = request.repos.itemprops(path_parts, rev)
|
||||
mime_type = itemprops.get('svn:mime-type')
|
||||
@@ -1458,7 +1488,7 @@ def markup_or_annotate(request, is_annotate):
|
||||
cfg = request.cfg
|
||||
path, rev = _orig_path(request, is_annotate and 'annotate' or 'revision')
|
||||
lines = fp = image_src_href = None
|
||||
annotation = None
|
||||
annotation = 'none'
|
||||
revision = None
|
||||
mime_type = calculate_mime_type(request, path, rev)
|
||||
|
||||
@@ -1497,7 +1527,7 @@ def markup_or_annotate(request, is_annotate):
|
||||
fp.close()
|
||||
|
||||
data = common_template_data(request, revision)
|
||||
data.update({
|
||||
data.merge(ezt.TemplateData({
|
||||
'mime_type' : mime_type,
|
||||
'log' : None,
|
||||
'date' : None,
|
||||
@@ -1517,20 +1547,18 @@ def markup_or_annotate(request, is_annotate):
|
||||
'lines' : lines,
|
||||
'properties' : get_itemprops(request, path, rev),
|
||||
'annotation' : annotation,
|
||||
})
|
||||
}))
|
||||
|
||||
if cfg.options.show_log_in_markup:
|
||||
options = {'svn_latest_log': 1} ### FIXME: No longer needed?
|
||||
revs = request.repos.itemlog(path, revision, vclib.SORTBY_DEFAULT,
|
||||
revs = request.repos.itemlog(path, revision, vclib.SORTBY_REV,
|
||||
0, 1, options)
|
||||
entry = revs[-1]
|
||||
data.update({
|
||||
'date' : make_time_string(entry.date, cfg),
|
||||
'author' : entry.author,
|
||||
'changed' : entry.changed,
|
||||
'log' : htmlify(entry.log, cfg.options.mangle_email_addresses),
|
||||
'size' : entry.size,
|
||||
})
|
||||
data['date'] = make_time_string(entry.date, cfg)
|
||||
data['author'] = entry.author
|
||||
data['changed'] = entry.changed
|
||||
data['log'] = htmlify(entry.log, cfg.options.mangle_email_addresses)
|
||||
data['size'] = entry.size
|
||||
|
||||
if entry.date is not None:
|
||||
data['ago'] = html_time(request, entry.date, 1)
|
||||
@@ -1538,15 +1566,14 @@ def markup_or_annotate(request, is_annotate):
|
||||
if request.roottype == 'cvs':
|
||||
branch = entry.branch_number
|
||||
prev = entry.prev or entry.parent
|
||||
data.update({
|
||||
'state' : entry.dead and 'dead',
|
||||
'prev' : prev and prev.string,
|
||||
'vendor_branch' : ezt.boolean(branch and branch[2] % 2 == 1),
|
||||
'branches' : string.join(map(lambda x: x.name, entry.branches), ', '),
|
||||
'tags' : string.join(map(lambda x: x.name, entry.tags), ', '),
|
||||
'branch_points': string.join(map(lambda x: x.name,
|
||||
entry.branch_points), ', ')
|
||||
})
|
||||
data['state'] = entry.dead and 'dead'
|
||||
data['prev'] = prev and prev.string
|
||||
data['vendor_branch'] = ezt.boolean(branch and branch[2] % 2 == 1)
|
||||
|
||||
### TODO: Should this be using prep_tags() instead?
|
||||
data['branches'] = make_comma_sep_list_string(entry.branches)
|
||||
data['tags'] = make_comma_sep_list_string(entry.tags)
|
||||
data['branch_points']= make_comma_sep_list_string(entry.branch_points)
|
||||
|
||||
if path != request.path_parts:
|
||||
orig_path = _path_join(path)
|
||||
@@ -1649,10 +1676,14 @@ def view_roots(request):
|
||||
href=href))
|
||||
|
||||
data = common_template_data(request)
|
||||
data['roots'] = roots
|
||||
data.merge(ezt.TemplateData({
|
||||
'roots' : roots,
|
||||
}))
|
||||
generate_page(request, "roots", data)
|
||||
|
||||
def view_directory(request):
|
||||
cfg = request.cfg
|
||||
|
||||
# For Subversion repositories, the revision acts as a weak validator for
|
||||
# the directory listing (to take into account template changes or
|
||||
# revision property changes).
|
||||
@@ -1666,7 +1697,6 @@ def view_directory(request):
|
||||
return
|
||||
|
||||
# List current directory
|
||||
cfg = request.cfg
|
||||
options = {}
|
||||
if request.roottype == 'cvs':
|
||||
hideattic = int(request.query_dict.get('hideattic',
|
||||
@@ -1686,11 +1716,11 @@ def view_directory(request):
|
||||
# however, when sorting by other properties or not paging, we've no
|
||||
# choice but to fetch dirlogs for everything.
|
||||
debug.t_start("dirlogs")
|
||||
if cfg.options.use_pagesize and sortby == 'file':
|
||||
if cfg.options.dir_pagesize and sortby == 'file':
|
||||
dirlogs_first = int(request.query_dict.get('dir_pagestart', 0))
|
||||
if dirlogs_first > len(file_data):
|
||||
dirlogs_first = 0
|
||||
dirlogs_last = dirlogs_first + cfg.options.use_pagesize
|
||||
dirlogs_last = dirlogs_first + cfg.options.dir_pagesize
|
||||
for file in file_data:
|
||||
file.rev = None
|
||||
file.date = None
|
||||
@@ -1802,10 +1832,13 @@ def view_directory(request):
|
||||
|
||||
row.mime_type = calculate_mime_type(request, _path_parts(file_where),
|
||||
file.rev)
|
||||
row.view_href, row.download_href, row.download_text_href, \
|
||||
row.annotate_href, row.revision_href, \
|
||||
row.prefer_markup \
|
||||
= get_file_view_info(request, file_where, file.rev, row.mime_type)
|
||||
fvi = get_file_view_info(request, file_where, file.rev, row.mime_type)
|
||||
row.view_href = fvi.view_href
|
||||
row.download_href = fvi.download_href
|
||||
row.download_text_href = fvi.download_text_href
|
||||
row.annotate_href = fvi.annotate_href
|
||||
row.revision_href = fvi.revision_href
|
||||
row.prefer_markup = fvi.prefer_markup
|
||||
row.log_href = request.get_url(view_func=view_log,
|
||||
where=file_where,
|
||||
pathtype=vclib.FILE,
|
||||
@@ -1820,9 +1853,10 @@ def view_directory(request):
|
||||
|
||||
rows.append(row)
|
||||
|
||||
# prepare the data that will be passed to the template
|
||||
# Prepare the data that will be passed to the template, based on the
|
||||
# common template data.
|
||||
data = common_template_data(request)
|
||||
data.update({
|
||||
data.merge(ezt.TemplateData({
|
||||
'entries' : rows,
|
||||
'sortby' : sortby,
|
||||
'sortdir' : sortdir,
|
||||
@@ -1856,7 +1890,25 @@ def view_directory(request):
|
||||
'branch_tags': None,
|
||||
'plain_tags': None,
|
||||
'properties': get_itemprops(request, request.path_parts, request.pathrev),
|
||||
})
|
||||
'tree_rev' : None,
|
||||
'tree_rev_href' : None,
|
||||
'dir_paging_action' : None,
|
||||
'dir_paging_hidden_values' : [],
|
||||
'search_re_action' : None,
|
||||
'search_re_hidden_values' : [],
|
||||
|
||||
# Populated by paging()/paging_sws()
|
||||
'picklist' : [],
|
||||
'picklist_len' : 0,
|
||||
|
||||
# Populated by pathrev_form()
|
||||
'pathrev_action' : None,
|
||||
'pathrev_hidden_values' : [],
|
||||
'pathrev_clear_action' : None,
|
||||
'pathrev_clear_hidden_values' : [],
|
||||
'pathrev' : None,
|
||||
'lastrev' : None,
|
||||
}))
|
||||
|
||||
# clicking on sort column reverses sort order
|
||||
if sortdir == 'down':
|
||||
@@ -1867,24 +1919,27 @@ def view_directory(request):
|
||||
data['sortby_%s_href' % sortby] = request.get_url(params={'sortdir':
|
||||
revsortdir},
|
||||
escape=1)
|
||||
# CVS doesn't support sorting by rev
|
||||
if request.roottype == "cvs":
|
||||
data['sortby_rev_href'] = None
|
||||
|
||||
# set cvs-specific fields
|
||||
if request.roottype == 'cvs':
|
||||
plain_tags = options['cvs_tags']
|
||||
plain_tags.sort(icmp)
|
||||
plain_tags.reverse()
|
||||
data['plain_tags']= plain_tags
|
||||
|
||||
branch_tags = options['cvs_branches']
|
||||
branch_tags.sort(icmp)
|
||||
branch_tags.reverse()
|
||||
|
||||
data.update({
|
||||
'attic_showing' : ezt.boolean(not hideattic),
|
||||
'show_attic_href' : request.get_url(params={'hideattic': 0}, escape=1),
|
||||
'hide_attic_href' : request.get_url(params={'hideattic': 1}, escape=1),
|
||||
'branch_tags': branch_tags,
|
||||
'plain_tags': plain_tags,
|
||||
})
|
||||
data['branch_tags']= branch_tags
|
||||
|
||||
data['attic_showing'] = ezt.boolean(not hideattic)
|
||||
data['show_attic_href'] = request.get_url(params={'hideattic': 0},
|
||||
escape=1)
|
||||
data['hide_attic_href'] = request.get_url(params={'hideattic': 1},
|
||||
escape=1)
|
||||
|
||||
# set svn-specific fields
|
||||
elif request.roottype == 'svn':
|
||||
@@ -1897,22 +1952,20 @@ def view_directory(request):
|
||||
params={},
|
||||
escape=1)
|
||||
|
||||
if cfg.options.use_pagesize:
|
||||
if cfg.options.dir_pagesize:
|
||||
data['dir_paging_action'], data['dir_paging_hidden_values'] = \
|
||||
request.get_form(params={'dir_pagestart': None})
|
||||
|
||||
pathrev_form(request, data)
|
||||
|
||||
### one day, if EZT has "or" capability, we can lose this
|
||||
data['search_re_form'] = ezt.boolean(cfg.options.use_re_search)
|
||||
if data['search_re_form']:
|
||||
if cfg.options.use_re_search:
|
||||
data['search_re_action'], data['search_re_hidden_values'] = \
|
||||
request.get_form(params={'search': None})
|
||||
|
||||
if cfg.options.use_pagesize:
|
||||
if cfg.options.dir_pagesize:
|
||||
data['dir_pagestart'] = int(request.query_dict.get('dir_pagestart',0))
|
||||
data['entries'] = paging(data, 'entries', data['dir_pagestart'], 'name',
|
||||
cfg.options.use_pagesize)
|
||||
cfg.options.dir_pagesize)
|
||||
|
||||
generate_page(request, "directory", data)
|
||||
|
||||
@@ -2072,11 +2125,11 @@ def view_log(request):
|
||||
sortby = vclib.SORTBY_DEFAULT
|
||||
|
||||
first = last = 0
|
||||
if cfg.options.use_pagesize:
|
||||
if cfg.options.log_pagesize:
|
||||
log_pagestart = int(request.query_dict.get('log_pagestart', 0))
|
||||
first = log_pagestart - min(log_pagestart,
|
||||
(EXTRA_PAGES * cfg.options.use_pagesize))
|
||||
last = log_pagestart + ((EXTRA_PAGES + 1) * cfg.options.use_pagesize) + 1
|
||||
(EXTRA_PAGES * cfg.options.log_pagesize))
|
||||
last = log_pagestart + ((EXTRA_PAGES + 1) * cfg.options.log_pagesize) + 1
|
||||
show_revs = request.repos.itemlog(request.path_parts, request.pathrev,
|
||||
sortby, first, last - first, options)
|
||||
|
||||
@@ -2172,9 +2225,13 @@ def view_log(request):
|
||||
|
||||
# view/download links
|
||||
if pathtype is vclib.FILE:
|
||||
entry.view_href, entry.download_href, entry.download_text_href, \
|
||||
entry.annotate_href, entry.revision_href, entry.prefer_markup \
|
||||
= get_file_view_info(request, request.where, rev.string, mime_type)
|
||||
fvi = get_file_view_info(request, request.where, rev.string, mime_type)
|
||||
entry.view_href = fvi.view_href
|
||||
entry.download_href = fvi.download_href
|
||||
entry.download_text_href = fvi.download_text_href
|
||||
entry.annotate_href = fvi.annotate_href
|
||||
entry.revision_href = fvi.revision_href
|
||||
entry.prefer_markup = fvi.prefer_markup
|
||||
else:
|
||||
entry.revision_href = request.get_url(view_func=view_revision,
|
||||
params={'revision': rev.string},
|
||||
@@ -2232,8 +2289,16 @@ def view_log(request):
|
||||
entry.copy_path = request.server.escape(entry.copy_path)
|
||||
entries.append(entry)
|
||||
|
||||
diff_select_action, diff_select_hidden_values = \
|
||||
request.get_form(view_func=view_diff,
|
||||
params={'r1': None, 'r2': None, 'tr1': None,
|
||||
'tr2': None, 'diff_format': None})
|
||||
logsort_action, logsort_hidden_values = \
|
||||
request.get_form(params={'logsort': None})
|
||||
|
||||
|
||||
data = common_template_data(request)
|
||||
data.update({
|
||||
data.merge(ezt.TemplateData({
|
||||
'default_branch' : None,
|
||||
'mime_type' : mime_type,
|
||||
'rev_selected' : selected_rev,
|
||||
@@ -2241,6 +2306,8 @@ def view_log(request):
|
||||
'logsort' : logsort,
|
||||
'human_readable' : ezt.boolean(diff_format in ('h', 'l')),
|
||||
'log_pagestart' : None,
|
||||
'log_paging_action' : None,
|
||||
'log_paging_hidden_values' : [],
|
||||
'entries': entries,
|
||||
'head_prefer_markup' : ezt.boolean(0),
|
||||
'head_view_href' : None,
|
||||
@@ -2252,42 +2319,45 @@ def view_log(request):
|
||||
'tag_download_href': None,
|
||||
'tag_download_text_href': None,
|
||||
'tag_annotate_href': None,
|
||||
})
|
||||
'diff_select_action' : diff_select_action,
|
||||
'diff_select_hidden_values' : diff_select_hidden_values,
|
||||
'logsort_action' : logsort_action,
|
||||
'logsort_hidden_values' : logsort_hidden_values,
|
||||
'tags' : [],
|
||||
'branch_tags' : [],
|
||||
'plain_tags' : [],
|
||||
|
||||
# Populated by paging()/paging_sws()
|
||||
'picklist' : [],
|
||||
'picklist_len' : 0,
|
||||
|
||||
# Populated by pathrev_form()
|
||||
'pathrev_action' : None,
|
||||
'pathrev_hidden_values' : [],
|
||||
'pathrev_clear_action' : None,
|
||||
'pathrev_clear_hidden_values' : [],
|
||||
'pathrev' : None,
|
||||
'lastrev' : None,
|
||||
}))
|
||||
|
||||
lastrev = pathrev_form(request, data)
|
||||
|
||||
data['diff_select_action'], data['diff_select_hidden_values'] = \
|
||||
request.get_form(view_func=view_diff,
|
||||
params={'r1': None, 'r2': None, 'tr1': None,
|
||||
'tr2': None, 'diff_format': None})
|
||||
|
||||
data['logsort_action'], data['logsort_hidden_values'] = \
|
||||
request.get_form(params={'logsort': None})
|
||||
|
||||
if pathtype is vclib.FILE:
|
||||
if not request.pathrev or lastrev is None:
|
||||
view_href, download_href, download_text_href, \
|
||||
annotate_href, revision_href, prefer_markup \
|
||||
= get_file_view_info(request, request.where, None, mime_type, None)
|
||||
data.update({
|
||||
'head_view_href': view_href,
|
||||
'head_download_href': download_href,
|
||||
'head_download_text_href': download_text_href,
|
||||
'head_annotate_href': annotate_href,
|
||||
'head_prefer_markup': prefer_markup,
|
||||
})
|
||||
fvi = get_file_view_info(request, request.where, None, mime_type, None)
|
||||
data['head_view_href']= fvi.view_href
|
||||
data['head_download_href']= fvi.download_href
|
||||
data['head_download_text_href']= fvi.download_text_href
|
||||
data['head_annotate_href']= fvi.annotate_href
|
||||
data['head_prefer_markup']= fvi.prefer_markup
|
||||
|
||||
if request.pathrev and request.roottype == 'cvs':
|
||||
view_href, download_href, download_text_href, \
|
||||
annotate_href, revision_href, prefer_markup \
|
||||
= get_file_view_info(request, request.where, None, mime_type)
|
||||
data.update({
|
||||
'tag_view_href': view_href,
|
||||
'tag_download_href': download_href,
|
||||
'tag_download_text_href': download_text_href,
|
||||
'tag_annotate_href': annotate_href,
|
||||
'tag_prefer_markup': prefer_markup,
|
||||
})
|
||||
fvi = get_file_view_info(request, request.where, None, mime_type)
|
||||
data['tag_view_href']= fvi.view_href
|
||||
data['tag_download_href']= fvi.download_href
|
||||
data['tag_download_text_href']= fvi.download_text_href
|
||||
data['tag_annotate_href']= fvi.annotate_href
|
||||
data['tag_prefer_markup']= fvi.prefer_markup
|
||||
else:
|
||||
data['head_view_href'] = request.get_url(view_func=view_directory,
|
||||
params={}, escape=1)
|
||||
@@ -2307,23 +2377,20 @@ def view_log(request):
|
||||
branches.append(branch)
|
||||
data['default_branch'] = prep_tags(request, branches)
|
||||
|
||||
data['tags'] = tags = [ ]
|
||||
data['branch_tags'] = branch_tags = []
|
||||
data['plain_tags'] = plain_tags = []
|
||||
for tag, rev in tagitems:
|
||||
if rev.co_rev:
|
||||
tags.append(_item(rev=rev.co_rev.string, name=tag))
|
||||
data['tags'].append(_item(rev=rev.co_rev.string, name=tag))
|
||||
if rev.is_branch:
|
||||
branch_tags.append(tag)
|
||||
data['branch_tags'].append(tag)
|
||||
else:
|
||||
plain_tags.append(tag)
|
||||
data['plain_tags'].append(tag)
|
||||
|
||||
if cfg.options.use_pagesize:
|
||||
if cfg.options.log_pagesize:
|
||||
data['log_paging_action'], data['log_paging_hidden_values'] = \
|
||||
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.use_pagesize, first)
|
||||
'rev', cfg.options.log_pagesize, first)
|
||||
|
||||
generate_page(request, "log", data)
|
||||
|
||||
@@ -2377,8 +2444,6 @@ def view_cvsgraph(request):
|
||||
if not cfg.options.use_cvsgraph:
|
||||
raise debug.ViewVCException('Graph view is disabled', '403 Forbidden')
|
||||
|
||||
data = common_template_data(request)
|
||||
|
||||
# If cvsgraph can't find its supporting libraries, uncomment and set
|
||||
# accordingly. Do the same in view_cvsgraph_image().
|
||||
#os.environ['LD_LIBRARY_PATH'] = '/usr/lib:/usr/local/lib:/path/to/cvsgraph'
|
||||
@@ -2410,11 +2475,11 @@ def view_cvsgraph(request):
|
||||
escape=1, partial=1),
|
||||
rcsfile), 'rb', 0)
|
||||
|
||||
data.update({
|
||||
data = common_template_data(request)
|
||||
data.merge(ezt.TemplateData({
|
||||
'imagemap' : fp,
|
||||
'imagesrc' : imagesrc,
|
||||
})
|
||||
|
||||
}))
|
||||
generate_page(request, "graph", data)
|
||||
|
||||
def search_file(repos, path_parts, rev, search_re):
|
||||
@@ -2789,6 +2854,10 @@ def setup_diff(request):
|
||||
|
||||
|
||||
def view_patch(request):
|
||||
if 'diff' not in request.cfg.options.allowed_views:
|
||||
raise debug.ViewVCException('Diff generation is disabled',
|
||||
'403 Forbidden')
|
||||
|
||||
cfg = request.cfg
|
||||
query_dict = request.query_dict
|
||||
p1, p2, rev1, rev2, sym1, sym2 = setup_diff(request)
|
||||
@@ -2822,6 +2891,10 @@ def view_patch(request):
|
||||
|
||||
|
||||
def view_diff(request):
|
||||
if 'diff' not in request.cfg.options.allowed_views:
|
||||
raise debug.ViewVCException('Diff generation is disabled',
|
||||
'403 Forbidden')
|
||||
|
||||
cfg = request.cfg
|
||||
query_dict = request.query_dict
|
||||
p1, p2, rev1, rev2, sym1, sym2 = setup_diff(request)
|
||||
@@ -2913,20 +2986,35 @@ def view_diff(request):
|
||||
no_format_params = request.query_dict.copy()
|
||||
no_format_params['diff_format'] = None
|
||||
|
||||
fvi = get_file_view_info(request, path_left, rev1)
|
||||
left = _item(date=rcsdiff_date_reformat(date1, cfg),
|
||||
path=path_left, rev=rev1, tag=sym1)
|
||||
left.view_href, left.download_href, left.download_text_href, \
|
||||
left.annotate_href, left.revision_href, left.prefer_markup \
|
||||
= get_file_view_info(request, path_left, rev1)
|
||||
|
||||
path=path_left,
|
||||
rev=rev1,
|
||||
tag=sym1,
|
||||
view_href=fvi.view_href,
|
||||
download_href=fvi.download_href,
|
||||
download_text_href=fvi.download_text_href,
|
||||
annotate_href=fvi.annotate_href,
|
||||
revision_href=fvi.revision_href,
|
||||
prefer_markup=fvi.prefer_markup)
|
||||
|
||||
fvi = get_file_view_info(request, path_right, rev2)
|
||||
right = _item(date=rcsdiff_date_reformat(date2, cfg),
|
||||
path=path_right, rev=rev2, tag=sym2)
|
||||
right.view_href, right.download_href, right.download_text_href, \
|
||||
right.annotate_href, right.revision_href, right.prefer_markup \
|
||||
= get_file_view_info(request, path_right, rev2)
|
||||
path=path_right,
|
||||
rev=rev2,
|
||||
tag=sym2,
|
||||
view_href=fvi.view_href,
|
||||
download_href=fvi.download_href,
|
||||
download_text_href=fvi.download_text_href,
|
||||
annotate_href=fvi.annotate_href,
|
||||
revision_href=fvi.revision_href,
|
||||
prefer_markup=fvi.prefer_markup)
|
||||
|
||||
diff_format_action, diff_format_hidden_values = \
|
||||
request.get_form(params=no_format_params)
|
||||
|
||||
data = common_template_data(request)
|
||||
data.update({
|
||||
data.merge(ezt.TemplateData({
|
||||
'left' : left,
|
||||
'right' : right,
|
||||
'raw_diff' : raw_diff_fp,
|
||||
@@ -2938,11 +3026,9 @@ def view_diff(request):
|
||||
'patch_href' : request.get_url(view_func=view_patch,
|
||||
params=no_format_params,
|
||||
escape=1),
|
||||
})
|
||||
|
||||
data['diff_format_action'], data['diff_format_hidden_values'] = \
|
||||
request.get_form(params=no_format_params)
|
||||
|
||||
'diff_format_action' : diff_format_action,
|
||||
'diff_format_hidden_values' : diff_format_hidden_values,
|
||||
}))
|
||||
generate_page(request, "diff", data)
|
||||
|
||||
|
||||
@@ -3136,11 +3222,11 @@ def download_tarball(request):
|
||||
|
||||
def view_revision(request):
|
||||
if request.roottype == "cvs":
|
||||
raise ViewVCException("Revision view not supported for CVS repositories "
|
||||
"at this time.", "400 Bad Request")
|
||||
raise debug.ViewVCException("Revision view not supported for CVS "
|
||||
"repositories at this time.",
|
||||
"400 Bad Request")
|
||||
|
||||
cfg = request.cfg
|
||||
data = common_template_data(request)
|
||||
query_dict = request.query_dict
|
||||
try:
|
||||
rev = request.repos._getrev(query_dict.get('revision'))
|
||||
@@ -3169,6 +3255,7 @@ def view_revision(request):
|
||||
more_changes_href = None
|
||||
first_changes = None
|
||||
first_changes_href = None
|
||||
num_changes = len(changes)
|
||||
if limit_changes and len(changes) > limit_changes:
|
||||
more_changes = len(changes) - limit_changes
|
||||
params = query_dict.copy()
|
||||
@@ -3262,28 +3349,28 @@ def view_revision(request):
|
||||
pathtype=None,
|
||||
params={'revision': str(rev + 1)},
|
||||
escape=1)
|
||||
data.update({
|
||||
jump_rev_action, jump_rev_hidden_values = \
|
||||
request.get_form(params={'revision': None})
|
||||
|
||||
data = common_template_data(request)
|
||||
data.merge(ezt.TemplateData({
|
||||
'rev' : str(rev),
|
||||
'author' : author,
|
||||
'date' : date_str,
|
||||
'log' : msg and htmlify(msg, cfg.options.mangle_email_addresses) or None,
|
||||
'ago' : None,
|
||||
'ago' : date is not None and html_time(request, date, 1) or None,
|
||||
'changes' : changes,
|
||||
'prev_href' : prev_rev_href,
|
||||
'next_href' : next_rev_href,
|
||||
'num_changes' : num_changes,
|
||||
'limit_changes': limit_changes,
|
||||
'more_changes': more_changes,
|
||||
'more_changes_href': more_changes_href,
|
||||
'first_changes': first_changes,
|
||||
'first_changes_href': first_changes_href,
|
||||
})
|
||||
|
||||
if date is not None:
|
||||
data['ago'] = html_time(request, date, 1)
|
||||
|
||||
data['jump_rev_action'], data['jump_rev_hidden_values'] = \
|
||||
request.get_form(params={'revision': None})
|
||||
|
||||
'jump_rev_action' : jump_rev_action,
|
||||
'jump_rev_hidden_values' : jump_rev_hidden_values,
|
||||
}))
|
||||
if rev == youngest_rev:
|
||||
request.server.addheader("Cache-control", "no-store")
|
||||
generate_page(request, "revision", data)
|
||||
@@ -3316,32 +3403,32 @@ def view_queryform(request):
|
||||
% (request.rootname, request.where),
|
||||
'403 Forbidden')
|
||||
|
||||
data = common_template_data(request)
|
||||
|
||||
data['query_action'], data['query_hidden_values'] = \
|
||||
query_action, query_hidden_values = \
|
||||
request.get_form(view_func=view_query, params={'limit_changes': None})
|
||||
|
||||
# default values ...
|
||||
data['branch'] = request.query_dict.get('branch', '')
|
||||
data['branch_match'] = request.query_dict.get('branch_match', 'exact')
|
||||
data['dir'] = request.query_dict.get('dir', '')
|
||||
data['file'] = request.query_dict.get('file', '')
|
||||
data['file_match'] = request.query_dict.get('file_match', 'exact')
|
||||
data['who'] = request.query_dict.get('who', '')
|
||||
data['who_match'] = request.query_dict.get('who_match', 'exact')
|
||||
data['comment'] = request.query_dict.get('comment', '')
|
||||
data['comment_match'] = request.query_dict.get('comment_match', 'exact')
|
||||
data['querysort'] = request.query_dict.get('querysort', 'date')
|
||||
data['date'] = request.query_dict.get('date', 'hours')
|
||||
data['hours'] = request.query_dict.get('hours', '2')
|
||||
data['mindate'] = request.query_dict.get('mindate', '')
|
||||
data['maxdate'] = request.query_dict.get('maxdate', '')
|
||||
data['limit_changes'] = int(request.query_dict.get('limit_changes',
|
||||
request.cfg.options.limit_changes))
|
||||
|
||||
data['dir_href'] = request.get_url(view_func=view_directory, params={},
|
||||
escape=1)
|
||||
|
||||
limit_changes = \
|
||||
int(request.query_dict.get('limit_changes',
|
||||
request.cfg.options.limit_changes))
|
||||
|
||||
data = common_template_data(request)
|
||||
data.merge(ezt.TemplateData({
|
||||
'branch' : request.query_dict.get('branch', ''),
|
||||
'branch_match' : request.query_dict.get('branch_match', 'exact'),
|
||||
'dir' : request.query_dict.get('dir', ''),
|
||||
'file' : request.query_dict.get('file', ''),
|
||||
'file_match' : request.query_dict.get('file_match', 'exact'),
|
||||
'who' : request.query_dict.get('who', ''),
|
||||
'who_match' : request.query_dict.get('who_match', 'exact'),
|
||||
'comment' : request.query_dict.get('comment', ''),
|
||||
'comment_match' : request.query_dict.get('comment_match', 'exact'),
|
||||
'querysort' : request.query_dict.get('querysort', 'date'),
|
||||
'date' : request.query_dict.get('date', 'hours'),
|
||||
'hours' : request.query_dict.get('hours', '2'),
|
||||
'mindate' : request.query_dict.get('mindate', ''),
|
||||
'maxdate' : request.query_dict.get('maxdate', ''),
|
||||
'limit_changes' : limit_changes,
|
||||
'dir_href' : request.get_url(view_func=view_directory, params={},
|
||||
escape=1),
|
||||
}))
|
||||
generate_page(request, "query_form", data)
|
||||
|
||||
def parse_date(datestr):
|
||||
@@ -3812,7 +3899,7 @@ def view_query(request):
|
||||
return
|
||||
|
||||
data = common_template_data(request)
|
||||
data.update({
|
||||
data.merge(ezt.TemplateData({
|
||||
'sql': sql,
|
||||
'english_query': english_query(request),
|
||||
'queryform_href': request.get_url(view_func=view_queryform, escape=1),
|
||||
@@ -3828,8 +3915,7 @@ def view_query(request):
|
||||
params={'date': 'month'},
|
||||
escape=1,
|
||||
prefix=1),
|
||||
})
|
||||
|
||||
}))
|
||||
if format == 'rss':
|
||||
generate_page(request, "rss", data, "application/rss+xml")
|
||||
else:
|
||||
@@ -3965,9 +4051,14 @@ def load_config(pathname=None, server=None):
|
||||
cfg.set_defaults()
|
||||
cfg.load_config(pathname, server and server.getenv("HTTP_HOST"))
|
||||
|
||||
# load mime types file
|
||||
if cfg.general.mime_types_file:
|
||||
mimetypes.init([cfg.general.mime_types_file])
|
||||
# Load mime types file(s), but reverse the order -- our
|
||||
# configuration uses a most-to-least preferred approach, but the
|
||||
# 'mimetypes' package wants things the other way around.
|
||||
if cfg.general.mime_types_files:
|
||||
files = cfg.general.mime_types_files[:]
|
||||
files.reverse()
|
||||
files = map(lambda x: os.path.join(os.path.dirname(pathname), x), files)
|
||||
mimetypes.init(files)
|
||||
|
||||
debug.t_end('load-config')
|
||||
return cfg
|
||||
@@ -4012,7 +4103,7 @@ def main(server, cfg):
|
||||
|
||||
finally:
|
||||
debug.t_end('main')
|
||||
debug.dump()
|
||||
debug.t_dump(server.file())
|
||||
debug.DumpChildren(server)
|
||||
|
||||
|
||||
|
@@ -50,7 +50,7 @@ numbers, and not literal):
|
||||
|
||||
9. Go into an empty directory and run the 'make-release' script:
|
||||
|
||||
tools/make-release viewvc-X.Y.Z X.Y.Z
|
||||
tools/make-release viewvc-X.Y.Z tags/X.Y.Z
|
||||
|
||||
10. Verify the archive files:
|
||||
|
||||
|
@@ -49,7 +49,7 @@
|
||||
[else]
|
||||
[is changes.type "add"]
|
||||
<tr>
|
||||
<td id="l[changes.line_number]">[if-any right.annotate_href]<a href="[right.annotate_href]#l[changes.line_number]">[changes.line_number]</a>[else][changes.line_number][end]</td>
|
||||
<td class="vc_diff_line_number" id="l[changes.line_number]">[if-any right.annotate_href]<a href="[right.annotate_href]#l[changes.line_number]">[changes.line_number]</a>[else][changes.line_number][end]</td>
|
||||
<td class="vc_diff_empty"> </td>
|
||||
<td class="vc_diff_add"> [changes.right]</td>
|
||||
</tr>
|
||||
@@ -64,7 +64,7 @@
|
||||
[is changes.type "change"]
|
||||
<tr>
|
||||
[if-any changes.have_right]
|
||||
<td id="l[changes.line_number]">[if-any right.annotate_href]<a href="[right.annotate_href]#l[changes.line_number]">[changes.line_number]</a>[else][changes.line_number][end]</td>
|
||||
<td class="vc_diff_line_number" id="l[changes.line_number]">[if-any right.annotate_href]<a href="[right.annotate_href]#l[changes.line_number]">[changes.line_number]</a>[else][changes.line_number][end]</td>
|
||||
[else]
|
||||
<td></td>
|
||||
[end]
|
||||
@@ -112,7 +112,7 @@
|
||||
</tr>
|
||||
[else]
|
||||
<tr>
|
||||
<td id="l[changes.line_number]">[if-any right.annotate_href]<a href="[right.annotate_href]#l[changes.line_number]">[changes.line_number]</a>[else][changes.line_number][end]</td>
|
||||
<td class="vc_diff_line_number" id="l[changes.line_number]">[if-any right.annotate_href]<a href="[right.annotate_href]#l[changes.line_number]">[changes.line_number]</a>[else][changes.line_number][end]</td>
|
||||
<td class="vc_diff_nochange"> [changes.left]</td>
|
||||
<td class="vc_diff_nochange"> [changes.right]</td>
|
||||
</tr>
|
||||
|
@@ -4,23 +4,31 @@
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 200px" class="vc_header[is sortby "file"]_sort[end]">
|
||||
<a href="[sortby_file_href]#dirlist">File
|
||||
[if-any sortby_file_href]<a href="[sortby_file_href]#dirlist">File</a>[else]File[end]
|
||||
[is sortby "file"]
|
||||
<img class="vc_sortarrow" alt="[is sortdir "down"](rev)[end]"
|
||||
width="13" height="13"
|
||||
src="[docroot]/images/[is sortdir "up"]up[else]down[end].png" />
|
||||
[end]
|
||||
</a>
|
||||
</th>
|
||||
<th style="width: 96px" class="vc_header"></th>
|
||||
[if-any sortby_rev_href]
|
||||
<th class="vc_header[is sortby "rev"]_sort[end]">
|
||||
<a href="[sortby_rev_href]#dirlist">Last Change
|
||||
<a href="[sortby_rev_href]#dirlist">Last Change</a>
|
||||
[is sortby "rev"]
|
||||
<img class="vc_sortarrow" alt="[is sortdir "down"](rev)[end]"
|
||||
width="13" height="13"
|
||||
src="[docroot]/images/[is sortdir "up"]up[else]down[end].png" />
|
||||
[end]
|
||||
</a>
|
||||
[else]
|
||||
<th class="vc_header[is sortby "date"]_sort[end]">
|
||||
[if-any sortby_date_href]<a href="[sortby_date_href]#dirlist">Last Change</a>[else]Last Change[end]
|
||||
[is sortby "date"]
|
||||
<img class="vc_sortarrow" alt="[is sortdir "down"](date)[end]"
|
||||
width="13" height="13"
|
||||
src="[docroot]/images/[is sortdir "up"]up[else]down[end].png" />
|
||||
[end]
|
||||
[end]
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
@@ -4,50 +4,45 @@
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="vc_header[is sortby "file"]_sort[end]" colspan="2">
|
||||
<a href="[sortby_file_href]#dirlist">File
|
||||
[if-any sortby_file_href]<a href="[sortby_file_href]#dirlist">File</a>[else]File[end]
|
||||
[is sortby "file"]
|
||||
<img class="vc_sortarrow" alt="[is sortdir "down"](rev)[end]"
|
||||
width="13" height="13"
|
||||
src="[docroot]/images/[is sortdir "up"]up[else]down[end].png" />
|
||||
[end]
|
||||
</a>
|
||||
</th>
|
||||
<th class="vc_header[is sortby "rev"]_sort[end]">
|
||||
<a href="[sortby_rev_href]#dirlist">Rev.
|
||||
[if-any sortby_rev_href]<a href="[sortby_rev_href]#dirlist">Rev.</a>[else]Rev.[end]
|
||||
[is sortby "rev"]
|
||||
<img class="vc_sortarrow" alt="[is sortdir "down"](rev)[end]"
|
||||
width="13" height="13"
|
||||
src="[docroot]/images/[is sortdir "up"]up[else]down[end].png" />
|
||||
[end]
|
||||
</a>
|
||||
</th>
|
||||
<th class="vc_header[is sortby "date"]_sort[end]">
|
||||
<a href="[sortby_date_href]#dirlist">Age
|
||||
[if-any sortby_date_href]<a href="[sortby_date_href]#dirlist">Age</a>[else]Age[end]
|
||||
[is sortby "date"]
|
||||
<img class="vc_sortarrow" alt="[is sortdir "down"](rev)[end]"
|
||||
width="13" height="13"
|
||||
src="[docroot]/images/[is sortdir "up"]up[else]down[end].png" />
|
||||
[end]
|
||||
</a>
|
||||
</th>
|
||||
<th class="vc_header[is sortby "author"]_sort[end]">
|
||||
<a href="[sortby_author_href]#dirlist">Author
|
||||
[if-any sortby_author_href]<a href="[sortby_author_href]#dirlist">Author</a>[else]Author[end]
|
||||
[is sortby "author"]
|
||||
<img class="vc_sortarrow" alt="[is sortdir "down"](rev)[end]"
|
||||
width="13" height="13"
|
||||
src="[docroot]/images/[is sortdir "up"]up[else]down[end].png" />
|
||||
[end]
|
||||
</a>
|
||||
</th>
|
||||
[is cfg.options.show_logs "1"]
|
||||
<th class="vc_header[is sortby "log"]_sort[end]">
|
||||
<a href="[sortby_log_href]#dirlist">Last log entry
|
||||
[if-any sortby_log_href]<a href="[sortby_log_href]#dirlist">Last log entry</a>[else]Last log entry[end]
|
||||
[is sortby "log"]
|
||||
<img class="vc_sortarrow" alt="[is sortdir "down"](rev)[end]"
|
||||
width="13" height="13"
|
||||
src="[docroot]/images/[is sortdir "up"]up[else]down[end].png" />
|
||||
[end]
|
||||
</a>
|
||||
</th>
|
||||
[end]
|
||||
</tr>
|
||||
|
@@ -229,6 +229,8 @@ form { margin: 0; }
|
||||
font-family: sans-serif;
|
||||
font-size: smaller;
|
||||
}
|
||||
.vc_diff_line_number {
|
||||
}
|
||||
.vc_raw_diff {
|
||||
background-color: #cccccc;
|
||||
font-size: smaller;
|
||||
|
@@ -8,7 +8,7 @@
|
||||
<hr />
|
||||
<div class="vc_summary">
|
||||
Revision [if-any revision_href]<a href="[revision_href]"><strong>[rev]</strong></a>[else]<strong>[rev]</strong>[end] -
|
||||
([if-any annotation][is annotation "annotated"]<a href="[view_href]"><strong>hide annotations</strong></a>[end][else]<a href="[annotate_href]"><strong>show annotations</strong></a>[end])
|
||||
([is annotation "annotated"]<a href="[view_href]"><strong>hide annotations</strong></a>[else]<a href="[annotate_href]"><strong>show annotations</strong></a>[end])
|
||||
[if-any download_href](<a href="[download_href]"><strong>download</strong></a>)[end]
|
||||
[if-any download_text_href](<a href="[download_text_href]"><strong>as text</strong></a>)[end]
|
||||
|
||||
@@ -43,14 +43,12 @@ Revision [if-any revision_href]<a href="[revision_href]"><strong>[rev]</strong><
|
||||
[if-any lockinfo]
|
||||
<br />Lock status: <img src="[docroot]/images/lock.png" alt="Locked" width="16" height="16" /> [lockinfo]
|
||||
[end]
|
||||
[if-any annotation]
|
||||
[is annotation "binary"]
|
||||
<br /><strong>Unable to calculate annotation data on binary file contents.</strong>
|
||||
[end]
|
||||
[is annotation "error"]
|
||||
<br /><strong>Error occurred while calculating annotation data.</strong>
|
||||
[end]
|
||||
[end]
|
||||
[is state "dead"]
|
||||
<br /><strong><em>FILE REMOVED</em></strong>
|
||||
[end]
|
||||
|
@@ -32,7 +32,7 @@
|
||||
<td>[include "pathrev_form.ezt"]</td>
|
||||
</tr>
|
||||
|
||||
[if-any search_re_form]
|
||||
[if-any search_re_action]
|
||||
<tr>
|
||||
<td>Filter files by content:</td>
|
||||
<td><form method="get" action="[search_re_action]" style="display: inline;">
|
||||
@@ -63,7 +63,7 @@
|
||||
|
||||
</table>
|
||||
|
||||
[is cfg.options.use_pagesize "0"]
|
||||
[is picklist_len "0"]
|
||||
[else]
|
||||
[is picklist_len "1"]
|
||||
[else]
|
||||
|
@@ -2,7 +2,7 @@
|
||||
[is pathtype "file"]
|
||||
<a href="[up_href]"><img src="[docroot]/images/back_small.png" class="vc_icon" alt="Parent Directory" /> Parent Directory</a>
|
||||
[if-any log_href]
|
||||
| <a href="[log_href][if-any log_href_rev]#rev[log_href_rev][end]"><img src="[docroot]/images/log.png" class="vc_icon" alt="Revision Log" /> Revision Log</a>
|
||||
| <a href="[log_href]"><img src="[docroot]/images/log.png" class="vc_icon" alt="Revision Log" /> Revision Log</a>
|
||||
[end]
|
||||
[if-any graph_href]
|
||||
| <a href="[graph_href]"><img src="[docroot]/images/cvsgraph_16x16.png" class="vc_icon" alt="View Revision Graph" /> Revision Graph</a>
|
||||
|
@@ -1,4 +1,4 @@
|
||||
[is cfg.options.use_pagesize "0"]
|
||||
[is picklist_len "0"]
|
||||
[else]
|
||||
[is picklist_len "1"]
|
||||
[else]
|
||||
@@ -17,6 +17,4 @@
|
||||
</select>
|
||||
</form>
|
||||
[end]
|
||||
[end]
|
||||
|
||||
|
||||
[end]
|
@@ -28,6 +28,11 @@
|
||||
<td>[if-any date][date][else]<em>(unknown date)</em>[end]
|
||||
[if-any ago]<em>([ago] ago)</em>[end]</td>
|
||||
</tr>
|
||||
<tr align="left">
|
||||
<th>Changed paths:</th>
|
||||
<td><strong>[num_changes]</strong>
|
||||
[if-any more_changes](showing only [limit_changes]; <a href="[more_changes_href]">show all</a>)[end][if-any first_changes](<a href="[first_changes_href]">show only first [first_changes]</a>)[end]</td>
|
||||
</tr>
|
||||
<tr align="left">
|
||||
<th>Log Message:</th>
|
||||
<td><pre class="vc_log">[log]</pre></td>
|
||||
@@ -39,17 +44,6 @@
|
||||
|
||||
<p><strong>Changed paths:</strong></p>
|
||||
|
||||
[if-any more_changes]
|
||||
<div>
|
||||
Only [limit_changes] changes shown,
|
||||
<a href="[more_changes_href]">display [more_changes] more changes...</a>
|
||||
</div>
|
||||
[end]
|
||||
|
||||
[if-any first_changes]
|
||||
<div><a href="[first_changes_href]">Show only first [first_changes] changes...</div>
|
||||
[end]
|
||||
|
||||
<table cellspacing="1" cellpadding="2">
|
||||
<thead>
|
||||
<tr align="left">
|
||||
@@ -75,6 +69,11 @@
|
||||
<td colspan="5">No changed paths.</td>
|
||||
</tr>
|
||||
[end]
|
||||
[if-any more_changes]
|
||||
<tr>
|
||||
<td colspan="5">[[]<a href="[more_changes_href]">...</a>]</td>
|
||||
</tr>
|
||||
[end]
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
|
@@ -17,17 +17,18 @@
|
||||
|
||||
### Validate input
|
||||
if test $# != 2 && test $# != 1; then
|
||||
echo "Usage: $0 TARGET-DIRECTORY [TAGNAME]"
|
||||
echo "Usage: $0 TARGET-DIRECTORY [BRANCH]"
|
||||
echo ""
|
||||
echo "If TAGNAME is not provided, the release will be rolled from trunk."
|
||||
echo "If BRANCH (i.e. \"tags/1.1.0\" or \"branches/1.0.x\") is not provided,"
|
||||
echo "the release will be rolled from trunk."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
TARGET=${1}
|
||||
if test $# == 1; then
|
||||
if test $# = 1; then
|
||||
ROOT=trunk
|
||||
else
|
||||
ROOT=tags/${2}
|
||||
ROOT=${2}
|
||||
fi
|
||||
|
||||
if test -e ${TARGET}; then
|
||||
@@ -36,7 +37,8 @@ if test -e ${TARGET}; then
|
||||
fi
|
||||
|
||||
### Grab an export from the Subversion repository.
|
||||
echo "Exporting into:" ${TARGET}
|
||||
EXPORT_URL="http://viewvc.tigris.org/svn/viewvc/${ROOT}"
|
||||
echo "Exporting '${EXPORT_URL}' into '${TARGET}'"
|
||||
|
||||
for PLATFORM in unix windows; do
|
||||
if test ${PLATFORM} = windows; then
|
||||
@@ -48,7 +50,7 @@ for PLATFORM in unix windows; do
|
||||
echo "Beginning build for ${PLATFORM}:"
|
||||
|
||||
echo " Exporting source code..."
|
||||
svn export --quiet ${EOL} http://viewvc.tigris.org/svn/viewvc/${ROOT} ${TARGET}
|
||||
svn export --quiet ${EOL} ${EXPORT_URL} ${TARGET}
|
||||
|
||||
### Various shifting, cleanup.
|
||||
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- Mode: python -*-
|
||||
#
|
||||
# Copyright (C) 1999-2007 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
|
||||
@@ -58,10 +58,12 @@ FILE_INFO_LIST = [
|
||||
("bin/cvsdbadmin", "bin/cvsdbadmin", 0755, 1, 0, 0),
|
||||
("bin/svndbadmin", "bin/svndbadmin", 0755, 1, 0, 0),
|
||||
("bin/make-database", "bin/make-database", 0755, 1, 0, 0),
|
||||
("viewvc.conf.dist", "viewvc.conf.dist", 0644, 0, 0, 0),
|
||||
("viewvc.conf.dist", "viewvc.conf", 0644, 0, 1, 0),
|
||||
("cvsgraph.conf.dist", "cvsgraph.conf.dist", 0644, 0, 0, 0),
|
||||
("cvsgraph.conf.dist", "cvsgraph.conf", 0644, 0, 1, 0),
|
||||
("conf/viewvc.conf.dist", "viewvc.conf.dist", 0644, 0, 0, 0),
|
||||
("conf/viewvc.conf.dist", "viewvc.conf", 0644, 0, 1, 0),
|
||||
("conf/cvsgraph.conf.dist", "cvsgraph.conf.dist", 0644, 0, 0, 0),
|
||||
("conf/cvsgraph.conf.dist", "cvsgraph.conf", 0644, 0, 1, 0),
|
||||
("conf/mimetypes.conf.dist", "mimetypes.conf.dist", 0644, 0, 0, 0),
|
||||
("conf/mimetypes.conf.dist", "mimetypes.conf", 0644, 0, 1, 0),
|
||||
]
|
||||
if sys.platform == "win32":
|
||||
FILE_INFO_LIST.extend([
|
||||
|
Reference in New Issue
Block a user