Compare commits
189 Commits
Author | SHA1 | Date | |
---|---|---|---|
3c1cfef827 | |||
6c18327bbf | |||
cd14ba3825 | |||
8ca4b5b85a | |||
8b3d3363f2 | |||
44c5f2bb1a | |||
d3d81490e3 | |||
5814634779 | |||
b3000cf63b | |||
0a6f6a7a66 | |||
3ddd0caa42 | |||
983f9c7379 | |||
56c2b61458 | |||
![]() |
479a5b4506 | ||
![]() |
5d442fac7d | ||
![]() |
57e1ca8909 | ||
![]() |
8492aa772e | ||
![]() |
e854e254f9 | ||
![]() |
4b06eeeb94 | ||
![]() |
ac063ff93a | ||
![]() |
b5ac9522cc | ||
![]() |
a071627c59 | ||
![]() |
24e0a24ca9 | ||
![]() |
dfff9c0cc2 | ||
![]() |
0bd2b940f9 | ||
![]() |
24b979d9e2 | ||
![]() |
7d06bd21bc | ||
![]() |
fa08478619 | ||
![]() |
7d15648286 | ||
![]() |
76987f0851 | ||
![]() |
928bf6f1a6 | ||
![]() |
4cd52560ac | ||
![]() |
a0a40b6047 | ||
![]() |
e8c05fc096 | ||
![]() |
999c9de4d3 | ||
![]() |
131171943d | ||
![]() |
e415cd7bb0 | ||
![]() |
575b4d8a49 | ||
![]() |
3ec2c244a8 | ||
![]() |
160233f758 | ||
![]() |
72934bf6cd | ||
![]() |
a564b02d18 | ||
![]() |
80ccb26b20 | ||
![]() |
1b75ada880 | ||
![]() |
ecadbf9fd3 | ||
![]() |
8dc02448bc | ||
![]() |
8aca8406a3 | ||
![]() |
639d1c25db | ||
![]() |
e363cf19b1 | ||
![]() |
83c7e6fe49 | ||
![]() |
361a00ff13 | ||
![]() |
e8f25d9c7b | ||
![]() |
c6582d1480 | ||
![]() |
ceb4990dec | ||
![]() |
12434cb5b7 | ||
![]() |
f4f2e432a7 | ||
![]() |
7eb621bcd1 | ||
![]() |
5de0639a9c | ||
![]() |
e25a91837e | ||
![]() |
6df7a894d1 | ||
![]() |
04d3d504e0 | ||
![]() |
33fffa82e8 | ||
![]() |
fdd255f0ff | ||
![]() |
0b5123e1b8 | ||
![]() |
56614d0f13 | ||
![]() |
94c0c90329 | ||
![]() |
a4c3bd1a46 | ||
![]() |
a9701721e2 | ||
![]() |
5c1ac512d1 | ||
![]() |
cd9c47fe46 | ||
![]() |
bb906c1f70 | ||
![]() |
b9a894f708 | ||
![]() |
1fae3f7e3e | ||
![]() |
c73ba23f6e | ||
![]() |
0f323a50a4 | ||
![]() |
f3ba9d5e0a | ||
![]() |
1cda6497e1 | ||
![]() |
b9f2b63c09 | ||
![]() |
b1cffd5f2d | ||
![]() |
323a4d5629 | ||
![]() |
d65737cc43 | ||
![]() |
67b205634e | ||
![]() |
4e9089255c | ||
![]() |
bf062cc41b | ||
![]() |
ab7e1bdc64 | ||
![]() |
e17b0dce21 | ||
![]() |
552d04e882 | ||
![]() |
f0a1418fbf | ||
![]() |
75be406156 | ||
![]() |
964531a7a9 | ||
![]() |
4304976db7 | ||
![]() |
8a649198d4 | ||
![]() |
e78c234550 | ||
![]() |
8367e08370 | ||
![]() |
b7c8b5eb6f | ||
06bfb6a5fe | |||
![]() |
04d3b88f6a | ||
![]() |
d85d6578da | ||
![]() |
7a40e1c902 | ||
![]() |
c8dbd38e0c | ||
![]() |
82ea92e4a4 | ||
![]() |
be67aab7dc | ||
![]() |
8ecc076ebc | ||
![]() |
6a0562d708 | ||
![]() |
6835e74f20 | ||
![]() |
4b05147064 | ||
![]() |
a208ec46ab | ||
![]() |
86c313bcf8 | ||
![]() |
a2e45b4468 | ||
![]() |
5ed8c4967a | ||
![]() |
dbd3e4af59 | ||
![]() |
5349a36a18 | ||
![]() |
81df47c357 | ||
![]() |
c916450eac | ||
![]() |
e4ea3a9f85 | ||
![]() |
e6be979387 | ||
![]() |
2896c70f26 | ||
![]() |
50b67b3ddb | ||
![]() |
3c7ad9405c | ||
![]() |
ab286694fe | ||
![]() |
1cf0815b3d | ||
![]() |
355033b015 | ||
![]() |
2f99f7b72c | ||
![]() |
e8d7fb16ff | ||
![]() |
e1cc47c375 | ||
![]() |
5a55d3c0cd | ||
![]() |
00d1ffe3e0 | ||
![]() |
0d3176a320 | ||
![]() |
053cc33ffd | ||
![]() |
93144b2168 | ||
![]() |
c102b6b2a0 | ||
![]() |
7cd0e372bb | ||
![]() |
4e047ae281 | ||
![]() |
1128625ac3 | ||
![]() |
15e2d27b7d | ||
![]() |
86dcf849e3 | ||
![]() |
5f66346633 | ||
![]() |
6586c8e4d7 | ||
![]() |
d34f8f5946 | ||
![]() |
842f0e712a | ||
![]() |
0ad8ee1554 | ||
![]() |
0f545ca76b | ||
![]() |
c3f2777a4e | ||
![]() |
45c636fd11 | ||
![]() |
2d9276a06d | ||
![]() |
eb6edef712 | ||
![]() |
b574b8594d | ||
![]() |
3bfb004158 | ||
![]() |
23eea873fa | ||
![]() |
9f0557ff85 | ||
![]() |
00f38a1b55 | ||
![]() |
3b4f7698af | ||
![]() |
0114b46db0 | ||
![]() |
a0c895b5a6 | ||
![]() |
e74a8ac42d | ||
![]() |
d94e658457 | ||
![]() |
cbcffad79a | ||
![]() |
025eb36df4 | ||
![]() |
33a8f2849c | ||
![]() |
1bbf731b83 | ||
![]() |
cd68fb0f79 | ||
![]() |
97e5d91c18 | ||
![]() |
28ba6929af | ||
![]() |
3187e57026 | ||
![]() |
a30b597260 | ||
![]() |
1480000938 | ||
![]() |
bfe175e5cd | ||
![]() |
2cadb542a2 | ||
![]() |
13b23a5696 | ||
![]() |
822ec29624 | ||
![]() |
f9b1b8a50c | ||
![]() |
6978ac9e5d | ||
![]() |
230e2f1700 | ||
![]() |
899204468b | ||
![]() |
712761df3f | ||
![]() |
73eaad686b | ||
![]() |
6556287ff3 | ||
![]() |
4b51a62390 | ||
![]() |
5ea538f50e | ||
![]() |
521261bb34 | ||
![]() |
9e55dba9f9 | ||
![]() |
9ac8f10967 | ||
![]() |
6ef2a85ae9 | ||
![]() |
1200a15887 | ||
![]() |
0fddc0bb87 | ||
![]() |
28a41fb268 | ||
![]() |
585580ec57 | ||
![]() |
f3aa325419 | ||
![]() |
9b00bc278f |
25
CHANGES
@@ -1,3 +1,28 @@
|
||||
4Intra.net/CUSTIS improvements
|
||||
|
||||
* Support for full-text search over file contents, including binary
|
||||
documents like *.doc and so on using Sphinx Search and Apache Tika
|
||||
server. Patched Tika with fixes for #TIKA709 and #TIKA964 is highly
|
||||
recommended:
|
||||
http://wiki.4intra.net/public/tika-app-1.2-fix-TIKA709-TIKA964.jar
|
||||
(SHA1 efef722a5e2322f7c2616d096552a48134dc5faa)
|
||||
* Access right checks in query results.
|
||||
* Access right checks for repository root directories.
|
||||
* New query parameters: repository, repo type, revision number.
|
||||
* Authorizer for CVSnt ACLs.
|
||||
* InnoDB, additional database indexes and some search query
|
||||
optimisations.
|
||||
* Support for specifying path to MySQL UNIX socket.
|
||||
* Asynchronous hook examples for updating SVN and CVS repos.
|
||||
* Slightly more correct charset guessing, especially for Russian.
|
||||
* Support for diffing added/removed files.
|
||||
* File lists in RSS feeds for 'classic' template.
|
||||
* Path configuration via a single 'viewvcinstallpath.py' file,
|
||||
not via editing multiple bin/* files.
|
||||
* Link to repository list instead of viewvc.org from the logo
|
||||
* "rcsfile service" support used to workaround command execution
|
||||
problems (forks) from Apache mod_python.
|
||||
|
||||
Version 1.2.0 (released ??-???-????)
|
||||
|
||||
* bumped minimum support Python version to 2.4
|
||||
|
3
README
@@ -1,6 +1,9 @@
|
||||
ViewVC -- Viewing the content of CVS/SVN repositories with a Webbrowser.
|
||||
|
||||
This is the 4Intra.net patched version with some extra features.
|
||||
|
||||
Please read the file INSTALL for more information.
|
||||
|
||||
And see windows/README for more information on running ViewVC on
|
||||
Microsoft Windows.
|
||||
|
||||
|
@@ -24,15 +24,15 @@
|
||||
#
|
||||
|
||||
#########################################################################
|
||||
#
|
||||
# INSTALL-TIME CONFIGURATION
|
||||
#
|
||||
# These values will be set during the installation process. During
|
||||
# development, they will remain None.
|
||||
# development, there will be no 'viewvcinstallpath.py'
|
||||
#
|
||||
|
||||
LIBRARY_DIR = None
|
||||
CONF_PATHNAME = None
|
||||
import viewvcinstallpath
|
||||
LIBRARY_DIR = viewvcinstallpath.LIBRARY_DIR
|
||||
CONF_PATHNAME = viewvcinstallpath.CONF_PATHNAME
|
||||
|
||||
#########################################################################
|
||||
#
|
||||
|
@@ -24,15 +24,15 @@
|
||||
#
|
||||
|
||||
#########################################################################
|
||||
#
|
||||
# INSTALL-TIME CONFIGURATION
|
||||
#
|
||||
# These values will be set during the installation process. During
|
||||
# development, they will remain None.
|
||||
# development, there will be no 'viewvcinstallpath.py'
|
||||
#
|
||||
|
||||
LIBRARY_DIR = None
|
||||
CONF_PATHNAME = None
|
||||
import viewvcinstallpath
|
||||
LIBRARY_DIR = viewvcinstallpath.LIBRARY_DIR
|
||||
CONF_PATHNAME = viewvcinstallpath.CONF_PATHNAME
|
||||
|
||||
#########################################################################
|
||||
#
|
||||
|
@@ -22,15 +22,15 @@
|
||||
#
|
||||
|
||||
#########################################################################
|
||||
#
|
||||
# INSTALL-TIME CONFIGURATION
|
||||
#
|
||||
# These values will be set during the installation process. During
|
||||
# development, they will remain None.
|
||||
# development, there will be no 'viewvcinstallpath.py'
|
||||
#
|
||||
|
||||
LIBRARY_DIR = None
|
||||
CONF_PATHNAME = None
|
||||
import viewvcinstallpath
|
||||
LIBRARY_DIR = viewvcinstallpath.LIBRARY_DIR
|
||||
CONF_PATHNAME = viewvcinstallpath.CONF_PATHNAME
|
||||
|
||||
#########################################################################
|
||||
#
|
||||
|
@@ -22,15 +22,15 @@
|
||||
#
|
||||
|
||||
#########################################################################
|
||||
#
|
||||
# INSTALL-TIME CONFIGURATION
|
||||
#
|
||||
# These values will be set during the installation process. During
|
||||
# development, they will remain None.
|
||||
# development, there will be no 'viewvcinstallpath.py'
|
||||
#
|
||||
|
||||
LIBRARY_DIR = None
|
||||
CONF_PATHNAME = None
|
||||
import viewvcinstallpath
|
||||
LIBRARY_DIR = viewvcinstallpath.LIBRARY_DIR
|
||||
CONF_PATHNAME = viewvcinstallpath.CONF_PATHNAME
|
||||
|
||||
#########################################################################
|
||||
#
|
||||
|
216
bin/custis-install
Executable file
@@ -0,0 +1,216 @@
|
||||
#!/bin/sh
|
||||
# ViewVC installation script for CustIS
|
||||
|
||||
if [ -f custis-install-config ]; then
|
||||
. custis-install-config
|
||||
else
|
||||
cat >custis-install-config <<EOF
|
||||
CVS_ASYNC=
|
||||
SVN_ASYNC=
|
||||
CVS_USER=www-data
|
||||
CVS_GROUP=cvs.users
|
||||
CVSROOTS=
|
||||
SVNROOT=
|
||||
SVN_FORBIDDENRE=
|
||||
|
||||
DB_HOST=
|
||||
DB_PORT=
|
||||
DB_SOCKET=/var/run/mysqld/mysqld.sock
|
||||
DB=
|
||||
DB_USER=
|
||||
DB_PASSWD=
|
||||
|
||||
VIEWVC_DIR=
|
||||
VIEWVC_URI=/
|
||||
VIEWVC_URI_SLASH=/
|
||||
VIEWVC_STATIC_URI=/static
|
||||
http_proxy=
|
||||
no_proxy=
|
||||
EOF
|
||||
echo Empty 'custis-install-config' initialized, please edit it before installation.
|
||||
exit
|
||||
fi
|
||||
|
||||
if [ ! "$DB" -o ! "$VIEWVC_DIR" ]; then
|
||||
echo Please set up 'custis-install-config' before installation.
|
||||
exit
|
||||
fi
|
||||
|
||||
################################################################################
|
||||
|
||||
export http_proxy
|
||||
export no_proxy
|
||||
|
||||
DEPS="python libapache2-mod-python rcs diff cvsnt subversion subversion-tools python-setuptools python-subversion python-mysqldb cvsgraph"
|
||||
|
||||
echo "*** Installing dependency packages: $DEPS"
|
||||
apt-get install $DEPS
|
||||
|
||||
echo "*** Installing Pygments for Python"
|
||||
wget http://pypi.python.org/packages/source/P/Pygments/Pygments-0.11.1.tar.gz
|
||||
tar -zxf Pygments-0.11.1.tar.gz
|
||||
cd Pygments-0.11.1
|
||||
python setup.py install
|
||||
cd ..
|
||||
|
||||
echo "*** Installing ViewVC into $VIEWVC_DIR"
|
||||
if [ ! -e $VIEWVC_DIR/viewvc.conf ]; then
|
||||
../viewvc-install <<EOF
|
||||
$VIEWVC_DIR
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
EOF
|
||||
fi
|
||||
|
||||
echo "*** Writing ViewVC configuration into $VIEWVC_DIR/viewvc.conf"
|
||||
for CVSROOT in $CVSROOTS; do
|
||||
if [ "$vccvsroots" ]; then
|
||||
vccvsroots="$vccvsroots, "
|
||||
fi
|
||||
vcrootname=`basename $CVSROOT`
|
||||
vccvsroots="$vccvsroots$vcrootname: $CVSROOT"
|
||||
done;
|
||||
cat >"$VIEWVC_DIR/viewvc.conf" <<EOF
|
||||
[general]
|
||||
cvs_roots = $vccvsroots
|
||||
root_parents = $SVNROOT : svn
|
||||
cvsnt_exe_path = /usr/bin/cvsnt
|
||||
mime_types_file = /etc/mime.types
|
||||
address = Admin address: stas [gav-gav] custis [ru]
|
||||
kv_files =
|
||||
languages = en-us, ru-ru
|
||||
|
||||
[utilities]
|
||||
rcs_dir = /usr/bin
|
||||
cvsnt = /usr/bin/cvsnt
|
||||
svn = /usr/bin/svn
|
||||
diff = /usr/bin/diff
|
||||
cvsgraph = /usr/bin/cvsgraph
|
||||
|
||||
[options]
|
||||
allowed_views = markup, annotate, roots
|
||||
authorizer = forbiddenre
|
||||
checkout_magic = 0
|
||||
cross_copies = 1
|
||||
cvsgraph_conf = $VIEWVC_DIR/cvsgraph.conf
|
||||
default_file_view = log
|
||||
diff_format = h
|
||||
docroot = $VIEWVC_STATIC_URI
|
||||
enable_syntax_coloration = 1
|
||||
generate_etags = 1
|
||||
hide_attic = 1
|
||||
hide_cvsroot = 1
|
||||
hide_errorful_entries = 0
|
||||
hr_breakable = 1
|
||||
hr_funout = 0
|
||||
hr_ignore_keyword_subst = 1
|
||||
hr_ignore_white = 1
|
||||
hr_intraline = 0
|
||||
http_expiration_time = 600
|
||||
limit_changes = 100
|
||||
log_sort = date
|
||||
mangle_email_addresses = 1
|
||||
root_as_url_component = 1
|
||||
short_log_len = 80
|
||||
show_log_in_markup = 1
|
||||
show_logs = 1
|
||||
show_subdir_lastmod = 0
|
||||
sort_by = file
|
||||
sort_group_dirs = 1
|
||||
svn_config_dir =
|
||||
template_dir = templates
|
||||
use_cvsgraph = 1
|
||||
use_localtime = 1
|
||||
use_pagesize = 0
|
||||
use_rcsparse = 0
|
||||
use_re_search = 0
|
||||
|
||||
[templates]
|
||||
|
||||
[cvsdb]
|
||||
enabled = 1
|
||||
host = $DB_HOST
|
||||
socket = $DB_SOCKET
|
||||
database_name = $DB
|
||||
user = $DB_USER
|
||||
passwd = $DB_PASSWD
|
||||
readonly_user = $DB_USER
|
||||
readonly_passwd = $DB_PASSWD
|
||||
|
||||
[vhosts]
|
||||
|
||||
[authz-forbidden]
|
||||
forbidden =
|
||||
|
||||
[authz-forbiddenre]
|
||||
forbiddenre = $SVN_FORBIDDENRE
|
||||
|
||||
[authz-svnauthz]
|
||||
authzfile =
|
||||
EOF
|
||||
|
||||
echo "*** Initializing database: $DB using $DB_USER@$DB_HOST"
|
||||
$VIEWVC_DIR/bin/make-database <<EOF
|
||||
$DB_HOST
|
||||
$DB_USER
|
||||
$DB_PASSWD
|
||||
$DB
|
||||
EOF
|
||||
|
||||
echo "*** Configuring Apache"
|
||||
cat >/etc/apache2/sites-available/viewvc <<EOF
|
||||
<VirtualHost *:80>
|
||||
ServerName viewvc.office.custis.ru
|
||||
ServerAlias viewvc
|
||||
ServerAdmin sysadmins@custis.ru
|
||||
ServerSignature Off
|
||||
ErrorLog /var/log/apache2/viewvc-error.log
|
||||
TransferLog /var/log/apache2/viewvc-access.log
|
||||
LogLevel warn
|
||||
# ViewVC at $VIEWVC_URI installed at $VIEWVC_DIR
|
||||
DocumentRoot $VIEWVC_DIR/bin/mod_python
|
||||
Alias $VIEWVC_STATIC_URI $VIEWVC_DIR/templates/docroot
|
||||
Alias $VIEWVC_URI $VIEWVC_DIR/bin/mod_python/
|
||||
<Location ~ ^${VIEWVC_URI_SLASH}*(\?.*)?$>
|
||||
Options -Indexes
|
||||
RewriteEngine On
|
||||
RewriteRule .* ${VIEWVC_URI_SLASH}viewvc.py%{REQUEST_URI} [R,L]
|
||||
</Location>
|
||||
<Directory $VIEWVC_DIR/bin/mod_python>
|
||||
Options +ExecCGI
|
||||
AddHandler python-program .py
|
||||
PythonHandler handler
|
||||
PythonDebug Off
|
||||
</Directory>
|
||||
</VirtualHost>
|
||||
EOF
|
||||
a2enmod python
|
||||
a2enmod mod_python
|
||||
a2enmod rewrite
|
||||
a2ensite viewvc
|
||||
|
||||
echo "*** Restarting Apache"
|
||||
apache2ctl stop
|
||||
sleep 1
|
||||
apache2ctl start
|
||||
|
||||
echo "*** Building commit database for CVS"
|
||||
for CVSROOT in $CVSROOTS; do
|
||||
$VIEWVC_DIR/bin/cvsdbadmin rebuild $CVSROOT
|
||||
done;
|
||||
|
||||
echo "*** Building commit database for Subversion repositories"
|
||||
for i in `ls $SVNROOT`; do
|
||||
if [ -d "$SVNROOT/$i" ]; then
|
||||
$VIEWVC_DIR/bin/svndbadmin -v rebuild "$SVNROOT/$i"
|
||||
fi
|
||||
done;
|
||||
|
||||
# setup hooks for CVS
|
||||
./setup-cvs-hooks "$CVSROOTS" "$VIEWVC_DIR" "$CVS_USER" "$CVS_GROUP" "$CVS_ASYNC"
|
||||
|
||||
# setup hooks for Subversion
|
||||
./setup-svn-hooks "$SVNROOT" "$VIEWVC_DIR" "$SVN_ASYNC"
|
@@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
#!/usr/bin/python
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2013 The ViewCVS Group. All Rights Reserved.
|
||||
@@ -18,15 +18,15 @@
|
||||
#
|
||||
|
||||
#########################################################################
|
||||
#
|
||||
# INSTALL-TIME CONFIGURATION
|
||||
#
|
||||
# These values will be set during the installation process. During
|
||||
# development, they will remain None.
|
||||
# development, there will be no 'viewvcinstallpath.py'
|
||||
#
|
||||
|
||||
LIBRARY_DIR = None
|
||||
CONF_PATHNAME = None
|
||||
import viewvcinstallpath
|
||||
LIBRARY_DIR = viewvcinstallpath.LIBRARY_DIR
|
||||
CONF_PATHNAME = viewvcinstallpath.CONF_PATHNAME
|
||||
|
||||
# Adjust sys.path to include our library directory
|
||||
import sys
|
||||
@@ -43,17 +43,23 @@ import os
|
||||
import cvsdb
|
||||
import viewvc
|
||||
import vclib.ccvs
|
||||
from stat import *
|
||||
|
||||
|
||||
|
||||
def UpdateFile(db, repository, path, update, quiet_level):
|
||||
def UpdateFile(db, repository, path, update, latest_checkin, quiet_level, encoding = None):
|
||||
try:
|
||||
if update:
|
||||
mtime = os.stat(repository.rcsfile(path, 1))[ST_MTIME]
|
||||
if mtime < latest_checkin:
|
||||
return
|
||||
commit_list = cvsdb.GetUnrecordedCommitList(repository, path, db)
|
||||
else:
|
||||
commit_list = cvsdb.GetCommitListFromRCSFile(repository, path)
|
||||
except cvsdb.error, e:
|
||||
print '[ERROR] %s' % (e)
|
||||
return
|
||||
except vclib.ItemNotFound, e:
|
||||
return
|
||||
|
||||
file = '/'.join(path)
|
||||
printing = 0
|
||||
@@ -68,6 +74,8 @@ def UpdateFile(db, repository, path, update, quiet_level):
|
||||
|
||||
## add the commits into the database
|
||||
for commit in commit_list:
|
||||
if encoding:
|
||||
commit.SetFile(commit.GetFile().decode(encoding).encode('utf-8'))
|
||||
db.AddCommit(commit)
|
||||
if printing:
|
||||
sys.stdout.write('.')
|
||||
@@ -76,7 +84,8 @@ def UpdateFile(db, repository, path, update, quiet_level):
|
||||
print
|
||||
|
||||
|
||||
def RecurseUpdate(db, repository, directory, update, quiet_level):
|
||||
def RecurseUpdate(db, repository, directory, update, latest_checkin,
|
||||
quiet_level, encoding = None):
|
||||
for entry in repository.listdir(directory, None, {}):
|
||||
path = directory + [entry.name]
|
||||
|
||||
@@ -84,11 +93,14 @@ def RecurseUpdate(db, repository, directory, update, quiet_level):
|
||||
continue
|
||||
|
||||
if entry.kind is vclib.DIR:
|
||||
RecurseUpdate(db, repository, path, update, quiet_level)
|
||||
RecurseUpdate(db, repository, path, update, latest_checkin,
|
||||
quiet_level, encoding)
|
||||
continue
|
||||
|
||||
if entry.kind is vclib.FILE:
|
||||
UpdateFile(db, repository, path, update, quiet_level)
|
||||
UpdateFile(db, repository, path, update, latest_checkin,
|
||||
quiet_level, encoding)
|
||||
|
||||
|
||||
def RootPath(path, quiet_level):
|
||||
"""Break os path into cvs root path and other parts"""
|
||||
@@ -177,7 +189,7 @@ if __name__ == '__main__':
|
||||
if quiet_level < 2:
|
||||
print "Purging existing data for repository root `%s'" % root
|
||||
try:
|
||||
db.PurgeRepository(root)
|
||||
db.PurgeRepository(root, len(path_parts) and '/'.join(path_parts) or '')
|
||||
except cvsdb.UnknownRepositoryError, e:
|
||||
if command == 'purge':
|
||||
sys.stderr.write("ERROR: " + str(e) + "\n")
|
||||
@@ -185,11 +197,15 @@ if __name__ == '__main__':
|
||||
|
||||
if command in ('rebuild', 'update'):
|
||||
repository = vclib.ccvs.CVSRepository(None, rootpath, None,
|
||||
cfg.utilities, 0)
|
||||
cfg.utilities, 0, cfg.guesser())
|
||||
latest_checkin = db.GetLatestCheckinTime(repository)
|
||||
if latest_checkin is None:
|
||||
command = 'rebuild'
|
||||
RecurseUpdate(db, repository, path_parts,
|
||||
command == 'update', quiet_level)
|
||||
command == 'update', latest_checkin, quiet_level,
|
||||
cfg.options.cvs_ondisk_charset)
|
||||
except KeyboardInterrupt:
|
||||
print
|
||||
print '** break **'
|
||||
|
||||
|
||||
sys.exit(0)
|
||||
|
57
bin/cvsnt-import-cvsacl
Executable file
@@ -0,0 +1,57 @@
|
||||
#!/usr/bin/perl
|
||||
|
||||
use strict;
|
||||
my ($type, $path, $branch, $user, $perm);
|
||||
|
||||
my $R = ''; # -R for recursive
|
||||
my $lvl = {
|
||||
r => 1,
|
||||
t => 2,
|
||||
w => 3,
|
||||
c => 4,
|
||||
a => 4,
|
||||
p => 5,
|
||||
};
|
||||
|
||||
while(<>)
|
||||
{
|
||||
chomp;
|
||||
next if /^\s*#/so;
|
||||
($type, $path, $branch, $user, $perm) = split /:/, $_;
|
||||
($user, $perm) = split /!/, $user;
|
||||
next unless $perm;
|
||||
$perm = [ sort { $lvl->{$b} cmp $lvl->{$a} } split //, $perm ];
|
||||
$perm = $perm->[0];
|
||||
if ($perm eq 't')
|
||||
{
|
||||
$perm = 'read,tag,nowrite,nocreate,nocontrol';
|
||||
}
|
||||
elsif ($perm eq 'r')
|
||||
{
|
||||
$perm = 'read,notag,nowrite,nocreate,nocontrol';
|
||||
}
|
||||
elsif ($perm eq 'w')
|
||||
{
|
||||
$perm = 'read,tag,write,nocreate,nocontrol';
|
||||
}
|
||||
elsif ($perm eq 'c' || $perm eq 'a')
|
||||
{
|
||||
$perm = 'read,tag,write,create,nocontrol';
|
||||
}
|
||||
elsif ($perm eq 'p')
|
||||
{
|
||||
$perm = 'read,tag,write,create,control';
|
||||
}
|
||||
print "cvs rchacl$R -a $perm";
|
||||
print " -u '$user'" if $user ne 'ALL';
|
||||
print " -r '$branch'" if $branch ne 'ALL';
|
||||
if ($path ne 'ALL')
|
||||
{
|
||||
print " '$path'";
|
||||
}
|
||||
else
|
||||
{
|
||||
print ' `ls $CVSROOT | grep -v '."'#cvs'`";
|
||||
}
|
||||
print "\n";
|
||||
}
|
21
bin/cvsnt-rcsfile-inetd.pl
Executable file
@@ -0,0 +1,21 @@
|
||||
#!/usr/bin/perl
|
||||
# Very simple inetd/xinetd "cvsnt rcsfile" service
|
||||
|
||||
# Useful for ViewVC as there is an unpleasant non-stable bug, probably somewhere
|
||||
# inside mod_python or Apache, which SOMETIMES causes cvsnt subprocesses forked
|
||||
# from mod_python to die. This gives empty diff outputs or different errors like
|
||||
# "Error: Rlog output ended early. Expected RCS file ..."
|
||||
# This script removes forking from mod_python code and solves the issue.
|
||||
# Additional profit of this script is that you can probably browse REMOTE cvs
|
||||
# repositories, if you expose this service to ViewVC, although it is not tested.
|
||||
|
||||
# USAGE: (local) create an inetd service with this script as server listening
|
||||
# on some port of 127.0.0.1 and put "rcsfile_socket = 127.0.0.1:port"
|
||||
# into "utilities" section of viewvc.conf
|
||||
|
||||
$args = <STDIN>;
|
||||
$args =~ s/\s+$//so;
|
||||
@args = $args =~ /\'([^\']+)\'/giso;
|
||||
|
||||
# We don't execute shell, so this is mostly safe, not a backdoor :)
|
||||
exec('/usr/bin/cvsnt', 'rcsfile', @args);
|
@@ -17,15 +17,15 @@
|
||||
#
|
||||
|
||||
#########################################################################
|
||||
#
|
||||
# INSTALL-TIME CONFIGURATION
|
||||
#
|
||||
# These values will be set during the installation process. During
|
||||
# development, they will remain None.
|
||||
# development, there will be no 'viewvcinstallpath.py'
|
||||
#
|
||||
|
||||
LIBRARY_DIR = None
|
||||
CONF_PATHNAME = None
|
||||
import viewvcinstallpath
|
||||
LIBRARY_DIR = viewvcinstallpath.LIBRARY_DIR
|
||||
CONF_PATHNAME = viewvcinstallpath.CONF_PATHNAME
|
||||
|
||||
# Adjust sys.path to include our library directory
|
||||
import sys
|
||||
|
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env python
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2013 The ViewCVS Group. All Rights Reserved.
|
||||
# Copyright (C) 1999-2009 The ViewCVS Group. All Rights Reserved.
|
||||
#
|
||||
# By using this file, you agree to the terms and conditions set forth in
|
||||
# the LICENSE.html file which can be found at the top level of the ViewVC
|
||||
@@ -16,8 +16,7 @@
|
||||
#
|
||||
# -----------------------------------------------------------------------
|
||||
|
||||
import os
|
||||
import sys
|
||||
import os, sys, string
|
||||
import popen2
|
||||
import getopt
|
||||
|
||||
@@ -41,10 +40,11 @@ CREATE TABLE branches (
|
||||
branch varchar(64) binary DEFAULT '' NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE branch (branch)
|
||||
) ENGINE=MyISAM;
|
||||
) TYPE=InnoDB;
|
||||
|
||||
DROP TABLE IF EXISTS checkins;
|
||||
CREATE TABLE checkins (
|
||||
id int NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
type enum('Change','Add','Remove'),
|
||||
ci_when datetime DEFAULT '0000-00-00 00:00:00' NOT NULL,
|
||||
whoid mediumint(9) DEFAULT '0' NOT NULL,
|
||||
@@ -58,13 +58,14 @@ CREATE TABLE checkins (
|
||||
removedlines int(11) DEFAULT '0' NOT NULL,
|
||||
descid mediumint(9),
|
||||
UNIQUE repositoryid (repositoryid,dirid,fileid,revision),
|
||||
KEY repositoryid_when (repositoryid,ci_when),
|
||||
KEY ci_when (ci_when),
|
||||
KEY whoid (whoid),
|
||||
KEY repositoryid_2 (repositoryid),
|
||||
KEY whoid (whoid,ci_when),
|
||||
KEY dirid (dirid),
|
||||
KEY fileid (fileid),
|
||||
KEY branchid (branchid)
|
||||
) ENGINE=MyISAM;
|
||||
KEY branchid (branchid),
|
||||
KEY descid (descid)
|
||||
) TYPE=InnoDB;
|
||||
|
||||
DROP TABLE IF EXISTS descs;
|
||||
CREATE TABLE descs (
|
||||
@@ -72,8 +73,9 @@ CREATE TABLE descs (
|
||||
description text,
|
||||
hash bigint(20) DEFAULT '0' NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
KEY hash (hash)
|
||||
) ENGINE=MyISAM;
|
||||
KEY hash (hash),
|
||||
FULLTEXT KEY description (description)
|
||||
) TYPE=MyISAM;
|
||||
|
||||
DROP TABLE IF EXISTS dirs;
|
||||
CREATE TABLE dirs (
|
||||
@@ -81,7 +83,7 @@ CREATE TABLE dirs (
|
||||
dir varchar(255) binary DEFAULT '' NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE dir (dir)
|
||||
) ENGINE=MyISAM;
|
||||
) TYPE=InnoDB;
|
||||
|
||||
DROP TABLE IF EXISTS files;
|
||||
CREATE TABLE files (
|
||||
@@ -89,7 +91,7 @@ CREATE TABLE files (
|
||||
file varchar(255) binary DEFAULT '' NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE file (file)
|
||||
) ENGINE=MyISAM;
|
||||
) TYPE=InnoDB;
|
||||
|
||||
DROP TABLE IF EXISTS people;
|
||||
CREATE TABLE people (
|
||||
@@ -97,7 +99,7 @@ CREATE TABLE people (
|
||||
who varchar(128) binary DEFAULT '' NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE who (who)
|
||||
) ENGINE=MyISAM;
|
||||
) TYPE=InnoDB;
|
||||
|
||||
DROP TABLE IF EXISTS repositories;
|
||||
CREATE TABLE repositories (
|
||||
@@ -105,7 +107,7 @@ CREATE TABLE repositories (
|
||||
repository varchar(64) binary DEFAULT '' NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE repository (repository)
|
||||
) ENGINE=MyISAM;
|
||||
) TYPE=InnoDB;
|
||||
|
||||
DROP TABLE IF EXISTS tags;
|
||||
CREATE TABLE tags (
|
||||
@@ -119,7 +121,13 @@ CREATE TABLE tags (
|
||||
KEY dirid (dirid),
|
||||
KEY fileid (fileid),
|
||||
KEY branchid (branchid)
|
||||
) ENGINE=MyISAM;
|
||||
) TYPE=InnoDB;
|
||||
|
||||
DROP TABLE IF EXISTS contents;
|
||||
CREATE TABLE contents (
|
||||
id int NOT NULL PRIMARY KEY,
|
||||
content MEDIUMTEXT NOT NULL DEFAULT ''
|
||||
) TYPE=MyISAM;
|
||||
"""
|
||||
|
||||
## ------------------------------------------------------------------------
|
||||
@@ -133,10 +141,11 @@ CREATE TABLE branches (
|
||||
branch varchar(64) binary DEFAULT '' NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE branch (branch)
|
||||
) ENGINE=MyISAM;
|
||||
) TYPE=InnoDB;
|
||||
|
||||
DROP TABLE IF EXISTS commits;
|
||||
CREATE TABLE commits (
|
||||
id int NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
type enum('Change','Add','Remove'),
|
||||
ci_when datetime DEFAULT '0000-00-00 00:00:00' NOT NULL,
|
||||
whoid mediumint(9) DEFAULT '0' NOT NULL,
|
||||
@@ -150,14 +159,14 @@ CREATE TABLE commits (
|
||||
removedlines int(11) DEFAULT '0' NOT NULL,
|
||||
descid mediumint(9),
|
||||
UNIQUE repositoryid (repositoryid,dirid,fileid,revision),
|
||||
KEY repositoryid_when (repositoryid,ci_when),
|
||||
KEY ci_when (ci_when),
|
||||
KEY whoid (whoid),
|
||||
KEY repositoryid_2 (repositoryid),
|
||||
KEY whoid (whoid,ci_when),
|
||||
KEY dirid (dirid),
|
||||
KEY fileid (fileid),
|
||||
KEY branchid (branchid),
|
||||
KEY descid (descid)
|
||||
) ENGINE=MyISAM;
|
||||
) TYPE=InnoDB;
|
||||
|
||||
DROP TABLE IF EXISTS descs;
|
||||
CREATE TABLE descs (
|
||||
@@ -165,8 +174,9 @@ CREATE TABLE descs (
|
||||
description text,
|
||||
hash bigint(20) DEFAULT '0' NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
KEY hash (hash)
|
||||
) ENGINE=MyISAM;
|
||||
KEY hash (hash),
|
||||
FULLTEXT KEY description (description)
|
||||
) TYPE=MyISAM;
|
||||
|
||||
DROP TABLE IF EXISTS dirs;
|
||||
CREATE TABLE dirs (
|
||||
@@ -174,7 +184,7 @@ CREATE TABLE dirs (
|
||||
dir varchar(255) binary DEFAULT '' NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE dir (dir)
|
||||
) ENGINE=MyISAM;
|
||||
) TYPE=InnoDB;
|
||||
|
||||
DROP TABLE IF EXISTS files;
|
||||
CREATE TABLE files (
|
||||
@@ -182,7 +192,7 @@ CREATE TABLE files (
|
||||
file varchar(255) binary DEFAULT '' NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE file (file)
|
||||
) ENGINE=MyISAM;
|
||||
) TYPE=InnoDB;
|
||||
|
||||
DROP TABLE IF EXISTS people;
|
||||
CREATE TABLE people (
|
||||
@@ -190,7 +200,7 @@ CREATE TABLE people (
|
||||
who varchar(128) binary DEFAULT '' NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE who (who)
|
||||
) ENGINE=MyISAM;
|
||||
) TYPE=InnoDB;
|
||||
|
||||
DROP TABLE IF EXISTS repositories;
|
||||
CREATE TABLE repositories (
|
||||
@@ -198,7 +208,7 @@ CREATE TABLE repositories (
|
||||
repository varchar(64) binary DEFAULT '' NOT NULL,
|
||||
PRIMARY KEY (id),
|
||||
UNIQUE repository (repository)
|
||||
) ENGINE=MyISAM;
|
||||
) TYPE=InnoDB;
|
||||
|
||||
DROP TABLE IF EXISTS tags;
|
||||
CREATE TABLE tags (
|
||||
@@ -212,7 +222,7 @@ CREATE TABLE tags (
|
||||
KEY dirid (dirid),
|
||||
KEY fileid (fileid),
|
||||
KEY branchid (branchid)
|
||||
) ENGINE=MyISAM;
|
||||
) TYPE=InnoDB;
|
||||
|
||||
DROP TABLE IF EXISTS metadata;
|
||||
CREATE TABLE metadata (
|
||||
@@ -220,8 +230,14 @@ CREATE TABLE metadata (
|
||||
value text,
|
||||
PRIMARY KEY (name),
|
||||
UNIQUE name (name)
|
||||
) ENGINE=MyISAM;
|
||||
) TYPE=InnoDB;
|
||||
INSERT INTO metadata (name, value) VALUES ('version', '1');
|
||||
|
||||
DROP TABLE IF EXISTS contents;
|
||||
CREATE TABLE contents (
|
||||
id int NOT NULL PRIMARY KEY,
|
||||
content MEDIUMTEXT NOT NULL DEFAULT ''
|
||||
) TYPE=MyISAM;
|
||||
"""
|
||||
|
||||
BONSAI_COMPAT="""
|
||||
@@ -246,20 +262,15 @@ options.) This script will use the 'mysql' program to create the
|
||||
database for you. You will then need to set the appropriate
|
||||
parameters in the [cvsdb] section of your viewvc.conf file.
|
||||
|
||||
NOTE: If a hostname or port is supplied at the command line or during
|
||||
interactive prompting, this script will pass '--protocol=TCP' to
|
||||
'mysql'.
|
||||
|
||||
Options:
|
||||
|
||||
--dbname=ARG Use ARG as the ViewVC database name to create.
|
||||
[Default: ViewVC]
|
||||
|
||||
--help Show this usage message.
|
||||
|
||||
--hostname=ARG Use ARG as the hostname for the MySQL connection.
|
||||
|
||||
--port=ARG Use ARG as the port for the MySQL connection.
|
||||
--hostname=ARG Use ARG as the hostname for the MySQL connection.
|
||||
[Default: localhost]
|
||||
|
||||
--password=ARG Use ARG as the password for the MySQL connection.
|
||||
|
||||
@@ -268,7 +279,7 @@ Options:
|
||||
--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))
|
||||
@@ -279,11 +290,10 @@ Options:
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
# Parse the command-line options, if any.
|
||||
dbname = version = hostname = port = username = password = None
|
||||
dbname = version = hostname = username = password = None
|
||||
opts, args = getopt.getopt(sys.argv[1:], '', [ 'dbname=',
|
||||
'help',
|
||||
'hostname=',
|
||||
'port=',
|
||||
'password=',
|
||||
'username=',
|
||||
'version=',
|
||||
@@ -297,8 +307,6 @@ if __name__ == "__main__":
|
||||
dbname = value
|
||||
elif name == '--hostname':
|
||||
hostname = value
|
||||
elif name == '--port':
|
||||
port = value
|
||||
elif name == '--username':
|
||||
username = value
|
||||
elif name == '--password':
|
||||
@@ -311,9 +319,7 @@ if __name__ == "__main__":
|
||||
|
||||
# Prompt for information not provided via command-line options.
|
||||
if hostname is None:
|
||||
hostname = raw_input("MySQL Hostname (leave blank for default): ")
|
||||
if port is None:
|
||||
port = raw_input("MySQL Port (leave blank for default): ")
|
||||
hostname = raw_input("MySQL Hostname [default: localhost]: ") or ""
|
||||
if username is None:
|
||||
username = raw_input("MySQL User: ")
|
||||
if password is None:
|
||||
@@ -321,30 +327,24 @@ if __name__ == "__main__":
|
||||
if dbname is None:
|
||||
dbname = raw_input("ViewVC Database Name [default: ViewVC]: ") or "ViewVC"
|
||||
|
||||
# Create the database.
|
||||
dscript = DATABASE_SCRIPT_COMMON.replace("<dbname>", dbname)
|
||||
# Create the database
|
||||
dscript = string.replace(DATABASE_SCRIPT_COMMON, "<dbname>", dbname)
|
||||
if version == "1.0":
|
||||
print BONSAI_COMPAT
|
||||
dscript = dscript + DATABASE_SCRIPT_VERSION_0
|
||||
else:
|
||||
dscript = dscript + DATABASE_SCRIPT_VERSION_1
|
||||
|
||||
# Calculate command arguments.
|
||||
cmd_args = "--user=%s --password=%s" % (username, password)
|
||||
if hostname or port:
|
||||
cmd_args = cmd_args + " --protocol=TCP"
|
||||
if hostname:
|
||||
cmd_args = cmd_args + " --host=%s" % (hostname)
|
||||
if port:
|
||||
cmd_args = cmd_args + " --port=%s" % (port)
|
||||
|
||||
host_option = hostname and "--host=%s" % (hostname) or ""
|
||||
if sys.platform == "win32":
|
||||
cmd = "mysql %s" % (cmd_args)
|
||||
cmd = "mysql --user=%s --password=%s %s "\
|
||||
% (username, password, host_option)
|
||||
mysql = os.popen(cmd, "w") # popen2.Popen3 is not provided on windows
|
||||
mysql.write(dscript)
|
||||
status = mysql.close()
|
||||
else:
|
||||
cmd = "{ mysql %s ; } 2>&1" % (cmd_args)
|
||||
cmd = "{ mysql --user=%s --password=%s %s ; } 2>&1" \
|
||||
% (username, password, host_option)
|
||||
pipes = popen2.Popen3(cmd)
|
||||
pipes.tochild.write(dscript)
|
||||
pipes.tochild.close()
|
||||
|
@@ -1,3 +1,3 @@
|
||||
AddHandler python-program .py
|
||||
PythonHandler handler
|
||||
PythonDebug On
|
||||
PythonDebug Off
|
||||
|
6
bin/mod_python/handler.py
Normal file → Executable file
@@ -20,10 +20,8 @@ import os.path
|
||||
def handler(req):
|
||||
path, module_name = os.path.split(req.filename)
|
||||
module_name, module_ext = os.path.splitext(module_name)
|
||||
try:
|
||||
module = apache.import_module(module_name, path=[path])
|
||||
except ImportError:
|
||||
raise apache.SERVER_RETURN, apache.HTTP_NOT_FOUND
|
||||
# Let it be 500 Internal Server Error in case of import error
|
||||
module = apache.import_module(module_name, path=[path])
|
||||
|
||||
req.add_common_vars()
|
||||
module.index(req)
|
||||
|
9
bin/mod_python/query.py
Normal file → Executable file
@@ -1,3 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2013 The ViewCVS Group. All Rights Reserved.
|
||||
@@ -21,15 +22,15 @@
|
||||
#
|
||||
|
||||
#########################################################################
|
||||
#
|
||||
# INSTALL-TIME CONFIGURATION
|
||||
#
|
||||
# These values will be set during the installation process. During
|
||||
# development, they will remain None.
|
||||
# development, there will be no 'viewvcinstallpath.py'
|
||||
#
|
||||
|
||||
LIBRARY_DIR = None
|
||||
CONF_PATHNAME = None
|
||||
import viewvcinstallpath
|
||||
LIBRARY_DIR = viewvcinstallpath.LIBRARY_DIR
|
||||
CONF_PATHNAME = viewvcinstallpath.CONF_PATHNAME
|
||||
|
||||
#########################################################################
|
||||
#
|
||||
|
16
bin/mod_python/viewvc.py
Normal file → Executable file
@@ -1,3 +1,4 @@
|
||||
#!/usr/bin/env python
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2013 The ViewCVS Group. All Rights Reserved.
|
||||
@@ -21,15 +22,15 @@
|
||||
#
|
||||
|
||||
#########################################################################
|
||||
#
|
||||
# INSTALL-TIME CONFIGURATION
|
||||
#
|
||||
# These values will be set during the installation process. During
|
||||
# development, they will remain None.
|
||||
# development, there will be no 'viewvcinstallpath.py'
|
||||
#
|
||||
|
||||
LIBRARY_DIR = None
|
||||
CONF_PATHNAME = None
|
||||
import viewvcinstallpath
|
||||
LIBRARY_DIR = viewvcinstallpath.LIBRARY_DIR
|
||||
CONF_PATHNAME = viewvcinstallpath.CONF_PATHNAME
|
||||
|
||||
#########################################################################
|
||||
#
|
||||
@@ -43,6 +44,13 @@ if LIBRARY_DIR:
|
||||
|
||||
import sapi
|
||||
import imp
|
||||
import signal
|
||||
|
||||
# Totally ignore SIGPIPE - needed for overcoming popen() errors
|
||||
def sigpipe(signum, frame):
|
||||
pass
|
||||
|
||||
signal.signal(signal.SIGPIPE, sigpipe)
|
||||
|
||||
# Import real ViewVC module
|
||||
fp, pathname, description = imp.find_module('viewvc', [LIBRARY_DIR])
|
||||
|
57
bin/setup-cvs-hooks
Executable file
@@ -0,0 +1,57 @@
|
||||
#!/bin/sh
|
||||
|
||||
CVSROOTS=$1
|
||||
VIEWVC_DIR=$2
|
||||
CVS_USER=$3
|
||||
CVS_GROUP=$4
|
||||
CVS_ASYNC=$5
|
||||
|
||||
if [ ! "$CVSROOTS" -o ! "$VIEWVC_DIR" -o ! "$CVS_USER" -o ! "$CVS_GROUP" ]; then
|
||||
echo "USAGE: $0 <CVS_ROOTS> <VIEWVC_DIR> <CVS_USER> <CVS_GROUP> [CVS_ASYNC]"
|
||||
exit
|
||||
fi
|
||||
|
||||
echo "*** Setting up commit hooks for CVS repositories (job=$CVS_ASYNC)"
|
||||
chgrp $CVS_GROUP $VIEWVC_DIR
|
||||
chmod 775 $VIEWVC_DIR
|
||||
chmod 1777 .
|
||||
for CVSROOT in $CVSROOTS; do
|
||||
vcrootname=`basename $CVSROOT`
|
||||
if [ "$CVS_ASYNC" ]; then
|
||||
VHOOK="touch $VIEWVC_DIR/.cvs-updated-$vcrootname"
|
||||
else
|
||||
VHOOK="$VIEWVC_DIR/bin/cvsdbadmin update $CVSROOT >/dev/null"
|
||||
fi;
|
||||
su $CVS_USER -s /bin/sh <<EOSH
|
||||
CVSROOT=$CVSROOT cvs co CVSROOT
|
||||
if [ $? -eq 0 ]; then
|
||||
cd CVSROOT
|
||||
mv loginfo loginfo.bak
|
||||
grep -v '/.cvs-updated' <loginfo.bak | grep -v '/bin/cvsdbadmin update' >loginfo
|
||||
cat >>loginfo <<EOF
|
||||
ALL $VHOOK
|
||||
EOF
|
||||
cvs ci -m 'CVS commit hook for ViewVC' loginfo
|
||||
cd ..
|
||||
rm -Rf CVSROOT
|
||||
fi
|
||||
EOSH
|
||||
if [ "$CVS_ASYNC" ]; then
|
||||
cat >$VIEWVC_DIR/cvshook-$vcrootname <<EOF
|
||||
#!/bin/sh
|
||||
if [ -e "$VIEWVC_DIR/.cvs-updated-$vcrootname" ]; then
|
||||
rm "$VIEWVC_DIR/.cvs-updated-$vcrootname"
|
||||
$VIEWVC_DIR/bin/cvsdbadmin update $CVSROOT >/dev/null
|
||||
fi
|
||||
EOF
|
||||
chmod 755 $VIEWVC_DIR/cvshook-$vcrootname
|
||||
cat >/etc/cron.d/viewvc-cvs-$vcrootname <<EOF
|
||||
*/5 * * * * root $VIEWVC_DIR/cvshook-$vcrootname
|
||||
EOF
|
||||
fi
|
||||
done;
|
||||
|
||||
if [ "$CVS_ASYNC" ]; then
|
||||
echo "*** Reloading cron daemon"
|
||||
/etc/init.d/cron reload
|
||||
fi
|
36
bin/setup-svn-hooks
Executable file
@@ -0,0 +1,36 @@
|
||||
#!/bin/sh
|
||||
|
||||
SVNROOT=$1
|
||||
VIEWVC_DIR=$2
|
||||
SVN_ASYNC=$3
|
||||
|
||||
if [ ! "$SVNROOT" -o ! "$VIEWVC_DIR" ]; then
|
||||
echo "USAGE: $0 <SVNROOT> <VIEWVC_DIR>"
|
||||
exit
|
||||
fi
|
||||
|
||||
echo "*** Setting up commit hooks for Subversion"
|
||||
for i in `ls $SVNROOT`; do
|
||||
if [ -d "$SVNROOT/$i" ]; then
|
||||
if [ "$SVN_ASYNC" ]; then
|
||||
cat >"$SVNROOT/$i/hooks/post-commit.tmp" <<EOF
|
||||
#!/bin/sh
|
||||
echo "\$1 \$2" >> $VIEWVC_DIR/.svn-updated
|
||||
EOF
|
||||
else
|
||||
cat >"$SVNROOT/$i/hooks/post-commit.tmp" <<EOF
|
||||
#!/bin/sh
|
||||
$VIEWVC_DIR/bin/svndbadmin update \$1 \$2
|
||||
EOF
|
||||
fi
|
||||
chmod 755 "$SVNROOT/$i/hooks/post-commit.tmp"
|
||||
mv "$SVNROOT/$i/hooks/post-commit.tmp" "$SVNROOT/$i/hooks/post-commit"
|
||||
fi
|
||||
done;
|
||||
|
||||
if [ "$SVN_ASYNC" ]; then
|
||||
cat >/etc/cron.d/viewvc-svn <<EOF
|
||||
*/10 * * * * root $VIEWVC_DIR/bin/svnupdate-async.sh "$VIEWVC_DIR"
|
||||
EOF
|
||||
/etc/init.d/cron reload
|
||||
fi
|
@@ -16,15 +16,20 @@
|
||||
#
|
||||
# -----------------------------------------------------------------------
|
||||
|
||||
"""Run "standalone.py -p <port>" to start an HTTP server on a given port
|
||||
on the local machine to generate ViewVC web pages.
|
||||
"""
|
||||
|
||||
#
|
||||
# INSTALL-TIME CONFIGURATION
|
||||
#
|
||||
# These values will be set during the installation process. During
|
||||
# development, they will remain None.
|
||||
# development, there will be no 'viewvcinstallpath.py'
|
||||
#
|
||||
|
||||
LIBRARY_DIR = None
|
||||
CONF_PATHNAME = None
|
||||
import viewvcinstallpath
|
||||
LIBRARY_DIR = viewvcinstallpath.LIBRARY_DIR
|
||||
CONF_PATHNAME = viewvcinstallpath.CONF_PATHNAME
|
||||
|
||||
import sys
|
||||
import os
|
||||
|
234
bin/svndbadmin
@@ -35,15 +35,15 @@
|
||||
#
|
||||
|
||||
#########################################################################
|
||||
#
|
||||
# INSTALL-TIME CONFIGURATION
|
||||
#
|
||||
# These values will be set during the installation process. During
|
||||
# development, they will remain None.
|
||||
# development, there will be no 'viewvcinstallpath.py'
|
||||
#
|
||||
|
||||
LIBRARY_DIR = None
|
||||
CONF_PATHNAME = None
|
||||
import viewvcinstallpath
|
||||
LIBRARY_DIR = viewvcinstallpath.LIBRARY_DIR
|
||||
CONF_PATHNAME = viewvcinstallpath.CONF_PATHNAME
|
||||
|
||||
# Adjust sys.path to include our library directory
|
||||
import sys
|
||||
@@ -57,7 +57,12 @@ else:
|
||||
#########################################################################
|
||||
|
||||
import os
|
||||
import string
|
||||
import socket
|
||||
import select
|
||||
import re
|
||||
import mimetypes
|
||||
import time
|
||||
|
||||
import svn.core
|
||||
import svn.repos
|
||||
@@ -67,14 +72,21 @@ import svn.delta
|
||||
import cvsdb
|
||||
import viewvc
|
||||
import vclib
|
||||
from viewvcmagic import ContentMagic
|
||||
|
||||
class SvnRepo:
|
||||
"""Class used to manage a connection to a SVN repository."""
|
||||
def __init__(self, path):
|
||||
def __init__(self, path, index_content = None, tika_client = None, guesser = None,
|
||||
svn_ignore_mimetype = False, verbose = False):
|
||||
self.path = path
|
||||
self.repo = svn.repos.svn_repos_open(path)
|
||||
self.fs = svn.repos.svn_repos_fs(self.repo)
|
||||
self.rev_max = svn.fs.youngest_rev(self.fs)
|
||||
self.index_content = index_content
|
||||
self.tika_client = tika_client
|
||||
self.guesser = guesser
|
||||
self.verbose = verbose
|
||||
self.svn_ignore_mimetype = svn_ignore_mimetype
|
||||
def __getitem__(self, rev):
|
||||
if rev is None:
|
||||
rev = self.rev_max
|
||||
@@ -84,7 +96,36 @@ class SvnRepo:
|
||||
rev = SvnRev(self, rev)
|
||||
return rev
|
||||
|
||||
_re_diff_change_command = re.compile('(\d+)(?:,(\d+))?([acd])(\d+)(?:,(\d+))?')
|
||||
_re_diff_change_command = re.compile('^(\d+)(?:,(\d+))?([acd])(\d+)(?:,(\d+))?')
|
||||
|
||||
class StupidBufferedReader:
|
||||
def __init__(self, fp, buffer = 262144):
|
||||
self.fp = fp
|
||||
self.bufsize = buffer
|
||||
self.buffer = ''
|
||||
self.eof = False
|
||||
def __iter__(self):
|
||||
return self
|
||||
def next(self):
|
||||
if self.eof:
|
||||
raise StopIteration
|
||||
return self.readline()
|
||||
def readline(self):
|
||||
if self.eof:
|
||||
return ''
|
||||
p = self.buffer.find('\n')
|
||||
while p < 0:
|
||||
b = self.fp.read(self.bufsize)
|
||||
if not len(b):
|
||||
r = self.buffer
|
||||
self.buffer = ''
|
||||
self.eof = True
|
||||
return r
|
||||
self.buffer = self.buffer + b
|
||||
p = self.buffer.find('\n')
|
||||
r = self.buffer[0:p+1]
|
||||
self.buffer = self.buffer[p+1:]
|
||||
return r
|
||||
|
||||
def _get_diff_counts(diff_fp):
|
||||
"""Calculate the plus/minus counts by parsing the output of a
|
||||
@@ -97,8 +138,7 @@ def _get_diff_counts(diff_fp):
|
||||
GNU diff manual."""
|
||||
|
||||
plus, minus = 0, 0
|
||||
line = diff_fp.readline()
|
||||
while line:
|
||||
for line in diff_fp:
|
||||
match = re.match(_re_diff_change_command, line)
|
||||
if match:
|
||||
# size of first range
|
||||
@@ -124,9 +164,79 @@ def _get_diff_counts(diff_fp):
|
||||
# RdL - remove range R of file1, which would have been
|
||||
# at line L of file2
|
||||
minus = minus + count1
|
||||
line = diff_fp.readline()
|
||||
return plus, minus
|
||||
|
||||
class TikaClient:
|
||||
# Create tika client
|
||||
def __init__(self, tika_server, mime_types, verbose):
|
||||
self.tika_server = tika_server
|
||||
self.mime_types = mime_types
|
||||
self.verbose = verbose
|
||||
self.addr = tika_server.split(':')
|
||||
# Split address
|
||||
if len(self.addr) != 2:
|
||||
raise Exception('tika_server value is incorrect: \''+tika_server+'\', please use \'host:port\' format')
|
||||
self.addr = (self.addr[0], int(self.addr[1]))
|
||||
# Build regexp for MIME types
|
||||
m = re.split('\s+', mime_types.strip())
|
||||
self.mime_regexp = re.compile('|'.join('^'+re.escape(i).replace('\\*', '.*')+'$' for i in m))
|
||||
|
||||
# Extract text content from file using Tika which runs in server mode
|
||||
def get_text(self, filename, mime_type, log_filename):
|
||||
if not self.mime_regexp.match(mime_type):
|
||||
# Tika can't handle this mime type, return nothing
|
||||
return ''
|
||||
fd = None
|
||||
s = None
|
||||
text = ''
|
||||
fsize = 0
|
||||
try:
|
||||
# Read original file
|
||||
fd = open(filename, 'rb')
|
||||
data = fd.read()
|
||||
fsize = len(data)
|
||||
if not fsize:
|
||||
return ''
|
||||
# Connect to Tika
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
s.connect(self.addr)
|
||||
s.setblocking(0)
|
||||
sockfd = s.fileno()
|
||||
# Tika is somewhat delicate about network IO, so:
|
||||
# Read and write using poll(2) system call
|
||||
p = select.poll()
|
||||
p.register(sockfd)
|
||||
while 1:
|
||||
fds = p.poll()
|
||||
if not fds:
|
||||
break
|
||||
(pollfd, event) = fds[0]
|
||||
if event & select.POLLIN:
|
||||
# Exception or empty data means EOF...
|
||||
try: part = os.read(sockfd, 65536)
|
||||
except: break
|
||||
if not part: break
|
||||
text += part
|
||||
if event & select.POLLOUT:
|
||||
if not len(data):
|
||||
# Shutdown output and forget about POLLOUT
|
||||
s.shutdown(socket.SHUT_WR)
|
||||
p.modify(sockfd, select.POLLIN)
|
||||
else:
|
||||
# Write and consume some data
|
||||
l = os.write(sockfd, data)
|
||||
data = data[l:]
|
||||
if len(text) == 0:
|
||||
raise Exception('Empty response from Tika server')
|
||||
if self.verbose:
|
||||
print "Extracted %d bytes from %s (%s) of size %d" % (len(text), log_filename, mime_type, fsize)
|
||||
except Exception, e:
|
||||
if self.verbose:
|
||||
print "Error extracting text from %s (%s) of size %d: %s" % (log_filename, mime_type, fsize, str(e))
|
||||
finally:
|
||||
if fd: fd.close()
|
||||
if s: s.close()
|
||||
return text
|
||||
|
||||
class SvnRev:
|
||||
"""Class used to hold information about a particular revision of
|
||||
@@ -150,13 +260,14 @@ class SvnRev:
|
||||
|
||||
# get a root for the current revisions
|
||||
fsroot = self._get_root_for_rev(rev)
|
||||
|
||||
|
||||
# find changes in the revision
|
||||
editor = svn.repos.ChangeCollector(repo.fs, fsroot)
|
||||
e_ptr, e_baton = svn.delta.make_editor(editor)
|
||||
svn.repos.svn_repos_replay(fsroot, e_ptr, e_baton)
|
||||
|
||||
self.changes = []
|
||||
changes_hash = {}
|
||||
for path, change in editor.changes.items():
|
||||
# skip non-file changes
|
||||
if change.item_kind != svn.core.svn_node_file:
|
||||
@@ -185,14 +296,61 @@ class SvnRev:
|
||||
action = 'change'
|
||||
|
||||
if action == 'remove':
|
||||
diffobj = svn.fs.FileDiff(base_root, base_path, None, None)
|
||||
diffobj = svn.fs.FileDiff(base_root, change.base_path, None, None, None, ['-b', '-B'])
|
||||
else:
|
||||
diffobj = svn.fs.FileDiff(base_root, base_path,
|
||||
fsroot, change.path)
|
||||
diffobj = svn.fs.FileDiff(base_root, change.base_path, fsroot, change.path, None, ['-b', '-B'])
|
||||
|
||||
diff_fp = diffobj.get_pipe()
|
||||
diff_fp = StupidBufferedReader(diff_fp)
|
||||
plus, minus = _get_diff_counts(diff_fp)
|
||||
self.changes.append((path, action, plus, minus))
|
||||
|
||||
# CustIS Bug 50473: a workaround for svnlib behaviour in file movements (FILE1 -> FILE2 + FILE1 -> null)
|
||||
if change.base_path:
|
||||
if not change.path and change.base_path in changes_hash:
|
||||
minus = 0
|
||||
elif change.path:
|
||||
changes_hash[change.base_path] = change.path
|
||||
|
||||
content = ''
|
||||
mime = ''
|
||||
# need to check if binary file's content changed when copying,
|
||||
# if not, don't extract it, just get it from previous revision later
|
||||
if repo.index_content and action != 'remove' and change.path and (not change.base_path
|
||||
or svn.fs.contents_changed(
|
||||
base_root and base_root or None,
|
||||
base_root and change.base_path or None,
|
||||
fsroot, change.path
|
||||
)):
|
||||
props = svn.fs.node_proplist(fsroot, change.path)
|
||||
if not repo.svn_ignore_mimetype:
|
||||
mime = props.get('svn:mime-type', None)
|
||||
else:
|
||||
mime = None
|
||||
mime = repo.guesser.guess_mime(
|
||||
mime,
|
||||
os.path.basename(change.path),
|
||||
diffobj.tempfile2
|
||||
)
|
||||
# Read and guess charset by ourselves for text files
|
||||
if mime and mime.startswith('text/') or (mime.startswith('application/') and mime.endswith('xml')):
|
||||
try:
|
||||
fd = open(diffobj.tempfile2, 'rb')
|
||||
content = fd.read()
|
||||
fd.close()
|
||||
except: pass
|
||||
# Guess charset
|
||||
if content:
|
||||
content, charset = repo.guesser.guess_charset(content)
|
||||
if charset:
|
||||
content = content.encode('utf-8')
|
||||
if repo.verbose:
|
||||
print 'Guessed %s for %s' % (charset, change.path)
|
||||
elif repo.verbose:
|
||||
print 'Failed to guess charset for %s, not indexing' % (change.path, )
|
||||
# Try to extract content using Tika from binary documents
|
||||
elif repo.tika_client:
|
||||
content = repo.tika_client.get_text(diffobj.tempfile2, mime, change.path)
|
||||
self.changes.append((path, action, plus, minus, content, mime))
|
||||
|
||||
def _get_root_for_rev(self, rev):
|
||||
"""Fetch a revision root from a cache of such, or a fresh root
|
||||
@@ -213,7 +371,7 @@ def handle_revision(db, command, repo, rev, verbose, force=0):
|
||||
if verbose: print "skipped (no changes)."
|
||||
return
|
||||
|
||||
for (path, action, plus, minus) in revision.changes:
|
||||
for (path, action, plus, minus, content, mime) in revision.changes:
|
||||
directory, file = os.path.split(path)
|
||||
commit = cvsdb.CreateCommit()
|
||||
commit.SetRepository(repo.path)
|
||||
@@ -226,6 +384,8 @@ def handle_revision(db, command, repo, rev, verbose, force=0):
|
||||
commit.SetPlusCount(plus)
|
||||
commit.SetMinusCount(minus)
|
||||
commit.SetBranch(None)
|
||||
commit.SetContent(content)
|
||||
commit.SetMimeType(mime)
|
||||
|
||||
if action == 'add':
|
||||
commit.SetTypeAdd()
|
||||
@@ -253,6 +413,7 @@ def main(command, repository, revs=[], verbose=0, force=0):
|
||||
cfg = viewvc.load_config(CONF_PATHNAME)
|
||||
db = cvsdb.ConnectDatabase(cfg)
|
||||
|
||||
repository = os.path.realpath(repository)
|
||||
# Purge what must be purged.
|
||||
if command in ('rebuild', 'purge'):
|
||||
if verbose:
|
||||
@@ -264,24 +425,29 @@ def main(command, repository, revs=[], verbose=0, force=0):
|
||||
sys.stderr.write("ERROR: " + str(e) + "\n")
|
||||
sys.exit(1)
|
||||
|
||||
tika_client = None
|
||||
if cfg.utilities.tika_server:
|
||||
tika_client = TikaClient(cfg.utilities.tika_server, cfg.utilities.tika_mime_types, verbose)
|
||||
repo = SvnRepo(
|
||||
path = repository,
|
||||
index_content = cfg.cvsdb.index_content,
|
||||
tika_client = tika_client,
|
||||
guesser = cfg.guesser(),
|
||||
svn_ignore_mimetype = cfg.options.svn_ignore_mimetype,
|
||||
verbose = verbose,
|
||||
)
|
||||
# Record what must be recorded.
|
||||
if command in ('rebuild', 'update'):
|
||||
if not os.path.exists(repository):
|
||||
sys.stderr.write('ERROR: could not find repository %s\n'
|
||||
% (repository))
|
||||
sys.exit(1)
|
||||
repo = SvnRepo(repository)
|
||||
if command == 'rebuild' or (command == 'update' and not revs):
|
||||
for rev in range(repo.rev_max+1):
|
||||
handle_revision(db, command, repo, rev, verbose)
|
||||
elif command == 'update':
|
||||
if revs[0] is None:
|
||||
revs[0] = repo.rev_max
|
||||
if revs[1] is None:
|
||||
revs[1] = repo.rev_max
|
||||
revs.sort()
|
||||
for rev in range(revs[0], revs[1]+1):
|
||||
handle_revision(db, command, repo, rev, verbose, force)
|
||||
if command == 'rebuild' or (command == 'update' and not revs):
|
||||
for rev in range(repo.rev_max+1):
|
||||
handle_revision(db, command, repo, rev, verbose, force)
|
||||
elif command == 'update':
|
||||
if revs[0] is None:
|
||||
revs[0] = repo.rev_max
|
||||
if revs[1] is None:
|
||||
revs[1] = repo.rev_max
|
||||
revs.sort()
|
||||
for rev in range(revs[0], revs[1]+1):
|
||||
handle_revision(db, command, repo, rev, verbose, force)
|
||||
|
||||
def _rev2int(r):
|
||||
if r == 'HEAD':
|
||||
@@ -314,7 +480,7 @@ Usage: 1. %s [-v] rebuild REPOS-PATH
|
||||
the database. If a range is specified, the revisions will be
|
||||
processed in ascending order, and you may specify "HEAD" to
|
||||
indicate "the youngest revision currently in the repository".
|
||||
|
||||
|
||||
3. Purge information specific to the repository located at REPOS-PATH
|
||||
from the database.
|
||||
|
||||
@@ -339,7 +505,7 @@ if __name__ == '__main__':
|
||||
del args[index]
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
|
||||
if len(args) < 3:
|
||||
usage()
|
||||
|
||||
|
50
bin/svnupdate-async
Executable file
@@ -0,0 +1,50 @@
|
||||
#!/usr/bin/perl
|
||||
# Скрипт для обновления SVN репозиториев svndbadmin-ом
|
||||
# Берёт номера ревизий и имена репозиториев из перечисленных файлов или STDIN,
|
||||
# группирует их по номерам и выводит список команд, необходимых для обновления
|
||||
|
||||
use strict;
|
||||
|
||||
# первый аргумент - путь к svndbadmin
|
||||
my $svndbadmin = shift @ARGV
|
||||
|| die "USAGE: $0 <path_to_svndbadmin> FILES...";
|
||||
|
||||
# считываем названия репозиториев и номера ревизий из файла
|
||||
my $tou = {};
|
||||
my ($repos, $rev);
|
||||
while (<>)
|
||||
{
|
||||
s/^\s+//so;
|
||||
s/\s+$//so;
|
||||
($repos, $rev) = split /\s+/, $_;
|
||||
$tou->{$repos}->{$rev} = 1;
|
||||
}
|
||||
|
||||
# превращаем номера ревизий в диапазоны ревизий
|
||||
my ($i, $j, $r, $nr);
|
||||
foreach $repos (keys %$tou)
|
||||
{
|
||||
$rev = [ sort keys %{$tou->{$repos}} ];
|
||||
$nr = [];
|
||||
$j = 0;
|
||||
for $i (1..@$rev)
|
||||
{
|
||||
if ($i > $#$rev || $rev->[$i]-$rev->[$j] > $i-$j)
|
||||
{
|
||||
$r = $rev->[$j];
|
||||
$r .= ":".$rev->[$i-1] if $i-$j > 1;
|
||||
push @$nr, $r;
|
||||
$j = $i;
|
||||
}
|
||||
}
|
||||
$tou->{$repos} = $nr;
|
||||
}
|
||||
|
||||
# выводим список команд для выполнения
|
||||
foreach $repos (keys %$tou)
|
||||
{
|
||||
foreach (@{$tou->{$repos}})
|
||||
{
|
||||
print "$svndbadmin update $repos $_\n";
|
||||
}
|
||||
}
|
8
bin/svnupdate-async.sh
Executable file
@@ -0,0 +1,8 @@
|
||||
#!/bin/sh
|
||||
|
||||
VIEWVC_DIR=$1
|
||||
|
||||
test -f "$VIEWVC_DIR/.svn-updating" -o ! -f "$VIEWVC_DIR/.svn-updated" && exit 0
|
||||
mv "$VIEWVC_DIR/.svn-updated" "$VIEWVC_DIR/.svn-updating"
|
||||
"$VIEWVC_DIR/bin/svnupdate-async" "$VIEWVC_DIR/bin/svndbadmin" "$VIEWVC_DIR/.svn-updating" | sh &> /tmp/svnupdate-async.log
|
||||
rm "$VIEWVC_DIR/.svn-updating"
|
41
bin/wsgi/viewvcwsgi.py
Normal file
@@ -0,0 +1,41 @@
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 1999-2013 The ViewCVS Group. All Rights Reserved.
|
||||
#
|
||||
# By using this file, you agree to the terms and conditions set forth in
|
||||
# the LICENSE.html file which can be found at the top level of the ViewVC
|
||||
# distribution or at http://viewvc.org/license-1.html.
|
||||
#
|
||||
# For more information, visit http://viewvc.org/
|
||||
#
|
||||
# -----------------------------------------------------------------------
|
||||
#
|
||||
# viewvc: View CVS/SVN repositories via a web browser
|
||||
#
|
||||
# -----------------------------------------------------------------------
|
||||
#
|
||||
# This is a wsgi entry point for the main ViewVC app. It's appropriate
|
||||
# for use with mod_wsgi. It defines a single application function that
|
||||
# is a valid wsgi entry point.
|
||||
#
|
||||
# -----------------------------------------------------------------------
|
||||
|
||||
import sys, os
|
||||
|
||||
import viewvcinstallpath
|
||||
LIBRARY_DIR = viewvcinstallpath.LIBRARY_DIR
|
||||
CONF_PATHNAME = viewvcinstallpath.CONF_PATHNAME
|
||||
|
||||
if LIBRARY_DIR:
|
||||
sys.path.insert(0, LIBRARY_DIR)
|
||||
else:
|
||||
sys.path.insert(0, os.path.abspath(os.path.join(
|
||||
os.path.dirname(__file__), "../../lib")))
|
||||
import sapi
|
||||
import viewvc
|
||||
|
||||
def application(environ, start_response):
|
||||
server = sapi.WsgiServer(environ, start_response)
|
||||
cfg = viewvc.load_config(CONF_PATHNAME, server)
|
||||
viewvc.main(server, cfg)
|
||||
return []
|
@@ -1,6 +1,6 @@
|
||||
##---------------------------------------------------------------------------
|
||||
##
|
||||
## Configuration file for ViewVC
|
||||
## Configuration file for ViewVC (4IntraNet patched version)
|
||||
##
|
||||
## Information on ViewVC is located at the following web site:
|
||||
## http://viewvc.org/
|
||||
@@ -301,6 +301,21 @@
|
||||
##
|
||||
#cvsnt =
|
||||
|
||||
# ViewVC can use an inetd service instead of local "cvsnt rcsfile"
|
||||
# This is recommended for all UNIX installations which use cvsnt,
|
||||
# as there is an unpleasant non-stable bug, probably somewhere
|
||||
# inside mod_python or Apache, which SOMETIMES causes cvsnt subprocesses forked
|
||||
# from mod_python to die. This gives empty diff outputs or different errors like
|
||||
# "Error: Rlog output ended early. Expected RCS file ..."
|
||||
# This script removes forking from mod_python code and solves the issue.
|
||||
# Additional profit of this script is that you can probably browse REMOTE cvs
|
||||
# repositories, if you expose this service to ViewVC, although it is not tested.
|
||||
|
||||
# See also bin/cvsnt-rcsfile-inetd.pl
|
||||
|
||||
#rcsfile_socket = host:port
|
||||
# Example: rcsfile_socket = 127.0.0.1:8071
|
||||
|
||||
## diff: Location of the GNU diff program, used for showing file
|
||||
## version differences.
|
||||
##
|
||||
@@ -317,6 +332,32 @@
|
||||
##
|
||||
#cvsgraph =
|
||||
|
||||
# Apache Tika TCP server host and port, used to extract text from binary documents
|
||||
# Note that as of 2011-09-12, Tika 0.9 has a bug which leads to hangups on processing
|
||||
# M$Word documents in server mode. So you must use the fixed version, downloaded from:
|
||||
# http://wiki.4intra.net/public/tika-app-0.9-fix-TIKA709.jar
|
||||
# (mirror) http://code.google.com/p/mediawiki4intranet/downloads/detail?name=tika-app-0.9-fix-TIKA709.jar
|
||||
# Or apply the patch by yourself and rebuild Tika from source, see patch here:
|
||||
# https://issues.apache.org/jira/browse/TIKA-709
|
||||
# Tika server should be started with command 'java -jar tika-app-0.9.jar -p PORT -t -eutf-8'
|
||||
|
||||
#tika_server = host:port
|
||||
# Example: tika_server = 127.0.0.1:8072
|
||||
|
||||
# This lists MIME types that can be processed by Tika
|
||||
# You may change it if your Tika is newer than 0.9 and supports more formats
|
||||
# (note) *+xml examples: xhtml+xml, rss+xml, atom+xml, docbook+xml, rdf+xml
|
||||
tika_mime_types =
|
||||
text/*
|
||||
application/*+xml
|
||||
application/xml
|
||||
application/vnd.oasis.opendocument.*
|
||||
application/vnd.openxmlformats
|
||||
application/vnd.ms-*
|
||||
application/msaccess
|
||||
application/msword
|
||||
application/pdf
|
||||
application/rtf
|
||||
|
||||
##---------------------------------------------------------------------------
|
||||
[options]
|
||||
@@ -713,7 +754,7 @@
|
||||
## character encodings? [Requires 'chardet' module, and is currently
|
||||
## used only for the 'markup' and 'annotate' views.]
|
||||
##
|
||||
#detect_encoding = 0
|
||||
detect_encoding = 1
|
||||
|
||||
## use_cvsgraph: Use CvsGraph to offer visual graphs of CVS revision history.
|
||||
##
|
||||
@@ -805,6 +846,17 @@
|
||||
##
|
||||
#limit_changes = 100
|
||||
|
||||
# You can also use primitive charset guessing instead of chardet (options.detect_encoding)
|
||||
# Just set this to the list of possible charsets in your repository.
|
||||
# ViewVC will simply try to decode content using each of them, and pick
|
||||
# the first which succeeds. UTF-8 is always tried automatically.
|
||||
#encodings = cp1251:iso-8859-1
|
||||
|
||||
# Sadly this is also required - for back-links from query results to files
|
||||
# in CVS, because it doesn't recode file names to UTF-8 as Subversion does.
|
||||
# Just set to cp1251 if you work with your CVS from Windowz.
|
||||
#cvs_ondisk_charset = cp1251
|
||||
|
||||
##---------------------------------------------------------------------------
|
||||
[templates]
|
||||
|
||||
@@ -888,6 +940,10 @@
|
||||
##
|
||||
#port = 3306
|
||||
|
||||
## socket: Database listening socket.
|
||||
## On Debian Linux, enable this:
|
||||
#socket = /var/run/mysqld/mysqld.sock
|
||||
|
||||
## database_name: ViewVC database name.
|
||||
##
|
||||
#database_name = ViewVC
|
||||
@@ -912,6 +968,51 @@
|
||||
##
|
||||
#readonly_passwd =
|
||||
|
||||
# ViewVC can use Sphinx (http://sphinxsearch.com) full-text search engine
|
||||
# to index file contents with full history and then search over them.
|
||||
# Also, Apache Tika console application can be used in TCP server mode to
|
||||
# add support for indexing binary documents (M$Word, PDF and etc).
|
||||
# See tika_server in [utilities].
|
||||
# Requires Sphinx >= 0.9.9 with a real-time updatable SphinxQL index.
|
||||
# Index must be created in sphinx.conf by hand and have the following fields:
|
||||
# rt_field = content
|
||||
# rt_attr_string = mimetype
|
||||
# rt_attr_timestamp = ci_when
|
||||
# rt_attr_uint = whoid
|
||||
# rt_attr_uint = repositoryid
|
||||
# rt_attr_uint = dirid
|
||||
# rt_attr_uint = fileid
|
||||
# rt_attr_uint = revision
|
||||
# rt_attr_uint = branchid
|
||||
|
||||
# Set to 1 to enable indexing of file contents using Sphinx and Tika
|
||||
index_content = 0
|
||||
|
||||
# Set to limit stored text file content size (max. 4MB - Sphinx limit)
|
||||
#content_max_size = 4194304
|
||||
|
||||
# Sphinx connection parameters:
|
||||
#sphinx_host =
|
||||
#sphinx_port =
|
||||
#sphinx_socket = /var/run/sphinxql.sock
|
||||
#sphinx_index = viewvc
|
||||
|
||||
## Parameters for snippet (excerpt) display
|
||||
|
||||
# Enable snippets? ViewVC indexes binary file contents in MySQL when enabled.
|
||||
enable_snippets = 1
|
||||
|
||||
# Regexp for MIME types in which \n means "newline"
|
||||
sphinx_preformatted_mime = text/(?!html|xml).*
|
||||
|
||||
# Sphinx snippet options - see http://sphinxsearch.com/docs/current.html#api-func-buildexcerpts
|
||||
sphinx_snippet_options =
|
||||
around: 15
|
||||
limit: 200
|
||||
before_match: <span style="color:red">
|
||||
after_match: </span>
|
||||
chunk_separator: ... \n
|
||||
|
||||
## row_limit: Maximum number of rows returned by a given normal query
|
||||
## to the database.
|
||||
##
|
||||
|
@@ -146,8 +146,9 @@ td {
|
||||
configuration's "general" section.</li>
|
||||
|
||||
<li>Finally, ensure that that the new <code>authorizer</code>
|
||||
option is set to either "forbidden" or "forbiddenre", depending
|
||||
on which of those you were using in ViewVC 1.0.x.</li>
|
||||
option is set to either "forbidden" (which is the default) or
|
||||
"forbiddenre", depending on which of those you were using in
|
||||
ViewVC 1.0.x.</li>
|
||||
|
||||
</ol>
|
||||
|
||||
@@ -223,9 +224,10 @@ td {
|
||||
<li>options/py2html_path</li>
|
||||
<li>options/use_enscript</li>
|
||||
<li>options/use_highlight</li>
|
||||
<li>options/use_pagesize</li>
|
||||
<li>options/use_php</li>
|
||||
<li>options/use_py2html</li>
|
||||
<li>options/use_pygments</li>
|
||||
<li>options/use_source_highlight</li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
@@ -233,23 +235,16 @@ td {
|
||||
<div class="h3">
|
||||
<h3>Checkin Database</h3>
|
||||
|
||||
<p>ViewVC 1.1 introduces to the <code>cvsdbadmin</code>
|
||||
and <code>svndbadmin</code> tools a new "purge" operation, which
|
||||
allows you to remove all the information related to a given root
|
||||
from your checkins database (without disturbing the information
|
||||
associated with other roots). Likewise, the "rebuild" command in
|
||||
those tools now implies a "purge" followed by an update.</p>
|
||||
|
||||
<p>As a related change, the <code>svndbadmin</code> program's
|
||||
"rebuild" subcommand has had its purpose become more defined. It
|
||||
no longer accepts a revision argument, and therefore can now only
|
||||
be used to completely rebuild the entirety of the checkin database
|
||||
information for a Subversion repository (instead of being able to
|
||||
only update the information related to single Subversion revision).
|
||||
For per-revision updating, use <code>svndbadmin update</code> and
|
||||
<p>In ViewVC 1.1, the <code>svndbadmin</code> program's "rebuild"
|
||||
subcommand has had its purpose become more defined. It no longer
|
||||
accepts a revision argument, and therefore can now only be used to
|
||||
completely rebuild the entirety of the checkin database information
|
||||
for a Subversion repository (instead of being able to only update
|
||||
the information related to single Subversion revision). For
|
||||
per-revision updating, use <code>svndbadmin update</code> and
|
||||
provide a revision (or revision range). And to get the previous
|
||||
rebuild-a-revision effect, pass the new <code>--force</code> option
|
||||
to <code>svndbadmin update</code>.</p>
|
||||
rebuild-a-revision effect, pass the new <code>--force</code>
|
||||
option to <code>svndbadmin update</code>.</p>
|
||||
|
||||
<p>In other words, where you once did this:</p>
|
||||
|
||||
@@ -263,19 +258,6 @@ td {
|
||||
</pre>
|
||||
</blockquote>
|
||||
|
||||
<p>To enhance the performance of the new "purge" operation, ViewVC 1.1
|
||||
introduces some slight changes to the checkin database schema. If
|
||||
you use the <code>make-database</code> tool to (re)create your
|
||||
checkins database, it will by default employ the new database
|
||||
schema. This should cause the database to be virtually unusable by
|
||||
previous versions of ViewVC, and that's by design. If, however,
|
||||
you need to (re)create your checkins database and you require
|
||||
compatibility with previous versions of ViewVC or ViewCVS, simply
|
||||
pass the "--version=1.0" option to the <code>make-database</code>
|
||||
script. Note that your "purge" and "rebuild" operations could be
|
||||
abysmally slow, though, as that version of the database schema is
|
||||
not optimized for those operations.</p>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="h3">
|
||||
@@ -323,22 +305,6 @@ td {
|
||||
<li>options/allow_tar</li>
|
||||
</ul>
|
||||
|
||||
<p>ViewVC now honors the "svn:mime-type" property stored on
|
||||
Subversion-versioned files as the primary source of MIME type
|
||||
determination (before falling back to name-based MIME mappings and
|
||||
such). However, this can negatively affect the viewability of
|
||||
certain files — especially images — whose
|
||||
"svn:mime-type" properties are set incorrectly, such as will happen
|
||||
if Subversion itself merely determines that the file isn't
|
||||
human-readable and uses the "application/octet-stream" MIME type to
|
||||
record this determination. To make ViewVC <em>not</em> honor the
|
||||
"svn:mime-type" property value, set the <code>svn_ignore_mimetype</code>
|
||||
configuration option.</p>
|
||||
|
||||
<p>Speaking of MIME types, the option <code>mime_types_file</code> is
|
||||
now <code>mime_types_files</code>, as it now carries multiple paths
|
||||
to MIME mappings files, ordered by preference.</p>
|
||||
|
||||
<p>The <code>use_rcsparse</code> option was moved from the "general"
|
||||
section to the "options" section.</p>
|
||||
|
||||
@@ -674,11 +640,6 @@ allowed_views = annotate, diff, markup, tar
|
||||
<td>revision.ezt</td>
|
||||
<td>now is an iterable list of objects with .name and .value attributes</td>
|
||||
</tr>
|
||||
<tr class="added">
|
||||
<td class="varname">num_changes</td>
|
||||
<td>revision.ezt</td>
|
||||
<td>added</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
@@ -707,7 +668,7 @@ allowed_views = annotate, diff, markup, tar
|
||||
<h3>Checkin Database</h3>
|
||||
|
||||
<p>ViewVC 1.0 reads and writes commit times in the MySQL database in
|
||||
UTC time rather than local time. This can cause times displayed on
|
||||
UTC time rather than local time. This can cause times displayed on
|
||||
the query page to be a few hours off if an old database is being
|
||||
used with a new version of ViewVC. The best way to fix this is to
|
||||
rebuild the database with the new version of cvsdbadmin, but it
|
||||
@@ -750,8 +711,7 @@ allowed_views = annotate, diff, markup, tar
|
||||
<li>options/root_as_url_component</li>
|
||||
<li>options/default_file_view</li>
|
||||
<li>options/sort_group_dirs</li>
|
||||
<li>options/dir_pagesize</li>
|
||||
<li>options/log_pagesize</li>
|
||||
<li>options/use_pagesize</li>
|
||||
<li>options/limit_changes</li>
|
||||
<li>options/use_localtime</li>
|
||||
<li>options/cross_copies</li>
|
||||
|
122
lib/config.py
@@ -18,7 +18,13 @@ import sys
|
||||
import os
|
||||
import ConfigParser
|
||||
import fnmatch
|
||||
|
||||
import vclib
|
||||
import vclib.ccvs
|
||||
import vclib.svn
|
||||
import cvsdb
|
||||
import viewvc
|
||||
import copy
|
||||
from viewvcmagic import ContentMagic
|
||||
|
||||
#########################################################################
|
||||
#
|
||||
@@ -137,6 +143,9 @@ class Config:
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
self.__guesser = None
|
||||
self.__root_configs = {}
|
||||
self.__parent = None
|
||||
self.root_options_overlayed = 0
|
||||
for section in self._base_sections:
|
||||
if section[-1] == '*':
|
||||
@@ -277,6 +286,34 @@ class Config:
|
||||
|
||||
return None
|
||||
|
||||
def get_root_config(self, rootname):
|
||||
"""Get configuration object with per-root overrides for 'rootname'"""
|
||||
if self.__parent:
|
||||
return self.__parent.get_root_config(rootname)
|
||||
elif rootname in self.__root_configs:
|
||||
return self.__root_configs[rootname]
|
||||
__guesser = self.__guesser
|
||||
__root_configs = self.__root_configs
|
||||
parser = self.parser
|
||||
self.parser = None
|
||||
self.__guesser = None
|
||||
self.__root_configs = None
|
||||
sub = copy.deepcopy(self)
|
||||
sub.parser = parser
|
||||
self.parser = parser
|
||||
self.__guesser = __guesser
|
||||
self.__root_configs = __root_configs
|
||||
self.__root_configs[rootname] = sub
|
||||
sub.__parent = self
|
||||
sub.overlay_root_options(rootname)
|
||||
return sub
|
||||
|
||||
def get_parent_config(self):
|
||||
"""Get the parent non-overridden config."""
|
||||
if self.__parent:
|
||||
return self.__parent
|
||||
return self
|
||||
|
||||
def overlay_root_options(self, rootname):
|
||||
"""Overlay per-root options for ROOTNAME atop the existing option
|
||||
set. This is a destructive change to the configuration."""
|
||||
@@ -311,54 +348,6 @@ class Config:
|
||||
d[option] = parser.get(section, option)
|
||||
return d.items()
|
||||
|
||||
def get_authorizer_and_params_hack(self, rootname):
|
||||
"""Return a 2-tuple containing the name and parameters of the
|
||||
authorizer configured for use with ROOTNAME.
|
||||
|
||||
### FIXME: This whole thing is a hack caused by our not being able
|
||||
### to non-destructively overlay root options when trying to do
|
||||
### something like a root listing (which might need to get
|
||||
### different authorizer bits for each and every root in the list).
|
||||
### Until we have a good way to do that, we expose this function,
|
||||
### which assumes that base and per-vhost configuration has been
|
||||
### absorbed into this object and that per-root options have *not*
|
||||
### been overlayed. See issue #371."""
|
||||
|
||||
# We assume that per-root options have *not* been overlayed.
|
||||
assert(self.root_options_overlayed == 0)
|
||||
|
||||
if not self.conf_path:
|
||||
return None, {}
|
||||
|
||||
# Figure out the authorizer by searching first for a per-root
|
||||
# override, then falling back to the base/vhost configuration.
|
||||
authorizer = None
|
||||
root_options_section = 'root-%s/options' % (rootname)
|
||||
if self.parser.has_section(root_options_section) \
|
||||
and self.parser.has_option(root_options_section, 'authorizer'):
|
||||
authorizer = self.parser.get(root_options_section, 'authorizer')
|
||||
if not authorizer:
|
||||
authorizer = self.options.authorizer
|
||||
|
||||
# No authorizer? Get outta here.
|
||||
if not authorizer:
|
||||
return None, {}
|
||||
|
||||
# Dig up the parameters for the authorizer, starting with the
|
||||
# base/vhost items, then overlaying any root-specific ones we find.
|
||||
params = {}
|
||||
authz_section = 'authz-%s' % (authorizer)
|
||||
if hasattr(self, authz_section):
|
||||
sub_config = getattr(self, authz_section)
|
||||
for attr in dir(sub_config):
|
||||
params[attr] = getattr(sub_config, attr)
|
||||
root_authz_section = 'root-%s/authz-%s' % (rootname, authorizer)
|
||||
for section in self.parser.sections():
|
||||
if section == root_authz_section:
|
||||
for key, value in self._get_parser_items(self.parser, section):
|
||||
params[key] = value
|
||||
return authorizer, params
|
||||
|
||||
def get_authorizer_params(self, authorizer=None):
|
||||
"""Return a dictionary of parameter names and values which belong
|
||||
to the configured authorizer (or AUTHORIZER, if provided)."""
|
||||
@@ -371,8 +360,14 @@ class Config:
|
||||
sub_config = getattr(self, authz_section)
|
||||
for attr in dir(sub_config):
|
||||
params[attr] = getattr(sub_config, attr)
|
||||
params['__config'] = self
|
||||
return params
|
||||
|
||||
|
||||
def guesser(self):
|
||||
if not self.__guesser:
|
||||
self.__guesser = ContentMagic(self.options.encodings)
|
||||
return self.__guesser
|
||||
|
||||
def set_defaults(self):
|
||||
"Set some default values in the configuration."
|
||||
|
||||
@@ -390,8 +385,12 @@ class Config:
|
||||
self.utilities.cvsnt = 'cvs'
|
||||
else:
|
||||
self.utilities.cvsnt = None
|
||||
self.utilities.rcsfile_socket = ''
|
||||
self.utilities.svn = ''
|
||||
self.utilities.diff = ''
|
||||
self.utilities.cvsgraph = ''
|
||||
self.utilities.tika_server = ''
|
||||
self.utilities.tika_mime_types = ''
|
||||
|
||||
self.options.root_as_url_component = 1
|
||||
self.options.checkout_magic = 0
|
||||
@@ -441,6 +440,8 @@ class Config:
|
||||
self.options.log_pagesize = 0
|
||||
self.options.log_pagesextra = 3
|
||||
self.options.limit_changes = 100
|
||||
self.options.cvs_ondisk_charset = 'cp1251'
|
||||
self.options.encodings = 'cp1251:iso-8859-1'
|
||||
|
||||
self.templates.diff = None
|
||||
self.templates.directory = None
|
||||
@@ -454,16 +455,33 @@ class Config:
|
||||
self.templates.roots = None
|
||||
|
||||
self.cvsdb.enabled = 0
|
||||
self.cvsdb.index_content = 0
|
||||
self.cvsdb.enable_snippets = 1
|
||||
self.cvsdb.content_max_size = 0
|
||||
self.cvsdb.host = ''
|
||||
self.cvsdb.port = 3306
|
||||
self.cvsdb.socket = ''
|
||||
self.cvsdb.database_name = ''
|
||||
self.cvsdb.user = ''
|
||||
self.cvsdb.passwd = ''
|
||||
self.cvsdb.readonly_user = ''
|
||||
self.cvsdb.readonly_passwd = ''
|
||||
self.cvsdb.readonly_passwd = ''
|
||||
self.cvsdb.row_limit = 1000
|
||||
self.cvsdb.rss_row_limit = 100
|
||||
self.cvsdb.check_database_for_root = 0
|
||||
self.cvsdb.fulltext_min_relevance = 0.2
|
||||
|
||||
self.cvsdb.sphinx_host = ''
|
||||
self.cvsdb.sphinx_port = 3307
|
||||
self.cvsdb.sphinx_socket = ''
|
||||
self.cvsdb.sphinx_index = ''
|
||||
self.cvsdb.sphinx_preformatted_mime = 'text/(?!html|xml).*'
|
||||
self.cvsdb.sphinx_snippet_options = \
|
||||
'around: 15\n'\
|
||||
'limit: 200\n'\
|
||||
'before_match: <span style="color:red">\n'\
|
||||
'after_match: </span>\n'\
|
||||
'chunk_separator: ... \n\n'
|
||||
|
||||
self.query.viewvc_base_url = None
|
||||
|
||||
@@ -490,7 +508,7 @@ class IllegalOverrideSection(ViewVCConfigurationError):
|
||||
def __str__(self):
|
||||
return "malformed configuration: illegal %s override section: %s" \
|
||||
% (self.override_type, self.section_name)
|
||||
|
||||
|
||||
class MalformedRoot(ViewVCConfigurationError):
|
||||
def __init__(self, config_name, value_given):
|
||||
Exception.__init__(self, config_name, value_given)
|
||||
|
804
lib/cvsdb.py
12
lib/dbi.py
@@ -59,5 +59,13 @@ def TicksFromDateTime(datetime):
|
||||
else:
|
||||
return time.mktime(t[:8] + (-1,))
|
||||
|
||||
def connect(host, port, user, passwd, db):
|
||||
return MySQLdb.connect(host=host, port=port, user=user, passwd=passwd, db=db)
|
||||
def connect(host, port, socket, user, passwd, db, charset = 'utf8'):
|
||||
return MySQLdb.connect(
|
||||
host = host,
|
||||
port = port,
|
||||
unix_socket = socket,
|
||||
user = user,
|
||||
passwd = passwd,
|
||||
db = db,
|
||||
charset = charset,
|
||||
use_unicode = charset == 'utf8')
|
||||
|
10
lib/ezt.py
@@ -805,18 +805,26 @@ class UnknownFormatConstantError(EZTException):
|
||||
"""The format specifier is an unknown value."""
|
||||
|
||||
def _raw_formatter(s):
|
||||
try: s = s.encode('utf-8')
|
||||
except: pass
|
||||
return s
|
||||
|
||||
def _html_formatter(s):
|
||||
try: s = s.encode('utf-8')
|
||||
except: pass
|
||||
return cgi.escape(s)
|
||||
|
||||
def _xml_formatter(s):
|
||||
try: s = s.encode('utf-8')
|
||||
except: pass
|
||||
s = s.replace('&', '&')
|
||||
s = s.replace('<', '<')
|
||||
s = s.replace('>', '>')
|
||||
return s
|
||||
|
||||
def _uri_formatter(s):
|
||||
try: s = s.encode('utf-8')
|
||||
except: pass
|
||||
return urllib.quote(s)
|
||||
|
||||
_formatters = {
|
||||
@@ -841,7 +849,7 @@ def test_parse():
|
||||
['', '["a \\"b[foo]" c.d f]', None, '']
|
||||
|
||||
def _test(argv):
|
||||
import doctest, ezt
|
||||
import doctest, ezt
|
||||
verbose = "-v" in argv
|
||||
return doctest.testmod(ezt, verbose=verbose)
|
||||
|
||||
|
283
lib/globalauth.py
Normal file
@@ -0,0 +1,283 @@
|
||||
# -*-python-*-
|
||||
# -----------------------------------------------------------------------
|
||||
# Simple Global Authentication client for ViewVC
|
||||
# License: GPLv2+
|
||||
# Author: Vitaliy Filippov
|
||||
# -----------------------------------------------------------------------
|
||||
#
|
||||
# USAGE:
|
||||
#
|
||||
# import globalauth
|
||||
# c = globalauth.GlobalAuthClient()
|
||||
# c.auth(server)
|
||||
# user_name = c.user_name
|
||||
# user_url = c.user_url
|
||||
#
|
||||
# auth() will call sys.exit() when it needs to stop request processing
|
||||
#
|
||||
# -----------------------------------------------------------------------
|
||||
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import struct
|
||||
import cgi
|
||||
import binascii
|
||||
import time
|
||||
import datetime
|
||||
import urllib
|
||||
import urllib2
|
||||
import anyjson
|
||||
import random
|
||||
import Cookie
|
||||
|
||||
import ga_config
|
||||
|
||||
class FileCache:
|
||||
|
||||
def __init__(self, dir):
|
||||
self.dir = dir
|
||||
if not os.path.isdir(dir):
|
||||
os.mkdir(dir)
|
||||
|
||||
def fn(self, key):
|
||||
key = re.sub('([^a-zA-Z0-9_\-]+)', lambda x: binascii.hexlify(x.group(1)), key)
|
||||
return self.dir+'/'+key
|
||||
|
||||
def clean(self):
|
||||
t = time.time()
|
||||
for fn in os.listdir(self.dir):
|
||||
if t > os.stat(self.dir+'/'+fn).st_mtime:
|
||||
os.unlink(self.dir+'/'+fn)
|
||||
|
||||
def set(self, key, value, expire = 86400):
|
||||
fn = self.fn(key)
|
||||
try:
|
||||
f = open(fn,'w')
|
||||
if not expire:
|
||||
expire = 86400
|
||||
expire = time.time()+expire
|
||||
f.write(value)
|
||||
f.close()
|
||||
os.chmod(fn, 0600)
|
||||
os.utime(fn, (expire, expire))
|
||||
except:
|
||||
raise
|
||||
return 1
|
||||
|
||||
def get(self, key):
|
||||
fn = self.fn(key)
|
||||
try:
|
||||
f = open(fn,'r')
|
||||
value = f.read()
|
||||
f.close()
|
||||
if time.time() > os.stat(fn).st_mtime:
|
||||
os.unlink(fn)
|
||||
return ''
|
||||
return value
|
||||
except:
|
||||
pass
|
||||
return ''
|
||||
|
||||
def delete(self, key):
|
||||
fn = self.fn(key)
|
||||
try:
|
||||
os.unlink(fn)
|
||||
except:
|
||||
pass
|
||||
|
||||
class GlobalAuthClient:
|
||||
|
||||
wd = { 0 : 'Mon', 1 : 'Tue', 2 : 'Wed', 3 : 'Thu', 4 : 'Fri', 5 : 'Sat', 6 : 'Sun' }
|
||||
ms = { 1 : 'Jan', 2 : 'Feb', 3 : 'Mar', 4 : 'Apr', 5 : 'May', 6 : 'Jun', 7 : 'Jul', 8 : 'Aug', 9 : 'Sep', 10 : 'Oct', 11 : 'Nov', 12 : 'Dec' }
|
||||
|
||||
def __init__(self, server):
|
||||
|
||||
self.server = server
|
||||
self.v = {}
|
||||
for name, values in server.params().items():
|
||||
self.v[name] = values[0]
|
||||
fs = server.FieldStorage()
|
||||
for name in fs:
|
||||
self.v[name] = fs[name].value
|
||||
|
||||
self.cookies = Cookie.SimpleCookie()
|
||||
# '' default value is needed here - else we die here under WSGI without any exception O_o
|
||||
self.cookies.load(self.server.getenv('HTTP_COOKIE', ''))
|
||||
self.user_name = ''
|
||||
self.user_url = ''
|
||||
|
||||
if not ga_config.gac.get('globalauth_server', '') and not ga_config.gac.get('fof_sudo_server', ''):
|
||||
raise Exception('ga_config.gac must contain at least globalauth_server="URL" or fof_sudo_server="URL"')
|
||||
|
||||
self.gac = {
|
||||
'cookie_name' : 'simple_global_auth',
|
||||
'cookie_expire' : 86400*7,
|
||||
'cookie_path' : '/',
|
||||
'cookie_domain' : '',
|
||||
'globalauth_server' : '',
|
||||
'cache_dir' : os.path.abspath(os.path.dirname(__file__))+'/cache',
|
||||
'cut_email_at' : 0,
|
||||
'ga_always_require' : 0,
|
||||
'fof_sudo_server' : '',
|
||||
'fof_sudo_cookie' : 'fof_sudo_id',
|
||||
'gc_probability' : 20,
|
||||
}
|
||||
|
||||
for i in self.gac:
|
||||
if ga_config.gac.get(i, None) is not None:
|
||||
self.gac[i] = ga_config.gac[i]
|
||||
|
||||
self.cache = FileCache(self.gac['cache_dir'])
|
||||
|
||||
def auth(self):
|
||||
if self.gac['fof_sudo_server']:
|
||||
self.auth_fof_sudo()
|
||||
if not self.user_name and self.gac['globalauth_server']:
|
||||
self.auth_ga()
|
||||
|
||||
def auth_ga(self):
|
||||
i = random.randint(1, self.gac['gc_probability'])
|
||||
if i == 1:
|
||||
self.cache.clean()
|
||||
r_id = self.cookies.get(self.gac['cookie_name'], '')
|
||||
if r_id:
|
||||
r_id = r_id.value
|
||||
ga_id = self.v.get('ga_id', '')
|
||||
if self.v.get('ga_client', ''):
|
||||
self.ga_client(r_id, ga_id)
|
||||
return
|
||||
r_data = ''
|
||||
if r_id == 'nologin':
|
||||
r_data = 'nologin'
|
||||
elif r_id != '':
|
||||
r_data = self.cache.get('D'+r_id)
|
||||
if r_data != 'nologin':
|
||||
try: r_data = anyjson.deserialize(r_data)
|
||||
except: r_data = ''
|
||||
is_browser = re.match('opera|firefox|chrome|safari', self.server.getenv('HTTP_USER_AGENT'), re.I)
|
||||
if not r_data and (is_browser or self.gac['ga_always_require']) or self.v.get('ga_require', None):
|
||||
self.ga_begin()
|
||||
elif r_data and r_data != 'nologin':
|
||||
self.set_user(r_data)
|
||||
|
||||
def ga_client(self, r_id, ga_id):
|
||||
ga_key = self.v.get('ga_key', '')
|
||||
if ga_key and ga_key == self.cache.get('K'+ga_id):
|
||||
# Server-to-server request
|
||||
self.cache.delete('K'+ga_id)
|
||||
data = ''
|
||||
if self.v.get('ga_nologin','') != '':
|
||||
data = 'nologin'
|
||||
else:
|
||||
try: data = anyjson.deserialize(self.v.get('ga_data',''))
|
||||
except: raise
|
||||
if data != '':
|
||||
if data != 'nologin':
|
||||
data = anyjson.serialize(data)
|
||||
self.cache.set('D'+ga_id, data)
|
||||
self.server.header('text/plain')
|
||||
self.server.write('1')
|
||||
sys.exit()
|
||||
elif ga_key == '' and r_id != ga_id:
|
||||
# User redirect with different key
|
||||
d = self.cache.get('D'+ga_id)
|
||||
if d != 'nologin' and d != '':
|
||||
try: d = anyjson.deserialize(d)
|
||||
except: d = ''
|
||||
if d != '':
|
||||
self.setcookie(ga_id)
|
||||
self.redirect(self.clean_uri())
|
||||
self.server.header('text/plain', status=404)
|
||||
self.server.write('GlobalAuth key doesn\'t match')
|
||||
sys.exit()
|
||||
|
||||
def ga_begin(self):
|
||||
ga_id = binascii.hexlify(os.urandom(16))
|
||||
ga_key = binascii.hexlify(os.urandom(16))
|
||||
url = self.add_param(self.gac['globalauth_server'], '')
|
||||
try:
|
||||
resp = urllib2.urlopen(url+'ga_id='+urllib2.quote(ga_id)+'&ga_key='+urllib2.quote(ga_key))
|
||||
resp.read()
|
||||
if resp.code != 200:
|
||||
raise Exception(resp)
|
||||
except:
|
||||
self.setcookie('nologin')
|
||||
self.redirect(self.clean_uri())
|
||||
return_uri = 'http://'+self.server.getenv('HTTP_HOST')+self.server.getenv('REQUEST_URI')
|
||||
return_uri = self.add_param(return_uri, 'ga_client=1')
|
||||
self.cache.set('K'+ga_id, ga_key)
|
||||
url = url+'ga_id='+urllib2.quote(ga_id)+'&ga_url='+urllib2.quote(return_uri)
|
||||
if self.v.get('ga_require', '') == '' and not self.gac['ga_always_require']:
|
||||
url = url+'&ga_check=1'
|
||||
self.redirect(url)
|
||||
|
||||
def add_param(self, url, param):
|
||||
if url.find('?') != -1:
|
||||
url = url+'&'
|
||||
else:
|
||||
url = url+'?'
|
||||
return url+param
|
||||
|
||||
def auth_fof_sudo(self):
|
||||
sudo_id = self.cookies.get(self.gac['fof_sudo_cookie'], '')
|
||||
if sudo_id:
|
||||
sudo_id = sudo_id.value
|
||||
if sudo_id != '':
|
||||
url = self.gac['fof_sudo_server']
|
||||
if url.find('?') != -1:
|
||||
url = url+'&'
|
||||
else:
|
||||
url = url+'?'
|
||||
try:
|
||||
resp = urllib2.urlopen(url+'id='+urllib2.quote(sudo_id))
|
||||
d = resp.read()
|
||||
if resp.code != 200:
|
||||
raise Exception(resp)
|
||||
d = anyjson.deserialize(d)
|
||||
self.set_user(d)
|
||||
except:
|
||||
pass
|
||||
|
||||
def log(self, s):
|
||||
sys.stderr.write(s+"\n")
|
||||
sys.stderr.flush()
|
||||
|
||||
def redirect(self, url):
|
||||
self.server.addheader('Location', url)
|
||||
self.server.header(status='302 Moved Temporarily')
|
||||
self.server.write('This document is located <a href="%s">here</a>.' % url)
|
||||
sys.exit()
|
||||
|
||||
def setcookie(self, value):
|
||||
dom = self.gac['cookie_domain']
|
||||
if not dom:
|
||||
dom = self.server.getenv('HTTP_HOST')
|
||||
exp = ''
|
||||
if self.gac['cookie_expire'] > 0:
|
||||
tm = int(time.time()+self.gac['cookie_expire'])
|
||||
tm = datetime.datetime.utcfromtimestamp(tm)
|
||||
tm = "%s, %02d-%s-%04d %02d:%02d:%02d GMT" % (self.wd[tm.weekday()], tm.day, self.ms[tm.month], tm.year, tm.hour, tm.minute, tm.second)
|
||||
exp = '; expires='+tm
|
||||
self.server.addheader('Set-Cookie', "%s=%s; path=%s; domain=%s%s" % (self.gac['cookie_name'], value, self.gac['cookie_path'], dom, exp))
|
||||
|
||||
def clean_uri(self):
|
||||
uriargs = self.v.copy()
|
||||
for i in [ 'ga_id', 'ga_res', 'ga_key', 'ga_client', 'ga_nologin', 'ga_require' ]:
|
||||
uriargs.pop(i, None)
|
||||
uri = self.server.getenv('REQUEST_URI')
|
||||
p = uri.find('?')
|
||||
if p != -1:
|
||||
uri = uri[0:p]
|
||||
uri = 'http://'+self.server.getenv('HTTP_HOST')+uri+'?'+urllib.urlencode(uriargs)
|
||||
return uri
|
||||
|
||||
def set_user(self, r_data):
|
||||
r_email = r_data.get('user_email', '').encode('utf-8')
|
||||
r_url = r_data.get('user_url', '').encode('utf-8')
|
||||
if self.gac['cut_email_at']:
|
||||
p = r_email.find('@')
|
||||
if p != -1:
|
||||
r_email = r_email[0:p]
|
||||
self.user_name = r_email
|
||||
self.user_url = r_url
|
154
lib/pygments/lexers/sp4.py
Executable file
@@ -0,0 +1,154 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
pygments.lexers.sp4
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Lexer for CustIS m4-preprocessed PL/SQL.
|
||||
|
||||
:copyright: 2009+ by Vitaliy Filippov <vitalif@mail.ru>.
|
||||
:license: BSD, see LICENSE for more details.
|
||||
,
|
||||
'Sp4Lexer': ('pygments.lexers.sp4', 'SP4', ('sp4',), ('*.sp4'), ('text/x-sp4',))
|
||||
"""
|
||||
|
||||
import re
|
||||
|
||||
from pygments.lexer import Lexer, RegexLexer, include, bygroups, using, this, \
|
||||
do_insertions
|
||||
from pygments.token import Error, Punctuation, \
|
||||
Text, Comment, Operator, Keyword, Name, String, Number, Generic
|
||||
from pygments.util import shebang_matches
|
||||
|
||||
|
||||
__all__ = ['Sp4Lexer']
|
||||
|
||||
line_re = re.compile('.*?\n')
|
||||
|
||||
|
||||
class Sp4Lexer(RegexLexer):
|
||||
name = 'SP4'
|
||||
aliases = ['sp4']
|
||||
filenames = ['*.sp4']
|
||||
mimetypes = ['text/x-sp4']
|
||||
|
||||
flags = re.IGNORECASE
|
||||
tokens = {
|
||||
'root': [
|
||||
(r'\s+', Text),
|
||||
(r'--.*?\n', Comment.Single),
|
||||
(r'/\*', Comment.Multiline, 'multiline-comments'),
|
||||
(r'(ABORT|ABS|ABSOLUTE|ACCESS|ADA|ADD|ADMIN|AFTER|AGGREGATE|'
|
||||
r'ALIAS|ALL|ALLOCATE|ALTER|ANALYSE|ANALYZE|AND|ANY|ARE|AS|'
|
||||
r'ASC|ASENSITIVE|ASSERTION|ASSIGNMENT|ASYMMETRIC|AT|ATOMIC|'
|
||||
r'AUTHORIZATION|AVG|BACKWARD|BEFORE|BEGIN|BETWEEN|BITVAR|'
|
||||
r'BIT_LENGTH|BOTH|BREADTH|BY|C|CACHE|CALL|CALLED|CARDINALITY|'
|
||||
r'CASCADE|CASCADED|CASE|CAST|CATALOG|CATALOG_NAME|CHAIN|'
|
||||
r'CHARACTERISTICS|CHARACTER_LENGTH|CHARACTER_SET_CATALOG|'
|
||||
r'CHARACTER_SET_NAME|CHARACTER_SET_SCHEMA|CHAR_LENGTH|CHECK|'
|
||||
r'CHECKED|CHECKPOINT|CLASS|CLASS_ORIGIN|CLOB|CLOSE|CLUSTER|'
|
||||
r'COALSECE|COBOL|COLLATE|COLLATION|COLLATION_CATALOG|'
|
||||
r'COLLATION_NAME|COLLATION_SCHEMA|COLUMN|COLUMN_NAME|'
|
||||
r'COMMAND_FUNCTION|COMMAND_FUNCTION_CODE|COMMENT|COMMIT|'
|
||||
r'COMMITTED|COMPLETION|CONDITION_NUMBER|CONNECT|CONNECTION|'
|
||||
r'CONNECTION_NAME|CONSTRAINT|CONSTRAINTS|CONSTRAINT_CATALOG|'
|
||||
r'CONSTRAINT_NAME|CONSTRAINT_SCHEMA|CONSTRUCTOR|CONTAINS|'
|
||||
r'CONTINUE|CONVERSION|CONVERT|COPY|CORRESPONTING|COUNT|'
|
||||
r'CREATE|CREATEDB|CREATEUSER|CROSS|CUBE|CURRENT|CURRENT_DATE|'
|
||||
r'CURRENT_PATH|CURRENT_ROLE|CURRENT_TIME|CURRENT_TIMESTAMP|'
|
||||
r'CURRENT_USER|CURSOR|CURSOR_NAME|CYCLE|DATA|DATABASE|'
|
||||
r'DATETIME_INTERVAL_CODE|DATETIME_INTERVAL_PRECISION|DAY|'
|
||||
r'DEALLOCATE|DECLARE|DEFAULT|DEFAULTS|DEFERRABLE|DEFERRED|'
|
||||
r'DEFINED|DEFINER|DELETE|DELIMITER|DELIMITERS|DEREF|DESC|'
|
||||
r'DESCRIBE|DESCRIPTOR|DESTROY|DESTRUCTOR|DETERMINISTIC|'
|
||||
r'DIAGNOSTICS|DICTIONARY|DISCONNECT|DISPATCH|DISTINCT|DO|'
|
||||
r'DOMAIN|DROP|DYNAMIC|DYNAMIC_FUNCTION|DYNAMIC_FUNCTION_CODE|'
|
||||
r'EACH|ELSE|ENCODING|ENCRYPTED|END|END-EXEC|EQUALS|ESCAPE|EVERY|'
|
||||
r'EXCEPT|ESCEPTION|EXCLUDING|EXCLUSIVE|EXEC|EXECUTE|EXISTING|'
|
||||
r'EXISTS|EXPLAIN|EXTERNAL|EXTRACT|FALSE|FETCH|FINAL|FIRST|FOR|'
|
||||
r'FORCE|FOREIGN|FORTRAN|FORWARD|FOUND|FREE|FREEZE|FROM|FULL|'
|
||||
r'FUNCTION|G|GENERAL|GENERATED|GET|GLOBAL|GO|GOTO|GRANT|GRANTED|'
|
||||
r'GROUP|GROUPING|HANDLER|HAVING|HIERARCHY|HOLD|HOST|IDENTITY|'
|
||||
r'IGNORE|ILIKE|IMMEDIATE|IMMUTABLE|IMPLEMENTATION|IMPLICIT|IN|'
|
||||
r'INCLUDING|INCREMENT|INDEX|INDITCATOR|INFIX|INHERITS|INITIALIZE|'
|
||||
r'INITIALLY|INNER|INOUT|INPUT|INSENSITIVE|INSERT|INSTANTIABLE|'
|
||||
r'INSTEAD|INTERSECT|INTO|INVOKER|IS|ISNULL|ISOLATION|ITERATE|JOIN|'
|
||||
r'K|KEY|KEY_MEMBER|KEY_TYPE|LANCOMPILER|LANGUAGE|LARGE|LAST|'
|
||||
r'LATERAL|LEADING|LEFT|LENGTH|LESS|LEVEL|LIKE|LILMIT|LISTEN|LOAD|'
|
||||
r'LOCAL|LOCALTIME|LOCALTIMESTAMP|LOCATION|LOCATOR|LOCK|LOWER|M|'
|
||||
r'MAP|MATCH|MAX|MAXVALUE|MESSAGE_LENGTH|MESSAGE_OCTET_LENGTH|'
|
||||
r'MESSAGE_TEXT|METHOD|MIN|MINUTE|MINVALUE|MOD|MODE|MODIFIES|'
|
||||
r'MODIFY|MONTH|MORE|MOVE|MUMPS|NAMES|NATIONAL|NATURAL|NCHAR|'
|
||||
r'NCLOB|NEW|NEXT|NO|NOCREATEDB|NOCREATEUSER|NONE|NOT|NOTHING|'
|
||||
r'NOTIFY|NOTNULL|NULL|NULLABLE|NULLIF|OBJECT|OCTET_LENGTH|OF|OFF|'
|
||||
r'OFFSET|OIDS|OLD|ON|ONLY|OPEN|OPERATION|OPERATOR|OPTION|OPTIONS|'
|
||||
r'OR|ORDER|ORDINALITY|OUT|OUTER|OUTPUT|OVERLAPS|OVERLAY|OVERRIDING|'
|
||||
r'OWNER|PAD|PARAMETER|PARAMETERS|PARAMETER_MODE|PARAMATER_NAME|'
|
||||
r'PARAMATER_ORDINAL_POSITION|PARAMETER_SPECIFIC_CATALOG|'
|
||||
r'PARAMETER_SPECIFIC_NAME|PARAMATER_SPECIFIC_SCHEMA|PARTIAL|'
|
||||
r'PASCAL|PENDANT|PLACING|PLI|POSITION|POSTFIX|PRECISION|PREFIX|'
|
||||
r'PREORDER|PREPARE|PRESERVE|PRIMARY|PRIOR|PRIVILEGES|PROCEDURAL|'
|
||||
r'PROCEDURE|PUBLIC|READ|READS|RECHECK|RECURSIVE|REF|REFERENCES|'
|
||||
r'REFERENCING|REINDEX|RELATIVE|RENAME|REPEATABLE|REPLACE|RESET|'
|
||||
r'RESTART|RESTRICT|RESULT|RETURN|RETURNED_LENGTH|'
|
||||
r'RETURNED_OCTET_LENGTH|RETURNED_SQLSTATE|RETURNS|REVOKE|RIGHT|'
|
||||
r'ROLE|ROLLBACK|ROLLUP|ROUTINE|ROUTINE_CATALOG|ROUTINE_NAME|'
|
||||
r'ROUTINE_SCHEMA|ROW|ROWS|ROW_COUNT|RULE|SAVE_POINT|SCALE|SCHEMA|'
|
||||
r'SCHEMA_NAME|SCOPE|SCROLL|SEARCH|SECOND|SECURITY|SELECT|SELF|'
|
||||
r'SENSITIVE|SERIALIZABLE|SERVER_NAME|SESSION|SESSION_USER|SET|'
|
||||
r'SETOF|SETS|SHARE|SHOW|SIMILAR|SIMPLE|SIZE|SOME|SOURCE|SPACE|'
|
||||
r'SPECIFIC|SPECIFICTYPE|SPECIFIC_NAME|SQL|SQLCODE|SQLERROR|'
|
||||
r'SQLEXCEPTION|SQLSTATE|SQLWARNINIG|STABLE|START|STATE|STATEMENT|'
|
||||
r'STATIC|STATISTICS|STDIN|STDOUT|STORAGE|STRICT|STRUCTURE|STYPE|'
|
||||
r'SUBCLASS_ORIGIN|SUBLIST|SUBSTRING|SUM|SYMMETRIC|SYSID|SYSTEM|'
|
||||
r'SYSTEM_USER|TABLE|TABLE_NAME| TEMP|TEMPLATE|TEMPORARY|TERMINATE|'
|
||||
r'THAN|THEN|TIMESTAMP|TIMEZONE_HOUR|TIMEZONE_MINUTE|TO|TOAST|'
|
||||
r'TRAILING|TRANSATION|TRANSACTIONS_COMMITTED|'
|
||||
r'TRANSACTIONS_ROLLED_BACK|TRANSATION_ACTIVE|TRANSFORM|'
|
||||
r'TRANSFORMS|TRANSLATE|TRANSLATION|TREAT|TRIGGER|TRIGGER_CATALOG|'
|
||||
r'TRIGGER_NAME|TRIGGER_SCHEMA|TRIM|TRUE|TRUNCATE|TRUSTED|TYPE|'
|
||||
r'UNCOMMITTED|UNDER|UNENCRYPTED|UNION|UNIQUE|UNKNOWN|UNLISTEN|'
|
||||
r'UNNAMED|UNNEST|UNTIL|UPDATE|UPPER|USAGE|USER|'
|
||||
r'USER_DEFINED_TYPE_CATALOG|USER_DEFINED_TYPE_NAME|'
|
||||
r'USER_DEFINED_TYPE_SCHEMA|USING|VACUUM|VALID|VALIDATOR|VALUES|'
|
||||
r'VARIABLE|VERBOSE|VERSION|VIEW|VOLATILE|WHEN|WHENEVER|WHERE|'
|
||||
r'WITH|WITHOUT|WORK|WRITE|YEAR|ZONE|BINARY_INTEGER|BODY|BREAK|'
|
||||
r'CONSTANT|DEFINITION|DELETING|DLOB|DUMMY|ELSIF|ERRLVL|ERROR|'
|
||||
r'EXCEPTION|EXIT|IF|INSERTING|ISOPEN|LOOP|NO_DATA_FOUND|NOTFOUND|'
|
||||
r'OTHERS|PACKAGE|PRAGMA|RAISE|RECORD|RESTRICT_REFERENCES|RETURNING|'
|
||||
r'RNDS|RNPS|ROWCOUNT|ROWNUM|ROWTYPE|SAVEPOINT|SQLERRM|TOO_MANY_ROWS|'
|
||||
r'UPDATING|WHILE|WNDS|WNPS|BULK|CHR|COLLECT|GREATEST|INSTR|LEAST|'
|
||||
r'LENGTHB|NOCOPY|NOWAIT|NVL|RPAD|SUBST|SUBSTB|SUBSTR|SYSDATE|'
|
||||
r'TABLESPACE|TO_CHAR|TO_DATE|TO_NUMBER|TRUNC)\b', Keyword),
|
||||
(r'(ARRAY|BIGINT|BINARY|BIT|BLOB|BOOLEAN|CHAR|CHARACTER|DATE|'
|
||||
r'DEC|DECIMAL|FLOAT|INT|INTEGER|INTERVAL|NUMBER|NUMERIC|REAL|'
|
||||
r'SERIAL|SMALLINT|VARCHAR|VARCHAR2|VARYING|INT8|SERIAL8|TEXT)\b',
|
||||
Name.Builtin),
|
||||
(r'(_5date_args|_actual_area|_ASSERT|_doc_code|_doc_var|_doc_var_list|'
|
||||
r'_enforce|_ent|_enum|_enums_define|_enums_member_define|_field|'
|
||||
r'_fields|_first|_FMT|_in_list|_index|_index_unique|_indexes'
|
||||
r'_MAX_STRLEN|_MID_STRLEN|_param|_package|_pk|_plsql_param|_plsql_return|'
|
||||
r'_private_function|_private_procedure|_private_type|_private_var|'
|
||||
r'_protected_function|_protected_procedure|_protected_type|_protected_var|'
|
||||
r'_public_function|_public_procedure|_public_type|_public_var|_quote|_RAISE|'
|
||||
r'_RAISEW|_reference|_references|_request_arg|_request_define|'
|
||||
r'_request_res|_STR_CONST|_substr|_table|_tail|builtin|cdr|changecom|'
|
||||
r'changequote|changeword|debugfile|decr|define|divert|dummy_list|dumpdef|'
|
||||
r'errprint|eval|foreach|forloop|GetNth|ifelse|include|incr|index|indir|'
|
||||
r'len|lowcase|maketemp|Nth|patsubst|popdef|pushdef|regexp|'
|
||||
r'remove_prefix|shift|sinclude|Size|syscmd|TRACE|traceoff|traceon|'
|
||||
r'translit|undefine|undivert|upcase)\b',
|
||||
Name.Function),
|
||||
(r'[+*/<>=~!@#%^&|`?^-]', Operator),
|
||||
(r'[0-9]+', Number.Integer),
|
||||
(r"'(''|[^'\\]|\\\'|\\\\)*'", String.Single),
|
||||
(r'"(""|[^"\\]|\\\"|\\\\)*"', String.Symbol),
|
||||
(r'[a-zA-Z_][a-zA-Z0-9_]*', Name),
|
||||
(r'[;:()\[\],\.]', Punctuation)
|
||||
],
|
||||
'multiline-comments': [
|
||||
(r'/\*', Comment.Multiline, 'multiline-comments'),
|
||||
(r'\*/', Comment.Multiline, '#pop'),
|
||||
(r'[^/\*]+', Comment.Multiline),
|
||||
(r'[/*]', Comment.Multiline)
|
||||
]
|
||||
}
|
38
lib/query.py
@@ -41,12 +41,22 @@ class FormData:
|
||||
self.file = ""
|
||||
self.who = ""
|
||||
self.sortby = ""
|
||||
self.textquery = ""
|
||||
self.date = ""
|
||||
self.hours = 0
|
||||
|
||||
self.decode_thyself(form)
|
||||
|
||||
def decode_thyself(self, form):
|
||||
try:
|
||||
self.textquery = string.strip(form["textquery"].value)
|
||||
except KeyError:
|
||||
pass
|
||||
except TypeError:
|
||||
pass
|
||||
else:
|
||||
self.valid = 1
|
||||
|
||||
try:
|
||||
self.repository = form["repository"].value.strip()
|
||||
except KeyError:
|
||||
@@ -247,10 +257,15 @@ def form_to_cvsdb_query(cfg, form_data):
|
||||
cmd = decode_command(cmd)
|
||||
query.SetAuthor(str, cmd)
|
||||
|
||||
if form_data.textquery:
|
||||
query.SetTextQuery(form_data.textquery)
|
||||
|
||||
if form_data.sortby == "author":
|
||||
query.SetSortMethod("author")
|
||||
elif form_data.sortby == "file":
|
||||
query.SetSortMethod("file")
|
||||
elif form_data.sortby == "relevance" and form_data.textquery:
|
||||
query.SetSortMethod("relevance")
|
||||
else:
|
||||
query.SetSortMethod("date")
|
||||
|
||||
@@ -285,11 +300,10 @@ def is_forbidden(cfg, cvsroot_name, module):
|
||||
# the base and per-vhost configuration for authorizer and
|
||||
# authorizer parameters.
|
||||
if cvsroot_name:
|
||||
authorizer, params = cfg.get_authorizer_and_params_hack(cvsroot_name)
|
||||
else:
|
||||
authorizer = cfg.options.authorizer
|
||||
params = cfg.get_authorizer_params()
|
||||
|
||||
cfg = cfg.get_root_config(cvsroot_name)
|
||||
authorizer = cfg.options.authorizer
|
||||
params = cfg.get_authorizer_params()
|
||||
|
||||
# If CVSROOT_NAME isn't configured to use an authorizer, nothing
|
||||
# is forbidden. If it's configured to use something other than
|
||||
# the 'forbidden' authorizer, complain. Otherwise, check for
|
||||
@@ -314,7 +328,7 @@ def is_forbidden(cfg, cvsroot_name, module):
|
||||
|
||||
def build_commit(server, cfg, desc, files, cvsroots, viewvc_link):
|
||||
ob = _item(num_files=len(files), files=[])
|
||||
ob.log = desc and server.escape(desc).replace('\n', '<br />') or ''
|
||||
ob.log = desc and server.escape(desc).replace('\n', '<br />') or ' '
|
||||
|
||||
for commit in files:
|
||||
repository = commit.GetRepository()
|
||||
@@ -365,6 +379,9 @@ def build_commit(server, cfg, desc, files, cvsroots, viewvc_link):
|
||||
flink = '[%s] %s' % (repository, file)
|
||||
dlink = None
|
||||
|
||||
ob.relevance = commit.GetRelevance()
|
||||
ob.plus += int(commit.GetPlusCount())
|
||||
ob.minus += int(commit.GetMinusCount())
|
||||
ob.files.append(_item(date=ctime,
|
||||
author=commit.GetAuthor(),
|
||||
link=flink,
|
||||
@@ -378,9 +395,8 @@ def build_commit(server, cfg, desc, files, cvsroots, viewvc_link):
|
||||
|
||||
return ob
|
||||
|
||||
def run_query(server, cfg, form_data, viewvc_link):
|
||||
def run_query(server, cfg, db, form_data, viewvc_link):
|
||||
query = form_to_cvsdb_query(cfg, form_data)
|
||||
db = cvsdb.ConnectDatabaseReadOnly(cfg)
|
||||
db.RunQuery(query)
|
||||
|
||||
commit_list = query.GetCommitList()
|
||||
@@ -430,9 +446,9 @@ def main(server, cfg, viewvc_link):
|
||||
form = server.FieldStorage()
|
||||
form_data = FormData(form)
|
||||
|
||||
db = cvsdb.ConnectDatabaseReadOnly(cfg, None)
|
||||
if form_data.valid:
|
||||
commits, row_limit_reached = run_query(server, cfg,
|
||||
form_data, viewvc_link)
|
||||
commits, row_limit_reached = run_query(server, cfg, db, form_data, viewvc_link)
|
||||
query = None
|
||||
else:
|
||||
commits = [ ]
|
||||
@@ -447,6 +463,7 @@ def main(server, cfg, viewvc_link):
|
||||
'cfg' : cfg,
|
||||
'address' : cfg.general.address,
|
||||
'vsn' : viewvc.__version__,
|
||||
'textquery' : server.escape(form_data.textquery),
|
||||
'repository' : server.escape(form_data.repository),
|
||||
'branch' : server.escape(form_data.branch),
|
||||
'directory' : server.escape(form_data.directory),
|
||||
@@ -460,6 +477,7 @@ def main(server, cfg, viewvc_link):
|
||||
'commits' : commits,
|
||||
'num_commits' : len(commits),
|
||||
'rss_href' : None,
|
||||
'repositories' : db.GetRepositoryList(),
|
||||
'hours' : form_data.hours and form_data.hours or 2,
|
||||
})
|
||||
|
||||
|
@@ -32,6 +32,8 @@ server = None
|
||||
# that character as-is, and sometimes needs to embed escaped values
|
||||
# into HTML attributes.
|
||||
def escape(s):
|
||||
try: s = s.encode('utf8')
|
||||
except: pass
|
||||
s = str(s)
|
||||
s = s.replace('&', '&')
|
||||
s = s.replace('>', '>')
|
||||
|
@@ -41,7 +41,7 @@ class GenericViewVCAuthorizer:
|
||||
pass
|
||||
|
||||
|
||||
|
||||
|
||||
##############################################################################
|
||||
|
||||
class ViewVCAuthorizer(GenericViewVCAuthorizer):
|
||||
|
92
lib/vcauth/cvsntacl/__init__.py
Normal file
@@ -0,0 +1,92 @@
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 2009 Vitaliy Filippov.
|
||||
#
|
||||
# By using this file, you agree to the terms and conditions set forth in
|
||||
# the LICENSE.html file which can be found at the top level of the ViewVC
|
||||
# distribution or at http://viewvc.org/license-1.html.
|
||||
#
|
||||
# For more information, visit http://viewvc.org/
|
||||
#
|
||||
# -----------------------------------------------------------------------
|
||||
|
||||
import vcauth
|
||||
import vclib
|
||||
import string
|
||||
from xml.dom.minidom import parse
|
||||
|
||||
class ViewVCAuthorizer(vcauth.GenericViewVCAuthorizer):
|
||||
"""An authorizer which uses CVSnt access control lists (which are in form
|
||||
of XML files in CVS/ subdirectories in the repository)."""
|
||||
|
||||
def __init__(self, username, params={}):
|
||||
self.username = username
|
||||
self.params = params
|
||||
self.cfg = params['__config']
|
||||
self.default = params.get('default', 0)
|
||||
self.cached = {}
|
||||
self.xmlcache = {}
|
||||
|
||||
def dom_rights(self, doc, rightname, filename, username):
|
||||
result = None
|
||||
if filename:
|
||||
for node in doc.getElementsByTagName('file'):
|
||||
if node.getAttribute('name') == filename:
|
||||
for acl in node.getElementsByTagName('acl'):
|
||||
if not acl.getAttribute('branch'):
|
||||
u = acl.getAttribute('user')
|
||||
if result is None and (not u or u == 'anonymous') or u == username:
|
||||
for r in acl.getElementsByTag(rightname):
|
||||
result = not r.getAttribute('deny')
|
||||
break
|
||||
if result is None:
|
||||
for node in doc.getElementsByTagName('directory'):
|
||||
for acl in node.getElementsByTagName('acl'):
|
||||
if not acl.getAttribute('branch'):
|
||||
u = acl.getAttribute('user')
|
||||
if result is None and (not u or u == 'anonymous') or u == username:
|
||||
for r in acl.getElementsByTag(rightname):
|
||||
result = not r.getAttribute('deny')
|
||||
return result
|
||||
|
||||
def check(self, rootname, path_parts, filename):
|
||||
d = self.cfg.general.cvs_roots.get(rootname,None)
|
||||
if not d:
|
||||
return self.default
|
||||
i = len(path_parts)
|
||||
r = None
|
||||
while i >= 0:
|
||||
try:
|
||||
xml = d
|
||||
if len(path_parts):
|
||||
xml = xml + '/' + string.join(path_parts, '/')
|
||||
xml = xml + '/CVS/fileattr.xml'
|
||||
if self.cached.get(xml, None) is not None:
|
||||
return self.cached.get(xml, None)
|
||||
doc = self.xmlcache.get(xml, None)
|
||||
if doc is None:
|
||||
doc = parse(xml)
|
||||
self.xmlcache[xml] = doc
|
||||
r = self.dom_rights(doc, 'read', filename, self.username)
|
||||
if r is not None:
|
||||
self.cached[xml] = r
|
||||
return r
|
||||
raise Exception(None)
|
||||
except:
|
||||
if len(path_parts) > 0:
|
||||
path_parts = path_parts[:-1]
|
||||
filename = ''
|
||||
i = i-1
|
||||
return self.default
|
||||
|
||||
def check_root_access(self, rootname):
|
||||
return self.check(rootname, [], '')
|
||||
|
||||
def check_path_access(self, rootname, path_parts, pathtype, rev=None):
|
||||
if not path_parts:
|
||||
return self.check(rootname, [], '')
|
||||
if pathtype == vclib.DIR:
|
||||
return self.check(rootname, path_parts, '')
|
||||
f = path_parts[-1]
|
||||
path_parts = path_parts[:-1]
|
||||
return self.check(rootname, path_parts, f)
|
62
lib/vcauth/grp/__init__.py
Normal file
@@ -0,0 +1,62 @@
|
||||
# -*-python-*-
|
||||
#
|
||||
# Copyright (C) 2009 Vitaliy Filippov.
|
||||
#
|
||||
# By using this file, you agree to the terms and conditions set forth in
|
||||
# the LICENSE.html file which can be found at the top level of the ViewVC
|
||||
# distribution or at http://viewvc.org/license-1.html.
|
||||
#
|
||||
# For more information, visit http://viewvc.org/
|
||||
#
|
||||
# -----------------------------------------------------------------------
|
||||
|
||||
import vcauth
|
||||
import vclib
|
||||
import string
|
||||
import grp
|
||||
import re
|
||||
|
||||
class ViewVCAuthorizer(vcauth.GenericViewVCAuthorizer):
|
||||
"""A simple authorizer checking system group membership for every
|
||||
repository and every user."""
|
||||
|
||||
def __init__(self, username, params={}):
|
||||
self.username = username
|
||||
self.params = params
|
||||
self.cfg = params['__config']
|
||||
self.cached = {}
|
||||
self.grp = {}
|
||||
self.byroot = {}
|
||||
self.fmt = map(lambda l: l.strip(), params.get('group_name_format', 'svn.%s|svn.%s.ro').split('|'))
|
||||
byr = params.get('by_root', '')
|
||||
for i in byr.split(','):
|
||||
if i.find(':') < 0:
|
||||
continue
|
||||
(root, auth) = i.split(':', 2)
|
||||
self.byroot[root.strip()] = map(lambda l: l.strip(), auth.split('|'))
|
||||
|
||||
def check_root_access(self, rootname):
|
||||
r = self.cached.get(rootname, None)
|
||||
if r is not None:
|
||||
return r
|
||||
grent = self.grp.get(rootname, None)
|
||||
if grent is None:
|
||||
grent = map(lambda grn: self.getgrnam(grn, rootname), self.byroot.get(rootname, self.fmt))
|
||||
self.grp[rootname] = grent
|
||||
r = 0
|
||||
for i in grent:
|
||||
if i and i.gr_mem and len(i.gr_mem) and self.username in i.gr_mem:
|
||||
r = 1
|
||||
break
|
||||
self.cached[rootname] = r
|
||||
return r
|
||||
|
||||
def getgrnam(self, grn, rootname):
|
||||
try:
|
||||
r = grp.getgrnam(grn.replace('%s', re.sub('[^\w\.\-]+', '', rootname)))
|
||||
except KeyError:
|
||||
r = None
|
||||
return r
|
||||
|
||||
def check_path_access(self, rootname, path_parts, pathtype, rev=None):
|
||||
return self.check_root_access(rootname)
|
@@ -342,7 +342,7 @@ class NonTextualFileContents(Error):
|
||||
# ======================================================================
|
||||
# Implementation code used by multiple vclib modules
|
||||
|
||||
import popen
|
||||
import tempfile
|
||||
import os
|
||||
import time
|
||||
|
||||
@@ -352,7 +352,7 @@ def _diff_args(type, options):
|
||||
if type == CONTEXT:
|
||||
if options.has_key('context'):
|
||||
if options['context'] is None:
|
||||
args.append('--context=-1')
|
||||
args.append('--context=%i' % 0x01ffffff)
|
||||
else:
|
||||
args.append('--context=%i' % options['context'])
|
||||
else:
|
||||
@@ -360,7 +360,7 @@ def _diff_args(type, options):
|
||||
elif type == UNIFIED:
|
||||
if options.has_key('context'):
|
||||
if options['context'] is None:
|
||||
args.append('--unified=-1')
|
||||
args.append('--unified=%i' % 0x01ffffff)
|
||||
else:
|
||||
args.append('--unified=%i' % options['context'])
|
||||
else:
|
||||
@@ -386,11 +386,15 @@ class _diff_fp:
|
||||
def __init__(self, temp1, temp2, info1=None, info2=None, diff_cmd='diff', diff_opts=[]):
|
||||
self.temp1 = temp1
|
||||
self.temp2 = temp2
|
||||
self.temp3 = tempfile.mktemp()
|
||||
args = diff_opts[:]
|
||||
if info1 and info2:
|
||||
args.extend(["-L", self._label(info1), "-L", self._label(info2)])
|
||||
args.extend([temp1, temp2])
|
||||
self.fp = popen.popen(diff_cmd, args, "r")
|
||||
args.insert(0, diff_cmd)
|
||||
os.system("'"+"' '".join(args)+"' > '"+self.temp3+"' 2> '"+self.temp3+"'")
|
||||
self.fp = open(self.temp3, 'rb')
|
||||
self.fp.seek(0)
|
||||
|
||||
def read(self, bytes):
|
||||
return self.fp.read(bytes)
|
||||
@@ -398,6 +402,9 @@ class _diff_fp:
|
||||
def readline(self):
|
||||
return self.fp.readline()
|
||||
|
||||
def readlines(self):
|
||||
return self.fp.readlines()
|
||||
|
||||
def close(self):
|
||||
try:
|
||||
if self.fp:
|
||||
@@ -405,13 +412,17 @@ class _diff_fp:
|
||||
self.fp = None
|
||||
finally:
|
||||
try:
|
||||
if self.temp1:
|
||||
if self.temp1 and self.temp1 != '/dev/null':
|
||||
os.remove(self.temp1)
|
||||
self.temp1 = None
|
||||
self.temp1 = None
|
||||
finally:
|
||||
if self.temp2:
|
||||
if self.temp2 and self.temp2 != '/dev/null':
|
||||
os.remove(self.temp2)
|
||||
self.temp2 = None
|
||||
self.temp2 = None
|
||||
try:
|
||||
os.remove(self.temp3)
|
||||
finally:
|
||||
self.temp3 = None
|
||||
|
||||
def __del__(self):
|
||||
self.close()
|
||||
@@ -429,7 +440,7 @@ def check_root_access(repos):
|
||||
if not auth:
|
||||
return 1
|
||||
return auth.check_root_access(repos.rootname())
|
||||
|
||||
|
||||
def check_path_access(repos, path_parts, pathtype=None, rev=None):
|
||||
"""Return 1 iff the associated username is permitted to read
|
||||
revision REV of the path PATH_PARTS (of type PATHTYPE) in repository
|
||||
@@ -440,5 +451,7 @@ def check_path_access(repos, path_parts, pathtype=None, rev=None):
|
||||
return 1
|
||||
if not pathtype:
|
||||
pathtype = repos.itemtype(path_parts, rev)
|
||||
if not path_parts:
|
||||
return auth.check_root_access(repos.rootname())
|
||||
return auth.check_path_access(repos.rootname(), path_parts, pathtype, rev)
|
||||
|
||||
|
@@ -57,11 +57,11 @@ def find_root_in_parent(parent_path, rootname):
|
||||
return None
|
||||
|
||||
|
||||
def CVSRepository(name, rootpath, authorizer, utilities, use_rcsparse):
|
||||
def CVSRepository(name, rootpath, authorizer, utilities, use_rcsparse, charset_guesser = None):
|
||||
rootpath = canonicalize_rootpath(rootpath)
|
||||
if use_rcsparse:
|
||||
import ccvs
|
||||
return ccvs.CCVSRepository(name, rootpath, authorizer, utilities)
|
||||
return ccvs.CCVSRepository(name, rootpath, authorizer, utilities, charset_guesser)
|
||||
else:
|
||||
import bincvs
|
||||
return bincvs.BinCVSRepository(name, rootpath, authorizer, utilities)
|
||||
return bincvs.BinCVSRepository(name, rootpath, authorizer, utilities, charset_guesser)
|
||||
|
@@ -20,6 +20,8 @@ import sys
|
||||
import stat
|
||||
import re
|
||||
import time
|
||||
import cvsdb
|
||||
import socket
|
||||
import calendar
|
||||
|
||||
# ViewVC libs
|
||||
@@ -30,14 +32,15 @@ def _path_join(path_parts):
|
||||
return '/'.join(path_parts)
|
||||
|
||||
class BaseCVSRepository(vclib.Repository):
|
||||
def __init__(self, name, rootpath, authorizer, utilities):
|
||||
def __init__(self, name, rootpath, authorizer, utilities, charset_guesser = None):
|
||||
if not os.path.isdir(rootpath):
|
||||
raise vclib.ReposNotFound(name)
|
||||
|
||||
raise vclib.ReposNotFound(name)
|
||||
|
||||
self.name = name
|
||||
self.rootpath = rootpath
|
||||
self.auth = authorizer
|
||||
self.utilities = utilities
|
||||
self.guesser = charset_guesser
|
||||
|
||||
# See if this repository is even viewable, authz-wise.
|
||||
if not vclib.check_root_access(self):
|
||||
@@ -59,7 +62,7 @@ class BaseCVSRepository(vclib.Repository):
|
||||
|
||||
def authorizer(self):
|
||||
return self.auth
|
||||
|
||||
|
||||
def itemtype(self, path_parts, rev):
|
||||
basepath = self._getpath(path_parts)
|
||||
kind = None
|
||||
@@ -80,7 +83,7 @@ class BaseCVSRepository(vclib.Repository):
|
||||
def itemprops(self, path_parts, rev):
|
||||
self.itemtype(path_parts, rev) # does auth-check
|
||||
return {} # CVS doesn't support properties
|
||||
|
||||
|
||||
def listdir(self, path_parts, rev, options):
|
||||
if self.itemtype(path_parts, rev) != vclib.DIR: # does auth-check
|
||||
raise vclib.Error("Path '%s' is not a directory."
|
||||
@@ -121,7 +124,7 @@ class BaseCVSRepository(vclib.Repository):
|
||||
data.append(CVSDirEntry(name, kind, errors, 1))
|
||||
|
||||
return data
|
||||
|
||||
|
||||
def _getpath(self, path_parts):
|
||||
return apply(os.path.join, (self.rootpath,) + tuple(path_parts))
|
||||
|
||||
@@ -166,7 +169,7 @@ class BinCVSRepository(BaseCVSRepository):
|
||||
filename, default_branch, tags, lockinfo, msg, eof = _parse_log_header(fp)
|
||||
revs = []
|
||||
while not eof:
|
||||
revision, eof = _parse_log_entry(fp)
|
||||
revision, eof = _parse_log_entry(fp, self.guesser)
|
||||
if revision:
|
||||
revs.append(revision)
|
||||
revs = _file_log(revs, tags, lockinfo, default_branch, rev)
|
||||
@@ -209,14 +212,14 @@ class BinCVSRepository(BaseCVSRepository):
|
||||
used_rlog = 1
|
||||
if not tip_rev:
|
||||
raise vclib.Error("Unable to find valid revision")
|
||||
fp = self.rcs_popen('co', ('-p' + tip_rev.string, full_name), 'rb')
|
||||
fp = self.rcs_popen('co', ('-p' + tip_rev.string, full_name), 'rb')
|
||||
filename, revision = _parse_co_header(fp)
|
||||
|
||||
|
||||
if filename is None:
|
||||
# CVSNT's co exits without any output if a dead revision is requested.
|
||||
# Bug at http://www.cvsnt.org/cgi-bin/bugzilla/show_bug.cgi?id=190
|
||||
# As a workaround, we invoke rlog to find the first non-dead revision
|
||||
# that precedes it and check out that revision instead. Of course,
|
||||
# that precedes it and check out that revision instead. Of course,
|
||||
# if we've already invoked rlog above, we just reuse its output.
|
||||
if not used_rlog:
|
||||
tip_rev = self._get_tip_revision(full_name + ',v', rev)
|
||||
@@ -225,7 +228,7 @@ class BinCVSRepository(BaseCVSRepository):
|
||||
raise vclib.Error(
|
||||
'Could not find non-dead revision preceding "%s"' % rev)
|
||||
fp = self.rcs_popen('co', ('-p' + tip_rev.undead.string,
|
||||
full_name), 'rb')
|
||||
full_name), 'rb')
|
||||
filename, revision = _parse_co_header(fp)
|
||||
|
||||
if filename is None:
|
||||
@@ -264,7 +267,7 @@ class BinCVSRepository(BaseCVSRepository):
|
||||
for entry in entries:
|
||||
if vclib.check_path_access(self, path_parts + [entry.name], None, rev):
|
||||
entries_to_fetch.append(entry)
|
||||
alltags = _get_logs(self, path_parts, entries_to_fetch, rev, subdirs)
|
||||
alltags = _get_logs(self, path_parts, entries_to_fetch, rev, subdirs, self.guesser)
|
||||
branches = options['cvs_branches'] = []
|
||||
tags = options['cvs_tags'] = []
|
||||
for name, rev in alltags.items():
|
||||
@@ -309,7 +312,7 @@ class BinCVSRepository(BaseCVSRepository):
|
||||
# Retrieve revision objects
|
||||
revs = []
|
||||
while not eof:
|
||||
revision, eof = _parse_log_entry(fp)
|
||||
revision, eof = _parse_log_entry(fp, self.guesser)
|
||||
if revision:
|
||||
revs.append(revision)
|
||||
|
||||
@@ -328,7 +331,17 @@ class BinCVSRepository(BaseCVSRepository):
|
||||
return filtered_revs
|
||||
|
||||
def rcs_popen(self, rcs_cmd, rcs_args, mode, capture_err=1):
|
||||
if self.utilities.cvsnt:
|
||||
a = []
|
||||
if self.utilities.rcsfile_socket:
|
||||
a = self.utilities.rcsfile_socket.split(':')
|
||||
if len(a) == 2:
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
s.connect((a[0], int(a[1])))
|
||||
s = s.makefile()
|
||||
s.write('\''+rcs_cmd+'\' \''+'\' \''.join(rcs_args)+"\'\x0d\x0a")
|
||||
s.flush()
|
||||
return s
|
||||
elif self.utilities.cvsnt:
|
||||
cmd = self.utilities.cvsnt
|
||||
args = ['rcsfile', rcs_cmd]
|
||||
args.extend(list(rcs_args))
|
||||
@@ -342,12 +355,12 @@ class BinCVSRepository(BaseCVSRepository):
|
||||
raise vclib.Error("Path '%s' is not a file." % (_path_join(path_parts)))
|
||||
|
||||
from vclib.ccvs import blame
|
||||
source = blame.BlameSource(self.rcsfile(path_parts, 1), rev, include_text)
|
||||
source = blame.BlameSource(self.rcsfile(path_parts, 1), rev, self.guesser, include_text)
|
||||
return source, source.revision
|
||||
|
||||
def revinfo(self, rev):
|
||||
raise vclib.UnsupportedFeature
|
||||
|
||||
|
||||
def rawdiff(self, path_parts1, rev1, path_parts2, rev2, type, options={}):
|
||||
"""see vclib.Repository.rawdiff docstring
|
||||
|
||||
@@ -355,6 +368,12 @@ class BinCVSRepository(BaseCVSRepository):
|
||||
|
||||
ignore_keyword_subst - boolean, ignore keyword substitution
|
||||
"""
|
||||
if not path_parts1:
|
||||
path_parts1 = path_parts2
|
||||
rev1 = '1.0'
|
||||
if not path_parts2:
|
||||
path_parts2 = path_parts1
|
||||
rev2 = '1.0'
|
||||
if self.itemtype(path_parts1, rev1) != vclib.FILE: # does auth-check
|
||||
raise vclib.Error("Path '%s' is not a file." % (_path_join(path_parts1)))
|
||||
if self.itemtype(path_parts2, rev2) != vclib.FILE: # does auth-check
|
||||
@@ -367,8 +386,7 @@ class BinCVSRepository(BaseCVSRepository):
|
||||
rcsfile = self.rcsfile(path_parts1, 1)
|
||||
if path_parts1 != path_parts2:
|
||||
raise NotImplementedError, "cannot diff across paths in cvs"
|
||||
args.extend(['-r' + rev1, '-r' + rev2, rcsfile])
|
||||
|
||||
args.extend(['-N', '-r' + rev1, '-r' + rev2, rcsfile])
|
||||
fp = self.rcs_popen('rcsdiff', args, 'rt')
|
||||
|
||||
# Eat up the non-GNU-diff-y headers.
|
||||
@@ -377,7 +395,6 @@ class BinCVSRepository(BaseCVSRepository):
|
||||
if not line or line[0:5] == 'diff ':
|
||||
break
|
||||
return fp
|
||||
|
||||
|
||||
class CVSDirEntry(vclib.DirEntry):
|
||||
def __init__(self, name, kind, errors, in_attic, absent=0):
|
||||
@@ -439,9 +456,9 @@ def _match_revs_tags(revlist, taglist):
|
||||
example: if revision is 1.2.3.4, parent is 1.2
|
||||
|
||||
"undead"
|
||||
If the revision is dead, then this is a reference to the first
|
||||
If the revision is dead, then this is a reference to the first
|
||||
previous revision which isn't dead, otherwise it's a reference
|
||||
to itself. If all the previous revisions are dead it's None.
|
||||
to itself. If all the previous revisions are dead it's None.
|
||||
|
||||
"branch_number"
|
||||
tuple representing branch number or empty tuple if on trunk
|
||||
@@ -653,7 +670,7 @@ def _parse_co_header(fp):
|
||||
pass
|
||||
else:
|
||||
break
|
||||
|
||||
|
||||
raise COMalformedOutput, "Unable to find revision in co output stream"
|
||||
|
||||
# if your rlog doesn't use 77 '=' characters, then this must change
|
||||
@@ -674,7 +691,7 @@ _EOF_ERROR = 'error message found' # rlog issued an error
|
||||
# ^rlog\: (.*)(?:\:\d+)?\: (.*)$
|
||||
#
|
||||
# But for some reason the windows version of rlog omits the "rlog: " prefix
|
||||
# for the first error message when the standard error stream has been
|
||||
# for the first error message when the standard error stream has been
|
||||
# redirected to a file or pipe. (the prefix is present in subsequent errors
|
||||
# and when rlog is run from the console). So the expression below is more
|
||||
# complicated
|
||||
@@ -703,7 +720,7 @@ def _parse_log_header(fp):
|
||||
Returns: filename, default branch, tag dictionary, lock dictionary,
|
||||
rlog error message, and eof flag
|
||||
"""
|
||||
|
||||
|
||||
filename = head = branch = msg = ""
|
||||
taginfo = { } # tag name => number
|
||||
lockinfo = { } # revision => locker
|
||||
@@ -732,7 +749,7 @@ def _parse_log_header(fp):
|
||||
else:
|
||||
# oops. this line isn't lock info. stop parsing tags.
|
||||
state = 0
|
||||
|
||||
|
||||
if state == 0:
|
||||
if line[:9] == 'RCS file:':
|
||||
filename = line[10:-1]
|
||||
@@ -783,7 +800,7 @@ _re_log_info = re.compile(r'^date:\s+([^;]+);'
|
||||
r'(\s+commitid:\s+([a-zA-Z0-9]+))?\n$')
|
||||
### _re_rev should be updated to extract the "locked" flag
|
||||
_re_rev = re.compile(r'^revision\s+([0-9.]+).*')
|
||||
def _parse_log_entry(fp):
|
||||
def _parse_log_entry(fp, guesser):
|
||||
"""Parse a single log entry.
|
||||
|
||||
On entry, fp should point to the first line of the entry (the "revision"
|
||||
@@ -849,6 +866,9 @@ def _parse_log_entry(fp):
|
||||
raise ValueError, 'invalid year'
|
||||
date = calendar.timegm(tm)
|
||||
|
||||
if guesser:
|
||||
log = guesser.utf8(log)
|
||||
|
||||
return Revision(rev, date,
|
||||
# author, state, lines changed
|
||||
match.group(2), match.group(3) == "dead", match.group(5),
|
||||
@@ -900,7 +920,7 @@ def _file_log(revs, taginfo, lockinfo, cur_branch, filter):
|
||||
except ValueError:
|
||||
view_tag = None
|
||||
else:
|
||||
tags.append(view_tag)
|
||||
tags.append(view_tag)
|
||||
|
||||
# Match up tags and revisions
|
||||
_match_revs_tags(revs, tags)
|
||||
@@ -908,13 +928,13 @@ def _file_log(revs, taginfo, lockinfo, cur_branch, filter):
|
||||
# Match up lockinfo and revision
|
||||
for rev in revs:
|
||||
rev.lockinfo = lockinfo.get(rev.string)
|
||||
|
||||
|
||||
# Add artificial ViewVC tag HEAD, which acts like a non-branch tag pointing
|
||||
# at the latest revision on the MAIN branch. The HEAD revision doesn't have
|
||||
# anything to do with the "head" revision number specified in the RCS file
|
||||
# and in rlog output. HEAD refers to the revision that the CVS and RCS co
|
||||
# commands will check out by default, whereas the "head" field just refers
|
||||
# to the highest revision on the trunk.
|
||||
# to the highest revision on the trunk.
|
||||
taginfo['HEAD'] = _add_tag('HEAD', taginfo['MAIN'].co_rev)
|
||||
|
||||
# Determine what revisions to return
|
||||
@@ -952,10 +972,10 @@ def _file_log(revs, taginfo, lockinfo, cur_branch, filter):
|
||||
_remove_tag(view_tag)
|
||||
else:
|
||||
filtered_revs = revs
|
||||
|
||||
|
||||
return filtered_revs
|
||||
|
||||
def _get_logs(repos, dir_path_parts, entries, view_tag, get_dirs):
|
||||
def _get_logs(repos, dir_path_parts, entries, view_tag, get_dirs, guesser):
|
||||
alltags = { # all the tags seen in the files of this dir
|
||||
'MAIN' : '',
|
||||
'HEAD' : '1.1'
|
||||
@@ -1002,7 +1022,7 @@ def _get_logs(repos, dir_path_parts, entries, view_tag, get_dirs):
|
||||
= _parse_log_header(rlog)
|
||||
|
||||
if eof == _EOF_LOG:
|
||||
# the rlog output ended early. this can happen on errors that rlog
|
||||
# the rlog output ended early. this can happen on errors that rlog
|
||||
# thinks are so serious that it stops parsing the current file and
|
||||
# refuses to parse any of the files that come after it. one of the
|
||||
# errors that triggers this obnoxious behavior looks like:
|
||||
@@ -1050,8 +1070,8 @@ def _get_logs(repos, dir_path_parts, entries, view_tag, get_dirs):
|
||||
eof = _EOF_FILE
|
||||
|
||||
# we don't care about the specific values -- just the keys and whether
|
||||
# the values point to branches or revisions. this the fastest way to
|
||||
# merge the set of keys and keep values that allow us to make the
|
||||
# the values point to branches or revisions. this the fastest way to
|
||||
# merge the set of keys and keep values that allow us to make the
|
||||
# distinction between branch tags and normal tags
|
||||
alltags.update(taginfo)
|
||||
|
||||
@@ -1060,7 +1080,7 @@ def _get_logs(repos, dir_path_parts, entries, view_tag, get_dirs):
|
||||
while not eof:
|
||||
|
||||
# fetch one of the log entries
|
||||
entry, eof = _parse_log_entry(rlog)
|
||||
entry, eof = _parse_log_entry(rlog, guesser)
|
||||
|
||||
if not entry:
|
||||
# parsing error
|
||||
@@ -1096,7 +1116,7 @@ def _get_logs(repos, dir_path_parts, entries, view_tag, get_dirs):
|
||||
file.dead = 0
|
||||
#file.errors.append("No revisions exist on %s" % (view_tag or "MAIN"))
|
||||
file.absent = 1
|
||||
|
||||
|
||||
# done with this file now, skip the rest of this file's revisions
|
||||
if not eof:
|
||||
_skip_file(rlog)
|
||||
@@ -1209,7 +1229,7 @@ def _newest_file(dirpath):
|
||||
newest_time = 0
|
||||
|
||||
### FIXME: This sucker is leaking unauthorized paths! ###
|
||||
|
||||
|
||||
for subfile in os.listdir(dirpath):
|
||||
### filter CVS locks? stale NFS handles?
|
||||
if subfile[-2:] != ',v':
|
||||
|
@@ -31,6 +31,7 @@ import time
|
||||
import math
|
||||
import rcsparse
|
||||
import vclib
|
||||
import cvsdb
|
||||
|
||||
class CVSParser(rcsparse.Sink):
|
||||
# Precompiled regular expressions
|
||||
@@ -413,7 +414,7 @@ class CVSParser(rcsparse.Sink):
|
||||
|
||||
|
||||
class BlameSource:
|
||||
def __init__(self, rcs_file, opt_rev=None, include_text=False):
|
||||
def __init__(self, rcs_file, opt_rev=None, charset_guesser=None, include_text=False):
|
||||
# Parse the CVS file
|
||||
parser = CVSParser()
|
||||
revision = parser.parse_cvs_file(rcs_file, opt_rev)
|
||||
@@ -427,6 +428,7 @@ class BlameSource:
|
||||
self.lines = lines
|
||||
self.num_lines = count
|
||||
self.parser = parser
|
||||
self.guesser = charset_guesser
|
||||
self.include_text = include_text
|
||||
|
||||
# keep track of where we are during an iteration
|
||||
@@ -446,9 +448,14 @@ class BlameSource:
|
||||
prev_rev = self.parser.prev_revision.get(rev)
|
||||
line_number = idx + 1
|
||||
author = self.parser.revision_author[rev]
|
||||
thisline = self.lines[idx]
|
||||
|
||||
if not self.include_text:
|
||||
thisline = None
|
||||
elif self.guesser:
|
||||
thisline = self.guesser.utf8(self.lines[idx])
|
||||
else:
|
||||
thisline = self.lines[idx]
|
||||
|
||||
### TODO: Put a real date in here.
|
||||
item = vclib.Annotation(thisline, line_number, rev, prev_rev, author, None)
|
||||
self.last = item
|
||||
|
@@ -18,6 +18,7 @@ import tempfile
|
||||
import vclib
|
||||
import rcsparse
|
||||
import blame
|
||||
import cvsdb
|
||||
|
||||
### The functionality shared with bincvs should probably be moved to a
|
||||
### separate module
|
||||
@@ -66,6 +67,8 @@ class CCVSRepository(BaseCVSRepository):
|
||||
entry.path = path
|
||||
try:
|
||||
rcsparse.parse(open(path, 'rb'), InfoSink(entry, rev, alltags))
|
||||
if self.guesser:
|
||||
entry.log = self.guesser.utf8(entry.log)
|
||||
except IOError, e:
|
||||
entry.errors.append("rcsparse error: %s" % e)
|
||||
except RuntimeError, e:
|
||||
@@ -118,21 +121,30 @@ class CCVSRepository(BaseCVSRepository):
|
||||
return filtered_revs
|
||||
|
||||
def rawdiff(self, path_parts1, rev1, path_parts2, rev2, type, options={}):
|
||||
if self.itemtype(path_parts1, rev1) != vclib.FILE: # does auth-check
|
||||
if path_parts1 and self.itemtype(path_parts1, rev1) != vclib.FILE: # does auth-check
|
||||
raise vclib.Error("Path '%s' is not a file." % (_path_join(path_parts1)))
|
||||
if self.itemtype(path_parts2, rev2) != vclib.FILE: # does auth-check
|
||||
if path_parts2 and self.itemtype(path_parts2, rev2) != vclib.FILE: # does auth-check
|
||||
raise vclib.Error("Path '%s' is not a file." % (_path_join(path_parts2)))
|
||||
if not path_parts1 and not path_parts2:
|
||||
raise vclib.Error("Nothing to diff.")
|
||||
|
||||
temp1 = tempfile.mktemp()
|
||||
open(temp1, 'wb').write(self.openfile(path_parts1, rev1, {})[0].getvalue())
|
||||
temp2 = tempfile.mktemp()
|
||||
open(temp2, 'wb').write(self.openfile(path_parts2, rev2, {})[0].getvalue())
|
||||
if path_parts1:
|
||||
temp1 = tempfile.mktemp()
|
||||
open(temp1, 'wb').write(self.openfile(path_parts1, rev1, {})[0].getvalue())
|
||||
r1 = self.itemlog(path_parts1, rev1, vclib.SORTBY_DEFAULT, 0, 0, {})[-1]
|
||||
info1 = (self.rcsfile(path_parts1, root=1, v=0), r1.date, r1.string)
|
||||
else:
|
||||
temp1 = '/dev/null'
|
||||
info1 = ('/dev/null', '', '')
|
||||
|
||||
r1 = self.itemlog(path_parts1, rev1, vclib.SORTBY_DEFAULT, 0, 0, {})[-1]
|
||||
r2 = self.itemlog(path_parts2, rev2, vclib.SORTBY_DEFAULT, 0, 0, {})[-1]
|
||||
|
||||
info1 = (self.rcsfile(path_parts1, root=1, v=0), r1.date, r1.string)
|
||||
info2 = (self.rcsfile(path_parts2, root=1, v=0), r2.date, r2.string)
|
||||
if path_parts2:
|
||||
temp2 = tempfile.mktemp()
|
||||
open(temp2, 'wb').write(self.openfile(path_parts2, rev2, {})[0].getvalue())
|
||||
r2 = self.itemlog(path_parts2, rev2, vclib.SORTBY_DEFAULT, 0, 0, {})[-1]
|
||||
info2 = (self.rcsfile(path_parts2, root=1, v=0), r2.date, r2.string)
|
||||
else:
|
||||
temp2 = '/dev/null'
|
||||
info2 = ('/dev/null', '', '')
|
||||
|
||||
diff_args = vclib._diff_args(type, options)
|
||||
|
||||
@@ -142,7 +154,7 @@ class CCVSRepository(BaseCVSRepository):
|
||||
def annotate(self, path_parts, rev=None, include_text=False):
|
||||
if self.itemtype(path_parts, rev) != vclib.FILE: # does auth-check
|
||||
raise vclib.Error("Path '%s' is not a file." % (_path_join(path_parts)))
|
||||
source = blame.BlameSource(self.rcsfile(path_parts, 1), rev, include_text)
|
||||
source = blame.BlameSource(self.rcsfile(path_parts, 1), rev, self.guesser, include_text)
|
||||
return source, source.revision
|
||||
|
||||
def revinfo(self, rev):
|
||||
|
@@ -443,33 +443,48 @@ class RemoteSubversionRepository(vclib.Repository):
|
||||
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)
|
||||
r1 = self._getrev(rev1)
|
||||
r2 = self._getrev(rev2)
|
||||
if not vclib.check_path_access(self, path_parts1, vclib.FILE, rev1):
|
||||
raise vclib.ItemNotFound(path_parts1)
|
||||
if not vclib.check_path_access(self, path_parts2, vclib.FILE, rev2):
|
||||
raise vclib.ItemNotFound(path_parts2)
|
||||
|
||||
if path_parts1 is not None:
|
||||
p1 = self._getpath(path_parts1)
|
||||
r1 = self._getrev(rev1)
|
||||
if not vclib.check_path_access(self, path_parts1, vclib.FILE, rev1):
|
||||
raise vclib.ItemNotFound(path_parts1)
|
||||
else:
|
||||
p1 = None
|
||||
|
||||
if path_parts2 is not None:
|
||||
if not p1:
|
||||
raise vclib.ItemNotFound(parh_parts2)
|
||||
p2 = self._getpath(path_parts2)
|
||||
r2 = self._getrev(rev2)
|
||||
if not vclib.check_path_access(self, path_parts2, vclib.FILE, rev2):
|
||||
raise vclib.ItemNotFound(path_parts2)
|
||||
else:
|
||||
p2 = None
|
||||
|
||||
args = vclib._diff_args(type, options)
|
||||
|
||||
def _date_from_rev(rev):
|
||||
date, author, msg, revprops, changes = self._revinfo(rev)
|
||||
return date
|
||||
|
||||
|
||||
try:
|
||||
temp1 = cat_to_tempfile(self, p1, r1)
|
||||
temp2 = cat_to_tempfile(self, p2, r2)
|
||||
info1 = p1, _date_from_rev(r1), r1
|
||||
info2 = p2, _date_from_rev(r2), r2
|
||||
if p1:
|
||||
temp1 = cat_to_tempfile(self, p1, r1)
|
||||
else:
|
||||
temp1 = '/dev/null'
|
||||
if p2:
|
||||
temp2 = cat_to_tempfile(self, p2, r2)
|
||||
else:
|
||||
temp2 = '/dev/null'
|
||||
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:
|
||||
if e.apr_err == core.SVN_ERR_FS_NOT_FOUND:
|
||||
raise vclib.InvalidRevision
|
||||
raise
|
||||
|
||||
def isexecutable(self, path_parts, rev):
|
||||
props = self.itemprops(path_parts, rev) # does authz-check
|
||||
return props.has_key(core.SVN_PROP_EXECUTABLE)
|
||||
|
@@ -21,7 +21,7 @@ import tempfile
|
||||
import popen
|
||||
import re
|
||||
import urllib
|
||||
from svn import fs, repos, core, client, delta
|
||||
from svn import fs, repos, core, client, delta, diff
|
||||
|
||||
|
||||
### Require Subversion 1.3.1 or better.
|
||||
@@ -306,8 +306,8 @@ class BlameSource:
|
||||
try:
|
||||
### TODO: Is this use of FIRST_REV always what we want? Should we
|
||||
### pass 1 here instead and do filtering later?
|
||||
client.blame2(local_url, _rev2optrev(rev), _rev2optrev(first_rev),
|
||||
_rev2optrev(rev), self._blame_cb, ctx)
|
||||
client.blame3(local_url, _rev2optrev(rev), _rev2optrev(first_rev),
|
||||
_rev2optrev(rev), diff.svn_diff_file_options_t(), True, self._blame_cb, ctx)
|
||||
except core.SubversionException, e:
|
||||
_fix_subversion_exception(e)
|
||||
if e.apr_err == core.SVN_ERR_CLIENT_IS_BINARY_FILE:
|
||||
@@ -537,15 +537,24 @@ class LocalSubversionRepository(vclib.Repository):
|
||||
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)
|
||||
r1 = self._getrev(rev1)
|
||||
r2 = self._getrev(rev2)
|
||||
if not vclib.check_path_access(self, path_parts1, vclib.FILE, rev1):
|
||||
raise vclib.ItemNotFound(path_parts1)
|
||||
if not vclib.check_path_access(self, path_parts2, vclib.FILE, rev2):
|
||||
raise vclib.ItemNotFound(path_parts2)
|
||||
|
||||
if path_parts1:
|
||||
p1 = self._getpath(path_parts1)
|
||||
r1 = self._getrev(rev1)
|
||||
if not vclib.check_path_access(self, path_parts1, vclib.FILE, rev1):
|
||||
raise vclib.ItemNotFound(path_parts1)
|
||||
else:
|
||||
p1 = None
|
||||
|
||||
if path_parts2:
|
||||
p2 = self._getpath(path_parts2)
|
||||
r2 = self._getrev(rev2)
|
||||
if not vclib.check_path_access(self, path_parts2, vclib.FILE, rev2):
|
||||
raise vclib.ItemNotFound(path_parts2)
|
||||
else:
|
||||
if not p1:
|
||||
raise vclib.ItemNotFound(path_parts2)
|
||||
p2 = None
|
||||
|
||||
args = vclib._diff_args(type, options)
|
||||
|
||||
def _date_from_rev(rev):
|
||||
@@ -553,16 +562,25 @@ class LocalSubversionRepository(vclib.Repository):
|
||||
return date
|
||||
|
||||
try:
|
||||
temp1 = temp_checkout(self, p1, r1)
|
||||
temp2 = temp_checkout(self, p2, r2)
|
||||
info1 = p1, _date_from_rev(r1), r1
|
||||
info2 = p2, _date_from_rev(r2), r2
|
||||
if p1:
|
||||
temp1 = temp_checkout(self, p1, r1)
|
||||
info1 = p1, _date_from_rev(r1), r1
|
||||
else:
|
||||
temp1 = '/dev/null'
|
||||
info1 = '/dev/null', _date_from_rev(rev1), rev1
|
||||
if p2:
|
||||
temp2 = temp_checkout(self, p2, r2)
|
||||
info2 = p2, _date_from_rev(r2), r2
|
||||
else:
|
||||
temp2 = '/dev/null'
|
||||
info2 = '/dev/null', _date_from_rev(rev2), rev2
|
||||
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
|
||||
if e.apr_err != _SVN_ERR_CEASE_INVOCATION:
|
||||
raise
|
||||
|
||||
def isexecutable(self, path_parts, rev):
|
||||
props = self.itemprops(path_parts, rev) # does authz-check
|
||||
@@ -902,7 +920,7 @@ class LocalSubversionRepository(vclib.Repository):
|
||||
while history:
|
||||
path, peg_revision = fs.history_location(history)
|
||||
if peg_revision <= limit_revision:
|
||||
return max(peg_revision, limit_revision), _cleanup_path(path)
|
||||
return peg_revision, _cleanup_path(path)
|
||||
history = fs.history_prev(history, 1)
|
||||
return peg_revision, _cleanup_path(path)
|
||||
else:
|
||||
|
814
lib/viewvc.py
75
lib/viewvcmagic.py
Normal file
@@ -0,0 +1,75 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
import mimetypes
|
||||
import magic
|
||||
|
||||
have_chardet = 0
|
||||
try:
|
||||
import chardet
|
||||
have_chardet = 1
|
||||
except: pass
|
||||
|
||||
class ContentMagic:
|
||||
|
||||
def __init__(self, encodings):
|
||||
self.encodings = encodings.split(':')
|
||||
self.mime_magic = None
|
||||
self.errors = []
|
||||
# Try to load magic
|
||||
self.mime_magic = magic.open(magic.MAGIC_MIME_TYPE)
|
||||
self.mime_magic.load()
|
||||
|
||||
# returns MIME type
|
||||
def guess_mime(self, mime, filename, tempfile):
|
||||
if mime == 'application/octet-stream':
|
||||
mime = ''
|
||||
if not mime and filename:
|
||||
mime = mimetypes.guess_type(filename)[0]
|
||||
if not mime and tempfile and self.mime_magic:
|
||||
if type(tempfile) == type(''):
|
||||
mime = self.mime_magic.file(tempfile)
|
||||
else:
|
||||
c = tempfile.read(4096)
|
||||
mime = self.mime_magic.buffer(c)
|
||||
return mime
|
||||
|
||||
# returns (utf8_content, charset)
|
||||
def guess_charset(self, content):
|
||||
# Try UTF-8
|
||||
charset = 'utf-8'
|
||||
try: content = content.decode('utf-8')
|
||||
except: charset = None
|
||||
if charset is None and have_chardet and len(content) > 64:
|
||||
# Try to guess with chardet
|
||||
try:
|
||||
# Only detect on first 256KB if content is longer
|
||||
if len(content) > 256*1024:
|
||||
charset = chardet.detect(content[0:256*1024])
|
||||
else:
|
||||
charset = chardet.detect(content)
|
||||
if charset and charset['encoding']:
|
||||
charset = charset['encoding']
|
||||
if charset == 'MacCyrillic':
|
||||
# Silly MacCyr, try cp1251
|
||||
try:
|
||||
content = content.decode('windows-1251')
|
||||
charset = 'windows-1251'
|
||||
except: content = content.decode(charset)
|
||||
else:
|
||||
content = content.decode(charset)
|
||||
except: charset = None
|
||||
# Then try to guess primitively
|
||||
if charset is None:
|
||||
for charset in self.encodings:
|
||||
try:
|
||||
content = content.decode(charset)
|
||||
break
|
||||
except: charset = None
|
||||
return (content, charset)
|
||||
|
||||
# guess and encode return value into UTF-8
|
||||
def utf8(self, content):
|
||||
(uni, charset) = self.guess_charset(content)
|
||||
if charset:
|
||||
return uni.encode('utf-8')
|
||||
return content
|
5
templates-contrib/README
Normal file
@@ -0,0 +1,5 @@
|
||||
This directory contains ViewVC template sets contributed by their
|
||||
respective authors and expected to work against ViewVC 1.0.x. They
|
||||
are not necessarily supported by the ViewVC development community, and
|
||||
do not necessarily carry the same license or copyright as ViewVC
|
||||
itself.
|
7
templates-contrib/newvc/README
Normal file
@@ -0,0 +1,7 @@
|
||||
Template Set: newvc
|
||||
Author(s): C. Michael Pilato <cmpilato@red-bean.com>
|
||||
Compatibility: ViewVC 1.1
|
||||
|
||||
The "newvc" template set uses top navigation tabs to flip between
|
||||
various views of a file or directory, and aims for a clean-yet-modern
|
||||
look and feel.
|
128
templates-contrib/newvc/templates/diff.ezt
Normal file
@@ -0,0 +1,128 @@
|
||||
[# Setup page definitions]
|
||||
[define page_title]Diff of:[end]
|
||||
[define help_href][docroot]/help_rootview.html[end]
|
||||
[# end]
|
||||
[include "include/header.ezt" "diff"]
|
||||
|
||||
<form method="get" action="[diff_format_action]" style="display: inline;">
|
||||
<div>
|
||||
[for diff_format_hidden_values]<input type="hidden" name="[diff_format_hidden_values.name]" value="[diff_format_hidden_values.value]"/>[end]
|
||||
<select name="diff_format" onchange="submit()">
|
||||
<option value="h" [is diff_format "h"]selected="selected"[end]>Colored Diff</option>
|
||||
<option value="l" [is diff_format "l"]selected="selected"[end]>Long Colored Diff</option>
|
||||
<option value="f" [is diff_format "f"]selected="selected"[end]>Full Colored Diff</option>
|
||||
<option value="u" [is diff_format "u"]selected="selected"[end]>Unidiff</option>
|
||||
<option value="c" [is diff_format "c"]selected="selected"[end]>Context Diff</option>
|
||||
<option value="s" [is diff_format "s"]selected="selected"[end]>Side by Side</option>
|
||||
</select>
|
||||
<input type="submit" value="Show" />
|
||||
(<a href="[patch_href]">Generate patch</a>)
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div id="vc_main_body">
|
||||
<!-- ************************************************************** -->
|
||||
|
||||
[if-any raw_diff]
|
||||
<pre>[raw_diff]</pre>
|
||||
[else]
|
||||
|
||||
[define change_right][end]
|
||||
[define last_change_type][end]
|
||||
|
||||
[# these should live in stylesheets]
|
||||
|
||||
<table cellpadding="0" cellspacing="0" style="width: 100%;">
|
||||
[for changes]
|
||||
[is changes.type "change"][else]
|
||||
[if-any change_right][change_right][define change_right][end][end]
|
||||
[end]
|
||||
[is changes.type "header"]
|
||||
<tr>
|
||||
<th class="vc_header" style="width:6%;"><strong>#</strong></th>
|
||||
<th colspan="2" class="vc_header">
|
||||
<strong>Line [changes.line_info_left]</strong> |
|
||||
<strong>Line [changes.line_info_right]</strong>
|
||||
</th>
|
||||
</tr>
|
||||
[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_plusminus"><strong style="color: green;">+</strong></td>
|
||||
<td class="vc_diff_add">[changes.right]</td>
|
||||
</tr>
|
||||
[else]
|
||||
[is changes.type "remove"]
|
||||
<tr>
|
||||
<td style="text-decoration: line-through">[changes.line_number]</td>
|
||||
<td class="vc_diff_plusminus"><strong style="color: red;">–</strong></td>
|
||||
<td class="vc_diff_remove">[changes.left]</td>
|
||||
</tr>
|
||||
[else]
|
||||
[is changes.type "change"]
|
||||
[if-any changes.have_left]
|
||||
<tr>
|
||||
<td style="text-decoration: line-through">[changes.line_number]</td>
|
||||
<td class="vc_diff_plusminus"><strong style="color: yellow;"><</strong></td>
|
||||
<td class="vc_diff_changes1">[changes.left]</td>
|
||||
</tr>
|
||||
[end]
|
||||
[define change_right][change_right]
|
||||
[if-any changes.have_right]
|
||||
<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_plusminus"><strong style="color: yellow;">></strong></td>
|
||||
<td class="vc_diff_changes2">[changes.right]</td>
|
||||
</tr>[end]
|
||||
[end]
|
||||
[else]
|
||||
[is changes.type "no-changes"]
|
||||
<tr><td colspan="3" style="vc_diff_nochange"><strong>- No changes -</strong></td></tr>
|
||||
[else]
|
||||
[is changes.type "binary-diff"]
|
||||
<tr><td colspan="3" class="vc_diff_binary"><strong>- Binary file revisions differ -</strong></td></tr>
|
||||
[else]
|
||||
[is changes.type "error"]
|
||||
<tr><td colspan="3" class="vc_diff_error"><strong>- ViewVC depends on rcsdiff and GNU diff
|
||||
to create this page. ViewVC cannot find GNU diff. Even if you
|
||||
have GNU diff installed, the rcsdiff program must be configured
|
||||
and compiled with the GNU diff location. -</strong></td></tr>
|
||||
[else][# a line of context]
|
||||
<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_plusminus"> </td>
|
||||
<td style="font-family: monospace; white-space: pre;">[changes.right]</td>
|
||||
</tr>
|
||||
[end][end][end][end][end][end][end]
|
||||
[define last_change_type][changes.type][end]
|
||||
[end]
|
||||
[if-any change_right][change_right][end]
|
||||
</table>
|
||||
|
||||
<h3>Diff Legend</h3>
|
||||
<table class="auto" cellspacing="0">
|
||||
<tr>
|
||||
<td class="vc_diff_plusminus"><strong style="color: red;">–</strong></td>
|
||||
<td class="vc_diff_remove">Removed lines</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="vc_diff_plusminus"><strong style="color: green;">+</strong></td>
|
||||
<td class="vc_diff_add">Added lines</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="vc_diff_plusminus"><strong style="color: yellow;"><</strong></td>
|
||||
<td class="vc_diff_changes1">Changed lines</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="vc_diff_plusminus"><strong style="color: yellow;">></strong></td>
|
||||
<td class="vc_diff_changes2">Changed lines</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
[end]
|
||||
|
||||
<!-- ************************************************************** -->
|
||||
</div>
|
||||
|
||||
[include "include/footer.ezt"]
|
139
templates-contrib/newvc/templates/directory.ezt
Normal file
@@ -0,0 +1,139 @@
|
||||
[# setup page definitions]
|
||||
[define page_title]Index of:[end]
|
||||
[define help_href][docroot]/help_[if-any where]dir[else]root[end]view.html[end]
|
||||
[# end]
|
||||
[include "include/header.ezt" "directory"]
|
||||
|
||||
[if-any where][else]
|
||||
<!-- you may insert repository access instructions here -->
|
||||
[end]
|
||||
|
||||
<table class="auto">
|
||||
[is cfg.options.use_pagesize "0"][else][is picklist_len "1"][else]
|
||||
<tr>
|
||||
<td>Jump to page:</td>
|
||||
<td><form method="get" action="[dir_paging_action]">
|
||||
[for dir_paging_hidden_values]<input type="hidden" name="[dir_paging_hidden_values.name]" value="[dir_paging_hidden_values.value]"/>[end]
|
||||
<select name="dir_pagestart" onchange="submit()">
|
||||
[for picklist]
|
||||
<option [is picklist.count dir_pagestart]selected[end] value="[picklist.count]">Page [picklist.page]: [picklist.start] to [picklist.end]</option>
|
||||
[end]
|
||||
</select>
|
||||
<input type="submit" value="Go" />
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
[end][end]
|
||||
</table>
|
||||
|
||||
<div id="vc_main_body">
|
||||
<!-- ************************************************************** -->
|
||||
|
||||
<div id="vc_togglables">
|
||||
[is roottype "svn"]
|
||||
[if-any rev]r<a href="[revision_href]">[rev]</a>[end]
|
||||
[else]
|
||||
[is num_dead "0"]
|
||||
[else]
|
||||
[if-any attic_showing]
|
||||
<a href="[hide_attic_href]">Hide
|
||||
[else]
|
||||
<a href="[show_attic_href]">Show
|
||||
[end]
|
||||
dead files</a>
|
||||
[end]
|
||||
[end]
|
||||
</div>
|
||||
|
||||
<table cellspacing="2" class="fixed" id="dirlist">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 200px" class="vc_header[is sortby "file"]_sort[end]">
|
||||
<a href="[sortby_file_href]#dirlist">File
|
||||
[is sortby "file"]
|
||||
<img class="vc_sortarrow" alt="[is sortdir "down"](rev)[end]"
|
||||
width="13" height="13"
|
||||
src="[docroot]/images/[is sortdir "up"]up[else]down[end].png" />
|
||||
[end]
|
||||
</a>
|
||||
</th>
|
||||
<th class="vc_header[is sortby "rev"]_sort[end]">
|
||||
<a href="[sortby_rev_href]#dirlist">Last Change
|
||||
[is sortby "rev"]
|
||||
<img class="vc_sortarrow" alt="[is sortdir "down"](rev)[end]"
|
||||
width="13" height="13"
|
||||
src="[docroot]/images/[is sortdir "up"]up[else]down[end].png" />
|
||||
[end]
|
||||
</a>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
[if-any up_href]
|
||||
<tr class="vc_row_odd">
|
||||
<td colspan="2">
|
||||
<a href="[up_href]">
|
||||
<img src="[docroot]/images/back_small.png" alt="" class="vc_icon"
|
||||
/> ../</a>
|
||||
</td>
|
||||
</tr>
|
||||
[end]
|
||||
[for entries]
|
||||
[define click_href][is entries.pathtype "dir"][entries.view_href][else][if-any entries.prefer_markup][entries.view_href][else][entries.download_href][end][end][end]
|
||||
|
||||
<tr class="vc_row_[if-index entries even]even[else]odd[end]">
|
||||
<td style="width: 200px" onclick="jumpTo('[click_href]')">
|
||||
<a name="[entries.anchor]" href="[click_href]" title="[is entries.pathtype "dir"]View Directory Contents[else][if-any entries.prefer_markup]View[else]Download[end] File Contents[end]">
|
||||
<img src="[docroot]/images/[is entries.pathtype "dir"]dir[else][is entries.state "dead"]broken[else]text[end][end].png" alt="" class="vc_icon" />
|
||||
[entries.name][is entries.pathtype "dir"]/[end]</a>
|
||||
[is entries.state "dead"](dead)[end]
|
||||
</td>
|
||||
|
||||
<td [if-any entries.log_href]onclick="jumpTo('[entries.log_href]')"[end]>
|
||||
[if-any entries.rev]
|
||||
<strong>[if-any entries.log_href]<a href="[entries.log_href]" title="Revision [entries.rev]">[entries.rev]</a>[else][entries.rev][end]</strong>
|
||||
([entries.ago] ago)
|
||||
by <em>[entries.author]</em>:
|
||||
[entries.log]
|
||||
[is entries.pathtype "dir"][is roottype "cvs"]
|
||||
<em>(from [entries.log_file]/[entries.log_rev])</em>
|
||||
[end][end]
|
||||
[end]
|
||||
</td>
|
||||
</tr>
|
||||
[end]
|
||||
</tbody>
|
||||
|
||||
</table>
|
||||
|
||||
<div id="vc_view_summary">
|
||||
[if-any search_re_form]
|
||||
<form class="inline" method="get" action="[search_re_action]">
|
||||
<div class="inline">
|
||||
[for search_re_hidden_values]<input type="hidden" name="[search_re_hidden_values.name]" value="[search_re_hidden_values.value]"/>[end]
|
||||
<input type="text" name="search" value="[search_re]" />
|
||||
<input type="submit" value="Search Files" />
|
||||
</div>
|
||||
</form>
|
||||
[if-any search_re]
|
||||
<form class="inline" method="get" action="[search_re_action]">
|
||||
<div class="inline">
|
||||
[for search_re_hidden_values]<input type="hidden" name="[search_re_hidden_values.name]" value="[search_re_hidden_values.value]"/>[end]
|
||||
<input type="submit" value="Show all files" />
|
||||
</div>
|
||||
</form>
|
||||
[end]
|
||||
|
||||
[end]
|
||||
[include "include/pathrev_form.ezt"]
|
||||
|
||||
[files_shown] file[is files_shown "1"][else]s[end] shown
|
||||
</div>
|
||||
|
||||
[include "include/props.ezt"]
|
||||
|
||||
<!-- ************************************************************** -->
|
||||
</div>
|
||||
|
||||
[include "include/footer.ezt"]
|
8
templates-contrib/newvc/templates/docroot/help.css
Normal file
@@ -0,0 +1,8 @@
|
||||
/************************************/
|
||||
/*** ViewVC Help CSS Stylesheet ***/
|
||||
/************************************/
|
||||
body { margin: 0.5em; }
|
||||
img { border: none; }
|
||||
table { width: 100%; }
|
||||
td { vertical-align: top; }
|
||||
col.menu { width:12em; }
|
126
templates-contrib/newvc/templates/docroot/help_dirview.html
Normal file
@@ -0,0 +1,126 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<title>ViewVC Help: Directory View</title>
|
||||
<link rel="stylesheet" href="help.css" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<table>
|
||||
<col class="menu" />
|
||||
<col />
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<h1>ViewVC Help: Directory View</h1>
|
||||
</td>
|
||||
</tr>
|
||||
<tr><td>
|
||||
<h3>Help</h3>
|
||||
<a href="help_rootview.html">General</a><br />
|
||||
<strong>Directory View</strong><br />
|
||||
<a href="help_log.html">Log View</a><br />
|
||||
|
||||
<h3>Internet</h3>
|
||||
<a href="http://viewvc.org/index.html">Home</a><br />
|
||||
<a href="http://viewvc.org/upgrading.html">Upgrading</a><br />
|
||||
<a href="http://viewvc.org/contributing.html">Contributing</a><br />
|
||||
<a href="http://viewvc.org/license-1.html">License</a><br />
|
||||
</td><td colspan="2">
|
||||
|
||||
<p>The directory listing view should be a familiar sight to any
|
||||
computer user. It shows the path of the current directory being viewed
|
||||
at the top of the page. Below that is a table summarizing the
|
||||
directory contents, and then comes actual contents, a sortable list of
|
||||
all files and subdirectories inside the current directory.</p>
|
||||
|
||||
<p><a name="summary"></a>The summary table is made up of some or all
|
||||
of the following rows:</p>
|
||||
<ul>
|
||||
<li><a name="summary-files-shown"><strong>Files Shown</strong></a>
|
||||
- Number of files shown in the directory listing. This might be less
|
||||
than the actual number of files in the directory if a
|
||||
<a href="#option-search">regular expression search</a> is in place,
|
||||
hiding files which don't meet the search criteria. In CVS directory
|
||||
listings, this row will also have a link to toggle display of
|
||||
<a href="help_rootview.html#dead-files">dead files</a>, if any are
|
||||
present.</li>
|
||||
|
||||
<li><a name="summary-revision"><strong>Directory
|
||||
Revision</strong></a> - For Subversion directories only.
|
||||
Shown as "# of #" where the first number is the most recent
|
||||
repository revision where the directory (or a path underneath it)
|
||||
was modified. The second number is just the latest repository
|
||||
revision. Both numbers are links to
|
||||
<a href="help_rootview.html#view-rev">revision views</a></li>
|
||||
|
||||
<li><a name="summary-sticky-revision-tag"><strong>Sticky
|
||||
Revision/Tag</strong></a> - shows the current
|
||||
<a href="help_rootview.html#sticky-revision-tag">sticky revision or
|
||||
tag</a> and contains form fields to set or clear it.</li>
|
||||
|
||||
<li><a name="summary-search"><strong>Current Search</strong></a> -
|
||||
If a <a href="#option-search">regular expression search</a> is in place,
|
||||
shows the search string.</li>
|
||||
|
||||
<li><a name="summary-query"><strong>Query</strong></a> - Provides
|
||||
a link to a <a href="help_rootview.html#view-query">query form</a>
|
||||
for the directory</li>
|
||||
</ul>
|
||||
|
||||
<p><a name="list"></a>The actual directory list is a table with
|
||||
filenames and directory names in one column and information about the
|
||||
most recent revisions where each file or directory was modified in the
|
||||
other columns. Column headers can be clicked to sort the directory
|
||||
entries in order by a column, and clicked again to reverse the sort
|
||||
order.</p>
|
||||
|
||||
<p>
|
||||
<!-- If using directory.ezt template -->
|
||||
File names are links to <a href="help_log.html">log views</a>
|
||||
showing a list of revisions where a file was modified. Revision
|
||||
numbers are links to either
|
||||
<a href="help_rootview.html#view-markup">view</a>
|
||||
or <a href="help_rootview.html#view-checkout">download</a> a file
|
||||
(depending on its file type). The links are reversed for directories.
|
||||
Directory revision numbers are links to <a href="help_log.html">log
|
||||
views</a>, while directory names are links showing the contents of those
|
||||
directories.
|
||||
|
||||
<!-- If using dir_alt.ezt template -->
|
||||
<!--
|
||||
File and directory names are links to retrieve their contents.
|
||||
File links may be either
|
||||
<a href="help_rootview.html#view-markup">view</a>
|
||||
or <a href="help_rootview.html#view-download">download</a> links
|
||||
depending on the file type. Directory links go to directory
|
||||
listings. Revision numbers are links to <a href="help_log.html">log
|
||||
views</a> showing lists of revisions where a file or directory was
|
||||
modified.
|
||||
-->
|
||||
|
||||
Also, in CVS repositories with the <a
|
||||
href="help_rootview.html#view-graph">graph view</a> enabled, there
|
||||
will be small icons next to file names which are links to revision
|
||||
graphs.</p>
|
||||
|
||||
<p>Depending on how ViewVC is configured, there may be more options
|
||||
at the bottom of directory pages:</p>
|
||||
|
||||
<ul>
|
||||
<li><a name="option-search"><strong>Regular expression
|
||||
search</strong></a> - If enabled, will show a form field accepting
|
||||
a search string (a
|
||||
<a href="http://doc.python.org/lib/re-syntax.html">python regular
|
||||
expression</a>). Once submitted, only files that have at least
|
||||
one occurance of the expression will show up in directory listings.
|
||||
</li>
|
||||
<li><a name="option-tarball"><strong>Tarball download</strong></a> -
|
||||
If enabled, will show a link to download a gzipped tar archive of
|
||||
the directory contents.</li>
|
||||
</ul>
|
||||
|
||||
</td></tr></table>
|
||||
<hr />
|
||||
<address><a href="mailto:users@viewvc.tigris.org">ViewVC Users Mailinglist</a></address>
|
||||
</body>
|
||||
</html>
|
71
templates-contrib/newvc/templates/docroot/help_log.html
Normal file
@@ -0,0 +1,71 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<title>ViewVC Help: Log View</title>
|
||||
<link rel="stylesheet" href="help.css" type="text/css" />
|
||||
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
|
||||
</head>
|
||||
<body>
|
||||
<table>
|
||||
<col class="menu" />
|
||||
<col />
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<h1>ViewVC Help: Log View</h1>
|
||||
</td>
|
||||
</tr>
|
||||
<tr><td>
|
||||
<h3>Help</h3>
|
||||
<a href="help_rootview.html">General</a><br />
|
||||
<a href="help_dirview.html">Directory View</a><br />
|
||||
<strong>Log View</strong><br />
|
||||
|
||||
<h3>Internet</h3>
|
||||
<a href="http://viewvc.org/index.html">Home</a><br />
|
||||
<a href="http://viewvc.org/upgrading.html">Upgrading</a><br />
|
||||
<a href="http://viewvc.org/contributing.html">Contributing</a><br />
|
||||
<a href="http://viewvc.org/license-1.html">License</a><br />
|
||||
</td><td colspan="2">
|
||||
<p>
|
||||
The log view displays the revision history of the selected source
|
||||
file or directory. For each revision the following information is
|
||||
displayed:
|
||||
|
||||
<ul>
|
||||
<li>The revision number. In Subversion repositories, this is a
|
||||
link to the <a href="help_rootview.html#view-rev">revision
|
||||
view</a></li>
|
||||
<li>For files, links to
|
||||
<a href="help_rootview.html#view-markup">view</a>,
|
||||
<a href="help_rootview.html#view-checkout">download</a>, and
|
||||
<a href="help_rootview.html#view-annotate">annotate</a> the
|
||||
revision. For directories, a link to
|
||||
<a href="help_dirview.html">list directory contents</a></li>
|
||||
<li>A link to select the revision for diffs (see below)</li>
|
||||
<li>The date and age of the change</li>
|
||||
<li>The author of the modification</li>
|
||||
<li>The CVS branch (usually <em>MAIN</em>, if not on a branch)</li>
|
||||
<li>Possibly a list of CVS tags bound to the revision (if any)</li>
|
||||
<li>The size of the change measured in added and removed lines of
|
||||
code. (CVS only)</li>
|
||||
<li>The size of the file in bytes at the time of the revision
|
||||
(Subversion only)</li>
|
||||
<li>Links to view diffs to the previous revision or possibly to
|
||||
an arbitrary selected revision (if any, see above)</li>
|
||||
<li>If the revision is the result of a copy, the path and revision
|
||||
copied from</li>
|
||||
<li>If the revision precedes a copy or rename, the path at the
|
||||
time of the revision</li>
|
||||
<li>And last but not least, the commit log message which should tell
|
||||
about the reason for the change.</li>
|
||||
</ul>
|
||||
<p>
|
||||
At the bottom of the page you will find a form which allows
|
||||
to request diffs between arbitrary revisions.
|
||||
</p>
|
||||
</td></tr></table>
|
||||
<hr />
|
||||
<address><a href="mailto:users@viewvc.tigris.org">ViewVC Users Mailinglist</a></address>
|
||||
</body>
|
||||
</html>
|
66
templates-contrib/newvc/templates/docroot/help_query.html
Normal file
@@ -0,0 +1,66 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<title>ViewVC Help: Query The Commit Database</title>
|
||||
<link rel="stylesheet" href="help.css" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<table>
|
||||
<col class="menu" />
|
||||
<col />
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<h1>ViewVC Help: Query The Commit Database</h1>
|
||||
</td>
|
||||
</tr>
|
||||
<tr><td>
|
||||
<h3>Other Help:</h3>
|
||||
<a href="help_rootview.html">General</a><br />
|
||||
<a href="help_dirview.html">Directory View</a><br />
|
||||
<a href="help_log.html">Classic Log View</a><br />
|
||||
<a href="help_logtable.html">Alternative Log View</a><br />
|
||||
<strong>Query Database</strong>
|
||||
|
||||
<h3>Internet</h3>
|
||||
<a href="http://viewvc.org/index.html">Home</a><br />
|
||||
<a href="http://viewvc.org/upgrading.html">Upgrading</a><br />
|
||||
<a href="http://viewvc.org/contributing.html">Contributing</a><br />
|
||||
<a href="http://viewvc.org/license-1.html">License</a><br />
|
||||
</td><td colspan="2">
|
||||
|
||||
<p>
|
||||
Select your parameters for querying the CVS commit database in the
|
||||
form at the top of the page. You
|
||||
can search for multiple matches by typing a comma-seperated list
|
||||
into the text fields. Regular expressions, and wildcards are also
|
||||
supported. Blank text input fields are treated as wildcards.
|
||||
</p>
|
||||
<p>
|
||||
Any of the text entry fields can take a comma-seperated list of
|
||||
search arguments. For example, to search for all commits from
|
||||
authors <em>jpaint</em> and <em>gstein</em>, just type: <code>jpaint,
|
||||
gstein</code> in the <em>Author</em> input box. If you are searching
|
||||
for items containing spaces or quotes, you will need to quote your
|
||||
request. For example, the same search above with quotes is:
|
||||
<code>"jpaint", "gstein"</code>.
|
||||
</p>
|
||||
<p>
|
||||
Wildcard and regular expression searches are entered in a similar
|
||||
way to the quoted requests. You must quote any wildcard or
|
||||
regular expression request, and a command character preceeds the
|
||||
first quote. The command character <code>l</code>(lowercase L) is for wildcard
|
||||
searches, and the wildcard character is a percent (<code>%</code>). The
|
||||
command character for regular expressions is <code>r</code>, and is
|
||||
passed directly to MySQL, so you'll need to refer to the MySQL
|
||||
manual for the exact regex syntax. It is very similar to Perl. A
|
||||
wildard search for all files with a <em>.py</em> extention is:
|
||||
<code>l"%.py"</code> in the <em>File</em> input box. The same search done
|
||||
with a regular expression is: <code>r".*\.py"</code>.
|
||||
</p>
|
||||
<p>
|
||||
All search types can be mixed, as long as they are seperated by
|
||||
commas.
|
||||
</p>
|
||||
</td></tr></table>
|
||||
</body></html>
|
166
templates-contrib/newvc/templates/docroot/help_rootview.html
Normal file
@@ -0,0 +1,166 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<title>ViewVC Help: General</title>
|
||||
<link rel="stylesheet" href="help.css" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<table>
|
||||
<col class="menu" />
|
||||
<col />
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<h1>ViewVC Help: General</h1>
|
||||
</td>
|
||||
</tr>
|
||||
<tr><td>
|
||||
<h3>Help</h3>
|
||||
<strong>General</strong><br />
|
||||
<a href="help_dirview.html">Directory View</a><br />
|
||||
<a href="help_log.html">Log View</a><br />
|
||||
|
||||
<h3>Internet</h3>
|
||||
<a href="http://viewvc.org/index.html">Home</a><br />
|
||||
<a href="http://viewvc.org/upgrading.html">Upgrading</a><br />
|
||||
<a href="http://viewvc.org/contributing.html">Contributing</a><br />
|
||||
<a href="http://viewvc.org/license-1.html">License</a><br />
|
||||
</td><td colspan="2">
|
||||
|
||||
<p><em>ViewVC</em> is a WWW interface for CVS and Subversion
|
||||
repositories. It allows you to browse the files and directories in a
|
||||
repository while showing you metadata from the repository history: log
|
||||
messages, modification dates, author names, revision numbers, copy
|
||||
history, and so on. It provides several different views of repository
|
||||
data to help you find the information you are looking for:</p>
|
||||
|
||||
<ul>
|
||||
<li><a name="view-dir" href="help_dirview.html"><strong>Directory
|
||||
View</strong></a> - Shows a list of files and subdirectories in a
|
||||
directory of the repository, along with metadata like author names and
|
||||
log entries.</li>
|
||||
|
||||
<li><a name="view-log" href="help_log.html"><strong>Log
|
||||
View</strong></a> - Shows a revision by revision list of all the
|
||||
changes that have made to a file or directory in the repository, with
|
||||
metadata and links to views of each revision.</li>
|
||||
|
||||
<li><a name="view-markup"><strong>File Contents View (Markup
|
||||
View)</strong></a> - Shows the contents of a file at a particular
|
||||
revision, with revision information at the top of the page. File
|
||||
revisions which are GIF, PNG, or JPEG images are displayed inline on
|
||||
the page. Other file types are displayed as marked up text. The markup
|
||||
may be limited to turning URLs and email addresses into links, or
|
||||
configured to show colorized source code.</li>
|
||||
|
||||
<li><a name="view-checkout"><strong>File Download (Checkout
|
||||
View)</strong></a> - Retrieves the unaltered contents of a file
|
||||
revision. Browsers may try to display the file, or just save it to
|
||||
disk.</li>
|
||||
|
||||
<li><a name="view-annotate"><strong>File Annotate View</strong></a> -
|
||||
Shows the contents of a file revision and breaks it down line by line,
|
||||
showing the revision number where each one was last modified, along
|
||||
with links and other information. <em>This view is disabled in some
|
||||
ViewVC configurations</em></li>
|
||||
|
||||
<li><a name="view-diff"><strong>File Diff View</strong></a> - Shows
|
||||
the changes made between two revisions of a file</li>
|
||||
|
||||
<li><a name="view-tarball"><strong>Directory Tarball View</strong> -
|
||||
Retrieves a gzipped tar archive containing the contents of a
|
||||
directory.<em>This view is disabled in the default ViewVC
|
||||
configuration.</em></li>
|
||||
|
||||
<li><a name="view-query"><strong>Directory Query View</strong></a> -
|
||||
Shows information about changes made to all subdirectories and files
|
||||
under a parent directory, sorted and filtered by criteria you specify.
|
||||
<em>This view is disabled in the default ViewVC configuration.</em>
|
||||
</li>
|
||||
|
||||
<li><a name="view-rev"><strong>Revision View</strong> - Shows
|
||||
information about a revision including log message, author, and a list
|
||||
of changed paths. <em>For Subversion repositories only.</em></li>
|
||||
|
||||
<li><a name="view-graph"><strong>Graph View</strong></a> - Shows a
|
||||
graphical representation of a file's revisions and branches complete
|
||||
with tag and author names and links to markup and diff pages.
|
||||
<em>For CVS repositories only, and disabled in the default
|
||||
configuration.</em></li>
|
||||
</ul>
|
||||
|
||||
<h3><a name="multiple-repositories">Multiple Repositories</a></h3>
|
||||
|
||||
<p>A single installation of ViewVC is often used to provide access to
|
||||
more than one repository. In these installations, ViewVC shows a
|
||||
<em>Project Root</em> drop down box in the top right corner of every
|
||||
generated page to allow for quick access to any repository.</p>
|
||||
|
||||
<h3><a name="sticky-revision-tag">Sticky Revision and Tag</a></h3>
|
||||
|
||||
<p>By default, ViewVC will show the files and directories and revisions
|
||||
that currently exist in the repository. But it's also possible to browse
|
||||
the contents of a repository at a point in its past history by choosing
|
||||
a "sticky tag" (in CVS) or a "sticky revision" (in Subversion) from the
|
||||
forms at the top of directory and log pages. They're called sticky
|
||||
because once they're chosen, they stick around when you navigate to
|
||||
other pages, until you reset them. When they're set, directory and log
|
||||
pages only show revisions preceding the specified point in history. In
|
||||
CVS, when a tag refers to a branch or a revision on a branch, only
|
||||
revisions from the branch history are shown, including branch points and
|
||||
their preceding revisions.</p>
|
||||
|
||||
<h3><a name="dead-files">Dead Files</a></h3>
|
||||
|
||||
<p>In CVS directory listings, ViewVC can optionally display dead files.
|
||||
Dead files are files which used to be in a directory but are currently
|
||||
deleted, or files which just don't exist in the currently selected
|
||||
<a href="#sticky-revision-tag">sticky tag</a>. Dead files cannot be
|
||||
shown in Subversion repositories. The only way to see a deleted file in
|
||||
a Subversion directory is to navigate to a sticky revision where the
|
||||
file previously existed.</p>
|
||||
|
||||
<h3><a name="artificial-tags">Artificial Tags</a></h3>
|
||||
|
||||
<p>In CVS Repositories, ViewVC adds artificial tags <em>HEAD</em> and
|
||||
<em>MAIN</em> to tag listings and accepts them in place of revision
|
||||
numbers and real tag names in all URLs. <em>MAIN</em> acts like a branch
|
||||
tag pointing at the default branch, while <em>HEAD</em> acts like a
|
||||
revision tag pointing to the latest revision on the default branch. The
|
||||
default branch is usually just the trunk, but may be set to other
|
||||
branches inside individual repository files. CVS will always check out
|
||||
revisions from a file's default branch when no other branch is specified
|
||||
on the command line.</p>
|
||||
|
||||
<h3><a name="more-information">More Information</a></h3>
|
||||
|
||||
<p>More information about <em>ViewVC</em> is available from
|
||||
<a href="http://viewvc.org/">viewvc.org</a>.
|
||||
See the links below for guides to CVS and Subversion</p>
|
||||
|
||||
<h4>Documentation about CVS</h4>
|
||||
<blockquote>
|
||||
<p>
|
||||
<a href="http://cvsbook.red-bean.com/"><em>Open Source
|
||||
Development with CVS</em></a><br />
|
||||
<a href="http://www.loria.fr/~molli/cvs/doc/cvs_toc.html">CVS
|
||||
User's Guide</a><br />
|
||||
<a href="http://cellworks.washington.edu/pub/docs/cvs/tutorial/cvs_tutorial_1.html">Another CVS tutorial</a><br />
|
||||
<a href="http://www.csc.calpoly.edu/~dbutler/tutorials/winter96/cvs/">Yet another CVS tutorial (a little old, but nice)</a><br />
|
||||
<a href="http://www.cs.utah.edu/dept/old/texinfo/cvs/FAQ.txt">An old but very useful FAQ about CVS</a>
|
||||
</p>
|
||||
</blockquote>
|
||||
|
||||
<h4>Documentation about Subversion</h3>
|
||||
<blockquote>
|
||||
<p>
|
||||
<a href="http://svnbook.red-bean.com/"><em>Version Control with
|
||||
Subversion</em></a><br />
|
||||
</p>
|
||||
</blockquote>
|
||||
|
||||
</td></tr></table>
|
||||
<hr />
|
||||
<address><a href="mailto:users@viewvc.tigris.org">ViewVC Users Mailinglist</a></address>
|
||||
</body>
|
||||
</html>
|
BIN
templates-contrib/newvc/templates/docroot/images/back.png
Normal file
After Width: | Height: | Size: 337 B |
BIN
templates-contrib/newvc/templates/docroot/images/back_small.png
Normal file
After Width: | Height: | Size: 205 B |
BIN
templates-contrib/newvc/templates/docroot/images/broken.png
Normal file
After Width: | Height: | Size: 247 B |
BIN
templates-contrib/newvc/templates/docroot/images/cvs-logo.png
Normal file
After Width: | Height: | Size: 601 B |
BIN
templates-contrib/newvc/templates/docroot/images/dir.png
Normal file
After Width: | Height: | Size: 228 B |
BIN
templates-contrib/newvc/templates/docroot/images/down.png
Normal file
After Width: | Height: | Size: 167 B |
After Width: | Height: | Size: 1004 B |
BIN
templates-contrib/newvc/templates/docroot/images/forward.png
Normal file
After Width: | Height: | Size: 338 B |
BIN
templates-contrib/newvc/templates/docroot/images/svn-logo.png
Normal file
After Width: | Height: | Size: 1.0 KiB |
BIN
templates-contrib/newvc/templates/docroot/images/text.png
Normal file
After Width: | Height: | Size: 226 B |
BIN
templates-contrib/newvc/templates/docroot/images/up.png
Normal file
After Width: | Height: | Size: 168 B |
BIN
templates-contrib/newvc/templates/docroot/images/viewvc-logo.png
Normal file
After Width: | Height: | Size: 8.2 KiB |
4
templates-contrib/newvc/templates/docroot/scripts.js
Normal file
@@ -0,0 +1,4 @@
|
||||
function jumpTo(url)
|
||||
{
|
||||
window.location = url;
|
||||
}
|
332
templates-contrib/newvc/templates/docroot/styles.css
Normal file
@@ -0,0 +1,332 @@
|
||||
/*******************************/
|
||||
/*** ViewVC CSS Stylesheet ***/
|
||||
/*******************************/
|
||||
|
||||
/*** Standard Tags ***/
|
||||
html, body {
|
||||
background-color: white;
|
||||
color: black;
|
||||
font-family: sans-serif;
|
||||
font-size: 100%;
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
color: rgb(30%,30%,60%);
|
||||
}
|
||||
img { border: none; }
|
||||
table {
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
border: none;
|
||||
}
|
||||
td, th {
|
||||
vertical-align: top;
|
||||
}
|
||||
th { white-space: nowrap; }
|
||||
table.auto {
|
||||
width: auto;
|
||||
}
|
||||
table.fixed {
|
||||
width: 100%;
|
||||
table-layout: fixed;
|
||||
}
|
||||
table.fixed td {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
form { margin: 0; }
|
||||
address { font-style: normal; display: inline; }
|
||||
.inline { display: inline; }
|
||||
|
||||
/*** Icons ***/
|
||||
.vc_icon {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border: none;
|
||||
padding: 0 1px;
|
||||
}
|
||||
|
||||
#vc_header {
|
||||
padding: 0 0 10px 0;
|
||||
border-bottom: 10px solid #94bd5e;
|
||||
}
|
||||
|
||||
#vc_footer {
|
||||
text-align: right;
|
||||
font-size: 85%;
|
||||
padding: 10px 0 0 0;
|
||||
border-top: 10px solid #94bd5e;
|
||||
}
|
||||
|
||||
#vc_topmatter {
|
||||
float: right;
|
||||
text-align: right;
|
||||
font-size: 85%;
|
||||
}
|
||||
|
||||
#vc_current_path {
|
||||
color: rgb(50%,50%,50%);
|
||||
padding: 10px 0;
|
||||
font-size: 140%;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
#vc_current_path a {
|
||||
color: rgb(60%,60%,60%);
|
||||
}
|
||||
|
||||
#vc_current_path a:hover {
|
||||
background-color: rgb(90%,90%,90%);
|
||||
}
|
||||
|
||||
#vc_current_path .thisitem {
|
||||
color: #94bd5e;
|
||||
}
|
||||
|
||||
#vc_current_path .pathdiv {
|
||||
padding: 0 0.1em;
|
||||
}
|
||||
|
||||
#vc_view_selection_group {
|
||||
background: black;
|
||||
color: white;
|
||||
margin: 0 0 5px 0;
|
||||
padding: 5px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
#vc_view_selection_group a {
|
||||
padding: 5px;
|
||||
font-size: 100%;
|
||||
color: white;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#vc_view_selection_group a.vc_view_link_this, #vc_view_selection_group a.vc_view_link:hover {
|
||||
color: #94bd5e;
|
||||
}
|
||||
|
||||
#vc_view_selection_group a:hover {
|
||||
background-color: black;
|
||||
}
|
||||
|
||||
#vc_view_main {
|
||||
border-top: 1px solid black;
|
||||
border-bottom: 1px solid black;
|
||||
}
|
||||
|
||||
#vc_togglables {
|
||||
text-align: right;
|
||||
font-size: 85%;
|
||||
}
|
||||
|
||||
#vc_main_body {
|
||||
background: white;
|
||||
padding: 5px 0 20px 0;
|
||||
}
|
||||
|
||||
#vc_view_summary {
|
||||
font-size: 85%;
|
||||
text-align: right;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
|
||||
/*** Table Headers ***/
|
||||
.vc_header, .vc_header_sort {
|
||||
text-align: left;
|
||||
vertical-align: top;
|
||||
border-bottom: 1px solid black;
|
||||
background-color: rgb(80%,80%,80%);
|
||||
}
|
||||
.vc_header_sort {
|
||||
background-color: rgb(85%,85%,85%);
|
||||
}
|
||||
|
||||
|
||||
/*** Table Rows ***/
|
||||
.vc_row_even {
|
||||
background-color: rgb(95%,95%,95%);
|
||||
}
|
||||
.vc_row_odd {
|
||||
background-color: rgb(90%,90%,90%);
|
||||
}
|
||||
|
||||
|
||||
/*** Directory View ***/
|
||||
#dirlist td, #dirlist th {
|
||||
padding: 0.2em;
|
||||
vertical-align: middle;
|
||||
}
|
||||
#dirlist tr:hover {
|
||||
background-color: white;
|
||||
}
|
||||
|
||||
|
||||
/*** Log messages ***/
|
||||
.vc_log {
|
||||
/* unfortunately, white-space: pre-wrap isn't widely supported ... */
|
||||
white-space: -moz-pre-wrap; /* Mozilla based browsers */
|
||||
white-space: -pre-wrap; /* Opera 4 - 6 */
|
||||
white-space: -o-pre-wrap; /* Opera >= 7 */
|
||||
white-space: pre-wrap; /* CSS3 */
|
||||
word-wrap: break-word; /* IE 5.5+ */
|
||||
}
|
||||
|
||||
|
||||
/*** Properties Listing ***/
|
||||
.vc_properties {
|
||||
margin: 1em 0;
|
||||
}
|
||||
.vc_properties h2 {
|
||||
font-size: 115%;
|
||||
}
|
||||
.vc_properties td, .vc_properties th {
|
||||
padding: 0.2em;
|
||||
}
|
||||
|
||||
|
||||
/*** File Content Markup Styles ***/
|
||||
.vc_summary {
|
||||
background-color: #eeeeee;
|
||||
}
|
||||
#vc_file td {
|
||||
border-right-style: solid;
|
||||
border-right-color: #505050;
|
||||
text-decoration: none;
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
padding: 1px 5px;
|
||||
}
|
||||
.vc_file_line_number {
|
||||
border-right-width: 1px;
|
||||
background-color: #eeeeee;
|
||||
color: #505050;
|
||||
text-align: right;
|
||||
}
|
||||
.vc_file_line_author, .vc_file_line_rev {
|
||||
border-right-width: 1px;
|
||||
text-align: right;
|
||||
}
|
||||
.vc_file_line_text {
|
||||
border-right-width: 0px;
|
||||
background-color: white;
|
||||
font-family: monospace;
|
||||
text-align: left;
|
||||
white-space: pre;
|
||||
width: 100%;
|
||||
}
|
||||
.pygments-c { color: #408080; font-style: italic } /* Comment */
|
||||
.pygments-err { border: 1px solid #FF0000 } /* Error */
|
||||
.pygments-k { color: #008000; font-weight: bold } /* Keyword */
|
||||
.pygments-o { color: #666666 } /* Operator */
|
||||
.pygments-cm { color: #408080; font-style: italic } /* Comment.Multiline */
|
||||
.pygments-cp { color: #BC7A00 } /* Comment.Preproc */
|
||||
.pygments-c1 { color: #408080; font-style: italic } /* Comment.Single */
|
||||
.pygments-cs { color: #408080; font-style: italic } /* Comment.Special */
|
||||
.pygments-gd { color: #A00000 } /* Generic.Deleted */
|
||||
.pygments-ge { font-style: italic } /* Generic.Emph */
|
||||
.pygments-gr { color: #FF0000 } /* Generic.Error */
|
||||
.pygments-gh { color: #000080; font-weight: bold } /* Generic.Heading */
|
||||
.pygments-gi { color: #00A000 } /* Generic.Inserted */
|
||||
.pygments-go { color: #808080 } /* Generic.Output */
|
||||
.pygments-gp { color: #000080; font-weight: bold } /* Generic.Prompt */
|
||||
.pygments-gs { font-weight: bold } /* Generic.Strong */
|
||||
.pygments-gu { color: #800080; font-weight: bold } /* Generic.Subheading */
|
||||
.pygments-gt { color: #0040D0 } /* Generic.Traceback */
|
||||
.pygments-kc { color: #008000; font-weight: bold } /* Keyword.Constant */
|
||||
.pygments-kd { color: #008000; font-weight: bold } /* Keyword.Declaration */
|
||||
.pygments-kp { color: #008000 } /* Keyword.Pseudo */
|
||||
.pygments-kr { color: #008000; font-weight: bold } /* Keyword.Reserved */
|
||||
.pygments-kt { color: #B00040 } /* Keyword.Type */
|
||||
.pygments-m { color: #666666 } /* Literal.Number */
|
||||
.pygments-s { color: #BA2121 } /* Literal.String */
|
||||
.pygments-na { color: #7D9029 } /* Name.Attribute */
|
||||
.pygments-nb { color: #008000 } /* Name.Builtin */
|
||||
.pygments-nc { color: #0000FF; font-weight: bold } /* Name.Class */
|
||||
.pygments-no { color: #880000 } /* Name.Constant */
|
||||
.pygments-nd { color: #AA22FF } /* Name.Decorator */
|
||||
.pygments-ni { color: #999999; font-weight: bold } /* Name.Entity */
|
||||
.pygments-ne { color: #D2413A; font-weight: bold } /* Name.Exception */
|
||||
.pygments-nf { color: #0000FF } /* Name.Function */
|
||||
.pygments-nl { color: #A0A000 } /* Name.Label */
|
||||
.pygments-nn { color: #0000FF; font-weight: bold } /* Name.Namespace */
|
||||
.pygments-nt { color: #008000; font-weight: bold } /* Name.Tag */
|
||||
.pygments-nv { color: #19177C } /* Name.Variable */
|
||||
.pygments-ow { color: #AA22FF; font-weight: bold } /* Operator.Word */
|
||||
.pygments-w { color: #bbbbbb } /* Text.Whitespace */
|
||||
.pygments-mf { color: #666666 } /* Literal.Number.Float */
|
||||
.pygments-mh { color: #666666 } /* Literal.Number.Hex */
|
||||
.pygments-mi { color: #666666 } /* Literal.Number.Integer */
|
||||
.pygments-mo { color: #666666 } /* Literal.Number.Oct */
|
||||
.pygments-sb { color: #BA2121 } /* Literal.String.Backtick */
|
||||
.pygments-sc { color: #BA2121 } /* Literal.String.Char */
|
||||
.pygments-sd { color: #BA2121; font-style: italic } /* Literal.String.Doc */
|
||||
.pygments-s2 { color: #BA2121 } /* Literal.String.Double */
|
||||
.pygments-se { color: #BB6622; font-weight: bold } /* Literal.String.Escape */
|
||||
.pygments-sh { color: #BA2121 } /* Literal.String.Heredoc */
|
||||
.pygments-si { color: #BB6688; font-weight: bold } /* Literal.String.Interpol */
|
||||
.pygments-sx { color: #008000 } /* Literal.String.Other */
|
||||
.pygments-sr { color: #BB6688 } /* Literal.String.Regex */
|
||||
.pygments-s1 { color: #BA2121 } /* Literal.String.Single */
|
||||
.pygments-ss { color: #19177C } /* Literal.String.Symbol */
|
||||
.pygments-bp { color: #008000 } /* Name.Builtin.Pseudo */
|
||||
.pygments-vc { color: #19177C } /* Name.Variable.Class */
|
||||
.pygments-vg { color: #19177C } /* Name.Variable.Global */
|
||||
.pygments-vi { color: #19177C } /* Name.Variable.Instance */
|
||||
.pygments-il { color: #666666 } /* Literal.Number.Integer.Long */
|
||||
|
||||
|
||||
/*** Diff Styles ***/
|
||||
.vc_diff_plusminus { width: 1em; }
|
||||
.vc_diff_remove, .vc_diff_add, .vc_diff_changes1, .vc_diff_changes2 {
|
||||
font-family: monospace;
|
||||
white-space: pre;
|
||||
}
|
||||
.vc_diff_remove { background: rgb(100%,60%,60%); }
|
||||
.vc_diff_add { background: rgb(60%,100%,60%); }
|
||||
.vc_diff_changes1 { background: rgb(100%,100%,70%); color: rgb(50%,50%,50%); text-decoration: line-through; }
|
||||
.vc_diff_changes2 { background: rgb(100%,100%,0%); }
|
||||
.vc_diff_nochange, .vc_diff_binary, .vc_diff_error {
|
||||
font-family: sans-serif;
|
||||
font-size: smaller;
|
||||
}
|
||||
|
||||
/*** Intraline Diff Styles ***/
|
||||
.vc_idiff_add {
|
||||
background-color: #aaffaa;
|
||||
}
|
||||
.vc_idiff_change {
|
||||
background-color:#ffff77;
|
||||
}
|
||||
.vc_idiff_remove {
|
||||
background-color:#ffaaaa;
|
||||
}
|
||||
.vc_idiff_empty {
|
||||
background-color:#e0e0e0;
|
||||
}
|
||||
|
||||
table.vc_idiff col.content {
|
||||
width: 50%;
|
||||
}
|
||||
table.vc_idiff tbody {
|
||||
font-family: monospace;
|
||||
/* unfortunately, white-space: pre-wrap isn't widely supported ... */
|
||||
white-space: -moz-pre-wrap; /* Mozilla based browsers */
|
||||
white-space: -pre-wrap; /* Opera 4 - 6 */
|
||||
white-space: -o-pre-wrap; /* Opera >= 7 */
|
||||
white-space: pre-wrap; /* CSS3 */
|
||||
word-wrap: break-word; /* IE 5.5+ */
|
||||
}
|
||||
table.vc_idiff tbody th {
|
||||
background-color:#e0e0e0;
|
||||
text-align:right;
|
||||
}
|
||||
|
||||
|
||||
/*** Query Form ***/
|
||||
.vc_query_form {
|
||||
}
|
51
templates-contrib/newvc/templates/error.ezt
Normal file
@@ -0,0 +1,51 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<!-- ViewVC :: http://www.viewvc.org/ -->
|
||||
<head>
|
||||
<title>ViewVC Exception</title>
|
||||
</head>
|
||||
<body>
|
||||
<h3>An Exception Has Occurred</h3>
|
||||
|
||||
[if-any msg]
|
||||
<p>[msg]</p>
|
||||
[end]
|
||||
|
||||
[if-any status]
|
||||
<h4>HTTP Response Status</h4>
|
||||
<p><pre>[status]</pre></p>
|
||||
<hr />
|
||||
[end]
|
||||
|
||||
[if-any msg][else]
|
||||
<h4>Python Traceback</h4>
|
||||
<p><pre>
|
||||
[stacktrace]
|
||||
</pre></p>
|
||||
[end]
|
||||
|
||||
[# Here follows a bunch of space characters, present to ensure that
|
||||
our error message is larger than 512 bytes so that IE's "Friendly
|
||||
Error Message" won't show. For more information, see
|
||||
http://oreillynet.com/onjava/blog/2002/09/internet_explorer_subverts_err.html]
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
61
templates-contrib/newvc/templates/file.ezt
Normal file
@@ -0,0 +1,61 @@
|
||||
[# setup page definitions]
|
||||
[define page_title]Annotation of:[end]
|
||||
[define help_href][docroot]/help_rootview.html[end]
|
||||
[# end]
|
||||
[include "include/header.ezt" "annotate"]
|
||||
[include "include/fileview.ezt"]
|
||||
|
||||
<div id="vc_main_body">
|
||||
<!-- ************************************************************** -->
|
||||
|
||||
[define last_rev]0[end]
|
||||
[define rowclass]vc_row_odd[end]
|
||||
|
||||
[if-any lines]
|
||||
<div id="vc_file">
|
||||
<table cellspacing="0" cellpadding="0">
|
||||
<tr>
|
||||
<th class="vc_header">Line</th>
|
||||
[is annotation "annotated"]
|
||||
<th class="vc_header">User</th>
|
||||
<th class="vc_header">Rev</th>
|
||||
[end]
|
||||
<th class="vc_header">File contents</th>
|
||||
</tr>
|
||||
[for lines]
|
||||
[is lines.rev last_rev]
|
||||
[else]
|
||||
[is rowclass "vc_row_even"]
|
||||
[define rowclass]vc_row_odd[end]
|
||||
[else]
|
||||
[define rowclass]vc_row_even[end]
|
||||
[end]
|
||||
[end]
|
||||
|
||||
<tr class="[rowclass]" id="l[lines.line_number]">
|
||||
<td class="vc_file_line_number">[lines.line_number]</td>
|
||||
[is annotation "annotated"]
|
||||
<td class="vc_file_line_author">[is lines.rev last_rev] [else][lines.author][end]</td>
|
||||
<td class="vc_file_line_rev">[is lines.rev last_rev] [else][if-any lines.diff_href]<a href="[lines.diff_href]">[end][lines.rev][if-any lines.diff_href]</a>[end][end]</td>
|
||||
[end]
|
||||
<td class="vc_file_line_text">[lines.text]</td>
|
||||
</tr>
|
||||
[define last_rev][lines.rev][end]
|
||||
[end]
|
||||
</table>
|
||||
</div>
|
||||
|
||||
[else]
|
||||
[if-any image_src_href]
|
||||
<div id="vc_file_image">
|
||||
<img src="[image_src_href]" alt="" />
|
||||
</div>
|
||||
[end]
|
||||
[end]
|
||||
|
||||
[include "include/props.ezt"]
|
||||
|
||||
<!-- ************************************************************** -->
|
||||
</div>
|
||||
|
||||
[include "include/footer.ezt"]
|
15
templates-contrib/newvc/templates/graph.ezt
Normal file
@@ -0,0 +1,15 @@
|
||||
[# setup page definitions]
|
||||
[define page_title]Graph of:[end]
|
||||
[define help_href][docroot]/help_rootview.html[end]
|
||||
[# end]
|
||||
|
||||
[include "include/header.ezt" "graph"]
|
||||
|
||||
<div style="text-align:center;">
|
||||
[imagemap]
|
||||
<img usemap="#MyMapName"
|
||||
src="[imagesrc]"
|
||||
alt="Revisions of [where]" />
|
||||
</div>
|
||||
|
||||
[include "include/footer.ezt"]
|
70
templates-contrib/newvc/templates/include/diff_form.ezt
Normal file
@@ -0,0 +1,70 @@
|
||||
|
||||
<div style="border-bottom: solid 1px black;">
|
||||
<p id="diff">This form allows you to request diffs between any two
|
||||
revisions of this file.
|
||||
For each of the two "sides" of the diff,
|
||||
[if-any tags]
|
||||
select a symbolic revision name using the selection box, or choose
|
||||
'Use Text Field' and enter a numeric revision.
|
||||
[else]
|
||||
enter a numeric revision.
|
||||
[end]
|
||||
</p>
|
||||
|
||||
<form method="get" action="[diff_select_action]" id="diff_select">
|
||||
|
||||
<table cellpadding="2" cellspacing="0" class="auto">
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td>
|
||||
[for diff_select_hidden_values]<input type="hidden" name="[diff_select_hidden_values.name]" value="[diff_select_hidden_values.value]"/>[end]
|
||||
Diffs between
|
||||
[if-any tags]
|
||||
<select name="r1">
|
||||
<option value="text" selected="selected">Use Text Field</option>
|
||||
[for tags]
|
||||
<option value="[tags.rev]:[tags.name]">[tags.name]</option>
|
||||
[end]
|
||||
</select>
|
||||
<input type="text" size="12" name="tr1"
|
||||
value="[if-any rev_selected][rev_selected][else][first_revision][end]"
|
||||
onchange="document.getElementById('diff_select').r1.selectedIndex=0" />
|
||||
[else]
|
||||
<input type="text" size="12" name="r1"
|
||||
value="[if-any rev_selected][rev_selected][else][first_revision][end]" />
|
||||
[end]
|
||||
|
||||
and
|
||||
[if-any tags]
|
||||
<select name="r2">
|
||||
<option value="text" selected="selected">Use Text Field</option>
|
||||
[for tags]
|
||||
<option value="[tags.rev]:[tags.name]">[tags.name]</option>
|
||||
[end]
|
||||
</select>
|
||||
<input type="text" size="12" name="tr2"
|
||||
value="[last_revision]"
|
||||
onchange="document.getElementById('diff_select').r2.selectedIndex=0" />
|
||||
[else]
|
||||
<input type="text" size="12" name="r2" value="[last_revision]" />
|
||||
[end]
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td> </td>
|
||||
<td>
|
||||
Type of Diff should be a
|
||||
<select name="diff_format" onchange="submit()">
|
||||
<option value="h" [is diff_format "h"]selected="selected"[end]>Colored Diff</option>
|
||||
<option value="l" [is diff_format "l"]selected="selected"[end]>Long Colored Diff</option>
|
||||
<option value="f" [is diff_format "f"]selected="selected"[end]>Full Colored Diff</option>
|
||||
<option value="u" [is diff_format "u"]selected="selected"[end]>Unidiff</option>
|
||||
<option value="c" [is diff_format "c"]selected="selected"[end]>Context Diff</option>
|
||||
<option value="s" [is diff_format "s"]selected="selected"[end]>Side by Side</option>
|
||||
</select>
|
||||
<input type="submit" value=" Get Diffs " />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
</div>
|
74
templates-contrib/newvc/templates/include/fileview.ezt
Normal file
@@ -0,0 +1,74 @@
|
||||
<table class="auto">
|
||||
<tr>
|
||||
<td>Revision:</td>
|
||||
<td><strong>[if-any revision_href]<a href="[revision_href]">[rev]</a>[else][rev][end]</strong> [if-any vendor_branch] <em>(vendor branch)</em>[end]</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<tr>
|
||||
<td>Committed:</td>
|
||||
<td>[if-any date]<em>[date]</em> [end][if-any ago]([ago] ago) [end][if-any author]by <em>[author]</em>[end]</td>
|
||||
</tr>
|
||||
[if-any orig_path]
|
||||
<tr>
|
||||
<td>Original Path:</td>
|
||||
<td><strong><a href="[orig_href]"><em>[orig_path]</em></a></strong></td>
|
||||
</tr>
|
||||
[end]
|
||||
[if-any branches]
|
||||
<tr>
|
||||
<td>Branch:</td>
|
||||
<td><strong>[branches]</strong></td>
|
||||
</tr>
|
||||
[end]
|
||||
[if-any tags]
|
||||
<tr>
|
||||
<td>CVS Tags:</td>
|
||||
<td><strong>[tags]</strong></td>
|
||||
</tr>
|
||||
[end]
|
||||
[if-any branch_points]
|
||||
<tr>
|
||||
<td>Branch point for:</td>
|
||||
<td><strong>[branch_points]</strong></td>
|
||||
</tr>
|
||||
[end]
|
||||
[is roottype "cvs"][if-any changed]
|
||||
<tr>
|
||||
<td>Changes since <strong>[prev]</strong>:</td>
|
||||
<td><strong>[changed] lines</strong></td>
|
||||
</tr>
|
||||
[end][end]
|
||||
[is roottype "svn"][if-any size]
|
||||
<td>File size:</td>
|
||||
<td>[size] byte(s)</td>
|
||||
</tr>
|
||||
[end][end]
|
||||
[if-any lockinfo]
|
||||
<td>Lock status:</td>
|
||||
<td>[lockinfo]</td>
|
||||
[end]
|
||||
[is state "dead"]
|
||||
<tr>
|
||||
<td>State:</td>
|
||||
<td><strong><em>FILE REMOVED</em></strong></td>
|
||||
</tr>
|
||||
[end]
|
||||
[if-any annotation]
|
||||
[is annotation "binary"]
|
||||
<tr>
|
||||
<td colspan="2"><strong>Unable to calculate annotation data on binary file contents.</strong></td>
|
||||
</tr>
|
||||
[end]
|
||||
[is annotation "error"]
|
||||
<tr>
|
||||
<td colspan="2"><strong>Error occurred while calculating annotation data.</strong></td>
|
||||
</tr>
|
||||
[end]
|
||||
[end]
|
||||
[if-any log]
|
||||
<tr>
|
||||
<td>Log Message:</td>
|
||||
<td><pre class="vc_log">[log]</span></td>
|
||||
</tr>
|
||||
[end]
|
||||
</table>
|
10
templates-contrib/newvc/templates/include/footer.ezt
Normal file
@@ -0,0 +1,10 @@
|
||||
</div> <!-- vc_view_main -->
|
||||
|
||||
<div id="vc_footer">
|
||||
[if-any cfg.general.address]Administered by <address><a href="mailto:[cfg.general.address]">[cfg.general.address]</a></address><br/>[end]
|
||||
Powered by <a href="http://viewvc.tigris.org/">ViewVC [vsn]</a>
|
||||
[if-any rss_href]<br/><a href="[rss_href]" title="RSS 2.0 feed"><img src="[docroot]/images/feed-icon-16x16.jpg" class="vc_icon" alt="RSS 2.0 feed" /></a>[else] [end]
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
63
templates-contrib/newvc/templates/include/header.ezt
Normal file
@@ -0,0 +1,63 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
|
||||
<!-- ViewVC :: http://www.viewvc.org/ -->
|
||||
|
||||
<head>
|
||||
<title>[[]ViewVC] [page_title] [if-any rootname][rootname][if-any where]/[where][end][end]</title>
|
||||
<meta name="generator" content="ViewVC [vsn]" />
|
||||
<link rel="stylesheet" href="[docroot]/styles.css" type="text/css" />
|
||||
<script src="[docroot]/scripts.js"></script>
|
||||
[if-any rss_href]
|
||||
<link rel="alternate" type="application/rss+xml" href="[rss_href]" title="ViewVC RSS: [if-any rootname][rootname][if-any where]/[where][end][end]">
|
||||
[end]
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
<div id="vc_header">
|
||||
|
||||
<div id="vc_topmatter">
|
||||
[if-any username]Logged in as: <strong>[username]</strong> |[end]
|
||||
<a href="[help_href]">ViewVC Help</a>
|
||||
</div>
|
||||
|
||||
<div id="vc_logo">
|
||||
<a href="http://www.viewvc.org/"><img src="[docroot]/images/viewvc-logo.png" alt="ViewVC logotype" width="240" height="70" /></a>
|
||||
</div>
|
||||
|
||||
<div id="vc_view_selection_group">
|
||||
[is pathtype "dir"]
|
||||
<a class="vc_view_link[is view "dir"]_this[end]" href="[view_href]">View Directory</a>
|
||||
[if-any log_href]
|
||||
| <a class="vc_view_link[is view "log"]_this[end]" href="[log_href]">Revision Log</a>
|
||||
[end]
|
||||
[if-any queryform_href]
|
||||
| <a class="vc_view_link[is view "queryform"]_this[end]" href="[queryform_href]">Commit Query</a>
|
||||
[end]
|
||||
[if-any tarball_href]
|
||||
| <a class="vc_view_link" href="[tarball_href]">Download Tarball</a>
|
||||
[end]
|
||||
[end]
|
||||
[is pathtype "file"]
|
||||
<a class="vc_view_link[is view "markup"]_this[end]" href="[view_href]">View File</a>
|
||||
| <a class="vc_view_link[is view "log"]_this[end]" href="[log_href]">Revision Log</a>
|
||||
| <a class="vc_view_link[is view "annotate"]_this[end]" href="[annotate_href]">Show Annotations</a>
|
||||
[if-any graph_href]
|
||||
| <a class="vc_view_link[is view "graph"]_this[end]" href="[graph_href]">Revision Graph</a>
|
||||
[end]
|
||||
| <a class="vc_view_link" href="[download_href]">Download File</a>
|
||||
[end]
|
||||
[if-any revision_href]
|
||||
| <a class="vc_view_link[is view "revision"]_this[end]" href="[revision_href]">View Changeset</a>
|
||||
[end]
|
||||
| <a class="vc_view_link[is view "roots"]_this[end]" href="[roots_href]">Root Listing</a>
|
||||
</div>
|
||||
|
||||
<div id="vc_current_path">
|
||||
[if-any roots_href]<a href="[roots_href]">root</a>[end][if-any nav_path]<span class="pathdiv">/</span>[for nav_path][if-any nav_path.href]<a href="[nav_path.href]">[end][if-index nav_path last]<span class="thisitem">[end][nav_path.name][if-index nav_path last]</span>[end][if-any nav_path.href]</a>[end][if-index nav_path last][else]<span class="pathdiv">/</span>[end][end][end]
|
||||
</div>
|
||||
|
||||
</div> <!-- vc_header -->
|
||||
|
||||
<div id="vc_view_main">
|
53
templates-contrib/newvc/templates/include/pathrev_form.ezt
Normal file
@@ -0,0 +1,53 @@
|
||||
<form method="get" action="[pathrev_action]" style="display: inline">
|
||||
<div style="display: inline">
|
||||
[for pathrev_hidden_values]<input type="hidden" name="[pathrev_hidden_values.name]" value="[pathrev_hidden_values.value]"/>[end]
|
||||
[is roottype "cvs"]
|
||||
[define pathrev_selected][pathrev][end]
|
||||
<select name="pathrev" onchange="submit()">
|
||||
<option value=""></option>
|
||||
[if-any branch_tags]
|
||||
<optgroup label="Branches">
|
||||
[for branch_tags]
|
||||
[is branch_tags pathrev]
|
||||
<option selected>[branch_tags]</option>
|
||||
[define pathrev_selected][end]
|
||||
[else]
|
||||
<option>[branch_tags]</option>
|
||||
[end]
|
||||
[end]
|
||||
</optgroup>
|
||||
[end]
|
||||
<optgroup label="Non-branch tags">
|
||||
[for plain_tags]
|
||||
[is plain_tags pathrev]
|
||||
<option selected>[plain_tags]</option>
|
||||
[define pathrev_selected][end]
|
||||
[else]
|
||||
<option>[plain_tags]</option>
|
||||
[end]
|
||||
[end]
|
||||
</optgroup>
|
||||
[if-any pathrev_selected]
|
||||
<option selected>[pathrev_selected]</option>
|
||||
[end]
|
||||
</select>
|
||||
[else]
|
||||
<input type="text" name="pathrev" value="[pathrev]" size="6"/>
|
||||
[end]
|
||||
<input type="submit" value="Set Sticky [is roottype "cvs"]Tag[else]Revision[end]" />
|
||||
</div>
|
||||
</form>
|
||||
|
||||
[if-any pathrev]
|
||||
<form method="get" action="[pathrev_clear_action]" style="display: inline">
|
||||
<div style="display: inline">
|
||||
[for pathrev_clear_hidden_values]<input type="hidden" name="[pathrev_clear_hidden_values.name]" value="[pathrev_clear_hidden_values.value]"/>[end]
|
||||
[if-any lastrev]
|
||||
[is pathrev lastrev][else]<input type="submit" value="Set to [lastrev]" />[end]
|
||||
(<i>Current path doesn't exist after revision <strong>[lastrev]</strong></i>)
|
||||
[else]
|
||||
<input type="submit" value="Clear" />
|
||||
[end]
|
||||
</div>
|
||||
</form>
|
||||
[end]
|
26
templates-contrib/newvc/templates/include/props.ezt
Normal file
@@ -0,0 +1,26 @@
|
||||
[if-any properties]
|
||||
<hr/>
|
||||
<div class="vc_properties">
|
||||
<h2>Properties</h2>
|
||||
<table cellspacing="2" class="fixed">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="vc_header_sort" style="width: 200px;">Name</th>
|
||||
<th class="vc_header">Value</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
[for properties]
|
||||
<tr class="vc_row_[if-index properties even]even[else]odd[end]">
|
||||
<td><strong>[properties.name]</strong></td>
|
||||
[if-any properties.undisplayable]
|
||||
<td><em>Property value is undisplayable.</em></td>
|
||||
[else]
|
||||
<td style="white-space: pre;">[properties.value]</td>
|
||||
[end]
|
||||
</tr>
|
||||
[end]
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
[end]
|
247
templates-contrib/newvc/templates/log.ezt
Normal file
@@ -0,0 +1,247 @@
|
||||
[# setup page definitions]
|
||||
[define page_title]Log of:[end]
|
||||
[define help_href][docroot]/help_log.html[end]
|
||||
[# end]
|
||||
[include "include/header.ezt" "log"]
|
||||
|
||||
<table class="auto">
|
||||
|
||||
[if-any default_branch]
|
||||
<tr>
|
||||
<td>Default branch:</td>
|
||||
<td>[for default_branch]<a href="[default_branch.href]">[default_branch.name]</a>[if-index default_branch last][else], [end]
|
||||
[end]</td>
|
||||
</tr>
|
||||
[end]
|
||||
|
||||
[is pathtype "file"]
|
||||
[if-any view_href]
|
||||
<tr>
|
||||
<td>Links to HEAD:</td>
|
||||
<td>
|
||||
(<a href="[view_href]">view</a>)
|
||||
[if-any download_href](<a href="[download_href]">download</a>)[end]
|
||||
[if-any download_text_href](<a href="[download_text_href]">as text</a>)[end]
|
||||
[if-any annotate_href](<a href="[annotate_href]">annotate</a>)[end]
|
||||
</td>
|
||||
</tr>
|
||||
[end]
|
||||
|
||||
[if-any tag_view_href]
|
||||
<tr>
|
||||
<td>Links to [pathrev]:</td>
|
||||
<td>
|
||||
(<a href="[tag_view_href]">view</a>)
|
||||
[if-any tag_download_href](<a href="[tag_download_href]">download</a>)[end]
|
||||
[if-any tag_download_text_href](<a href="[tag_download_text_href]">as text</a>)[end]
|
||||
[if-any tag_annotate_href](<a href="[tag_annotate_href]">annotate</a>)[end]
|
||||
</td>
|
||||
</tr>
|
||||
[end]
|
||||
[end]
|
||||
|
||||
<tr>
|
||||
<td>Sticky [is roottype "cvs"]Tag[else]Revision[end]:</td>
|
||||
<td>[include "include/pathrev_form.ezt"]</td>
|
||||
</tr>
|
||||
|
||||
[is cfg.options.use_pagesize "0"][else][is picklist_len "1"][else]
|
||||
<tr>
|
||||
<td>Jump to page:</td>
|
||||
<td><form method="get" action="[log_paging_action]">
|
||||
[for log_paging_hidden_values]<input type="hidden" name="[log_paging_hidden_values.name]" value="[log_paging_hidden_values.value]"/>[end]
|
||||
<select name="log_pagestart" onchange="submit()">
|
||||
[for picklist]
|
||||
[if-any picklist.more]
|
||||
<option [is picklist.count log_pagestart]selected[end] value="[picklist.count]">Page [picklist.page]: [picklist.start] ...</option>
|
||||
[else]
|
||||
<option [is picklist.count log_pagestart]selected[end] value="[picklist.count]">Page [picklist.page]: [picklist.start] - [picklist.end]</option>
|
||||
[end]
|
||||
[end]
|
||||
</select>
|
||||
<input type="submit" value="Go" />
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
[end][end]
|
||||
|
||||
<tr>
|
||||
<td>Sort logs by:</td>
|
||||
<td><form method="get" action="[logsort_action]">
|
||||
<div>
|
||||
<a name="logsort"></a>
|
||||
[for logsort_hidden_values]<input type="hidden" name="[logsort_hidden_values.name]" value="[logsort_hidden_values.value]"/>[end]
|
||||
<select name="logsort" onchange="submit()">
|
||||
<option value="cvs" [is logsort "cvs"]selected="selected"[end]>Not sorted</option>
|
||||
<option value="date" [is logsort "date"]selected="selected"[end]>Commit date</option>
|
||||
<option value="rev" [is logsort "rev"]selected="selected"[end]>Revision</option>
|
||||
</select>
|
||||
<input type="submit" value=" Sort " />
|
||||
</div>
|
||||
</form>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
|
||||
<div id="vc_main_body">
|
||||
<!-- ************************************************************** -->
|
||||
|
||||
[define first_revision][end]
|
||||
[define last_revision][end]
|
||||
|
||||
[for entries]
|
||||
|
||||
[if-index entries first][define first_revision][entries.rev][end][end]
|
||||
[if-index entries last]
|
||||
[define last_revision][entries.rev][end]
|
||||
<div>
|
||||
[else]
|
||||
<div style="border-bottom: 1px dotted black">
|
||||
[end]
|
||||
|
||||
[is entries.state "dead"]
|
||||
Revision <strong>[entries.rev]</strong>
|
||||
[else]
|
||||
<a name="rev[entries.rev]"></a>
|
||||
[for entries.tag_names]<a name="[entries.tag_names]"></a>
|
||||
[end]
|
||||
[for entries.branch_names]<a name="[entries.branch_names]"></a>
|
||||
[end]
|
||||
|
||||
Revision [is roottype "svn"]<a href="[entries.revision_href]"><strong>[entries.rev]</strong></a>[else]<strong>[entries.rev]</strong>[end] -
|
||||
[if-any entries.view_href]
|
||||
[is pathtype "file"]
|
||||
(<a href="[entries.view_href]">view</a>)
|
||||
[else]
|
||||
<a href="[entries.view_href]">Directory Listing</a>
|
||||
[end]
|
||||
[end]
|
||||
[if-any entries.download_href](<a href="[entries.download_href]">download</a>)[end]
|
||||
[if-any entries.download_text_href](<a href="[entries.download_text_href]">as text</a>)[end]
|
||||
[if-any entries.annotate_href](<a href="[entries.annotate_href]">annotate</a>)[end]
|
||||
|
||||
[is pathtype "file"]
|
||||
[# if you don't want to allow select for diffs then remove this section]
|
||||
[is entries.rev rev_selected]
|
||||
- <strong>[[]selected]</strong>
|
||||
[else]
|
||||
- <a href="[entries.sel_for_diff_href]">[[]select for diffs]</a>
|
||||
[end]
|
||||
[end]
|
||||
[end]
|
||||
|
||||
[if-any entries.vendor_branch]
|
||||
<em>(vendor branch)</em>
|
||||
[end]
|
||||
|
||||
<br />
|
||||
|
||||
[is roottype "svn"]
|
||||
[if-index entries last]Added[else]Modified[end]
|
||||
[end]
|
||||
|
||||
<em>[if-any entries.date][entries.date][else](unknown date)[end]</em>
|
||||
[if-any entries.ago]([entries.ago] ago)[end]
|
||||
by <em>[if-any entries.author][entries.author][else](unknown author)[end]</em>
|
||||
|
||||
[if-any entries.orig_path]
|
||||
<br />Original Path: <a href="[entries.orig_href]"><em>[entries.orig_path]</em></a>
|
||||
[end]
|
||||
|
||||
[if-any entries.branches]
|
||||
<br />Branch:
|
||||
[for entries.branches]
|
||||
<a href="[entries.branches.href]"><strong>[entries.branches.name]</strong></a>[if-index entries.branches last][else],[end]
|
||||
[end]
|
||||
[end]
|
||||
|
||||
[if-any entries.tags]
|
||||
<br />CVS Tags:
|
||||
[for entries.tags]
|
||||
<a href="[entries.tags.href]"><strong>[entries.tags.name]</strong></a>[if-index entries.tags last][else],[end]
|
||||
[end]
|
||||
[end]
|
||||
|
||||
[if-any entries.branch_points]
|
||||
<br />Branch point for:
|
||||
[for entries.branch_points]
|
||||
<a href="[entries.branch_points.href]"><strong>[entries.branch_points.name]</strong></a>[if-index entries.branch_points last][else],[end]
|
||||
[end]
|
||||
[end]
|
||||
|
||||
[if-any entries.prev]
|
||||
[if-any entries.changed]
|
||||
[is roottype "cvs"]
|
||||
<br />Changes since <strong>[entries.prev]: [entries.changed] lines</strong>
|
||||
[end]
|
||||
[end]
|
||||
[end]
|
||||
|
||||
[if-any entries.lockinfo]
|
||||
<br />Lock status: [entries.lockinfo]
|
||||
[end]
|
||||
|
||||
[is roottype "svn"]
|
||||
[if-any entries.size]
|
||||
<br />File length: [entries.size] byte(s)
|
||||
[end]
|
||||
|
||||
[if-any entries.copy_path]
|
||||
<br />Copied from: <a href="[entries.copy_href]"><em>[entries.copy_path]</em></a> revision [entries.copy_rev]
|
||||
[end]
|
||||
[end]
|
||||
|
||||
[is entries.state "dead"]
|
||||
<br /><strong><em>FILE REMOVED</em></strong>
|
||||
[else]
|
||||
[is pathtype "file"]
|
||||
[if-any entries.prev]
|
||||
<br />Diff to <a href="[entries.diff_to_prev_href]">previous [entries.prev]</a>
|
||||
[if-any human_readable]
|
||||
[else]
|
||||
(<a href="[entries.diff_to_prev_href]&diff_format=h">colored</a>)
|
||||
[end]
|
||||
[end]
|
||||
|
||||
[is roottype "cvs"]
|
||||
[if-any entries.branch_point]
|
||||
, to <a href="[entries.diff_to_branch_href]">branch point [entries.branch_point]</a>
|
||||
[if-any human_readable]
|
||||
[else]
|
||||
(<a href="[entries.diff_to_branch_href]&diff_format=h">colored</a>)
|
||||
[end]
|
||||
[end]
|
||||
|
||||
[if-any entries.next_main]
|
||||
, to <a href="[entries.diff_to_main_href]">next main [entries.next_main]</a>
|
||||
[if-any human_readable]
|
||||
[else]
|
||||
(<a href="[entries.diff_to_main_href]&diff_format=h">colored</a>)
|
||||
[end]
|
||||
[end]
|
||||
[end]
|
||||
|
||||
[if-any entries.diff_to_sel_href]
|
||||
[if-any entries.prev], [else]<br />Diff[end]
|
||||
to <a href="[entries.diff_to_sel_href]">selected [rev_selected]</a>
|
||||
[if-any human_readable]
|
||||
[else]
|
||||
(<a href="[entries.diff_to_sel_href]&diff_format=h">colored</a>)
|
||||
[end]
|
||||
[end]
|
||||
[end]
|
||||
[end]
|
||||
|
||||
<pre class="vc_log">[entries.log]</pre>
|
||||
</div>
|
||||
[end]
|
||||
|
||||
<!-- ************************************************************** -->
|
||||
</div>
|
||||
|
||||
[is pathtype "file"]
|
||||
[include "include/diff_form.ezt"]
|
||||
[end]
|
||||
|
||||
[include "include/footer.ezt"]
|
18
templates-contrib/newvc/templates/markup.ezt
Normal file
@@ -0,0 +1,18 @@
|
||||
[# setup page definitions]
|
||||
[define page_title]View of:[end]
|
||||
[define help_href][docroot]/help_rootview.html[end]
|
||||
[# end]
|
||||
[include "include/header.ezt" "markup"]
|
||||
[include "include/fileview.ezt"]
|
||||
|
||||
<div id="vc_main_body">
|
||||
<!-- ************************************************************** -->
|
||||
|
||||
<div id="vc_markup"><pre>[markup]</pre></div>
|
||||
|
||||
[include "include/props.ezt"]
|
||||
|
||||
<!-- ************************************************************** -->
|
||||
</div>
|
||||
|
||||
[include "include/footer.ezt"]
|
241
templates-contrib/newvc/templates/query.ezt
Normal file
@@ -0,0 +1,241 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<!-- ViewVC :: http://www.viewvc.org/ -->
|
||||
<head>
|
||||
<title>Checkin Database Query</title>
|
||||
<link rel="stylesheet" href="[docroot]/styles.css" type="text/css" />
|
||||
</head>
|
||||
|
||||
<body>
|
||||
|
||||
[# setup page definitions]
|
||||
[define help_href][docroot]/help_query.html[end]
|
||||
[# end]
|
||||
|
||||
<p>
|
||||
Select your parameters for querying the CVS commit database. You
|
||||
can search for multiple matches by typing a comma-seperated list
|
||||
into the text fields. Regular expressions, and wildcards are also
|
||||
supported. Blank text input fields are treated as wildcards.
|
||||
</p>
|
||||
<p>
|
||||
Any of the text entry fields can take a comma-seperated list of
|
||||
search arguments. For example, to search for all commits from
|
||||
authors <em>jpaint</em> and <em>gstein</em>, just type: <strong>jpaint,
|
||||
gstein</strong> in the <em>Author</em> input box. If you are searching
|
||||
for items containing spaces or quotes, you will need to quote your
|
||||
request. For example, the same search above with quotes is:
|
||||
<strong>"jpaint", "gstein"</strong>.
|
||||
</p>
|
||||
<p>
|
||||
|
||||
Wildcard and regular expression searches are entered in a similar
|
||||
way to the quoted requests. You must quote any wildcard or
|
||||
regular expression request, and a command charactor preceeds the
|
||||
first quote. The command charactor <strong>l</strong> is for wildcard
|
||||
searches, and the wildcard charactor is a percent (<strong>%</strong>). The
|
||||
command charactor for regular expressions is <strong>r</strong>, and is
|
||||
passed directly to MySQL, so you'll need to refer to the MySQL
|
||||
manual for the exact regex syntax. It is very similar to Perl. A
|
||||
wildard search for all files with a <em>.py</em> extention is:
|
||||
<strong>l"%.py"</strong> in the <em>File</em> input box. The same search done
|
||||
with a regular expression is: <strong>r".*\.py"</strong>.
|
||||
</p>
|
||||
<p>
|
||||
All search types can be mixed, as long as they are seperated by
|
||||
commas.
|
||||
</p>
|
||||
|
||||
<form method="get" action="">
|
||||
|
||||
<div class="vc_query_form">
|
||||
<table cellspacing="0" cellpadding="2" class="auto">
|
||||
<tr>
|
||||
<td>
|
||||
<table>
|
||||
<tr>
|
||||
<td style="vertical-align:top;">
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td align="right">CVS Repository:</td>
|
||||
<td>
|
||||
<input type="text" name="repository" size="40" value="[repository]" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">CVS Branch:</td>
|
||||
<td>
|
||||
<input type="text" name="branch" size="40" value="[branch]" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">Directory:</td>
|
||||
<td>
|
||||
<input type="text" name="directory" size="40" value="[directory]" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">File:</td>
|
||||
<td>
|
||||
<input type="text" name="file" size="40" value="[file]" />
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="right">Author:</td>
|
||||
<td>
|
||||
<input type="text" name="who" size="40" value="[who]" />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</td>
|
||||
<td style="vertical-align:top;">
|
||||
|
||||
<table>
|
||||
<tr>
|
||||
<td align="left">Sort By:</td>
|
||||
<td>
|
||||
<select name="sortby">
|
||||
<option value="date" [is sortby "date"]selected="selected"[end]>Date</option>
|
||||
<option value="author" [is sortby "author"]selected="selected"[end]>Author</option>
|
||||
<option value="file" [is sortby "file"]selected="selected"[end]>File</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<table cellspacing="0" cellpadding="0">
|
||||
<tr>
|
||||
<td>Date:</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><input type="radio" name="date" value="hours"
|
||||
[is date "hours"]checked="checked"[end] /></td>
|
||||
<td>In the last
|
||||
<input type="text" name="hours" value="[hours]" size="4" />hours
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><input type="radio" name="date" value="day"
|
||||
[is date "day"]checked="checked"[end] /></td>
|
||||
<td>In the last day</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><input type="radio" name="date" value="week"
|
||||
[is date "week"]checked="checked"[end] /></td>
|
||||
<td>In the last week</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><input type="radio" name="date" value="month"
|
||||
[is date "month"]checked="checked"[end] /></td>
|
||||
<td>In the last month</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><input type="radio" name="date" value="all"
|
||||
[is date "all"]checked="checked"[end] /></td>
|
||||
<td>Since the beginning of time</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
<td>
|
||||
<input type="submit" value="Search" />
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
[is query "skipped"]
|
||||
[else]
|
||||
<p><strong>[num_commits]</strong> matches found.</p>
|
||||
|
||||
[if-any commits]
|
||||
<table cellspacing="0" cellpadding="2">
|
||||
<thead>
|
||||
<tr class="vc_header">
|
||||
<th>Revision</th>
|
||||
<th>File</th>
|
||||
<th>Branch</th>
|
||||
<th>+/-</th>
|
||||
<th>Date</th>
|
||||
<th>Author</th>
|
||||
[# uncommment, if you want a separate Description column: (also see below)
|
||||
<th>Description</th>
|
||||
]
|
||||
</tr>
|
||||
</thead>
|
||||
[for commits]
|
||||
<tbody>
|
||||
[for commits.files]
|
||||
<tr class="vc_row_[if-index commits even]even[else]odd[end]">
|
||||
<td style="vertical-align:top;">
|
||||
[if-any commits.files.rev][commits.files.rev][else] [end]
|
||||
</td>
|
||||
<td style="vertical-align:top;">[commits.files.link]</td>
|
||||
<td style="vertical-align:top;">
|
||||
[if-any commits.files.branch][commits.files.branch][else] [end]
|
||||
</td>
|
||||
<td style="vertical-align:top;">
|
||||
[is commits.files.type "Add"]<ins>[end]
|
||||
[is commits.files.type "Change"]<a href="[commits.files.difflink]">[end]
|
||||
[is commits.files.type "Remove"]<del>[end]
|
||||
[commits.files.plus]/[commits.files.minus]
|
||||
[is commits.files.type "Add"]</ins>[end]
|
||||
[is commits.files.type "Change"]</a>[end]
|
||||
[is commits.files.type "Remove"]</del>[end]
|
||||
</td>
|
||||
<td style="vertical-align:top;">
|
||||
[if-any commits.files.date][commits.files.date][else] [end]
|
||||
</td>
|
||||
<td style="vertical-align:top;">
|
||||
[if-any commits.files.author][commits.files.author][else] [end]
|
||||
</td>
|
||||
|
||||
[# uncommment, if you want a separate Description column:
|
||||
{if-index commits.files first{
|
||||
<td style="vertical-align:top;" rowspan="{commits.num_files}">
|
||||
{commits.log}
|
||||
</td>
|
||||
{end}
|
||||
|
||||
(substitute brackets for the braces)
|
||||
]
|
||||
</tr>
|
||||
[# and also take the following out in the "Description column"-case:]
|
||||
[if-index commits.files last]
|
||||
<tr class="vc_row_[if-index commits even]even[else]odd[end]">
|
||||
<td> </td>
|
||||
<td colspan="5"><strong>Log:</strong><br />
|
||||
<pre class="vc_log">[commits.log]</pre></td>
|
||||
</tr>
|
||||
[end]
|
||||
[# ---]
|
||||
[end]
|
||||
</tbody>
|
||||
[end]
|
||||
|
||||
<tr class="vc_header">
|
||||
<th style="text-align:left;vertical-align:top;"> </th>
|
||||
<th style="text-align:left;vertical-align:top;"> </th>
|
||||
<th style="text-align:left;vertical-align:top;"> </th>
|
||||
<th style="text-align:left;vertical-align:top;"> </th>
|
||||
<th style="text-align:left;vertical-align:top;"> </th>
|
||||
<th style="text-align:left;vertical-align:top;"> </th>
|
||||
[# uncommment, if you want a separate Description column:
|
||||
<th style="text-align:left;vertical-align:top;"> </th>
|
||||
]
|
||||
</tr>
|
||||
</table>
|
||||
[end]
|
||||
[end]
|
||||
[include "include/footer.ezt"]
|
202
templates-contrib/newvc/templates/query_form.ezt
Normal file
@@ -0,0 +1,202 @@
|
||||
[# setup page definitions]
|
||||
[define page_title]Query on:[end]
|
||||
[define help_href][docroot]/help_rootview.html[end]
|
||||
[# end]
|
||||
[include "include/header.ezt" "query"]
|
||||
|
||||
<form action="[query_action]" method="get">
|
||||
|
||||
<div class="vc_query_form">
|
||||
[for query_hidden_values]<input type="hidden" name="[query_hidden_values.name]" value="[query_hidden_values.value]"/>[end]
|
||||
<table cellspacing="0" cellpadding="5" class="auto">
|
||||
[is roottype "svn"]
|
||||
[# For subversion, the branch field is not used ]
|
||||
[else]
|
||||
<tr>
|
||||
<th style="text-align:right;vertical-align:top;">Branch:</th>
|
||||
<td>
|
||||
<input type="text" name="branch" value="[branch]" />
|
||||
<label for="branch_match_exact">
|
||||
<input type="radio" name="branch_match" id="branch_match_exact"
|
||||
value="exact" [is branch_match "exact"]checked="checked"[end] />
|
||||
exact
|
||||
</label>
|
||||
<label for="branch_match_glob">
|
||||
<input type="radio" name="branch_match" id="branch_match_glob"
|
||||
value="glob" [is branch_match "glob"]checked="checked"[end] />
|
||||
glob pattern
|
||||
</label>
|
||||
<label for="branch_match_regex">
|
||||
<input type="radio" name="branch_match" id="branch_match_regex"
|
||||
value="regex" [is branch_match "regex"]checked="checked"[end] />
|
||||
regex
|
||||
</label>
|
||||
<label for="branch_match_notregex">
|
||||
<input type="radio" name="branch_match" id="branch_match_notregex"
|
||||
value="notregex" [is branch_match "notregex"]checked="checked"[end] />
|
||||
<em>not</em> regex
|
||||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
[end]
|
||||
<tr>
|
||||
<th style="text-align:right;vertical-align:top;">Subdirectory:</th>
|
||||
<td>
|
||||
<input type="text" name="dir" value="[dir]" />
|
||||
<em>(You can list multiple directories separated by commas.)</em>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th style="text-align:right;vertical-align:top;">File:</th>
|
||||
<td>
|
||||
<input type="text" name="file" value="[file]" />
|
||||
<label for="file_match_exact">
|
||||
<input type="radio" name="file_match" id="file_match_exact"
|
||||
value="exact" [is file_match "exact"]checked="checked"[end] />
|
||||
exact
|
||||
</label>
|
||||
<label for="file_match_glob">
|
||||
<input type="radio" name="file_match" id="file_match_glob"
|
||||
value="glob" [is file_match "glob"]checked="checked"[end] />
|
||||
glob pattern
|
||||
</label>
|
||||
<label for="file_match_regex">
|
||||
<input type="radio" name="file_match" id="file_match_regex"
|
||||
value="regex" [is file_match "regex"]checked="checked"[end] />
|
||||
regex
|
||||
</label>
|
||||
<label for="file_match_notregex">
|
||||
<input type="radio" name="file_match" id="file_match_notregex"
|
||||
value="notregex" [is file_match "notregex"]checked="checked"[end] />
|
||||
<em>not</em> regex
|
||||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th style="text-align:right;vertical-align:top;">Who:</th>
|
||||
<td>
|
||||
<input type="text" name="who" value="[who]" />
|
||||
<label for="who_match_exact">
|
||||
<input type="radio" name="who_match" id="who_match_exact"
|
||||
value="exact" [is who_match "exact"]checked="checked"[end] />
|
||||
exact
|
||||
</label>
|
||||
<label for="who_match_glob">
|
||||
<input type="radio" name="who_match" id="who_match_glob"
|
||||
value="glob" [is who_match "glob"]checked="checked"[end] />
|
||||
glob pattern
|
||||
</label>
|
||||
<label for="who_match_regex">
|
||||
<input type="radio" name="who_match" id="who_match_regex"
|
||||
value="regex" [is who_match "regex"]checked="checked"[end] />
|
||||
regex
|
||||
</label>
|
||||
<label for="who_match_notregex">
|
||||
<input type="radio" name="who_match" id="who_match_notregex"
|
||||
value="notregex" [is who_match "notregex"]checked="checked"[end] />
|
||||
<em>not</em> regex
|
||||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th style="text-align:right;vertical-align:top;">Comment:</th>
|
||||
<td>
|
||||
<input type="text" name="comment" value="[comment]" />
|
||||
<label for="comment_match_exact">
|
||||
<input type="radio" name="comment_match" id="comment_match_exact"
|
||||
value="exact" [is comment_match "exact"]checked=""[end] />
|
||||
exact
|
||||
</label>
|
||||
<label for="comment_match_glob">
|
||||
<input type="radio" name="comment_match" id="comment_match_glob"
|
||||
value="glob" [is comment_match "glob"]checked=""[end] />
|
||||
glob pattern
|
||||
</label>
|
||||
<label for="comment_match_regex">
|
||||
<input type="radio" name="comment_match" id="comment_match_regex"
|
||||
value="regex" [is comment_match "regex"]checked=""[end] />
|
||||
regex
|
||||
</label>
|
||||
<label for="comment_match_notregex">
|
||||
<input type="radio" name="comment_match" id="comment_match_notregex"
|
||||
value="notregex" [is comment_match "notregex"]checked=""[end] />
|
||||
<em>not</em> regex
|
||||
</label>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th style="text-align:right;vertical-align:top;">Sort By:</th>
|
||||
<td>
|
||||
<select name="querysort">
|
||||
<option value="date" [is querysort "date"]selected="selected"[end]>Date</option>
|
||||
<option value="author" [is querysort "author"]selected="selected"[end]>Author</option>
|
||||
<option value="file" [is querysort "file"]selected="selected"[end]>File</option>
|
||||
</select>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th style="text-align:right;vertical-align:top;">Date:</th>
|
||||
<td>
|
||||
<table cellspacing="0" cellpadding="0">
|
||||
<tr>
|
||||
<td><input type="radio" name="date" id="date_hours"
|
||||
value="hours" [is date "hours"]checked="checked"[end] /></td>
|
||||
<td>
|
||||
<label for="date_hours">In the last</label>
|
||||
<input type="text" name="hours" value="[hours]" size="4" />
|
||||
hours
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><input type="radio" name="date" id="date_day"
|
||||
value="day" [is date "day"]checked="checked"[end] /></td>
|
||||
<td><label for="date_day">In the last day</label></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><input type="radio" name="date" id="date_week"
|
||||
value="week" [is date "week"]checked="checked"[end] /></td>
|
||||
<td><label for="date_week">In the last week</label></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><input type="radio" name="date" id="date_month"
|
||||
value="month" [is date "month"]checked="checked"[end] /></td>
|
||||
<td><label for="date_month">In the last month</label></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><input type="radio" name="date" id="date_all"
|
||||
value="all" [is date "all"]checked="checked"[end] /></td>
|
||||
<td><label for="date_all">Since the beginning of time</label></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><input type="radio" name="date" id="date_explicit"
|
||||
value="explicit" [is date "explicit"]checked="checked"[end] /></td>
|
||||
<td>
|
||||
<label for="date_explicit">Between</label>
|
||||
<input type="text" name="mindate" value="[mindate]" size="20" />
|
||||
and
|
||||
<input type="text" name="maxdate" value="[maxdate]" size="20" />
|
||||
<br />
|
||||
(use the form <strong>yyyy-mm-dd hh:mm:ss</strong>)
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th style="text-align:right;vertical-align:top;">Limit:</th>
|
||||
<td>
|
||||
Show at most
|
||||
<input type="text" name="limit_changes" value="[limit_changes]" size="5" />
|
||||
changed files per commit. <em>(Use 0 to show all files.)</em>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td><input type="submit" value="Search" /></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
</form>
|
||||
|
||||
[include "include/footer.ezt"]
|
86
templates-contrib/newvc/templates/query_results.ezt
Normal file
@@ -0,0 +1,86 @@
|
||||
[# setup page definitions]
|
||||
[define page_title]Query results in:[end]
|
||||
[define help_href][docroot]/help_rootview.html[end]
|
||||
[# end]
|
||||
|
||||
[include "include/header.ezt"]
|
||||
|
||||
<p><strong>[english_query]</strong></p>
|
||||
[# <!-- {sql} --> ]
|
||||
<p><a href="[queryform_href]">Modify query</a></p>
|
||||
<p><a href="[backout_href]">Show commands which could be used to back out these changes</a></p>
|
||||
|
||||
<p><strong>+[plus_count]/-[minus_count]</strong> lines changed.</p>
|
||||
|
||||
[if-any commits]
|
||||
<table cellspacing="1" cellpadding="2">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="vc_header">Revision</th>
|
||||
<th class="vc_header[is querysort "file"]_sort[end]">File</th>
|
||||
[if-any show_branch]
|
||||
<th class="vc_header">Branch</th>
|
||||
[end]
|
||||
<th class="vc_header">+/-</th>
|
||||
<th class="vc_header[is querysort "date"]_sort[end]">Date</th>
|
||||
<th class="vc_header[is querysort "author"]_sort[end]">Author</th>
|
||||
[# uncommment, if you want a separate Description column: (also see below)
|
||||
<th class="vc_header">Description</th>
|
||||
]
|
||||
</tr>
|
||||
</thead>
|
||||
[for commits]
|
||||
[for commits.files]
|
||||
<tbody>
|
||||
<tr class="vc_row_[if-index commits even]even[else]odd[end]">
|
||||
<td style="vertical-align: top;">
|
||||
[define rev_href][if-any commits.files.prefer_markup][commits.files.view_href][else][if-any commits.files.download_href][commits.files.download_href][end][end][end]
|
||||
[if-any commits.files.rev][if-any rev_href]<a href="[rev_href]">[end][commits.files.rev][if-any rev_href]</a>[end][else] [end]
|
||||
</td>
|
||||
<td style="vertical-align: top;">
|
||||
<a href="[commits.files.dir_href]">[commits.files.dir]/</a>
|
||||
<a href="[commits.files.log_href]">[commits.files.file]</a>
|
||||
</td>
|
||||
[if-any show_branch]
|
||||
<td style="vertical-align: top;">
|
||||
[if-any commits.files.branch][commits.files.branch][else] [end]
|
||||
</td>
|
||||
[end]
|
||||
<td style="vertical-align: top;">
|
||||
[# only show a diff link for changes ]
|
||||
[is commits.files.type "Add"]<ins>[end]
|
||||
[is commits.files.type "Change"]<a href="[commits.files.diff_href]">[end]
|
||||
[is commits.files.type "Remove"]<del>[end]
|
||||
[commits.files.plus]/[commits.files.minus]
|
||||
[is commits.files.type "Add"]</ins>[end]
|
||||
[is commits.files.type "Change"]</a>[end]
|
||||
[is commits.files.type "Remove"]</del>[end]
|
||||
</td>
|
||||
<td style="vertical-align: top;">
|
||||
[if-any commits.files.date][commits.files.date][else] [end]
|
||||
</td>
|
||||
<td style="vertical-align: top;">
|
||||
[if-any commits.files.author][commits.files.author][else] [end]
|
||||
</td>
|
||||
</tr>
|
||||
[end]
|
||||
[if-any commits.limited_files]
|
||||
<tr class="vc_row_[if-index commits even]even[else]odd[end]">
|
||||
<td> </td>
|
||||
<td colspan="5">
|
||||
<strong><em><small>Only first [commits.num_files] files shown.
|
||||
<a href="[limit_changes_href]">Show all files</a> or
|
||||
<a href="[queryform_href]">adjust limit</a>.</small></em></strong>
|
||||
</tr>
|
||||
[end]
|
||||
<tr class="vc_row_[if-index commits even]even[else]odd[end]">
|
||||
<td> </td>
|
||||
<td colspan="5"><strong>Log:</strong><br />
|
||||
<pre class="vc_log">[commits.log]</pre></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
[end]
|
||||
</table>
|
||||
[end]
|
||||
|
||||
[include "include/footer.ezt"]
|
83
templates-contrib/newvc/templates/revision.ezt
Normal file
@@ -0,0 +1,83 @@
|
||||
[# setup page definitions]
|
||||
[define page_title]Revision [rev] of:[end]
|
||||
[define help_href][docroot]/help_rootview.html[end]
|
||||
[# end]
|
||||
[include "include/header.ezt" "revision"]
|
||||
|
||||
<form method="get" action="[jump_rev_action]">
|
||||
<table cellspacing="1" cellpadding="2" style="width: auto;">
|
||||
<tr align="left">
|
||||
<th>Jump to revision:</th>
|
||||
<td>
|
||||
[for jump_rev_hidden_values]<input type="hidden" name="[jump_rev_hidden_values.name]" value="[jump_rev_hidden_values.value]"/>[end]
|
||||
<input type="text" name="revision" value="[rev]" />
|
||||
<input type="submit" value="Go" />
|
||||
[if-any prev_href]
|
||||
<a href="[prev_href]" title="Previous Revision"><img src="[docroot]/images/back.png" alt="Previous" width="20" height="22" /></a>[end]
|
||||
[if-any next_href] <a href="[next_href]" title="Next Revision"><img src="[docroot]/images/forward.png" width="20" height="22" alt="Next" /></a>[end]
|
||||
</td>
|
||||
</tr>
|
||||
<tr align="left">
|
||||
<th>Author:</th>
|
||||
<td>[if-any author][author][else]<em>(unknown author)</em>[end]</td>
|
||||
</tr>
|
||||
<tr align="left">
|
||||
<th>Date:</th>
|
||||
<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>Log Message:</th>
|
||||
<td><pre class="vc_log">[log]</pre></td>
|
||||
</tr>
|
||||
</table>
|
||||
</form>
|
||||
|
||||
<div id="vc_main_body">
|
||||
<!-- ************************************************************** -->
|
||||
|
||||
<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">
|
||||
<th class="vc_header_sort">Path</th>
|
||||
<th class="vc_header">Details</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
[if-any changes]
|
||||
[for changes]
|
||||
<tr class="vc_row_[if-index changes even]even[else]odd[end]">
|
||||
<td>[if-any changes.view_href]<a href="[changes.view_href]" title="View [is changes.pathtype "dir"]Directory[else]File[end] Contents">[end]<img src="[docroot]/images/[is changes.pathtype "dir"]dir[else]text[end].png" class="vc_icon" alt="Directory" />[changes.path][is changes.pathtype "dir"]/[end][if-any changes.view_href]</a>[end]
|
||||
[if-any changes.is_copy]<br /><em>(Copied from [changes.copy_path], r[changes.copy_rev])</em>[end]
|
||||
</td>
|
||||
<td>[if-any changes.log_href]<a href="[changes.log_href]" title="View Log">[end][changes.action][if-any changes.log_href]</a>[end]
|
||||
[if-any changes.text_mods], [if-any changes.diff_href]<a href="[changes.diff_href]" title="View Diff">[end]text changed[if-any changes.diff_href]</a>[end][end]
|
||||
[if-any changes.prop_mods], props changed[end]
|
||||
</td>
|
||||
</tr>
|
||||
[end]
|
||||
[else]
|
||||
<tr>
|
||||
<td colspan="5">No changed paths.</td>
|
||||
</tr>
|
||||
[end]
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- ************************************************************** -->
|
||||
</div>
|
||||
|
||||
[include "include/footer.ezt"]
|
33
templates-contrib/newvc/templates/roots.ezt
Normal file
@@ -0,0 +1,33 @@
|
||||
[# setup page definitions]
|
||||
[define page_title]Repository Listing[end]
|
||||
[define help_href][docroot]/help_rootview.html[end]
|
||||
[# end]
|
||||
|
||||
[include "include/header.ezt" "directory"]
|
||||
|
||||
<div id="vc_main_body">
|
||||
<!-- ************************************************************** -->
|
||||
|
||||
<table cellspacing="1" id="dirlist">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="vc_header_sort">Name</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
[if-any roots]
|
||||
[for roots]
|
||||
<tr class="vc_row_[if-index roots even]even[else]odd[end]">
|
||||
<td onclick="jumpTo('[roots.href]')"><a href="[roots.href]"><img src="[docroot]/images/[roots.type]-logo.png" alt="" class="vc_icon" />[roots.name]</a></td>
|
||||
</tr>
|
||||
[end]
|
||||
[end]
|
||||
</tbody>
|
||||
|
||||
</table>
|
||||
|
||||
<!-- ************************************************************** -->
|
||||
</div>
|
||||
|
||||
[include "include/footer.ezt"]
|
17
templates-contrib/newvc/templates/rss.ezt
Normal file
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0"?>
|
||||
<rss version="2.0">
|
||||
<channel>
|
||||
<link>[rss_link_href]</link>
|
||||
<title>[rootname] checkins[if-any where] (in [where])[end]</title>
|
||||
|
||||
<description>[is roottype "svn"]Subversion[else]CVS[end] commits to the[if-any where] [where] directory of the[end] [rootname] repository</description>
|
||||
|
||||
[for commits]<item>
|
||||
<title>[if-any commits.rev][commits.rev]: [end][[commits.author]] [commits.short_log]</title>
|
||||
[if-any commits.rss_url]<link>[commits.rss_url]</link>[end]
|
||||
<author>[commits.author]</author>
|
||||
<pubDate>[if-any commits.rss_date][commits.rss_date][else](unknown date)[end]</pubDate>
|
||||
<description><pre>[format "xml"][commits.log][end]</pre></description>
|
||||
</item>[end]
|
||||
</channel>
|
||||
</rss>
|
8
templates-contrib/tabbed/README
Normal file
@@ -0,0 +1,8 @@
|
||||
Template Set: tabbed
|
||||
Author(s): C. Michael Pilato <cmpilato@red-bean.com>,
|
||||
Russell Yanofsky <russ@yanofsky.org>
|
||||
Compatibility: ViewVC 1.1
|
||||
|
||||
The "tabbed" template set uses top navigation tabs to flip between
|
||||
various views of a file or directory.
|
||||
|
46
templates-contrib/tabbed/templates/annotate.ezt
Normal file
@@ -0,0 +1,46 @@
|
||||
[# setup page definitions]
|
||||
[define page_title]Annotation of:[end]
|
||||
[define help_href][docroot]/help_rootview.html[end]
|
||||
[# end]
|
||||
[include "include/header.ezt" "annotate"]
|
||||
[include "include/fileview.ezt"]
|
||||
|
||||
<div id="vc_main_body">
|
||||
<!-- ************************************************************** -->
|
||||
|
||||
[define last_rev]0[end]
|
||||
[define rowclass]vc_row_odd[end]
|
||||
|
||||
<table class="fixed" cellspacing="0" cellpadding="0">
|
||||
<tr>
|
||||
<th class="vc_header" style="text-align: center; width: 5em;">Line</th>
|
||||
<th class="vc_header" style="text-align: center; width: 8em;">User</th>
|
||||
<th class="vc_header" style="text-align: center; width: 5em;">Rev</th>
|
||||
<th class="vc_header" style="text-align: left;">File contents</th>
|
||||
</tr>
|
||||
[for lines]
|
||||
[is lines.rev last_rev]
|
||||
[else]
|
||||
[is rowclass "vc_row_even"]
|
||||
[define rowclass]vc_row_odd[end]
|
||||
[else]
|
||||
[define rowclass]vc_row_even[end]
|
||||
[end]
|
||||
[end]
|
||||
|
||||
<tr class="[rowclass]">
|
||||
<td id="l[lines.line_number]" class="vc_blame_metadata">[lines.line_number]</td>
|
||||
<td class="vc_blame_metadata">[is lines.rev last_rev] [else][lines.author][end]</td>
|
||||
<td class="vc_blame_metadata">[is lines.rev last_rev] [else][if-any lines.diff_url]<a href="[lines.diff_url]">[end][lines.rev][if-any lines.diff_url]</a>[end][end]</td>
|
||||
<td class="vc_blame_textdata" style="background: [is rowclass "vc_row_even"]white[else]rgb(95%,95%,95%)[end];">[lines.text]</td>
|
||||
</tr>
|
||||
[define last_rev][lines.rev][end]
|
||||
[end]
|
||||
</table>
|
||||
|
||||
[include "include/props.ezt"]
|
||||
|
||||
<!-- ************************************************************** -->
|
||||
</div>
|
||||
|
||||
[include "include/footer.ezt"]
|
128
templates-contrib/tabbed/templates/diff.ezt
Normal file
@@ -0,0 +1,128 @@
|
||||
[# Setup page definitions]
|
||||
[define page_title]Diff of:[end]
|
||||
[define help_href][docroot]/help_rootview.html[end]
|
||||
[# end]
|
||||
[include "include/header.ezt" "diff"]
|
||||
|
||||
<form method="get" action="[diff_format_action]" style="display: inline;">
|
||||
<div>
|
||||
[for diff_format_hidden_values]<input type="hidden" name="[diff_format_hidden_values.name]" value="[diff_format_hidden_values.value]"/>[end]
|
||||
<select name="diff_format" onchange="submit()">
|
||||
<option value="h" [is diff_format "h"]selected="selected"[end]>Colored Diff</option>
|
||||
<option value="l" [is diff_format "l"]selected="selected"[end]>Long Colored Diff</option>
|
||||
<option value="f" [is diff_format "f"]selected="selected"[end]>Full Colored Diff</option>
|
||||
<option value="u" [is diff_format "u"]selected="selected"[end]>Unidiff</option>
|
||||
<option value="c" [is diff_format "c"]selected="selected"[end]>Context Diff</option>
|
||||
<option value="s" [is diff_format "s"]selected="selected"[end]>Side by Side</option>
|
||||
</select>
|
||||
<input type="submit" value="Show" />
|
||||
(<a href="[patch_href]">Generate patch</a>)
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div id="vc_main_body">
|
||||
<!-- ************************************************************** -->
|
||||
|
||||
[if-any raw_diff]
|
||||
<pre>[raw_diff]</pre>
|
||||
[else]
|
||||
|
||||
[define change_right][end]
|
||||
[define last_change_type][end]
|
||||
|
||||
[# these should live in stylesheets]
|
||||
|
||||
<table cellpadding="0" cellspacing="0" style="width: 100%;">
|
||||
[for changes]
|
||||
[is changes.type "change"][else]
|
||||
[if-any change_right][change_right][define change_right][end][end]
|
||||
[end]
|
||||
[is changes.type "header"]
|
||||
<tr>
|
||||
<th class="vc_header" style="width:6%;"><strong>#</strong></th>
|
||||
<th colspan="2" class="vc_header">
|
||||
<strong>Line [changes.line_info_left]</strong> |
|
||||
<strong>Line [changes.line_info_right]</strong>
|
||||
</th>
|
||||
</tr>
|
||||
[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_plusminus"><strong style="color: green;">+</strong></td>
|
||||
<td class="vc_diff_add">[changes.right]</td>
|
||||
</tr>
|
||||
[else]
|
||||
[is changes.type "remove"]
|
||||
<tr>
|
||||
<td style="text-decoration: line-through">[changes.line_number]</td>
|
||||
<td class="vc_diff_plusminus"><strong style="color: red;">–</strong></td>
|
||||
<td class="vc_diff_remove">[changes.left]</td>
|
||||
</tr>
|
||||
[else]
|
||||
[is changes.type "change"]
|
||||
[if-any changes.have_left]
|
||||
<tr>
|
||||
<td style="text-decoration: line-through">[changes.line_number]</td>
|
||||
<td class="vc_diff_plusminus"><strong style="color: yellow;"><</strong></td>
|
||||
<td class="vc_diff_changes1">[changes.left]</td>
|
||||
</tr>
|
||||
[end]
|
||||
[define change_right][change_right]
|
||||
[if-any changes.have_right]
|
||||
<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_plusminus"><strong style="color: yellow;">></strong></td>
|
||||
<td class="vc_diff_changes2">[changes.right]</td>
|
||||
</tr>[end]
|
||||
[end]
|
||||
[else]
|
||||
[is changes.type "no-changes"]
|
||||
<tr><td colspan="3" style="vc_diff_nochange"><strong>- No changes -</strong></td></tr>
|
||||
[else]
|
||||
[is changes.type "binary-diff"]
|
||||
<tr><td colspan="3" class="vc_diff_binary"><strong>- Binary file revisions differ -</strong></td></tr>
|
||||
[else]
|
||||
[is changes.type "error"]
|
||||
<tr><td colspan="3" class="vc_diff_error"><strong>- ViewVC depends on rcsdiff and GNU diff
|
||||
to create this page. ViewVC cannot find GNU diff. Even if you
|
||||
have GNU diff installed, the rcsdiff program must be configured
|
||||
and compiled with the GNU diff location. -</strong></td></tr>
|
||||
[else][# a line of context]
|
||||
<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_plusminus"> </td>
|
||||
<td style="font-family: monospace; white-space: pre;">[changes.right]</td>
|
||||
</tr>
|
||||
[end][end][end][end][end][end][end]
|
||||
[define last_change_type][changes.type][end]
|
||||
[end]
|
||||
[if-any change_right][change_right][end]
|
||||
</table>
|
||||
|
||||
<h3>Diff Legend</h3>
|
||||
<table class="auto" cellspacing="0">
|
||||
<tr>
|
||||
<td class="vc_diff_plusminus"><strong style="color: red;">–</strong></td>
|
||||
<td class="vc_diff_remove">Removed lines</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="vc_diff_plusminus"><strong style="color: green;">+</strong></td>
|
||||
<td class="vc_diff_add">Added lines</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="vc_diff_plusminus"><strong style="color: yellow;"><</strong></td>
|
||||
<td class="vc_diff_changes1">Changed lines</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="vc_diff_plusminus"><strong style="color: yellow;">></strong></td>
|
||||
<td class="vc_diff_changes2">Changed lines</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
[end]
|
||||
|
||||
<!-- ************************************************************** -->
|
||||
</div>
|
||||
|
||||
[include "include/footer.ezt"]
|
132
templates-contrib/tabbed/templates/directory.ezt
Normal file
@@ -0,0 +1,132 @@
|
||||
[include "include/dir_header.ezt"]
|
||||
|
||||
<table cellspacing="1" cellpadding="2" class="fixed" id="dirlist">
|
||||
<thead>
|
||||
<tr>
|
||||
<th style="width: 200px" class="vc_header[is sortby "file"]_sort[end]">
|
||||
<a href="[sortby_file_href]#dirlist">File
|
||||
[is sortby "file"]
|
||||
<img class="vc_sortarrow" alt="[is sortdir "down"](rev)[end]"
|
||||
width="13" height="13"
|
||||
src="[docroot]/images/[is sortdir "up"]up[else]down[end].png" />
|
||||
[end]
|
||||
</a>
|
||||
</th>
|
||||
<th style="width: 96px" class="vc_header"></th>
|
||||
<th class="vc_header[is sortby "rev"]_sort[end]">
|
||||
<a href="[sortby_rev_href]#dirlist">Last Change
|
||||
[is sortby "rev"]
|
||||
<img class="vc_sortarrow" alt="[is sortdir "down"](rev)[end]"
|
||||
width="13" height="13"
|
||||
src="[docroot]/images/[is sortdir "up"]up[else]down[end].png" />
|
||||
[end]
|
||||
</a>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
|
||||
<tbody>
|
||||
[if-any up_href]
|
||||
<tr class="vc_row_odd">
|
||||
<td style="width: 200px">
|
||||
<a href="[up_href]">
|
||||
<img src="[docroot]/images/back_small.png" alt="" class="vc_icon"
|
||||
/> Parent Directory</a>
|
||||
</td>
|
||||
<td style="width: 96px; font-size: 0;"></td>
|
||||
<td> </td>
|
||||
</tr>
|
||||
[end]
|
||||
[for entries]
|
||||
<tr class="vc_row_[if-index entries even]even[else]odd[end]">
|
||||
<td style="width: 200px">
|
||||
<a name="[entries.anchor]" href="[is entries.pathtype "dir"][entries.view_href][else][if-any entries.prefer_markup][entries.view_href][else][entries.download_href][end][end]" title="[is entries.pathtype "dir"]View Directory Contents[else][if-any entries.prefer_markup]View[else]Download[end] File Contents[end]">
|
||||
<img src="[docroot]/images/[is entries.pathtype "dir"]dir[else][is entries.state "dead"]broken[else]text[end][end].png" alt="" class="vc_icon" />
|
||||
[entries.name][is entries.pathtype "dir"]/[end]</a>
|
||||
[is entries.state "dead"](dead)[end]
|
||||
</td>
|
||||
|
||||
[if-any entries.errors]
|
||||
<td colspan="2">[for entries.errors]<em>[entries.errors]</em>[end]</td>
|
||||
[else]
|
||||
[define view_icon_link][end]
|
||||
[define graph_icon_link][end]
|
||||
[define download_icon_link][end]
|
||||
[define annotate_icon_link][end]
|
||||
[define log_icon_link][if-any entries.log_href]<a
|
||||
href="[entries.log_href]"
|
||||
title="View Log"><img
|
||||
src="[docroot]/images/log.png"
|
||||
alt="View Log"
|
||||
class="vc_icon" /></a>[end][end]
|
||||
|
||||
[is entries.pathtype "dir"]
|
||||
[is roottype "cvs"]
|
||||
[# no point in showing icon when there's only one to choose from]
|
||||
[else]
|
||||
[define view_icon_link]<a
|
||||
href="[entries.view_href]"
|
||||
title="View Directory Listing"><img
|
||||
src="[docroot]/images/list.png"
|
||||
alt="View Directory Listing"
|
||||
class="vc_icon" /></a>[end]
|
||||
[end]
|
||||
[end]
|
||||
|
||||
[is entries.pathtype "file"]
|
||||
[define view_icon_link][if-any entries.view_href]<a
|
||||
href="[entries.view_href]"
|
||||
title="View File"><img
|
||||
src="[docroot]/images/view.png"
|
||||
alt="View File"
|
||||
class="vc_icon" /></a>[end][end]
|
||||
|
||||
[define graph_icon_link][if-any entries.graph_href]<a
|
||||
href="[entries.graph_href]"
|
||||
title="View Revision Graph"><img
|
||||
src="[docroot]/images/cvsgraph_16x16.png"
|
||||
alt="View Revision Graph"
|
||||
class="vc_icon" /></a>[end][end]
|
||||
|
||||
[define download_icon_link][if-any entries.download_href]<a
|
||||
href="[entries.download_href]"
|
||||
title="Download File"><img
|
||||
src="[docroot]/images/download.png"
|
||||
alt="Download File"
|
||||
class="vc_icon" /></a>[end][end]
|
||||
|
||||
[define annotate_icon_link][if-any entries.annotate_href]<a
|
||||
href="[entries.annotate_href]"
|
||||
title="Annotate File"><img
|
||||
src="[docroot]/images/annotate.png"
|
||||
alt="Annotate File"
|
||||
class="vc_icon" /></a>[end][end]
|
||||
[end]
|
||||
|
||||
<td style="width: 96px"
|
||||
>[# Icon column. We might want to add more icons like a tarball
|
||||
# icon for directories or a diff to previous icon for files.
|
||||
# Make sure this sucker has no whitespace in it, or the fixed
|
||||
# widthness of will suffer for large font sizes
|
||||
][log_icon_link][view_icon_link][graph_icon_link][download_icon_link][annotate_icon_link]</td>
|
||||
|
||||
<td>
|
||||
[if-any entries.rev]
|
||||
<strong>[if-any entries.revision_href]<a href="[entries.revision_href]" title="Revision [entries.rev]">[entries.rev]</a>[else][entries.rev][end]</strong>
|
||||
([entries.ago] ago)
|
||||
by <em>[entries.author]</em>:
|
||||
[entries.log]
|
||||
[is entries.pathtype "dir"][is roottype "cvs"]
|
||||
<em>(from [entries.log_file]/[entries.log_rev])</em>
|
||||
[end][end]
|
||||
[end]
|
||||
</td>
|
||||
[end]
|
||||
</tr>
|
||||
[end]
|
||||
</tbody>
|
||||
|
||||
</table>
|
||||
|
||||
[include "include/props.ezt"]
|
||||
[include "include/dir_footer.ezt"]
|
14
templates-contrib/tabbed/templates/docroot/help.css
Normal file
@@ -0,0 +1,14 @@
|
||||
/************************************/
|
||||
/*** ViewVC Help CSS Stylesheet ***/
|
||||
/************************************/
|
||||
|
||||
/*** Standard Tags ***/
|
||||
body {
|
||||
margin: 0.5em;
|
||||
}
|
||||
img { border: none; }
|
||||
|
||||
table { width: 100%; }
|
||||
td { vertical-align: top; }
|
||||
|
||||
col.menu { width:12em; }
|
130
templates-contrib/tabbed/templates/docroot/help_dirview.html
Normal file
@@ -0,0 +1,130 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<title>ViewVC Help: Directory View</title>
|
||||
<link rel="stylesheet" href="help.css" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<table>
|
||||
<col class="menu" />
|
||||
<col />
|
||||
<tr>
|
||||
<td><a href="http://viewvc.org/index.html"><img
|
||||
src="images/logo.png" alt="ViewVC logotype" /></a>
|
||||
</td>
|
||||
<td>
|
||||
<h1>ViewVC Help: Directory View</h1>
|
||||
</td>
|
||||
</tr>
|
||||
<tr><td>
|
||||
<h3>Help</h3>
|
||||
<a href="help_rootview.html">General</a><br />
|
||||
<strong>Directory View</strong><br />
|
||||
<a href="help_log.html">Log View</a><br />
|
||||
|
||||
<h3>Internet</h3>
|
||||
<a href="http://viewvc.org/index.html">Home</a><br />
|
||||
<a href="http://viewvc.org/upgrading.html">Upgrading</a><br />
|
||||
<a href="http://viewvc.org/contributing.html">Contributing</a><br />
|
||||
<a href="http://viewvc.org/license-1.html">License</a><br />
|
||||
</td><td colspan="2">
|
||||
|
||||
<p>The directory listing view should be a familiar sight to any
|
||||
computer user. It shows the path of the current directory being viewed
|
||||
at the top of the page. Below that is a table summarizing the
|
||||
directory contents, and then comes actual contents, a sortable list of
|
||||
all files and subdirectories inside the current directory.</p>
|
||||
|
||||
<p><a name="summary"></a>The summary table is made up of some or all
|
||||
of the following rows:</p>
|
||||
<ul>
|
||||
<li><a name="summary-files-shown"><strong>Files Shown</strong></a>
|
||||
- Number of files shown in the directory listing. This might be less
|
||||
than the actual number of files in the directory if a
|
||||
<a href="#option-search">regular expression search</a> is in place,
|
||||
hiding files which don't meet the search criteria. In CVS directory
|
||||
listings, this row will also have a link to toggle display of
|
||||
<a href="help_rootview.html#dead-files">dead files</a>, if any are
|
||||
present.</li>
|
||||
|
||||
<li><a name="summary-revision"><strong>Directory
|
||||
Revision</strong></a> - For Subversion directories only.
|
||||
Shown as "# of #" where the first number is the most recent
|
||||
repository revision where the directory (or a path underneath it)
|
||||
was modified. The second number is just the latest repository
|
||||
revision. Both numbers are links to
|
||||
<a href="help_rootview.html#view-rev">revision views</a></li>
|
||||
|
||||
<li><a name="summary-sticky-revision-tag"><strong>Sticky
|
||||
Revision/Tag</strong></a> - shows the current
|
||||
<a href="help_rootview.html#sticky-revision-tag">sticky revision or
|
||||
tag</a> and contains form fields to set or clear it.</li>
|
||||
|
||||
<li><a name="summary-search"><strong>Current Search</strong></a> -
|
||||
If a <a href="#option-search">regular expression search</a> is in place,
|
||||
shows the search string.</li>
|
||||
|
||||
<li><a name="summary-query"><strong>Query</strong></a> - Provides
|
||||
a link to a <a href="help_rootview.html#view-query">query form</a>
|
||||
for the directory</li>
|
||||
</ul>
|
||||
|
||||
<p><a name="list"></a>The actual directory list is a table with
|
||||
filenames and directory names in one column and information about the
|
||||
most recent revisions where each file or directory was modified in the
|
||||
other columns. Column headers can be clicked to sort the directory
|
||||
entries in order by a column, and clicked again to reverse the sort
|
||||
order.</p>
|
||||
|
||||
<p>
|
||||
<!-- If using directory.ezt template -->
|
||||
File names are links to <a href="help_log.html">log views</a>
|
||||
showing a list of revisions where a file was modified. Revision
|
||||
numbers are links to either
|
||||
<a href="help_rootview.html#view-markup">view</a>
|
||||
or <a href="help_rootview.html#view-checkout">download</a> a file
|
||||
(depending on its file type). The links are reversed for directories.
|
||||
Directory revision numbers are links to <a href="help_log.html">log
|
||||
views</a>, while directory names are links showing the contents of those
|
||||
directories.
|
||||
|
||||
<!-- If using dir_alt.ezt template -->
|
||||
<!--
|
||||
File and directory names are links to retrieve their contents.
|
||||
File links may be either
|
||||
<a href="help_rootview.html#view-markup">view</a>
|
||||
or <a href="help_rootview.html#view-download">download</a> links
|
||||
depending on the file type. Directory links go to directory
|
||||
listings. Revision numbers are links to <a href="help_log.html">log
|
||||
views</a> showing lists of revisions where a file or directory was
|
||||
modified.
|
||||
-->
|
||||
|
||||
Also, in CVS repositories with the
|
||||
<a href="help_rootview.html#view-graph">graph view</a> enabled, there
|
||||
will be small
|
||||
<img src="images/cvsgraph_16x16.png" width="16" height="16" alt="graph">
|
||||
icons next to file names which are links to revision graphs.</p>
|
||||
|
||||
<p>Depending on how ViewVC is configured, there may be more options
|
||||
at the bottom of directory pages:</p>
|
||||
|
||||
<ul>
|
||||
<li><a name="option-search"><strong>Regular expression
|
||||
search</strong></a> - If enabled, will show a form field accepting
|
||||
a search string (a
|
||||
<a href="http://doc.python.org/lib/re-syntax.html">python regular
|
||||
expression</a>). Once submitted, only files that have at least
|
||||
one occurance of the expression will show up in directory listings.
|
||||
</li>
|
||||
<li><a name="option-tarball"><strong>Tarball download</strong></a> -
|
||||
If enabled, will show a link to download a gzipped tar archive of
|
||||
the directory contents.</li>
|
||||
</ul>
|
||||
|
||||
</td></tr></table>
|
||||
<hr />
|
||||
<address><a href="mailto:users@viewvc.tigris.org">ViewVC Users Mailinglist</a></address>
|
||||
</body>
|
||||
</html>
|
74
templates-contrib/tabbed/templates/docroot/help_log.html
Normal file
@@ -0,0 +1,74 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<title>ViewVC Help: Log View</title>
|
||||
<link rel="stylesheet" href="help.css" type="text/css" />
|
||||
<meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
|
||||
</head>
|
||||
<body>
|
||||
<table>
|
||||
<col class="menu" />
|
||||
<col />
|
||||
<tr>
|
||||
<td><a href="http://viewvc.org/index.html"><img
|
||||
src="images/logo.png" alt="ViewVC logotype" /></a>
|
||||
</td>
|
||||
<td>
|
||||
<h1>ViewVC Help: Log View</h1>
|
||||
</td>
|
||||
</tr>
|
||||
<tr><td>
|
||||
<h3>Help</h3>
|
||||
<a href="help_rootview.html">General</a><br />
|
||||
<a href="help_dirview.html">Directory View</a><br />
|
||||
<strong>Log View</strong><br />
|
||||
|
||||
<h3>Internet</h3>
|
||||
<a href="http://viewvc.org/index.html">Home</a><br />
|
||||
<a href="http://viewvc.org/upgrading.html">Upgrading</a><br />
|
||||
<a href="http://viewvc.org/contributing.html">Contributing</a><br />
|
||||
<a href="http://viewvc.org/license-1.html">License</a><br />
|
||||
</td><td colspan="2">
|
||||
<p>
|
||||
The log view displays the revision history of the selected source
|
||||
file or directory. For each revision the following information is
|
||||
displayed:
|
||||
|
||||
<ul>
|
||||
<li>The revision number. In Subversion repositories, this is a
|
||||
link to the <a href="help_rootview.html#view-rev">revision
|
||||
view</a></li>
|
||||
<li>For files, links to
|
||||
<a href="help_rootview.html#view-markup">view</a>,
|
||||
<a href="help_rootview.html#view-checkout">download</a>, and
|
||||
<a href="help_rootview.html#view-annotate">annotate</a> the
|
||||
revision. For directories, a link to
|
||||
<a href="help_dirview.html">list directory contents</a></li>
|
||||
<li>A link to select the revision for diffs (see below)</li>
|
||||
<li>The date and age of the change</li>
|
||||
<li>The author of the modification</li>
|
||||
<li>The CVS branch (usually <em>MAIN</em>, if not on a branch)</li>
|
||||
<li>Possibly a list of CVS tags bound to the revision (if any)</li>
|
||||
<li>The size of the change measured in added and removed lines of
|
||||
code. (CVS only)</li>
|
||||
<li>The size of the file in bytes at the time of the revision
|
||||
(Subversion only)</li>
|
||||
<li>Links to view diffs to the previous revision or possibly to
|
||||
an arbitrary selected revision (if any, see above)</li>
|
||||
<li>If the revision is the result of a copy, the path and revision
|
||||
copied from</li>
|
||||
<li>If the revision precedes a copy or rename, the path at the
|
||||
time of the revision</li>
|
||||
<li>And last but not least, the commit log message which should tell
|
||||
about the reason for the change.</li>
|
||||
</ul>
|
||||
<p>
|
||||
At the bottom of the page you will find a form which allows
|
||||
to request diffs between arbitrary revisions.
|
||||
</p>
|
||||
</td></tr></table>
|
||||
<hr />
|
||||
<address><a href="mailto:users@viewvc.tigris.org">ViewVC Users Mailinglist</a></address>
|
||||
</body>
|
||||
</html>
|
67
templates-contrib/tabbed/templates/docroot/help_query.html
Normal file
@@ -0,0 +1,67 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<title>ViewVC Help: Query The Commit Database</title>
|
||||
<link rel="stylesheet" href="help.css" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<table>
|
||||
<col class="menu" />
|
||||
<col />
|
||||
<tr>
|
||||
<td><a href=".."><img
|
||||
src="images/logo.png" alt="ViewVC logotype" /></a>
|
||||
</td>
|
||||
<td><h1>ViewVC Help: Query The Commit Database</h1></td>
|
||||
</tr>
|
||||
<tr><td>
|
||||
<h3>Other Help:</h3>
|
||||
<a href="help_rootview.html">General</a><br />
|
||||
<a href="help_dirview.html">Directory View</a><br />
|
||||
<a href="help_log.html">Classic Log View</a><br />
|
||||
<a href="help_logtable.html">Alternative Log View</a><br />
|
||||
<strong>Query Database</strong>
|
||||
|
||||
<h3>Internet</h3>
|
||||
<a href="http://viewvc.org/index.html">Home</a><br />
|
||||
<a href="http://viewvc.org/upgrading.html">Upgrading</a><br />
|
||||
<a href="http://viewvc.org/contributing.html">Contributing</a><br />
|
||||
<a href="http://viewvc.org/license-1.html">License</a><br />
|
||||
</td><td colspan="2">
|
||||
|
||||
<p>
|
||||
Select your parameters for querying the CVS commit database in the
|
||||
form at the top of the page. You
|
||||
can search for multiple matches by typing a comma-seperated list
|
||||
into the text fields. Regular expressions, and wildcards are also
|
||||
supported. Blank text input fields are treated as wildcards.
|
||||
</p>
|
||||
<p>
|
||||
Any of the text entry fields can take a comma-seperated list of
|
||||
search arguments. For example, to search for all commits from
|
||||
authors <em>jpaint</em> and <em>gstein</em>, just type: <code>jpaint,
|
||||
gstein</code> in the <em>Author</em> input box. If you are searching
|
||||
for items containing spaces or quotes, you will need to quote your
|
||||
request. For example, the same search above with quotes is:
|
||||
<code>"jpaint", "gstein"</code>.
|
||||
</p>
|
||||
<p>
|
||||
Wildcard and regular expression searches are entered in a similar
|
||||
way to the quoted requests. You must quote any wildcard or
|
||||
regular expression request, and a command character preceeds the
|
||||
first quote. The command character <code>l</code>(lowercase L) is for wildcard
|
||||
searches, and the wildcard character is a percent (<code>%</code>). The
|
||||
command character for regular expressions is <code>r</code>, and is
|
||||
passed directly to MySQL, so you'll need to refer to the MySQL
|
||||
manual for the exact regex syntax. It is very similar to Perl. A
|
||||
wildard search for all files with a <em>.py</em> extention is:
|
||||
<code>l"%.py"</code> in the <em>File</em> input box. The same search done
|
||||
with a regular expression is: <code>r".*\.py"</code>.
|
||||
</p>
|
||||
<p>
|
||||
All search types can be mixed, as long as they are seperated by
|
||||
commas.
|
||||
</p>
|
||||
</td></tr></table>
|
||||
</body></html>
|
169
templates-contrib/tabbed/templates/docroot/help_rootview.html
Normal file
@@ -0,0 +1,169 @@
|
||||
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
||||
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
||||
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
||||
<head>
|
||||
<title>ViewVC Help: General</title>
|
||||
<link rel="stylesheet" href="help.css" type="text/css" />
|
||||
</head>
|
||||
<body>
|
||||
<table>
|
||||
<col class="menu" />
|
||||
<col />
|
||||
<tr>
|
||||
<td><a href=".."><img
|
||||
src="images/logo.png" alt="ViewVC logotype" /></a>
|
||||
</td>
|
||||
<td>
|
||||
<h1>ViewVC Help: General</h1>
|
||||
</td>
|
||||
</tr>
|
||||
<tr><td>
|
||||
<h3>Help</h3>
|
||||
<strong>General</strong><br />
|
||||
<a href="help_dirview.html">Directory View</a><br />
|
||||
<a href="help_log.html">Log View</a><br />
|
||||
|
||||
<h3>Internet</h3>
|
||||
<a href="http://viewvc.org/index.html">Home</a><br />
|
||||
<a href="http://viewvc.org/upgrading.html">Upgrading</a><br />
|
||||
<a href="http://viewvc.org/contributing.html">Contributing</a><br />
|
||||
<a href="http://viewvc.org/license-1.html">License</a><br />
|
||||
</td><td colspan="2">
|
||||
|
||||
<p><em>ViewVC</em> is a WWW interface for CVS and Subversion
|
||||
repositories. It allows you to browse the files and directories in a
|
||||
repository while showing you metadata from the repository history: log
|
||||
messages, modification dates, author names, revision numbers, copy
|
||||
history, and so on. It provides several different views of repository
|
||||
data to help you find the information you are looking for:</p>
|
||||
|
||||
<ul>
|
||||
<li><a name="view-dir" href="help_dirview.html"><strong>Directory
|
||||
View</strong></a> - Shows a list of files and subdirectories in a
|
||||
directory of the repository, along with metadata like author names and
|
||||
log entries.</li>
|
||||
|
||||
<li><a name="view-log" href="help_log.html"><strong>Log
|
||||
View</strong></a> - Shows a revision by revision list of all the
|
||||
changes that have made to a file or directory in the repository, with
|
||||
metadata and links to views of each revision.</li>
|
||||
|
||||
<li><a name="view-markup"><strong>File Contents View (Markup
|
||||
View)</strong></a> - Shows the contents of a file at a particular
|
||||
revision, with revision information at the top of the page. File
|
||||
revisions which are GIF, PNG, or JPEG images are displayed inline on
|
||||
the page. Other file types are displayed as marked up text. The markup
|
||||
may be limited to turning URLs and email addresses into links, or
|
||||
configured to show colorized source code.</li>
|
||||
|
||||
<li><a name="view-checkout"><strong>File Download (Checkout
|
||||
View)</strong></a> - Retrieves the unaltered contents of a file
|
||||
revision. Browsers may try to display the file, or just save it to
|
||||
disk.</li>
|
||||
|
||||
<li><a name="view-annotate"><strong>File Annotate View</strong></a> -
|
||||
Shows the contents of a file revision and breaks it down line by line,
|
||||
showing the revision number where each one was last modified, along
|
||||
with links and other information. <em>This view is disabled in some
|
||||
ViewVC configurations</em></li>
|
||||
|
||||
<li><a name="view-diff"><strong>File Diff View</strong></a> - Shows
|
||||
the changes made between two revisions of a file</li>
|
||||
|
||||
<li><a name="view-tarball"><strong>Directory Tarball View</strong> -
|
||||
Retrieves a gzipped tar archive containing the contents of a
|
||||
directory.<em>This view is disabled in the default ViewVC
|
||||
configuration.</em></li>
|
||||
|
||||
<li><a name="view-query"><strong>Directory Query View</strong></a> -
|
||||
Shows information about changes made to all subdirectories and files
|
||||
under a parent directory, sorted and filtered by criteria you specify.
|
||||
<em>This view is disabled in the default ViewVC configuration.</em>
|
||||
</li>
|
||||
|
||||
<li><a name="view-rev"><strong>Revision View</strong> - Shows
|
||||
information about a revision including log message, author, and a list
|
||||
of changed paths. <em>For Subversion repositories only.</em></li>
|
||||
|
||||
<li><a name="view-graph"><strong>Graph View</strong></a> - Shows a
|
||||
graphical representation of a file's revisions and branches complete
|
||||
with tag and author names and links to markup and diff pages.
|
||||
<em>For CVS repositories only, and disabled in the default
|
||||
configuration.</em></li>
|
||||
</ul>
|
||||
|
||||
<h3><a name="multiple-repositories">Multiple Repositories</a></h3>
|
||||
|
||||
<p>A single installation of ViewVC is often used to provide access to
|
||||
more than one repository. In these installations, ViewVC shows a
|
||||
<em>Project Root</em> drop down box in the top right corner of every
|
||||
generated page to allow for quick access to any repository.</p>
|
||||
|
||||
<h3><a name="sticky-revision-tag">Sticky Revision and Tag</a></h3>
|
||||
|
||||
<p>By default, ViewVC will show the files and directories and revisions
|
||||
that currently exist in the repository. But it's also possible to browse
|
||||
the contents of a repository at a point in its past history by choosing
|
||||
a "sticky tag" (in CVS) or a "sticky revision" (in Subversion) from the
|
||||
forms at the top of directory and log pages. They're called sticky
|
||||
because once they're chosen, they stick around when you navigate to
|
||||
other pages, until you reset them. When they're set, directory and log
|
||||
pages only show revisions preceding the specified point in history. In
|
||||
CVS, when a tag refers to a branch or a revision on a branch, only
|
||||
revisions from the branch history are shown, including branch points and
|
||||
their preceding revisions.</p>
|
||||
|
||||
<h3><a name="dead-files">Dead Files</a></h3>
|
||||
|
||||
<p>In CVS directory listings, ViewVC can optionally display dead files.
|
||||
Dead files are files which used to be in a directory but are currently
|
||||
deleted, or files which just don't exist in the currently selected
|
||||
<a href="#sticky-revision-tag">sticky tag</a>. Dead files cannot be
|
||||
shown in Subversion repositories. The only way to see a deleted file in
|
||||
a Subversion directory is to navigate to a sticky revision where the
|
||||
file previously existed.</p>
|
||||
|
||||
<h3><a name="artificial-tags">Artificial Tags</a></h3>
|
||||
|
||||
<p>In CVS Repositories, ViewVC adds artificial tags <em>HEAD</em> and
|
||||
<em>MAIN</em> to tag listings and accepts them in place of revision
|
||||
numbers and real tag names in all URLs. <em>MAIN</em> acts like a branch
|
||||
tag pointing at the default branch, while <em>HEAD</em> acts like a
|
||||
revision tag pointing to the latest revision on the default branch. The
|
||||
default branch is usually just the trunk, but may be set to other
|
||||
branches inside individual repository files. CVS will always check out
|
||||
revisions from a file's default branch when no other branch is specified
|
||||
on the command line.</p>
|
||||
|
||||
<h3><a name="more-information">More Information</a></h3>
|
||||
|
||||
<p>More information about <em>ViewVC</em> is available from
|
||||
<a href="http://viewvc.org/">viewvc.org</a>.
|
||||
See the links below for guides to CVS and Subversion</p>
|
||||
|
||||
<h4>Documentation about CVS</h4>
|
||||
<blockquote>
|
||||
<p>
|
||||
<a href="http://cvsbook.red-bean.com/"><em>Open Source
|
||||
Development with CVS</em></a><br />
|
||||
<a href="http://www.loria.fr/~molli/cvs/doc/cvs_toc.html">CVS
|
||||
User's Guide</a><br />
|
||||
<a href="http://cellworks.washington.edu/pub/docs/cvs/tutorial/cvs_tutorial_1.html">Another CVS tutorial</a><br />
|
||||
<a href="http://www.csc.calpoly.edu/~dbutler/tutorials/winter96/cvs/">Yet another CVS tutorial (a little old, but nice)</a><br />
|
||||
<a href="http://www.cs.utah.edu/dept/old/texinfo/cvs/FAQ.txt">An old but very useful FAQ about CVS</a>
|
||||
</p>
|
||||
</blockquote>
|
||||
|
||||
<h4>Documentation about Subversion</h3>
|
||||
<blockquote>
|
||||
<p>
|
||||
<a href="http://svnbook.red-bean.com/"><em>Version Control with
|
||||
Subversion</em></a><br />
|
||||
</p>
|
||||
</blockquote>
|
||||
|
||||
</td></tr></table>
|
||||
<hr />
|
||||
<address><a href="mailto:users@viewvc.tigris.org">ViewVC Users Mailinglist</a></address>
|
||||
</body>
|
||||
</html>
|
BIN
templates-contrib/tabbed/templates/docroot/images/annotate.png
Normal file
After Width: | Height: | Size: 764 B |
BIN
templates-contrib/tabbed/templates/docroot/images/back.png
Normal file
After Width: | Height: | Size: 337 B |
BIN
templates-contrib/tabbed/templates/docroot/images/back_small.png
Normal file
After Width: | Height: | Size: 205 B |
BIN
templates-contrib/tabbed/templates/docroot/images/broken.png
Normal file
After Width: | Height: | Size: 247 B |
BIN
templates-contrib/tabbed/templates/docroot/images/chalk.jpg
Normal file
After Width: | Height: | Size: 755 B |
BIN
templates-contrib/tabbed/templates/docroot/images/cvs-logo.png
Normal file
After Width: | Height: | Size: 601 B |