viewvc-4intranet/lib/query.py

435 lines
12 KiB
Python
Raw Normal View History

#!/usr/bin/env python
# -*-python-*-
#
# Copyright (C) 1999-2007 The ViewCVS Group. All Rights Reserved.
#
# By using this file, you agree to the terms and conditions set forth in
Work on issue 168, s/ViewCVS/ViewVC. This patch changes references to ViewCVS in comments, strings, and documentation. References to ViewCVS in filenames and urls still need to be fixed. Also, logo.png (the blimp) needs to be updated or replaced. This patch is by Gerard Gerritsen (sigcafe), the only change I've made is to restore a reference to ViewCVS in a comment about backwards compatibility. * windows/README * viewcvs-install * README * templates/include/footer.ezt * templates/include/header.ezt * templates/error.ezt * templates/query.ezt * templates/docroot/help.css * templates/docroot/help_query.html * templates/docroot/help_dirview.html * templates/docroot/help_rootview.html * templates/docroot/styles.css * templates/docroot/help_log.html * templates/diff.ezt * tools/make-release * lib/sapi.py * lib/dbi.py * lib/accept.py * lib/cvsdb.py * lib/config.py * lib/query.py * lib/vclib/bincvs/__init__.py * lib/vclib/svn/__init__.py * lib/vclib/__init__.py * lib/vclib/svn_ra/__init__.py * lib/vclib/ccvs/rcsparse/common.py * lib/vclib/ccvs/rcsparse/__init__.py * lib/vclib/ccvs/rcsparse/default.py * lib/vclib/ccvs/rcsparse/texttools.py * lib/vclib/ccvs/rcsparse/debug.py * lib/vclib/ccvs/__init__.py * lib/vclib/ccvs/blame.py * lib/blame.py * lib/popen.py * lib/compat.py * lib/viewcvs.py * lib/debug.py * INSTALL * bin/standalone.py * bin/make-database * bin/mod_python/query.py * bin/mod_python/viewcvs.py * bin/cgi/query.cgi * bin/cgi/viewcvs.cgi * bin/asp/query.asp * bin/asp/viewcvs.asp * bin/svndbadmin * bin/loginfo-handler * bin/cvsdbadmin * viewcvs.conf.dist git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@1200 8cb11bc2-c004-0410-86c3-e597b4017df7
2005-12-17 20:19:28 +03:00
# 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/
#
# -----------------------------------------------------------------------
#
# CGI script to process and display queries to CVSdb
#
Work on issue 168, s/ViewCVS/ViewVC. This patch changes references to ViewCVS in comments, strings, and documentation. References to ViewCVS in filenames and urls still need to be fixed. Also, logo.png (the blimp) needs to be updated or replaced. This patch is by Gerard Gerritsen (sigcafe), the only change I've made is to restore a reference to ViewCVS in a comment about backwards compatibility. * windows/README * viewcvs-install * README * templates/include/footer.ezt * templates/include/header.ezt * templates/error.ezt * templates/query.ezt * templates/docroot/help.css * templates/docroot/help_query.html * templates/docroot/help_dirview.html * templates/docroot/help_rootview.html * templates/docroot/styles.css * templates/docroot/help_log.html * templates/diff.ezt * tools/make-release * lib/sapi.py * lib/dbi.py * lib/accept.py * lib/cvsdb.py * lib/config.py * lib/query.py * lib/vclib/bincvs/__init__.py * lib/vclib/svn/__init__.py * lib/vclib/__init__.py * lib/vclib/svn_ra/__init__.py * lib/vclib/ccvs/rcsparse/common.py * lib/vclib/ccvs/rcsparse/__init__.py * lib/vclib/ccvs/rcsparse/default.py * lib/vclib/ccvs/rcsparse/texttools.py * lib/vclib/ccvs/rcsparse/debug.py * lib/vclib/ccvs/__init__.py * lib/vclib/ccvs/blame.py * lib/blame.py * lib/popen.py * lib/compat.py * lib/viewcvs.py * lib/debug.py * INSTALL * bin/standalone.py * bin/make-database * bin/mod_python/query.py * bin/mod_python/viewcvs.py * bin/cgi/query.cgi * bin/cgi/viewcvs.cgi * bin/asp/query.asp * bin/asp/viewcvs.asp * bin/svndbadmin * bin/loginfo-handler * bin/cvsdbadmin * viewcvs.conf.dist git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@1200 8cb11bc2-c004-0410-86c3-e597b4017df7
2005-12-17 20:19:28 +03:00
# This script is part of the ViewVC package. More information can be
# found at http://viewvc.org
#
# -----------------------------------------------------------------------
import os
import sys
import string
import time
import cvsdb
import viewvc
import ezt
import debug
import urllib
import vcauth
class FormData:
def __init__(self, form):
self.valid = 0
self.repository = ""
self.branch = ""
self.directory = ""
self.file = ""
self.who = ""
self.sortby = ""
self.date = ""
self.hours = 0
self.decode_thyself(form)
def decode_thyself(self, form):
try:
self.repository = string.strip(form["repository"].value)
except KeyError:
pass
except TypeError:
pass
else:
self.valid = 1
try:
self.branch = string.strip(form["branch"].value)
except KeyError:
pass
except TypeError:
pass
else:
self.valid = 1
try:
self.directory = string.strip(form["directory"].value)
except KeyError:
pass
except TypeError:
pass
else:
self.valid = 1
try:
self.file = string.strip(form["file"].value)
except KeyError:
pass
except TypeError:
pass
else:
self.valid = 1
try:
self.who = string.strip(form["who"].value)
except KeyError:
pass
except TypeError:
pass
else:
self.valid = 1
try:
self.sortby = string.strip(form["sortby"].value)
except KeyError:
pass
except TypeError:
pass
try:
self.date = string.strip(form["date"].value)
except KeyError:
pass
except TypeError:
pass
try:
self.hours = int(form["hours"].value)
except KeyError:
pass
except TypeError:
pass
except ValueError:
pass
else:
self.valid = 1
## returns a tuple-list (mod-str, string)
def listparse_string(str):
return_list = []
cmd = ""
temp = ""
escaped = 0
state = "eat leading whitespace"
for c in str:
## handle escaped charactors
if not escaped and c == "\\":
escaped = 1
continue
## strip leading white space
if state == "eat leading whitespace":
if c in string.whitespace:
continue
else:
state = "get command or data"
## parse to '"' or ","
if state == "get command or data":
## just add escaped charactors
if escaped:
escaped = 0
temp = temp + c
continue
## the data is in quotes after the command
elif c == "\"":
cmd = temp
temp = ""
state = "get quoted data"
continue
## this tells us there was no quoted data, therefore no
## command; add the command and start over
elif c == ",":
## strip ending whitespace on un-quoted data
temp = string.rstrip(temp)
return_list.append( ("", temp) )
temp = ""
state = "eat leading whitespace"
continue
## record the data
else:
temp = temp + c
continue
## parse until ending '"'
if state == "get quoted data":
## just add escaped charactors
if escaped:
escaped = 0
temp = temp + c
continue
## look for ending '"'
elif c == "\"":
return_list.append( (cmd, temp) )
cmd = ""
temp = ""
state = "eat comma after quotes"
continue
## record the data
else:
temp = temp + c
continue
## parse until ","
if state == "eat comma after quotes":
if c in string.whitespace:
continue
elif c == ",":
state = "eat leading whitespace"
continue
else:
print "format error"
sys.exit(1)
if cmd or temp:
return_list.append((cmd, temp))
return return_list
def decode_command(cmd):
if cmd == "r":
return "regex"
elif cmd == "l":
return "like"
else:
return "exact"
def form_to_cvsdb_query(form_data):
query = cvsdb.CreateCheckinQuery()
if form_data.repository:
for cmd, str in listparse_string(form_data.repository):
cmd = decode_command(cmd)
query.SetRepository(str, cmd)
if form_data.branch:
for cmd, str in listparse_string(form_data.branch):
cmd = decode_command(cmd)
query.SetBranch(str, cmd)
if form_data.directory:
for cmd, str in listparse_string(form_data.directory):
cmd = decode_command(cmd)
query.SetDirectory(str, cmd)
if form_data.file:
for cmd, str in listparse_string(form_data.file):
cmd = decode_command(cmd)
query.SetFile(str, cmd)
if form_data.who:
for cmd, str in listparse_string(form_data.who):
cmd = decode_command(cmd)
query.SetAuthor(str, cmd)
if form_data.sortby == "author":
query.SetSortMethod("author")
elif form_data.sortby == "file":
query.SetSortMethod("file")
else:
query.SetSortMethod("date")
if form_data.date:
if form_data.date == "hours" and form_data.hours:
query.SetFromDateHoursAgo(form_data.hours)
elif form_data.date == "day":
query.SetFromDateDaysAgo(1)
elif form_data.date == "week":
query.SetFromDateDaysAgo(7)
elif form_data.date == "month":
query.SetFromDateDaysAgo(31)
return query
def prev_rev(rev):
'''Returns a string representing the previous revision of the argument.'''
r = string.split(rev, '.')
# decrement final revision component
r[-1] = str(int(r[-1]) - 1)
# prune if we pass the beginning of the branch
if len(r) > 2 and r[-1] == '0':
r = r[:-2]
return string.join(r, '.')
def build_commit(server, cfg, auth, desc, files, cvsroots, viewvc_link):
ob = _item(num_files=len(files), files=[])
if desc:
ob.log = string.replace(server.escape(desc), '\n', '<br />')
else:
ob.log = '&nbsp;'
for commit in files:
dir_parts = filter(None, string.split(commit.GetDirectory(), '/'))
if dir_parts \
and ((dir_parts[0] == 'CVSROOT' and cfg.options.hide_cvsroot) \
or auth.check_directory_access(dir_parts)):
continue
ctime = commit.GetTime()
if not ctime:
ctime = "&nbsp;"
else:
if (cfg.options.use_localtime):
ctime = time.strftime("%y/%m/%d %H:%M %Z", time.localtime(ctime))
else:
ctime = time.strftime("%y/%m/%d %H:%M", time.gmtime(ctime)) \
+ ' UTC'
## make the file link
Fix file path issues in CVSdb on windows. Summary of changes: - Stop converting directory and file paths to lower case with native slashes before storing them in the database. Instead store with preserved case and forward slashes. - Stop trying to clean up paths haphazardly all over the cvsdb module, instead expect paths to be normalized before they get passed to cvsdb. * lib/cvsdb.py (Commit.SetRepository, Commit.SetDirectory, Commit.SetFile, CheckinDatabaseQuery.SetRepository, CheckinDatabaseQuery.SetDirectory): remove path cleanup code (RLogDataToCommitList) don't strip repository prefix because rlog module now does it (CleanRepository): new function * lib/rlog.py (_get_co_file): change to return paths with forward slashes and without repository prefixes (GetRLogData): update call to _get_co_file * tools/cvsdbadmin (UpdateFile, CommandUpdate, RebuildFile, CommandRebuild) remove calls to normcase here (module code): use CleanRepository function to clean up repository path * tools/loginfo-handler (CleanDirectory): removed (HeuristicArgParse, CvsNtArgParse): don't call CleanDirectory or normcase here (HeuristicArgParseDirectory): remove stray print statement (module code): use cvsdb.CleanRepository function to clean up repository path * tools/svndbadmin (module code): use cvsdb.CleanRepository function to clean up repository path * lib/viewcvs.py (view_query): change to use forward slashes in directory names instead of native slashes use cvsdb.CleanRepository function to clean up repository paths * lib/query.py (build_commit): change to handle forward slashes in directory paths instead of native slashes (run_query): use cvsdb.CleanRepository function to clean up repository path git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@952 8cb11bc2-c004-0410-86c3-e597b4017df7
2004-10-16 04:47:42 +04:00
repository = commit.GetRepository()
directory = commit.GetDirectory()
file = (directory and directory + "/") + commit.GetFile()
cvsroot_name = cvsroots.get(repository)
## if we couldn't find the cvsroot path configured in the
## viewvc.conf file, then don't make the link
if cvsroot_name:
flink = '[%s] <a href="%s/%s?root=%s">%s</a>' % (
cvsroot_name, viewvc_link, urllib.quote(file),
cvsroot_name, file)
if commit.GetType() == commit.CHANGE:
dlink = '%s/%s?root=%s&amp;view=diff&amp;r1=%s&amp;r2=%s' % (
viewvc_link, urllib.quote(file), cvsroot_name,
prev_rev(commit.GetRevision()), commit.GetRevision())
else:
dlink = None
else:
Fix file path issues in CVSdb on windows. Summary of changes: - Stop converting directory and file paths to lower case with native slashes before storing them in the database. Instead store with preserved case and forward slashes. - Stop trying to clean up paths haphazardly all over the cvsdb module, instead expect paths to be normalized before they get passed to cvsdb. * lib/cvsdb.py (Commit.SetRepository, Commit.SetDirectory, Commit.SetFile, CheckinDatabaseQuery.SetRepository, CheckinDatabaseQuery.SetDirectory): remove path cleanup code (RLogDataToCommitList) don't strip repository prefix because rlog module now does it (CleanRepository): new function * lib/rlog.py (_get_co_file): change to return paths with forward slashes and without repository prefixes (GetRLogData): update call to _get_co_file * tools/cvsdbadmin (UpdateFile, CommandUpdate, RebuildFile, CommandRebuild) remove calls to normcase here (module code): use CleanRepository function to clean up repository path * tools/loginfo-handler (CleanDirectory): removed (HeuristicArgParse, CvsNtArgParse): don't call CleanDirectory or normcase here (HeuristicArgParseDirectory): remove stray print statement (module code): use cvsdb.CleanRepository function to clean up repository path * tools/svndbadmin (module code): use cvsdb.CleanRepository function to clean up repository path * lib/viewcvs.py (view_query): change to use forward slashes in directory names instead of native slashes use cvsdb.CleanRepository function to clean up repository paths * lib/query.py (build_commit): change to handle forward slashes in directory paths instead of native slashes (run_query): use cvsdb.CleanRepository function to clean up repository path git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@952 8cb11bc2-c004-0410-86c3-e597b4017df7
2004-10-16 04:47:42 +04:00
flink = '[%s] %s' % (repository, file)
dlink = None
ob.files.append(_item(date=ctime,
author=commit.GetAuthor(),
link=flink,
rev=commit.GetRevision(),
branch=commit.GetBranch(),
plus=int(commit.GetPlusCount()),
minus=int(commit.GetMinusCount()),
type=commit.GetTypeString(),
difflink=dlink,
))
return ob
def run_query(server, cfg, form_data, viewvc_link):
auth_params = cfg.get_authorizer_params('forbidden')
auth = vcauth.forbidden.ViewVCAuthorizer(None, None, None, None,
auth_params)
query = form_to_cvsdb_query(form_data)
Tweak logic used to find installed paths ("lib" directory, configuration file, templates, etc). Specifically, make the following changes: - Get rid of hardcoded paths in module files ("lib" directory) and configuration files (viewcvs.conf and mod_python's .htaccess) - Allow stub scripts (for asp, cgi, and mod_python) to specify configuration files so it's possible to have multiple configurations of viewcvs running off a single installation. - Be more consistent about resolving paths when they aren't hardcoded (when ViewCVS is running from a source directory). In particular, try not to depend on the working directory. That way it's legal to run ./standalone.py instead of bin/standalone.py without getting an ImportError. - Get rid of global cfg variables in viewcvs.py and cvsdb.py. They led to all sorts of hacks in other files to pilfer and reset them. They were also possible sources of races in multithreaded environments like mod_python and asp. - Rewrite mod_python handler so library paths can be specified inside the stub files. * lib/apache.py removed, contained old mod_python handler * lib/config.py (Config.load_config): remove sys.argv voodoo, just load the configuration path specified in the pathname argument (Config.set_defaults): use relative path for cvsgraph_conf setting instead of hardcoded <VIEWCVS_INSTALL_DIRECTORY> literal * lib/cvsdb.py (CONF_PATHNAME, config, cfg): removed, configuration stuff (CheckinDatabase.__init__, CheckinDatabase.CreateSQLQueryString): add "_row_limit" member instead of using cfg object (CreateCheckinDatabase): removed, a do-nothing function (ConnectDatabaseReadOnly, ConnectDatabase): add cfg arguments (GetUnrecordedCommitList): add db argument * lib/query.py (CONF_PATHAME): removed (build_commit, run_query, main): add cfg arguments, use new viewcvs.get_template function * lib/viewcvs.py (CONF_PATHNAME, cfg, g_install_dir): removed (Request.__init__): add cfg member (Request.run_viewcvs, Request.get_link, check_freshness, get_view_template, generate_page, default_view, get_file_view_info, format_log, common_template_data, MarkupEnscript.__init__, markup_stream_python, markup_stream_php, make_time_string, view_markup, sort_file_data, view_directory, paging, view_log, view_annotate, view_cvsgraph_image, view_cvsgraph, view_doc, rcsdiff_date_reformat, spaced_html_text, DiffSource.__init__, DiffSource._get_row, view_patch, view_diff, generate_tarball, download_tarball, view_revision, is_query_supported, english_query, build_commit, view_query, view_error, main): stop using global config, use cfg arguments or request member instead (_install_path): new, use __file__ to locate template and configuation paths (get_view_template): use _install_path and return compiled template instead of path (is_viewable, default_view): rename is_viewable to default_view and return view instead of boolean (handle_config, load_config): rename handle_config to load_config and return config object instead of setting cfg global * bin/cgi/viewcvs.cgi * bin/cgi/query.cgi * bin/cvsdbadmin * bin/loginfo-handler * bin/standalone.py * bin/svndbadmin look for library relative to sys.argv[0] when no hardcoded library path is available. Also add configuration loading code. * bin/asp/viewcvs.asp * bin/asp/query.asp add configuration loading code * bin/mod_python/.htaccess specify new mod_python handler, remove reference to <VIEWCVS_APACHE_LIBRARY_DIRECTORY> * bin/mod_python/handler.py added, holds new mod_python handler * bin/mod_python/viewcvs.py * bin/mod_python/query.py rewrite for new handler, add hardcoded library and configuration paths * viewcvs.conf.dist remove references to <VIEWCVS_INSTALL_DIRECTORY> * viewcvs-install (FILE_INFO_LIST): stop hardcoding paths in config files (SetPythonPaths,): get rid of <VIEWCVS_INSTALL_DIRECTORY> and <VIEWCVS_APACHE_LIBRARY_DIRECTORY> substitutions (ApacheEscape, _re_apache): removed (InstallTree): stop hardcoding paths in lib directory git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@1173 8cb11bc2-c004-0410-86c3-e597b4017df7
2005-12-06 07:04:14 +03:00
db = cvsdb.ConnectDatabaseReadOnly(cfg)
db.RunQuery(query)
if not query.commit_list:
return [ ]
commits = [ ]
files = [ ]
cvsroots = {}
rootitems = cfg.general.svn_roots.items() + cfg.general.cvs_roots.items()
for key, value in rootitems:
Fix file path issues in CVSdb on windows. Summary of changes: - Stop converting directory and file paths to lower case with native slashes before storing them in the database. Instead store with preserved case and forward slashes. - Stop trying to clean up paths haphazardly all over the cvsdb module, instead expect paths to be normalized before they get passed to cvsdb. * lib/cvsdb.py (Commit.SetRepository, Commit.SetDirectory, Commit.SetFile, CheckinDatabaseQuery.SetRepository, CheckinDatabaseQuery.SetDirectory): remove path cleanup code (RLogDataToCommitList) don't strip repository prefix because rlog module now does it (CleanRepository): new function * lib/rlog.py (_get_co_file): change to return paths with forward slashes and without repository prefixes (GetRLogData): update call to _get_co_file * tools/cvsdbadmin (UpdateFile, CommandUpdate, RebuildFile, CommandRebuild) remove calls to normcase here (module code): use CleanRepository function to clean up repository path * tools/loginfo-handler (CleanDirectory): removed (HeuristicArgParse, CvsNtArgParse): don't call CleanDirectory or normcase here (HeuristicArgParseDirectory): remove stray print statement (module code): use cvsdb.CleanRepository function to clean up repository path * tools/svndbadmin (module code): use cvsdb.CleanRepository function to clean up repository path * lib/viewcvs.py (view_query): change to use forward slashes in directory names instead of native slashes use cvsdb.CleanRepository function to clean up repository paths * lib/query.py (build_commit): change to handle forward slashes in directory paths instead of native slashes (run_query): use cvsdb.CleanRepository function to clean up repository path git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@952 8cb11bc2-c004-0410-86c3-e597b4017df7
2004-10-16 04:47:42 +04:00
cvsroots[cvsdb.CleanRepository(value)] = key
current_desc = query.commit_list[0].GetDescription()
for commit in query.commit_list:
desc = commit.GetDescription()
if current_desc == desc:
files.append(commit)
continue
commits.append(build_commit(server, cfg, auth, current_desc, files,
cvsroots, viewvc_link))
files = [ commit ]
current_desc = desc
## add the last file group to the commit list
commits.append(build_commit(server, cfg, auth, current_desc, files,
cvsroots, viewvc_link))
return commits
def main(server, cfg, viewvc_link):
try:
form = server.FieldStorage()
form_data = FormData(form)
if form_data.valid:
commits = run_query(server, cfg, form_data, viewvc_link)
query = None
else:
commits = [ ]
query = 'skipped'
script_name = server.getenv('SCRIPT_NAME', '')
data = {
'cfg' : cfg,
'address' : cfg.general.address,
'vsn' : viewvc.__version__,
'repository' : server.escape(form_data.repository, 1),
'branch' : server.escape(form_data.branch, 1),
'directory' : server.escape(form_data.directory, 1),
'file' : server.escape(form_data.file, 1),
'who' : server.escape(form_data.who, 1),
'docroot' : cfg.options.docroot is None \
and viewvc_link + '/' + viewvc.docroot_magic_path \
or cfg.options.docroot,
'sortby' : form_data.sortby,
'date' : form_data.date,
'query' : query,
'commits' : commits,
'num_commits' : len(commits),
'rss_href' : None,
}
if form_data.hours:
data['hours'] = form_data.hours
else:
data['hours'] = 2
server.header()
# generate the page
template = viewvc.get_view_template(cfg, "query")
template.generate(server.file(), data)
except SystemExit, e:
pass
except:
exc_info = debug.GetExceptionData()
server.header(status=exc_info['status'])
debug.PrintException(server, exc_info)
class _item:
def __init__(self, **kw):
vars(self).update(kw)