1
0
mirror of https://github.com/vitalif/viewvc-4intranet synced 2019-04-16 04:14:59 +03:00

Compare commits

...

25 Commits
1.1.6 ... 1.1.7

Author SHA1 Message Date
cmpilato
d7d567f089 Tag the 1.1.7 final release.
git-svn-id: http://viewvc.tigris.org/svn/viewvc/tags/1.1.7@2466 8cb11bc2-c004-0410-86c3-e597b4017df7
2010-09-09 18:22:48 +00:00
cmpilato
514da91629 Let's release 1.1.7 today, shall we?
git-svn-id: http://viewvc.tigris.org/svn/viewvc/branches/1.1.x@2465 8cb11bc2-c004-0410-86c3-e597b4017df7
2010-09-09 18:21:15 +00:00
cmpilato
d2c8bb9878 Merge from trunk r2463, which bumps some copyright years.
git-svn-id: http://viewvc.tigris.org/svn/viewvc/branches/1.1.x@2464 8cb11bc2-c004-0410-86c3-e597b4017df7
2010-09-09 18:20:01 +00:00
cmpilato
fe274e9b9c Merge from trunk r2458, r2459, and r2460, whose combined log messages
might read like so:

   Allow users to tell the query script where ViewVC is located while
   still generating the same defaults as before.
   
   Also, fix the query script's WSGI and FastCGI deployments.
   
   * conf/viewvc.conf.dist
     (query, query.viewvc_base_url): New section and value.
   
   * lib/config.py
     (_base_sections): Add 'query'.
     (Config.set_defaults): Set default value for cfg.query.viewvc_base_url.
   
   * lib/sapi.py
     (WsgiServer.FieldStorage): Don't pass self._headers to
       cgi.FieldStorage() -- that parameter is for *input* headers, and
       self._headers is a collection of output headers.
   
   * bin/asp/query.asp,
   * bin/cgi/query.cgi,
   * bin/mod_python/query.py,
   * bin/wsgi/query.fcgi,
   * bin/wsgi/query.wsgi,
     Ask the configuration for the location of ViewVC before falling back
     to old defaults.
   
   * templates/query.ezt
     Don't reference unset variables.  Do test the log message for
     empty-ness, dropping a non-breaking space in place where it is.
   
   * templates/include/footer.ezt
     Don't reference unset variables.  
   
   * lib/query.py
     (build_commit): Allow ob.log to be empty.  Don't generate ViewVC
       links if we don't have a base URL for ViewVC.
     (main): Calculate docroot in light of possible absent viewvc_link.

Also:

* CHANGES
  Note these changes.


git-svn-id: http://viewvc.tigris.org/svn/viewvc/branches/1.1.x@2462 8cb11bc2-c004-0410-86c3-e597b4017df7
2010-09-09 15:31:52 +00:00
cmpilato
6603a67a91 * CHANGES
Tweak change description.


git-svn-id: http://viewvc.tigris.org/svn/viewvc/branches/1.1.x@2461 8cb11bc2-c004-0410-86c3-e597b4017df7
2010-09-09 15:27:55 +00:00
cmpilato
b50de1c92e Merge from trunk r2454 and r2455, whose log messages contained the
following:

   * lib/vclib/svn/svn_repos.py
     (_split_revprops): Special-case the handling of empty input.
   
   * lib/viewvc.py
     (_re_rewrite_svnrevref): Wrap the regexp with word boundaries.


git-svn-id: http://viewvc.tigris.org/svn/viewvc/branches/1.1.x@2456 8cb11bc2-c004-0410-86c3-e597b4017df7
2010-09-08 18:28:25 +00:00
cmpilato
dfd8dc82f6 Merge from trunk r2452, some release procedure tweaks.
git-svn-id: http://viewvc.tigris.org/svn/viewvc/branches/1.1.x@2453 8cb11bc2-c004-0410-86c3-e597b4017df7
2010-09-08 17:14:44 +00:00
cmpilato
1a942d1062 Merge from trunk r2446.
git-svn-id: http://viewvc.tigris.org/svn/viewvc/branches/1.1.x@2449 8cb11bc2-c004-0410-86c3-e597b4017df7
2010-09-07 19:22:26 +00:00
cmpilato
289a78eb99 Merge from trunk r2444, whose log message read like so:
Finish issue #464: Add support for FastCGI (using a WSGI end-around).
   
   * bin/wsgi/viewvc.fcgi,
   * bin/wsgi/query.fcgi
     New scripts.
   
   * INSTALL
     Note the additional configuration/deployment option.
   
   * viewvc-install
     Install the .fcgi files, too.
   
   Patch by: Mark A. Ziesemer <ziesemer{_AT_}tigris.org>
             (Tweaked minorly by me.)
   
Also:

* CHANGES
  Note this change.


git-svn-id: http://viewvc.tigris.org/svn/viewvc/branches/1.1.x@2447 8cb11bc2-c004-0410-86c3-e597b4017df7
2010-09-07 19:20:22 +00:00
cmpilato
2897763020 Merge some typo fixes from trunk (r2441, r2442).
git-svn-id: http://viewvc.tigris.org/svn/viewvc/branches/1.1.x@2443 8cb11bc2-c004-0410-86c3-e597b4017df7
2010-09-07 15:41:48 +00:00
cmpilato
47886423e5 Merge from trunk r2439, whose log message said a little somethin' like
this:

   Finish issue #113: Support auto-markup of revision references.
   
   * lib/viewvc.py
     (_re_rewrite_svnrevref): New regular expression.
     (ViewVCHtmlFormatter.format_svnrevref): New.
     (format_log): Accept 'request' parameter instead of 'cfg' (which can
       be obtained via the request).  For Subversion repositories,
       register a formatter which marks up revision references as links
       to the revision view.
     (): Update callers of format_log().

Also:

* CHANGES
  Note this change.


git-svn-id: http://viewvc.tigris.org/svn/viewvc/branches/1.1.x@2440 8cb11bc2-c004-0410-86c3-e597b4017df7
2010-09-07 15:20:10 +00:00
cmpilato
0890821839 Merge from trunk r2435, whose log message contained the following:
* lib/vclib/svn/svn_repos.py
     (BlameSource.__init__): Use client.create_context() instead of
       client.ctx_t() to avoid "NULL proxy object pool" error.


git-svn-id: http://viewvc.tigris.org/svn/viewvc/branches/1.1.x@2436 8cb11bc2-c004-0410-86c3-e597b4017df7
2010-09-03 16:21:25 +00:00
cmpilato
2903389d3e Merge from trunk r2430, whose log message rock opera production had
the following lyrics:

   Parse the "; charset=..." bit out of Subversion's svn:mime-type
   property, and use it to inform Pygments as to the file's encoding in
   the markup and annotate views (while still providing that information
   to the user agent in the checkout view).
   
   * lib/viewvc.py
     (parse_mime_type): New helper function.
     (calculate_mime_type): Now also return the encoding as possibly
       parsed from the svn:mime-type property.  Callers updated.
     (get_writeready_server_file): Add 'encoding' parameter.
     (markup_stream_pygments): Add 'encoding' parameter which, if
       provided, becomes the encoding passed to Pygments.
     (view_checkout): Pass the encoding as/if provided by
       calculate_mime_type() to get_writeready_server_file().

Also:

* CHANGES
  Record this change.

git-svn-id: http://viewvc.tigris.org/svn/viewvc/branches/1.1.x@2431 8cb11bc2-c004-0410-86c3-e597b4017df7
2010-08-25 20:18:46 +00:00
cmpilato
5bdea369e8 Merge from trunk r2428, whose log message bits were aligned in a
manner roughly similar to the following:

   ViewVC's options are defined and described to be lower-case, with the
   only exception being the freeform [vhost] section values and key-value
   file stuffs.  In those places, user-defined case could be helpful, and
   is certainly not documented as broken.  So allow it, per issue #466.
   
   * lib/config.py
     (Config.load_config, Config.load_kv_files): Override
       ConfigParser.optionxform() to avoid case normalization of
       option names.

Also:

* CHANGES
  Note this change.

(And yes, I'm running out of interesting ways to compose log messages
for merged changes.)


git-svn-id: http://viewvc.tigris.org/svn/viewvc/branches/1.1.x@2429 8cb11bc2-c004-0410-86c3-e597b4017df7
2010-08-23 20:29:53 +00:00
cmpilato
3699e8e0c7 Merge from trunk r2426, whose log message read like so:
* lib/viewvc.py
     (ViewVCHtmlFormatter): Was HtmlFormatter.  Which, uh, has the same
       name as an object imported from Pygments.
     (format_log): Track renamed class.

git-svn-id: http://viewvc.tigris.org/svn/viewvc/branches/1.1.x@2427 8cb11bc2-c004-0410-86c3-e597b4017df7
2010-08-19 04:19:55 +00:00
cmpilato
55c0b30bc0 Merge from trunk r2424, whose log message read like so:
Empower the revision view for remote Subversion repositories to
   display node kind information and, by extension, links to the markup
   and diff views for files.
   
   * lib/vclib/svn/svn_ra.py
     (RemoteSubversionRepository._revinfo_raw): Tweak _log_cb() inner
       function to make use of the svn_log_changed_path2_t information
       where available.

Also:

* CHANGES
  Note this change.

git-svn-id: http://viewvc.tigris.org/svn/viewvc/branches/1.1.x@2425 8cb11bc2-c004-0410-86c3-e597b4017df7
2010-08-13 17:50:42 +00:00
cmpilato
6fd321529a Merge from trunk r2421, whose log message read thusly:
Build the Subversion client context object correctly (thus avoiding a
   weird NULL proxy object pool error).
   
   * lib/vclib/svn/svn_ra.py
     (RemoteSubversionRepository.open): Use svn_client_create_context()
       instead of svn_client_ctx_t().

Also:

* CHANGES
  Note this change.

git-svn-id: http://viewvc.tigris.org/svn/viewvc/branches/1.1.x@2422 8cb11bc2-c004-0410-86c3-e597b4017df7
2010-08-13 16:20:11 +00:00
cmpilato
531877db4a Merge from trunk r2414, whose log message read thusly:
Finish issue #49 - authentication support for standalone.py.
   
   * bin/standalone.py
     (Options.htpasswd_file): New variable.
     (AuthenticationException): New.
     (ViewVCHTTPRequestHandler.handle_request): Handle AuthenticationException.
     (ViewVCHTTPRequestHandler.validate_password): New.
     (ViewVCHTTPRequestHandler.run_viewvc): If htpasswd authentication is
       enabled, then complain about missing authn creds, and validated
       any presented creds.
     (main): Present and handle the new --htpasswd-file option.  Also, do
       some rudimentary validation of --htpasswd-file and --config-file values.

Also:

* CHANGES
  Note this change.


git-svn-id: http://viewvc.tigris.org/svn/viewvc/branches/1.1.x@2415 8cb11bc2-c004-0410-86c3-e597b4017df7
2010-07-15 20:56:50 +00:00
cmpilato
51df003d8e Merge from trunk r2411, whose log message leans a little this way:
More improvements to standalone.py.
   
   * bin/standalone.py
     (NotViewVCLocationException): New exception.
     (ViewVCHTTPRequestHandler.do_GET, ViewVCHTTPRequestHandler.do_POST):
       Now just thin wrappers around...
     (ViewVCHTTPRequestHandler.handle_request): ...this new function.
     (ViewVCHTTPRequestHandler.is_viewvc): Allow for the case where the
       script alias is empty (a server root deployment).
     (ViewVCHTTPRequestHandler.redirect): Remove as unused (the code's
       been merged into handle_request()).
     (ViewVCHTTPRequestHandler.run_viewvc): Do the is_viewvc() check here
       now.

Also:

* CHANGES
  Note the fix made in this change.


git-svn-id: http://viewvc.tigris.org/svn/viewvc/branches/1.1.x@2412 8cb11bc2-c004-0410-86c3-e597b4017df7
2010-07-15 20:24:45 +00:00
cmpilato
7d05859d7e Merge from trunk r2407 and r2408, which are mostly just some formatting
changes for standalone.py.

git-svn-id: http://viewvc.tigris.org/svn/viewvc/branches/1.1.x@2410 8cb11bc2-c004-0410-86c3-e597b4017df7
2010-07-15 19:11:30 +00:00
cmpilato
2e48cd2ba1 Merge from trunk r2403, whose log message read like so:
Fix a bug which prevented 'standalone.py -r REPOS' from being used
   without a configuration file.
   
   * lib/config.py
     (Config.get_authorizer_and_params_hack): Make sure to always return
       a 2-tuple.  Callers will be expecting that, ya know?
   
   Reported by: Daniel Shahaf <d.s{__AT__}daniel.shahaf.name>

Also:

* CHANGES
  Note this change.

git-svn-id: http://viewvc.tigris.org/svn/viewvc/branches/1.1.x@2404 8cb11bc2-c004-0410-86c3-e597b4017df7
2010-06-17 20:09:06 +00:00
cmpilato
267b61f347 Merge from trunk r2401, whose log message read thusly:
Finish issue #453 by teaching ViewVC to display all displayable
   Subversion revision properties.
   
   NOTE: The svn_ra logic attempts to do the right thing when
         pre-Subversion 1.5 libraries are install, but I haven't had the
         chance to actually test this out myself.
   
   * templates/revision.ezt
     Include the props.ezt property handler template fragment for use
     with revision props.  Also, minor markup change to a header.
   
   * templates/docroot/styles.css
     Lose some unnecessary stylation.
    
   * lib/viewvc.py
     (get_itemprops): Lose unused variable has_binary_props.
     (view_revision): Handle new return value from repos.revinfo(),
       processing extra revision props similarly to the way that file/dir
       props are processed and passing them to the template data
       dictionary.
   
   * lib/vclib/svn/svn_ra.py
     Import _split_revprops() from svn_repos.
     (client_log): New compatibility wrapper.
     (add_log): Reformat as an svn_log_entry_receiver_t callback.
     (RemoteSubversionRepository.dirlogs, _date_from_rev): Track changes
       to self.revinfo().
     (RemoteSubversionRepository.itemlog): Now use client_log().
     (RemoteSubversionRepository._revinfo_raw): Now use client_log() and
       return revprops dict, too.
     (_log_cb): Reformat as an svn_log_entry_receiver_t callback.
   
   * lib/vclib/svn/svn_repos.py
     (_split_revprops): New helper.
     (_log_helper, LocalSubversionRepository.dirlogs, _date_from_rev):
       Track changes to repos._revinfo().
     (_revinfo): Use _split_revprops(), and now return revprops, too.
     (_revinfo_helper): Now return revprops dict, too.
     (_date_from_rev): 
   
   * lib/vclib/__init__.py
     (Repository.revinfo): Update docstring to indicate that this
       interface now returns a revprops dictionary, too.

Also:

* CHANGES
  Note this change.


git-svn-id: http://viewvc.tigris.org/svn/viewvc/branches/1.1.x@2402 8cb11bc2-c004-0410-86c3-e597b4017df7
2010-06-15 15:20:50 +00:00
cmpilato
7f53d5cc3c Merge from trunk r2399, whose log message read like so:
Offer a little more help to folks trying to configure the root_parents
   option.
   
   * conf/viewvc.conf.dist
     (root_parents): Rewrite the documentation for this to be more clear
       and to note the valid root type strings.
     
   * lib/viewvc.py
     (Request.run_viewvc, expand_root_parents): Make some error strings
       provide more helpful information.


git-svn-id: http://viewvc.tigris.org/svn/viewvc/branches/1.1.x@2400 8cb11bc2-c004-0410-86c3-e597b4017df7
2010-06-03 19:43:43 +00:00
cmpilato
af591ed9f7 Minor process and verbiage tweak. (Merge from trunk r2393.)
git-svn-id: http://viewvc.tigris.org/svn/viewvc/branches/1.1.x@2394 8cb11bc2-c004-0410-86c3-e597b4017df7
2010-06-02 14:38:23 +00:00
cmpilato
17492a3856 Begin a new release cycle.
git-svn-id: http://viewvc.tigris.org/svn/viewvc/branches/1.1.x@2389 8cb11bc2-c004-0410-86c3-e597b4017df7
2010-06-02 13:59:23 +00:00
24 changed files with 1179 additions and 682 deletions

15
CHANGES
View File

@@ -1,3 +1,18 @@
Version 1.1.7 (released 09-Sep-2010)
* display Subversion revision properties in the revision view (issue #453)
* fix exception in 'standalone.py -r REPOS' when run without a config file
* fix standalone.py server root deployments (--script-alias='')
* add rudimentary Basic authentication support to standalone.py (issue #49)
* fix obscure "unexpected NULL parent pool" Subversion bindings error
* enable path info / link display in remote Subversion root revision view
* fix vhost name case handling inconsistency (issue #466)
* use svn:mime-type property charset param as encoding hint
* markup Subversion revision references in log messages (issue #313)
* add rudimentary support for FastCGI-based deployments (issue #464)
* fix query script WSGI deployment
* add configuration to fix query script cross-linking to ViewVC
Version 1.1.6 (released 02-Jun-2010)
* add rudimentary support for WSGI-based deployments (issue #397)

27
INSTALL
View File

@@ -251,6 +251,33 @@ APACHE CONFIGURATION
Note: WSGI support in ViewVC is at this time quite rudimentary,
bordering on downright experimental. Your mileage may vary.
-----------------------------------------
METHOD F: Using mod_fcgid (if installed)
-----------------------------------------
This uses ViewVC's WSGI support (from above), but supports using FastCGI,
and is a somewhat hybrid approach of several of the above methods.
Especially if fcgi is already being used for other purposes, e.g. PHP,
also using fcgi can prevent the need for including additional modules
(e.g. mod_python or mod_wsgi) within Apache, which may help lessen Apache's
memory usage and/or help improve performance.
This depends on mod_fcgid:
http://httpd.apache.org/mod_fcgid/
as well as the fcgi server from Python's flup package:
http://pypi.python.org/pypi/flup
http://trac.saddi.com/flup
The following are some example httpd.conf fragments you can use to
support this configuration:
ScriptAlias /viewvc /usr/local/viewvc/bin/wsgi/viewvc.fcgi
ScriptAlias /query /usr/local/viewvc/bin/wsgi/query.fcgi
3) Restart Apache.
The commands to do this vary. "httpd -k restart" and "apache -k

View File

@@ -54,7 +54,10 @@ import query
server = sapi.AspServer(Server, Request, Response, Application)
try:
cfg = viewvc.load_config(CONF_PATHNAME, server)
query.main(server, cfg, "viewvc.asp")
viewvc_base_url = cfg.query.viewvc_base_url
if viewvc_base_url is None:
viewvc_base_url = "viewvc.asp"
query.main(server, cfg, viewvc_base_url)
finally:
s.close()

View File

@@ -54,4 +54,7 @@ import query
server = sapi.CgiServer()
cfg = viewvc.load_config(CONF_PATHNAME, server)
query.main(server, cfg, "viewvc.cgi")
viewvc_base_url = cfg.query.viewvc_base_url
if viewvc_base_url is None:
viewvc_base_url = "viewvc.cgi"
query.main(server, cfg, viewvc_base_url)

View File

@@ -1,6 +1,6 @@
# -*-python-*-
#
# Copyright (C) 1999-2008 The ViewCVS Group. All Rights Reserved.
# Copyright (C) 1999-2010 The ViewCVS Group. All Rights Reserved.
#
# By using this file, you agree to the terms and conditions set forth in
# the LICENSE.html file which can be found at the top level of the ViewVC
@@ -65,7 +65,10 @@ cfg = viewvc.load_config(CONF_PATHNAME)
def index(req):
server = sapi.ModPythonServer(req)
try:
query.main(server, cfg, "viewvc.py")
viewvc_base_url = cfg.query.viewvc_base_url
if viewvc_base_url is None:
viewvc_base_url = "viewvc.py"
query.main(server, cfg, viewvc_base_url)
finally:
server.close()

File diff suppressed because it is too large Load Diff

54
bin/wsgi/query.fcgi Normal file
View File

@@ -0,0 +1,54 @@
#!/usr/bin/python
# -*-python-*-
#
# Copyright (C) 1999-2010 The ViewCVS Group. All Rights Reserved.
#
# By using this file, you agree to the terms and conditions set forth in
# the LICENSE.html file which can be found at the top level of the ViewVC
# distribution or at http://viewvc.org/license-1.html.
#
# For more information, visit http://viewvc.org/
#
# -----------------------------------------------------------------------
#
# viewvc: View CVS/SVN repositories via a web browser
#
# -----------------------------------------------------------------------
#
# This is a fcgi entry point for the query ViewVC app. It's appropriate
# for use with mod_fcgid and flup. It defines a single application function
# that is a valid fcgi entry point.
#
# mod_fcgid: http://httpd.apache.org/mod_fcgid/
# flup:
# http://pypi.python.org/pypi/flup
# http://trac.saddi.com/flup
#
# -----------------------------------------------------------------------
import sys, os
LIBRARY_DIR = None
CONF_PATHNAME = None
if LIBRARY_DIR:
sys.path.insert(0, LIBRARY_DIR)
else:
sys.path.insert(0, os.path.abspath(os.path.join(sys.argv[0],
"../../../lib")))
import sapi
import viewvc
import query
from flup.server import fcgi
def application(environ, start_response):
server = sapi.WsgiServer(environ, start_response)
cfg = viewvc.load_config(CONF_PATHNAME, server)
viewvc_base_url = cfg.query.viewvc_base_url
if viewvc_base_url is None:
viewvc_base_url = "viewvc.fcgi"
query.main(server, cfg, viewvc_base_url)
return []
fcgi.WSGIServer(application).run()

View File

@@ -1,6 +1,6 @@
# -*-python-*-
#
# Copyright (C) 1999-2009 The ViewCVS Group. All Rights Reserved.
# Copyright (C) 1999-2010 The ViewCVS Group. All Rights Reserved.
#
# By using this file, you agree to the terms and conditions set forth in
# the LICENSE.html file which can be found at the top level of the ViewVC
@@ -16,7 +16,7 @@
#
# This is a wsgi entry point for the query ViewVC app. It's appropriate
# for use with mod_wsgi. It defines a single application function that
# is a walid wsgi entry point.
# is a valid wsgi entry point.
#
# -----------------------------------------------------------------------
@@ -38,5 +38,8 @@ import query
def application(environ, start_response):
server = sapi.WsgiServer(environ, start_response)
cfg = viewvc.load_config(CONF_PATHNAME, server)
query.main(server, cfg, "viewvc.wsgi")
viewvc_base_url = cfg.query.viewvc_base_url
if viewvc_base_url is None:
viewvc_base_url = "viewvc.wsgi"
query.main(server, cfg, viewvc_base_url)
return []

50
bin/wsgi/viewvc.fcgi Normal file
View File

@@ -0,0 +1,50 @@
#!/usr/bin/python
# -*-python-*-
#
# Copyright (C) 1999-2010 The ViewCVS Group. All Rights Reserved.
#
# By using this file, you agree to the terms and conditions set forth in
# the LICENSE.html file which can be found at the top level of the ViewVC
# distribution or at http://viewvc.org/license-1.html.
#
# For more information, visit http://viewvc.org/
#
# -----------------------------------------------------------------------
#
# viewvc: View CVS/SVN repositories via a web browser
#
# -----------------------------------------------------------------------
#
# This is a fcgi entry point for the main ViewVC app. It's appropriate
# for use with mod_fcgid and flup. It defines a single application function
# that is a valid fcgi entry point.
#
# mod_fcgid: http://httpd.apache.org/mod_fcgid/
# flup:
# http://pypi.python.org/pypi/flup
# http://trac.saddi.com/flup
#
# -----------------------------------------------------------------------
import sys, os
LIBRARY_DIR = None
CONF_PATHNAME = None
if LIBRARY_DIR:
sys.path.insert(0, LIBRARY_DIR)
else:
sys.path.insert(0, os.path.abspath(os.path.join(sys.argv[0],
"../../../lib")))
import sapi
import viewvc
from flup.server import fcgi
def application(environ, start_response):
server = sapi.WsgiServer(environ, start_response)
cfg = viewvc.load_config(CONF_PATHNAME, server)
viewvc.main(server, cfg)
return []
fcgi.WSGIServer(application).run()

View File

@@ -16,7 +16,7 @@
#
# 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 walid wsgi entry point.
# is a valid wsgi entry point.
#
# -----------------------------------------------------------------------

View File

@@ -106,27 +106,47 @@
##
#svn_roots =
## root_parents: Specifies a list of directories in which any number of
## repositories may reside. Rather than force you to add a new entry
## to 'cvs_roots' or 'svn_roots' each time you create a new repository,
## ViewVC rewards you for organising all your repositories under a few
## parent directories by allowing you to simply specifiy just those
## parent directories. ViewVC will then notice each repository in that
## directory as a new root whose name is the subdirectory of the parent
## path in which that repository lives.
## root_parents: Specifies a list of directories under which any
## number of repositories may reside. You can specify multiple root
## parents separated by commas or new lines, each of which is of the
## form "path: type" (where type is either "cvs" or "svn").
##
## You can specify multiple parent paths separated by commas or new lines.
## Rather than force you to add a new entry to 'cvs_roots' or
## 'svn_roots' each time you create a new repository, ViewVC rewards
## you for organizing all your repositories under a few parent
## directories by allowing you to simply tell it about those parent
## directories. ViewVC will then notice each repository of the
## specified type in that directory as a root whose name is the
## subdirectory in which that repository lives.
##
## WARNING: these names can, of course, clash with names you have
## defined in your cvs_roots or svn_roots configuration items. If this
## occurs, you can either rename the offending repository on disk, or
## grant new names to the clashing item in cvs_roots or svn_roots.
## Each parent path is processed sequentially, so repositories under
## later parent paths may override earlier ones.
## For example, if you have three Subversion repositories located at
## /opt/svn/projects, /opt/svn/websites, and /opt/svn/devstuff, you
## could list them individually in svn_roots like so:
##
## svn_roots = projects: /opt/svn/projects,
## websites: /opt/svn/websites,
## devstuff: /opt/svn/devstuff
##
## or you could instead use the root_parents configuration option:
##
## root_parents = /opt/svn: svn
##
## The benefit of this latter approach is that, as you add new
## repositories to your /opt/svn directory, they automatically become
## available for display in ViewVC without additional configuration.
##
## WARNING: the root names derived for repositories configured via the
## root_parents option can, of course, clash with names you have
## defined in your cvs_roots or svn_roots configuration items. If
## this occurs, you can either rename the offending repository on
## disk, or grant new names to the clashing item in cvs_roots or
## svn_roots. Each parent path is processed sequentially, so the
## names of repositories under later parent paths may override earlier
## ones.
##
## Example:
## root_parents = /opt/svn : svn,
## /opt/cvs : cvs
## root_parents = /opt/svn: svn,
## /opt/cvs: cvs
##
#root_parents =
@@ -997,3 +1017,30 @@
#force_username_case =
##---------------------------------------------------------------------------
[query]
## The configuration items in this section are used exclusively by the
## 'query' script, a separate script from ViewVC itself that ships
## with ViewVC and allows for queries into the ViewVC commits
## database. If you aren't using this separate script (which was made
## largely irrelevant by the introduction of an integrated "query"
## view in ViewVC itself, or aren't using the ViewVC commits database
## functionality at all, you can ignore these configurations items
## altogether.
## viewvc_base_url: Base URL at which ViewVC may be accessed on this
## server. The default value for this option is determined at
## run-time by the various front-ends to the query script.
##
## Examples:
## viewvc_base_url = /viewvc.py
## viewvc_base_url = /viewvc.wsgi
## viewvc_base_url = /cgi-bin/viewvc
## viewvc_base_url = viewvc
##
## To disable cross-linking between the query script and ViewVC,
## uncomment this option and leave its value empty.
##
#viewvc_base_url =
##---------------------------------------------------------------------------

View File

@@ -88,6 +88,11 @@ import fnmatch
# | vhosts |
# | |
# `-----------'
# ,-----------.
# | |
# | query |
# | |
# `-----------'
#
# ### TODO: Figure out what this all means for the 'kv' stuff.
#
@@ -100,6 +105,7 @@ class Config:
'cvsdb',
'general',
'options',
'query',
'templates',
'utilities',
)
@@ -145,6 +151,7 @@ class Config:
self.conf_path = os.path.isfile(pathname) and pathname or None
self.base = os.path.dirname(pathname)
self.parser = ConfigParser.ConfigParser()
self.parser.optionxform = lambda x: x # don't case-normalize option names.
self.parser.read(self.conf_path or [])
for section in self.parser.sections():
@@ -172,6 +179,7 @@ class Config:
fname = string.replace(fname, '%lang%', language)
parser = ConfigParser.ConfigParser()
parser.optionxform = lambda x: x # don't case-normalize option names.
parser.read(os.path.join(self.base, fname))
for section in parser.sections():
for option in parser.options(section):
@@ -322,7 +330,7 @@ class Config:
assert(self.root_options_overlayed == 0)
if not self.conf_path:
return None
return None, {}
# Figure out the authorizer by searching first for a per-root
# override, then falling back to the base/vhost configuration.
@@ -453,6 +461,8 @@ class Config:
self.cvsdb.rss_row_limit = 100
self.cvsdb.check_database_for_root = 0
self.query.viewvc_base_url = None
def _startswith(somestr, substr):
return somestr[:len(substr)] == substr

View File

@@ -312,11 +312,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=[])
if desc:
ob.log = string.replace(server.escape(desc), '\n', '<br />')
else:
ob.log = '&nbsp;'
ob.log = desc and string.replace(server.escape(desc), '\n', '<br />') or ''
for commit in files:
repository = commit.GetRepository()
@@ -350,9 +346,10 @@ def build_commit(server, cfg, desc, files, cvsroots, viewvc_link):
except:
raise Exception, str([directory, commit.GetFile()])
## if we couldn't find the cvsroot path configured in the
## viewvc.conf file, then don't make the link
if cvsroot_name:
## If we couldn't find the cvsroot path configured in the
## viewvc.conf file, or we don't have a VIEWVC_LINK, then
## don't make the link.
if cvsroot_name and viewvc_link:
flink = '[%s] <a href="%s/%s?root=%s">%s</a>' % (
cvsroot_name, viewvc_link, urllib.quote(file),
cvsroot_name, file)
@@ -435,6 +432,10 @@ def main(server, cfg, viewvc_link):
commits = [ ]
query = 'skipped'
docroot = cfg.options.docroot
if docroot is None and viewvc_link:
docroot = viewvc_link + '/' + viewvc.docroot_magic_path
data = ezt.TemplateData({
'cfg' : cfg,
'address' : cfg.general.address,
@@ -444,13 +445,9 @@ def main(server, cfg, viewvc_link):
'directory' : server.escape(form_data.directory),
'file' : server.escape(form_data.file),
'who' : server.escape(form_data.who),
'docroot' : cfg.options.docroot is None \
and viewvc_link + '/' + viewvc.docroot_magic_path \
or cfg.options.docroot,
'docroot' : docroot,
'sortby' : form_data.sortby,
'date' : form_data.date,
'query' : query,
'commits' : commits,
'num_commits' : len(commits),

View File

@@ -186,7 +186,7 @@ class CgiServer(Server):
def FieldStorage(fp=None, headers=None, outerboundary="",
environ=os.environ, keep_blank_values=0, strict_parsing=0):
return cgi.FieldStorage(fp, headers, outerboundary, environ,
keep_blank_values, strict_parsing)
keep_blank_values, strict_parsing)
def write(self, s):
sys.stdout.write(s)
@@ -244,7 +244,7 @@ class WsgiServer(Server):
def FieldStorage(self, fp=None, headers=None, outerboundary="",
environ=os.environ, keep_blank_values=0, strict_parsing=0):
return cgi.FieldStorage(self._environ["wsgi.input"], self._headers,
return cgi.FieldStorage(self._environ["wsgi.input"], headers,
outerboundary, self._environ, keep_blank_values,
strict_parsing)

View File

@@ -180,8 +180,10 @@ class Repository:
rev is the revision of the item to return information about
Return value is a 4-tuple containing the date, author, log
message, and a list of ChangedPath items representing paths changed
Return value is a 5-tuple containing: the date, author, log
message, a list of ChangedPath items representing paths changed,
and a dictionary mapping property names to property values for
properties stored on an item.
Raise vclib.UnsupportedFeature if the version control system
doesn't support a global revision concept.

View File

@@ -18,10 +18,9 @@ import os
import string
import re
import tempfile
import popen2
import time
import urllib
from svn_repos import Revision, SVNChangedPath, _datestr_to_date, _compare_paths, _path_parts, _cleanup_path, _rev2optrev, _fix_subversion_exception
from svn_repos import Revision, SVNChangedPath, _datestr_to_date, _compare_paths, _path_parts, _cleanup_path, _rev2optrev, _fix_subversion_exception, _split_revprops
from svn import core, delta, client, wc, ra
@@ -52,6 +51,29 @@ def get_directory_props(ra_session, path, rev):
props = ra.svn_ra_get_dir(ra_session, path, rev)
return props
def client_log(url, start_rev, end_rev, log_limit, cross_copies,
cb_func, ctx):
try:
client.svn_client_log4([url], start_rev, start_rev, end_rev,
log_limit, 1, not cross_copies, 0, None,
cb_func, ctx)
except NameError:
# Wrap old svn_log_message_receiver_t interface with a
# svn_log_entry_t one.
def cb_convert(paths, revision, author, date, message, pool):
class svn_log_entry_t:
pass
log_entry = svn_log_entry_t()
log_entry.changed_paths = paths
log_entry.revision = revision
log_entry.revprops = { core.SVN_PROP_REVISION_LOG : message,
core.SVN_PROP_REVISION_AUTHOR : author,
core.SVN_PROP_REVISION_DATE : date,
}
cb_func(log_entry, pool)
client.svn_client_log2([url], start_rev, end_rev, log_limit,
1, not cross_copies, cb_convert, ctx)
### END COMPATABILITY CODE ###
@@ -68,7 +90,11 @@ class LogCollector:
self.show_all_logs = show_all_logs
self.lockinfo = lockinfo
def add_log(self, paths, revision, author, date, message, pool):
def add_log(self, log_entry, pool):
paths = log_entry.changed_paths
revision = log_entry.revision
msg, author, date, revprops = _split_revprops(log_entry.revprops)
# Changed paths have leading slashes
changed_paths = paths.keys()
changed_paths.sort(lambda a, b: _compare_paths(a, b))
@@ -88,8 +114,8 @@ class LogCollector:
if change.copyfrom_path:
this_path = change.copyfrom_path + self.path[len(changed_path):]
if self.show_all_logs or this_path:
entry = Revision(revision, _datestr_to_date(date), author, message, None,
self.lockinfo, self.path[1:], None, None)
entry = Revision(revision, date, author, msg, None, self.lockinfo,
self.path[1:], None, None)
self.logs.append(entry)
if this_path:
self.path = this_path
@@ -157,7 +183,7 @@ class RemoteSubversionRepository(vclib.Repository):
# Setup the client context baton, complete with non-prompting authstuffs.
# TODO: svn_cmdline_setup_auth_baton() is mo' better (when available)
core.svn_config_ensure(self.config_dir)
self.ctx = client.svn_client_ctx_t()
self.ctx = client.svn_client_create_context()
self.ctx.auth_baton = core.svn_auth_open([
client.svn_client_get_simple_provider(),
client.svn_client_get_username_provider(),
@@ -252,7 +278,7 @@ class RemoteSubversionRepository(vclib.Repository):
if not vclib.check_path_access(self, entry_path_parts, entry.kind, rev):
continue
dirent = dirents[entry.name]
entry.date, entry.author, entry.log, changes = \
entry.date, entry.author, entry.log, revprops, changes = \
self.revinfo(dirent.created_rev)
entry.rev = str(dirent.created_rev)
entry.size = dirent.size
@@ -283,9 +309,8 @@ class RemoteSubversionRepository(vclib.Repository):
log_limit = 0
if limit:
log_limit = first + limit
client.svn_client_log2([url], _rev2optrev(rev), _rev2optrev(1),
log_limit, 1, not cross_copies,
lc.add_log, self.ctx)
client_log(url, _rev2optrev(rev), _rev2optrev(1), log_limit,
cross_copies, lc.add_log, self.ctx)
revs = lc.logs
revs.sort()
prev = None
@@ -337,7 +362,7 @@ class RemoteSubversionRepository(vclib.Repository):
if not cached_info:
cached_info = self._revinfo_raw(rev)
self._revinfo_cache[rev] = cached_info
return cached_info[0], cached_info[1], cached_info[2], cached_info[3]
return tuple(cached_info)
def rawdiff(self, path_parts1, rev1, path_parts2, rev2, type, options={}):
p1 = self._getpath(path_parts1)
@@ -352,7 +377,7 @@ class RemoteSubversionRepository(vclib.Repository):
args = vclib._diff_args(type, options)
def _date_from_rev(rev):
date, author, msg, changes = self.revinfo(rev)
date, author, msg, revprops, changes = self.revinfo(rev)
return date
try:
@@ -417,29 +442,54 @@ class RemoteSubversionRepository(vclib.Repository):
return revisions[0]
def _revinfo_raw(self, rev):
# return 5-tuple (date, author, message, changes)
# return 5-tuple (date, author, msg, revprops, changes)
optrev = _rev2optrev(rev)
revs = []
def _log_cb(changed_paths, revision, author,
datestr, message, pool, retval=revs):
date = _datestr_to_date(datestr)
def _log_cb(log_entry, pool, retval=revs):
### Subversion 1.5 and earlier didn't offer the 'changed_paths2'
### hash, and in Subversion 1.6, it's offered but broken.
try:
changed_paths = log_entry.changed_paths2
paths = (changed_paths or {}).keys()
except:
changed_paths = log_entry.changed_paths
paths = (changed_paths or {}).keys()
paths.sort(lambda a, b: _compare_paths(a, b))
revision = log_entry.revision
msg, author, date, revprops = _split_revprops(log_entry.revprops)
action_map = { 'D' : vclib.DELETED,
'A' : vclib.ADDED,
'R' : vclib.REPLACED,
'M' : vclib.MODIFIED,
}
paths = (changed_paths or {}).keys()
paths.sort(lambda a, b: _compare_paths(a, b))
changes = []
found_readable = found_unreadable = 0
for path in paths:
pathtype = None
change = changed_paths[path]
action = action_map.get(change.action, vclib.MODIFIED)
### svn_log_changed_path_t (which we might get instead of the
### svn_log_changed_path2_t we'd prefer) doesn't have the
### 'node_kind' member.
pathtype = None
if hasattr(change, 'node_kind'):
if change.node_kind == core.svn_node_dir:
pathtype = vclib.DIR
elif change.node_kind == core.svn_node_file:
pathtype = vclib.FILE
### svn_log_changed_path2_t only has the 'text_modified' and
### 'props_modified' bits in Subversion 1.7 and beyond. And
### svn_log_changed_path_t is without.
text_modified = props_modified = 0
if hasattr(change, 'text_modified'):
if change.text_modified == core.svn_tristate_true:
text_modified = 1
if hasattr(change, 'props_modified'):
if change.props_modified == core.svn_tristate_true:
props_modified = 1
### Wrong, diddily wrong wrong wrong. Can you say,
### "Manufacturing data left and right because it hurts to
### figure out the right stuff?"
action = action_map.get(change.action, vclib.MODIFIED)
if change.copyfrom_path and change.copyfrom_rev:
is_copy = 1
base_path = change.copyfrom_path
@@ -462,21 +512,21 @@ class RemoteSubversionRepository(vclib.Repository):
base_path = None
base_rev = None
changes.append(SVNChangedPath(path, revision, pathtype, base_path,
base_rev, action, is_copy, 0, 0))
base_rev, action, is_copy,
text_modified, props_modified))
found_readable = 1
else:
found_unreadable = 1
if found_unreadable:
message = None
msg = None
if not found_readable:
author = None
date = None
revs.append([date, author, message, changes])
revs.append([date, author, msg, revprops, changes])
client.svn_client_log([self.rootpath], optrev, optrev,
1, 0, _log_cb, self.ctx)
return revs[0][0], revs[0][1], revs[0][2], revs[0][3]
client_log(self.rootpath, optrev, optrev, 1, 0, _log_cb, self.ctx)
return tuple(revs[0])
##--- custom --##

View File

@@ -115,6 +115,27 @@ def _rootpath2url(rootpath, path):
return 'file://' + string.join([rootpath, path], "/")
# Given a dictionary REVPROPS of revision properties, pull special
# ones out of them and return a 4-tuple containing the log message,
# the author, the date (converted from the date string property), and
# a dictionary of any/all other revprops.
def _split_revprops(revprops):
if not revprops:
return None, None, None, {}
special_props = []
for prop in core.SVN_PROP_REVISION_LOG, \
core.SVN_PROP_REVISION_AUTHOR, \
core.SVN_PROP_REVISION_DATE:
if revprops.has_key(prop):
special_props.append(revprops[prop])
del(revprops[prop])
else:
special_props.append(None)
msg, author, datestr = tuple(special_props)
date = _datestr_to_date(datestr)
return msg, author, date, revprops
def _datestr_to_date(datestr):
try:
return core.svn_time_from_cstring(datestr) / 1000000
@@ -225,7 +246,7 @@ def _log_helper(svnrepos, path, rev, lockinfo):
copyfrom_rev, copyfrom_path = fs.copied_from(rev_root, path)
# Assemble our LogEntry
date, author, msg, changes = svnrepos._revinfo(rev)
date, author, msg, revprops, changes = svnrepos._revinfo(rev)
if fs.is_file(rev_root, path):
size = fs.file_length(rev_root, path)
else:
@@ -319,7 +340,7 @@ class BlameSource:
self.first_rev = first_rev
self.blame_data = []
ctx = client.ctx_t()
ctx = client.svn_client_create_context()
core.svn_config_ensure(config_dir)
ctx.config = core.svn_config_get_config(config_dir)
ctx.auth_baton = core.svn_auth_open([])
@@ -472,7 +493,7 @@ class LocalSubversionRepository(vclib.Repository):
continue
path = self._getpath(entry_path_parts)
entry_rev = _get_last_history_rev(fsroot, path)
date, author, msg, changes = self._revinfo(entry_rev)
date, author, msg, revprops, changes = self._revinfo(entry_rev)
entry.rev = str(entry_rev)
entry.date = date
entry.author = author
@@ -577,16 +598,13 @@ class LocalSubversionRepository(vclib.Repository):
# Get the revision property info. (Would use
# editor.get_root_props(), but something is broken there...)
revprops = fs.revision_proplist(self.fs_ptr, rev)
msg = revprops.get(core.SVN_PROP_REVISION_LOG)
author = revprops.get(core.SVN_PROP_REVISION_AUTHOR)
datestr = revprops.get(core.SVN_PROP_REVISION_DATE)
date = _datestr_to_date(datestr)
msg, author, date, revprops = _split_revprops(revprops)
# Optimization: If our caller doesn't care about the changed
# paths, and we don't need them to do authz determinations, let's
# get outta here.
if self.auth is None and not include_changed_paths:
return date, author, msg, None
return date, author, msg, revprops, None
# If we get here, then we either need the changed paths because we
# were asked for them, or we need them to do authorization checks.
@@ -661,7 +679,7 @@ class LocalSubversionRepository(vclib.Repository):
# here for authz reasons only. That means the minute we've
# found both a readable and an unreadable path, we can bail out.
if (not include_changed_paths) and found_readable and found_unreadable:
return date, author, None, None
return date, author, None, None, None
# Okay, we've process all our paths. Let's filter our metadata,
# and return the requested data.
@@ -671,9 +689,9 @@ class LocalSubversionRepository(vclib.Repository):
author = None
date = None
if include_changed_paths:
return date, author, msg, changedpaths.values()
return date, author, msg, revprops, changedpaths.values()
else:
return date, author, msg, None
return date, author, msg, revprops, None
# Consult the revinfo cache first. If we don't have cached info,
# or our caller wants changed paths and we don't have those for
@@ -681,10 +699,10 @@ class LocalSubversionRepository(vclib.Repository):
rev = self._getrev(rev)
cached_info = self._revinfo_cache.get(rev)
if not cached_info \
or (include_changed_paths and cached_info[3] is None):
or (include_changed_paths and cached_info[4] is None):
cached_info = _revinfo_helper(rev, include_changed_paths)
self._revinfo_cache[rev] = cached_info
return cached_info[0], cached_info[1], cached_info[2], cached_info[3]
return tuple(cached_info)
def revinfo(self, rev):
return self._revinfo(rev, 1)
@@ -702,7 +720,7 @@ class LocalSubversionRepository(vclib.Repository):
args = vclib._diff_args(type, options)
def _date_from_rev(rev):
date, author, msg, changes = self._revinfo(rev)
date, author, msg, revprops, changes = self._revinfo(rev)
return date
try:

View File

@@ -14,7 +14,7 @@
#
# -----------------------------------------------------------------------
__version__ = '1.1.6-dev'
__version__ = '1.1.7'
# this comes from our library; measure the startup time
import debug
@@ -273,7 +273,8 @@ class Request:
self.roottype = 'cvs'
else:
raise debug.ViewVCException(
'The root "%s" has an unknown type (%s).' % (self.rootname, type),
'The root "%s" has an unknown type ("%s"). Expected "cvs" or "svn".'
% (self.rootname, type),
"500 Internal Server Error")
# If this is using an old-style 'rev' parameter, redirect to new hotness.
@@ -896,14 +897,17 @@ def get_view_template(cfg, view_name, language="en"):
return template
def get_writeready_server_file(request, content_type=None):
def get_writeready_server_file(request, content_type=None, encoding=None):
"""Return a file handle to a response body stream, after outputting
any queued special headers (on REQUEST.server) and (optionally) a
'Content-Type' header whose value is CONTENT_TYPE. After this is
called, it is too late to add new headers to the response."""
'Content-Type' header whose value is CONTENT_TYPE and character set
is ENCODING. After this is called, it is too late to add new
headers to the response."""
if request.gzip_compress_level:
request.server.addheader('Content-Encoding', 'gzip')
if content_type:
if content_type and encoding:
request.server.header("%s; charset=%s" % (content_type, encoding))
elif content_type:
request.server.header(content_type)
else:
request.server.header()
@@ -1085,8 +1089,10 @@ _re_rewrite_url = re.compile('((http|https|ftp|file|svn|svn\+ssh)'
_re_rewrite_email = re.compile('([-a-zA-Z0-9_.\+]+)@'
'(([-a-zA-Z0-9]+\.)+[A-Za-z]{2,4})')
# Matches revision references
_re_rewrite_svnrevref = re.compile(r'\b(r|rev #?|revision #?)([0-9]+)\b')
class HtmlFormatter:
class ViewVCHtmlFormatter:
"""Format a string as HTML-encoded output with customizable markup
rules, for example turning strings that look like URLs into anchor links.
@@ -1152,6 +1158,25 @@ class HtmlFormatter:
trunc_s = mobj.group(1)[:maxlen]
return self._entity_encode(trunc_s), len(trunc_s)
def format_svnrevref(self, mobj, userdata, maxlen=0):
"""Return a 2-tuple containing:
- the text represented by MatchObject MOBJ, formatted as an
linkified URL to a ViewVC Subversion revision view, with no
more than MAXLEN characters in the non-HTML-tag portions.
If MAXLEN is 0, there is no maximum.
- the number of characters returned.
USERDATA is a function that accepts a revision reference
and returns a URL to that revision.
"""
s = mobj.group(0)
revref = mobj.group(2)
trunc_s = maxlen and s[:maxlen] or s
revref_url = userdata(revref)
return '<a href="%s">%s</a>' % (sapi.escape(revref_url),
sapi.escape(trunc_s)), \
len(trunc_s)
def format_text(self, s, unused, maxlen=0):
"""Return a 2-tuple containing:
- the text S, HTML-escaped, containing no more than MAXLEN
@@ -1240,13 +1265,22 @@ class HtmlFormatter:
s = ''
return tokens
def format_log(log, cfg, maxlen=0, htmlize=1):
def format_log(request, log, maxlen=0, htmlize=1):
if not log:
return log
cfg = request.cfg
if htmlize:
lf = HtmlFormatter()
lf = ViewVCHtmlFormatter()
lf.add_formatter(_re_rewrite_url, lf.format_url)
if request.roottype == 'svn':
def revision_to_url(rev):
return request.get_url(view_func=view_revision,
params={'revision': rev},
escape=1)
lf.add_formatter(_re_rewrite_svnrevref, lf.format_svnrevref,
revision_to_url)
if cfg.options.mangle_email_addresses == 2:
lf.add_formatter(_re_rewrite_email, lf.format_email_truncated)
elif cfg.options.mangle_email_addresses == 1:
@@ -1485,7 +1519,8 @@ class MarkupPipeWrapper:
if self.posttext:
ctx.fp.write(self.posttext)
def markup_stream_pygments(request, cfg, blame_data, fp, filename, mime_type):
def markup_stream_pygments(request, cfg, blame_data, fp, filename,
mime_type, encoding):
# Determine if we should use Pygments to highlight our output.
# Reasons not to include a) being told not to by the configuration,
# b) not being able to import the Pygments modules, and c) Pygments
@@ -1511,13 +1546,14 @@ def markup_stream_pygments(request, cfg, blame_data, fp, filename, mime_type):
get_lexer_by_name, \
get_lexer_for_mimetype, \
get_lexer_for_filename
encoding = 'guess'
if cfg.options.detect_encoding:
try:
import chardet
encoding = 'chardet'
except (SyntaxError, ImportError):
pass
if not encoding:
encoding = 'guess'
if cfg.options.detect_encoding:
try:
import chardet
encoding = 'chardet'
except (SyntaxError, ImportError):
pass
try:
lexer = get_lexer_for_mimetype(mime_type,
encoding=encoding,
@@ -1621,9 +1657,8 @@ def get_itemprops(request, path_parts, rev):
propnames = itemprops.keys()
propnames.sort()
props = []
has_binary_props = 0
for name in propnames:
value = format_log(itemprops[name], request.cfg)
value = format_log(request, itemprops[name])
undisplayable = ezt.boolean(0)
# skip non-utf8 property names
try:
@@ -1639,20 +1674,33 @@ def get_itemprops(request, path_parts, rev):
props.append(_item(name=name, value=value, undisplayable=undisplayable))
return props
def parse_mime_type(mime_type):
mime_parts = map(lambda x: x.strip(), string.split(mime_type, ';'))
type_subtype = mime_parts[0].lower()
parameters = {}
for part in mime_parts[1:]:
name, value = string.split(part, '=', 1)
parameters[name] = value
return type_subtype, parameters
def calculate_mime_type(request, path_parts, rev):
mime_type = None
"""Return a 2-tuple carrying the MIME content type and character
encoding for the file represented by PATH_PARTS in REV. Use REQUEST
for repository access as necessary."""
if not path_parts:
return None
return None, None
mime_type = encoding = None
if request.roottype == 'svn' \
and (not request.cfg.options.svn_ignore_mimetype):
try:
itemprops = request.repos.itemprops(path_parts, rev)
mime_type = itemprops.get('svn:mime-type')
if mime_type:
return mime_type
mime_type, parameters = parse_mime_type(mime_type)
return mime_type, parameters.get('charset')
except:
pass
return guess_mime(path_parts[-1])
return guess_mime(path_parts[-1]), None
def markup_or_annotate(request, is_annotate):
cfg = request.cfg
@@ -1660,7 +1708,7 @@ def markup_or_annotate(request, is_annotate):
lines = fp = image_src_href = None
annotation = 'none'
revision = None
mime_type = calculate_mime_type(request, path, rev)
mime_type, encoding = calculate_mime_type(request, path, rev)
# Is this a viewable image type?
if is_viewable_image(mime_type) \
@@ -1693,7 +1741,7 @@ def markup_or_annotate(request, is_annotate):
fp.close()
return
lines = markup_stream_pygments(request, cfg, blame_source, fp,
path[-1], mime_type)
path[-1], mime_type, encoding)
fp.close()
data = common_template_data(request, revision)
@@ -1727,7 +1775,7 @@ def markup_or_annotate(request, is_annotate):
data['date'] = make_time_string(entry.date, cfg)
data['author'] = entry.author
data['changed'] = entry.changed
data['log'] = format_log(entry.log, cfg)
data['log'] = format_log(request, entry.log)
data['size'] = entry.size
if entry.date is not None:
@@ -1943,8 +1991,8 @@ def view_directory(request):
row.date = make_time_string(file.date, cfg)
row.ago = html_time(request, file.date)
if cfg.options.show_logs:
row.log = format_log(file.log, cfg)
row.short_log = format_log(file.log, cfg,
row.log = format_log(request, file.log)
row.short_log = format_log(request, file.log,
maxlen=cfg.options.short_log_len)
row.lockinfo = file.lockinfo
row.anchor = request.server.escape(file.name)
@@ -2001,8 +2049,9 @@ def view_directory(request):
if request.roottype == 'svn':
row.size = file.size
row.mime_type = calculate_mime_type(request, _path_parts(file_where),
file.rev)
row.mime_type, encoding = calculate_mime_type(request,
_path_parts(file_where),
file.rev)
fvi = get_file_view_info(request, file_where, file.rev, row.mime_type)
row.view_href = fvi.view_href
row.download_href = fvi.download_href
@@ -2273,9 +2322,11 @@ def view_log(request):
if request.roottype == 'cvs':
raise debug.ViewVCException('Unsupported feature: log view on CVS '
'directory', '400 Bad Request')
mime_type = None
mime_type = encoding = None
else:
mime_type = calculate_mime_type(request, request.path_parts, request.pathrev)
mime_type, encoding = calculate_mime_type(request,
request.path_parts,
request.pathrev)
options = {}
options['svn_show_all_dir_logs'] = 1 ### someday make this optional?
@@ -2318,7 +2369,7 @@ def view_log(request):
entry.ago = None
if rev.date is not None:
entry.ago = html_time(request, rev.date, 1)
entry.log = format_log(rev.log or '', cfg)
entry.log = format_log(request, rev.log or '')
entry.size = rev.size
entry.lockinfo = rev.lockinfo
entry.branch_point = None
@@ -2576,10 +2627,11 @@ def view_checkout(request):
# The revision number acts as a strong validator.
if not check_freshness(request, None, revision):
mime_type, encoding = calculate_mime_type(request, path, rev)
mime_type = request.query_dict.get('content-type') \
or calculate_mime_type(request, path, rev) \
or mime_type \
or 'text/plain'
server_fp = get_writeready_server_file(request, mime_type)
server_fp = get_writeready_server_file(request, mime_type, encoding)
copy_stream(fp, server_fp)
fp.close()
@@ -3164,7 +3216,7 @@ def view_diff(request):
fvi = get_file_view_info(request, path_left, rev1)
left = _item(date=make_time_string(log_entry1.date, cfg),
author=log_entry1.author,
log=format_log(log_entry1.log, cfg),
log=format_log(request, log_entry1.log),
size=log_entry1.size,
ago=ago1,
path=path_left,
@@ -3180,7 +3232,7 @@ def view_diff(request):
fvi = get_file_view_info(request, path_right, rev2)
right = _item(date=make_time_string(log_entry2.date, cfg),
author=log_entry2.author,
log=format_log(log_entry2.log, cfg),
log=format_log(request, log_entry2.log),
size=log_entry2.size,
ago=ago2,
path=path_right,
@@ -3401,7 +3453,7 @@ def download_tarball(request):
def view_revision(request):
if request.roottype == "cvs":
if request.roottype != "svn":
raise debug.ViewVCException("Revision view not supported for CVS "
"repositories at this time.",
"400 Bad Request")
@@ -3420,9 +3472,29 @@ def view_revision(request):
return
# Fetch the revision information.
date, author, msg, changes = request.repos.revinfo(rev)
date, author, msg, revprops, changes = request.repos.revinfo(rev)
date_str = make_time_string(date, cfg)
# Fix up the revprops list (rather like get_itemprops()).
propnames = revprops.keys()
propnames.sort()
props = []
for name in propnames:
value = format_log(request, revprops[name])
undisplayable = ezt.boolean(0)
# skip non-utf8 property names
try:
unicode(name, 'utf8')
except:
continue
# note non-utf8 property values
try:
unicode(value, 'utf8')
except:
value = None
undisplayable = ezt.boolean(1)
props.append(_item(name=name, value=value, undisplayable=undisplayable))
# Sort the changes list by path.
def changes_sort_by_path(a, b):
return cmp(a.path_parts, b.path_parts)
@@ -3537,7 +3609,8 @@ def view_revision(request):
'rev' : str(rev),
'author' : author,
'date' : date_str,
'log' : format_log(msg, cfg),
'log' : format_log(request, msg),
'properties' : props,
'ago' : date is not None and html_time(request, date, 1) or None,
'changes' : changes,
'prev_href' : prev_rev_href,
@@ -3845,7 +3918,7 @@ def build_commit(request, files, max_files, dir_strip, format):
diff_href = request.get_url(view_func=view_diff,
where=where, pathtype=vclib.FILE,
params=diff_href_params, escape=1)
mime_type = calculate_mime_type(request, path_parts, exam_rev)
mime_type, encoding = calculate_mime_type(request, path_parts, exam_rev)
prefer_markup = ezt.boolean(default_view(mime_type, cfg) == view_markup)
# Update plus/minus line change count.
@@ -3894,8 +3967,8 @@ def build_commit(request, files, max_files, dir_strip, format):
commit.log = None
commit.short_log = None
else:
commit.log = format_log(desc, cfg, 0, format != 'rss')
commit.short_log = format_log(desc, cfg, cfg.options.short_log_len,
commit.log = format_log(request, desc, 0, format != 'rss')
commit.short_log = format_log(request, desc, cfg.options.short_log_len,
format != 'rss')
commit.author = request.server.escape(author)
commit.rss_date = make_rss_time_string(date, request.cfg)
@@ -4202,8 +4275,8 @@ def expand_root_parents(cfg):
pos = string.rfind(pp, ':')
if pos < 0:
raise debug.ViewVCException(
"The path '%s' in 'root_parents' does not include a "
"repository type." % (pp))
'The path "%s" in "root_parents" does not include a '
'repository type. Expected "cvs" or "svn".' % (pp))
repo_type = string.strip(pp[pos+1:])
pp = os.path.normpath(string.strip(pp[:pos]))
@@ -4218,8 +4291,9 @@ def expand_root_parents(cfg):
cfg.general.svn_roots.update(roots)
else:
raise debug.ViewVCException(
"The path '%s' in 'root_parents' has an unrecognized "
"repository type." % (pp))
'The path "%s" in "root_parents" has an unrecognized '
'repository type ("%s"). Expected "cvs" or "svn".'
% (pp, repo_type))
def find_root_in_parents(cfg, rootname, roottype):
"""Return the rootpath for configured ROOTNAME of ROOTTYPE."""

View File

@@ -38,48 +38,70 @@ numbers, and not literal):
should exactly reflect what you wish to distribute and dub "the
release".
7. Edit the file 'lib/viewvc.py' and remove the "-dev" suffix from
7. Update your release branch working copy to HEAD.
svn up
8. Edit the file 'lib/viewvc.py' and remove the "-dev" suffix from
__version__. The remainder should be of the form "X.Y.Z", where X,
Y, and Z are positive integers. Do NOT commit this change.
Y, and Z are positive integers.
8. Update your working copy to HEAD, and tag the release:
*** Do NOT commit this change. ***
svn up && svn cp -m "Tag the X.Y.Z final release." . ^/tags/X.Y.Z
9. "Peg" the contributed templates externals definition to the
current HEAD revision:
9. Go into an empty directory and run the 'make-release' script:
svn pedit svn:externals .
(squeeze "-rBASE_REV", where BASE_REV is the current HEAD revision
number, between 'templates-contrib' and the target URL).
*** Do NOT commit this change. ***
10. Tag the release:
svn cp -m "Tag the X.Y.Z final release." . ^/tags/X.Y.Z
This will create a copy of the release branch, plus your local
modifications to the svn:externals property and lib/viewvc.py
file, to the tag location.
11. Revert the changes in your working copy.
svn revert -R .
12. Go into an empty directory and run the 'make-release' script:
tools/make-release viewvc-X.Y.Z tags/X.Y.Z
10. Verify the archive files:
13. Verify the archive files:
- do they have a LICENSE.html file?
- do they have necessary include documentation?
- do they *not* have unnecessary stuff?
- do they install and work correctly?
11. Upload the created archive files (tar.gz and zip) into the Files
14. Upload the created archive files (tar.gz and zip) into the Files
and Documents section of the Tigris.org project, and modify the
CHECKSUMS document there accordingly. Also, drop a copy of the
archive files into the root directory of the viewvc.org website
(unversioned).
12. On trunk, update the websites (both the viewvc.org/ and www/ ones)
15. On trunk, update the websites (both the viewvc.org/ and www/ ones)
to refer to the new release files, and copy the CHANGES for the
new release into trunk's CHANGES file.
13. Edit the file 'lib/viewvc.py' again, re-adding the "-dev" suffix
and incrementing the patch number assigned to the __version__
variable, and add a new empty block in the branch's CHANGES file,
and commit:
16. Edit the file 'lib/viewvc.py' again, incrementing the patch number
assigned to the __version__ variable. Add a new empty block in
the branch's CHANGES file. Commit your changes:
svn ci -m "Begin a new release cycle."
14. Edit the Issue Tracker configuration options, adding a new Version
17. Edit the Issue Tracker configuration options, adding a new Version
for the just-released one, and a new Milestone for the next patch
(and possibly, minor or major) release. (For the Milestone sort
key, use a packed integer XXYYZZ: 1.0.3 == 10003, 2.11.4 == 21104.)
15. Write an announcement explaining all the cool new features and
post it to the announce@ list, to the project's News area, and to
other places interested in this sort of stuff, such as Freshmeat
(http://www.freshmeat.net).
18. Send to the announce@ list a message explaining all the cool new
features, and post similar announcements to other places interested
in this sort of stuff, such as Freshmeat (http://www.freshmeat.net).

View File

@@ -94,9 +94,6 @@ form { margin: 0; }
.vc_properties {
margin: 1em 0;
}
.vc_properties h2 {
font-size: 115%;
}
/*** File Content Markup Styles ***/

View File

@@ -5,7 +5,7 @@
<table>
<tr>
<td>[if-any cfg.general.address]<address><a href="mailto:[cfg.general.address]">[cfg.general.address]</a></address>[else]&nbsp;[end]</td>
<td style="text-align: right;"><strong><a href="[help_href]">ViewVC Help</a></strong></td>
<td style="text-align: right;">[if-any help_href]<strong><a href="[help_href]">ViewVC Help</a></strong>[else]&nbsp;[end]</td>
</tr>
<tr>
<td>Powered by <a href="http://viewvc.tigris.org/">ViewVC [vsn]</a></td>

View File

@@ -4,13 +4,13 @@
<!-- ViewVC :: http://www.viewvc.org/ -->
<head>
<title>Checkin Database Query</title>
<link rel="stylesheet" href="[docroot]/styles.css" type="text/css" />
[if-any docroot]<link rel="stylesheet" href="[docroot]/styles.css" type="text/css" />[end]
</head>
<body>
[# setup page definitions]
[define help_href][docroot]/help_query.html[end]
[define help_href][if-any docroot][docroot]/help_query.html[end][end]
[# end]
<p>
@@ -202,21 +202,21 @@
</td>
[# uncommment, if you want a separate Description column:
{if-index commits.files first{
{if-index commits.files first}
<td style="vertical-align:top;" rowspan="{commits.num_files}">
{commits.log}
{if-any commits.log}{commits.log}{else}&nbsp;{end}
</td>
{end}
(substitute brackets for the braces)
]
</tr>
[# and also take the following out in the "Description column"-case:]
[# and also take the following out in the "Description column" case:]
[if-index commits.files last]
<tr class="vc_row_[if-index commits even]even[else]odd[end]">
<td>&nbsp;</td>
<td colspan="5"><strong>Log:</strong><br />
<pre class="vc_log">[commits.log]</pre></td>
<pre class="vc_log">[if-any commits.log][commits.log][else]&nbsp;[end]</pre></td>
</tr>
[end]
[# ---]

View File

@@ -6,6 +6,7 @@
[include "include/header.ezt" "revision"]
<hr />
<form method="get" action="[jump_rev_action]">
<table cellspacing="1" cellpadding="2" style="width: auto;">
<tr align="left">
@@ -42,7 +43,7 @@
<hr />
<p><strong>Changed paths:</strong></p>
<h2>Changed paths</h2>
<table cellspacing="1" cellpadding="2">
<thead>
@@ -77,4 +78,5 @@
</tbody>
</table>
[include "include/props.ezt"]
[include "include/footer.ezt"]

View File

@@ -50,7 +50,9 @@ FILE_INFO_LIST = [
("bin/cgi/viewvc.cgi", "bin/cgi/viewvc.cgi", 0755, 1, 0, 0),
("bin/cgi/query.cgi", "bin/cgi/query.cgi", 0755, 1, 0, 0),
("bin/wsgi/viewvc.wsgi", "bin/wsgi/viewvc.wsgi", 0755, 1, 0, 0),
("bin/wsgi/viewvc.fcgi", "bin/wsgi/viewvc.fcgi", 0755, 1, 0, 0),
("bin/wsgi/query.wsgi", "bin/wsgi/query.wsgi", 0755, 1, 0, 0),
("bin/wsgi/query.fcgi", "bin/wsgi/query.fcgi", 0755, 1, 0, 0),
("bin/mod_python/viewvc.py", "bin/mod_python/viewvc.py", 0755, 1, 0, 0),
("bin/mod_python/query.py", "bin/mod_python/query.py", 0755, 1, 0, 0),
("bin/mod_python/handler.py", "bin/mod_python/handler.py", 0755, 1, 0, 0),