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

Compare commits

..

94 Commits

Author SHA1 Message Date
cmpilato
eb69c40687 Merge in 1.0.9 and 1.1.2's changes.
git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2242 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-08-11 16:00:21 +00:00
cmpilato
6cbb3fadac Note new latest release on project homepage.
git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2241 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-08-11 15:58:09 +00:00
cmpilato
cc4589ab10 Rename 'Source tarballs' left-nav as 'Downloads'.
git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2240 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-08-11 15:26:33 +00:00
cmpilato
fcff592db3 Rename 'Subversion' left-nav as 'Source Code'.
git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2239 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-08-11 15:25:55 +00:00
cmpilato
694a14e0d2 Update 'Mailing Lists' left-nav link.
git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2238 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-08-11 15:25:14 +00:00
cmpilato
205b3b67e1 Make it easier for folks to show/hide binary file contents in the
markup/annotate views.

* templates/file.ezt
  Add some customizable template logic to hide the contents of file's with
  non-human-readable file formats.  Were Greg Stein dead, he'd be rolling
  over in his grave right now.


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2228 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-07-16 19:28:29 +00:00
cmpilato
8df8e878f4 * lib/viewvc.py
(view_error): Settle for simple HTML-escaping of error messages
    rather than full htmlification.


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2225 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-07-14 20:43:46 +00:00
cmpilato
f038efef96 Fix issue #422: syntax coloration dropping initial blank lines from
files.

* lib/viewvc.py
  (markup_stream_pygments): Pass stripnl=False to Pygments lexers so
    they won't strip out leading blank lines from the files they are
    colorizing.


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2223 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-07-13 17:13:16 +00:00
cmpilato
52584dec66 Document some shortcomings of the path-based authz subsystem.
git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2222 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-07-13 14:09:17 +00:00
cmpilato
5c9f504727 * conf/viewvc.conf.dist
(allow_compress): Add a note about the speed penalty this option causes.


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2220 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-07-07 14:05:12 +00:00
cmpilato
7817608915 Try to avoid content spoofing errors. Prior to this change, a URL
like this:

   http://localhost/viewvc/subversion/?view=foo%22)%20was%20passed\
   %20as%20a%20parameter.20%20Visit%20http://www.baddy.com%20to%20\
   figure%20out%20why%20(%22foo

Would result in an error page that read as follows:

   An illegal value ("foo") was passed as a parameter. Visit
   http://www.baddy.com to figure out why ("foo") was passed as a
   parameter.

(where "http://www.baddy.com" was linkified, and could potentially
point to a malicious website.)

With this change, we will avoid printing unknown parameter names, and
will show the parameter name rather its value when a bogus value is
detected.  Yes, there's admittedly some information loss here that
might be useful to the well-meaning but fat-fingered user, but the
security aspect is more important.

* lib/viewvc.py
  (_validate_param): Don't print illegal parameter names, and show the
    (legal) parameter name rather than its value when that value is
    illegal.


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2217 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-07-06 19:03:06 +00:00
cmpilato
0292a54ec0 Some more around input validation, cleaning up some code and
tightening up some other bits.

* lib/viewvc.py
  (_validate_view, _validate_mimetype): New validation functions.
  (_re_validate_mimetype): Removed as unused.
  (_legal_params): Tweak the validation routines for 'view' and
    'content-type' to point to _validate_view() and _validate_mimetype(),
    respectively.
  (_validate_param): Now check for non-zero result from validation
    functions as the "valid" indicator, rather than requiring each of
    them to raise an exception in troubled times.
  (Request.run_viewvc): Lose now-unnecessary validation of
    'content-type' parameter -- the normal parameter validation stuff
    should catch problems there.


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2213 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-07-06 15:05:23 +00:00
cmpilato
6c93d8c8d1 * lib/viewvc.py
(Request.run_viewvc): Move the logic that maps view=rev to
    view=revision into the parameter validation loop.


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2212 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-07-06 14:48:53 +00:00
cmpilato
4f622d375b * lib/viewvc.py
(Request.run_viewvc): Use an intermediate variable to simplify some
    logic around input parameter validation.


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2211 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-07-06 14:46:21 +00:00
cmpilato
867514f9ef Minor comment tweak.
git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2209 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-06-17 21:22:14 +00:00
cmpilato
b36d8584e8 * conf/viewvc.conf.dist
Comment out all the options here, forcing folks to uncomment the
  stuff they want to modify.  This allows the parsing of this file to
  be optimized toward doing less work, while maintaining a consistent
  initial presentation.


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2207 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-06-17 14:32:16 +00:00
cmpilato
8e848a4025 Finish issue #415 - ModPythonServer shouldn't call sys.exit().
(This doesn't really fix anything, and hopefully doesn't break anything
either, but is merely a "good programming practice" cleanup item.)

* lib/viewvc.py
  (Request.run_viewvc): Ensure that server.redirect() is the last
    thing this function does (when it does it).

* lib/sapi.py
  (CgiServer.redirect): Avoid calling sys.exit().  Also, fix a use of
    print() that should be sys.stdout.write() (for consistency).
  (AspServer.redirect, ModPythonServer.redirect): Avoid calling sys.exit().


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2205 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-06-16 15:04:24 +00:00
cmpilato
e7e8beca0a Finish issue #336 - Custom cvsgraph rendering via CGI parameters.
* conf/viewvc.conf.dist
  (allowed_cvsgraph_useropts): New option.

* lib/config.py
  (Config.set_defaults): Set default value for new
    'allowed_cvsgraph_useropts' option.

* lib/viewvc.py
  (_legal_params): Add new legal parameters: 'gflip', 'gbbox',
    'gshow', 'gleft', and 'gmaxtag'.
  (cvsgraph_make_reqopt, cvsgraph_normalize_gshow, cvsgraph_extraopts):
    New helper functions.
  (view_cvsgraph_image): Now pass the -O option set to the cvsgraph
    binary.
  (view_cvsgraph): Now pass the -O option set to the cvsgraph binary.
    Also, add new template data stuff for generating a user-configurable
    graph display options form.

* templates/graph.ezt,
* templates/docroot/styles.css
  Add template stuff for generating a user-configurable graph display
  options form.

* docs/url-reference.html,
* docs/template-authoring-guide.html
  Update documentation.

* CHANGES
  Note this change.

Patch by:  Bertho Stultiens <bertho{_AT_}j.auh.dk> (originally),
           Jene Jasper <tigris{_AT_}shadowland.demon.nl> (port to 1.1.x),
           me (tweaks for official ViewVC inclusion)


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2204 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-06-15 20:18:35 +00:00
cmpilato
c3bdeea60b Correct some inconsistent markup in documentation.
git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2201 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-06-15 20:11:33 +00:00
cmpilato
3d8aecfd95 Tighten up some input validation.
* lib/viewvc.py
  (_re_validate_boolint): New.
  (_legal_params): Switch the validation function to _re_validate_boolint
   for the following: 'hideattic', 'makeimage', 'parent', 'tarball',
   and 'hidecvsroot'.


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2199 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-06-15 19:41:30 +00:00
cmpilato
c713952d5e Minor documentation wording tweak.
git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2197 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-06-15 19:06:26 +00:00
cmpilato
8910c295cc Finish issue #420 - "cvsdbadmin rebuild" and "svndbadmin rebuild"
complain about unknown repositories.

* bin/svndbadmin
  (main): When rebuilding, ignore the UnknownRepositoryError; when
    purging, turn that sucker into something readable.

* bin/cvsdbadmin
  (__main__): When rebuilding, ignore the UnknownRepositoryError; when
    purging, turn that sucker into something readable.


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2195 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-06-08 15:50:51 +00:00
cmpilato
1d496a8f51 Make error handling in cvsdb a little more flexible.
* lib/cvsdb.py
  (UnknownRepositoryError, DatabaseVersionError): New Exception classes.
  (CheckinDatabase.Connect): Raise DatabaseVersionError instead of a
    generic Exception.
  (CheckinDatabase.PurgeRepository): Raise UnknownRepositoryError
    instead of a generic Exception.

git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2194 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-06-08 15:23:16 +00:00
cmpilato
892a951493 Finish issue #419: svnauthz module doesn't match Subversion's
case-handling semantics.

* conf/viewvc.conf.dist
  (force_username_case): New option.

* lib/vcauth/svnauthz/__init__.py
  (ViewVCAuthorizer.__init__): Find and handle new force_username_case
    authorizer option.
  (ViewVCAuthorizer._get_paths_for_root): Replace ConfigParser.optionxform()
    (which does normalization of option names) with an identity function
    of sorts.


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2192 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-06-05 19:03:07 +00:00
cmpilato
1371a71f20 Consistify the layout -- at least on a section-by-section basis -- of
the viewvc.conf.dist file.

git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2190 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-06-05 17:52:47 +00:00
cmpilato
aba3033c27 Remove CHANGES item for change that should appear in 1.1.2 instead of 1.2.0.
git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2189 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-06-04 15:43:55 +00:00
cmpilato
74bfd3e9d8 Post-release fun.
* CHANGES
  Copy 1.1.1's changes here.

* www/index.html
  Update 'latest release' notes.

git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2186 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-06-03 15:05:32 +00:00
cmpilato
7cb54076fe Finish (for now) the 1.1.0 release ntoes.
git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2183 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-05-29 18:16:41 +00:00
cmpilato
197f352804 * templates/file.ezt
Use "Contents of /path/to/file" instead of "Annotate of /path/to/file" as
  the page title.


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2181 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-05-29 17:57:03 +00:00
cmpilato
f48559766a * lib/cvsdb.py
(CheckinDatabase.PurgeRepository): Don't allow the purge operation
    to actually *create* a "repositories" table entry.


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2179 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-05-29 15:09:51 +00:00
cmpilato
546501816b Fix issue #417 - "cvsdbadmin rebuild" fails to record some of the
commit/repository info.

* lib/cvsdb.py
  (CheckinDatabase.PurgeRepository): Clear all the ID caches after
    running a purge operation so that, if the purge is actually part
    of a rebuild, the subsequent update doesn't merely pull IDs from
    the cache (with the side-effect of not readding them to the database).

Reported by: Naran Babhu <naranbabhu{_AT_}tigris.org
             Martin Dessureault <martin{_AT_}austin.rr.com>


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2178 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-05-29 15:08:32 +00:00
cmpilato
8089335fc6 Fix issue #416 - Can't see query form due to missing template variables.
* lib/viewvc.py
  (view_queryform): Add 'query_action' and 'query_hidden_values' back
    to the data dictionary, as they were accidentally dropped in r2123.

Reported by: Naran Babhu <naranbabhu{_AT_}tigris.org>


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2175 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-05-28 13:59:47 +00:00
cmpilato
d739127ea4 Update external to point to 1.2 versions of contributed templates.
git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2172 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-05-18 13:28:53 +00:00
cmpilato
4b4f450ecb Update CHANGES list for 1.1.0 release.
git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2169 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-05-13 17:11:27 +00:00
cmpilato
588f9000e9 Update the viewvc.org site.
git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2168 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-05-13 14:44:58 +00:00
cmpilato
7ecae1790a One last tweak.
git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2167 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-05-13 14:43:13 +00:00
cmpilato
a154179492 Need ... homepage ... beauty...
git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2166 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-05-13 14:41:52 +00:00
cmpilato
cc4f8254d6 More Tigris homepage tweaks.
git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2165 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-05-13 14:40:24 +00:00
cmpilato
c695ede476 Update Tigris homepage.
git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2164 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-05-13 14:31:11 +00:00
cmpilato
c910df0835 Add left-nav link to source tarballs.
git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2163 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-05-13 14:20:53 +00:00
cmpilato
914e0e7521 Copy 1.0.8's CHANGES.
git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2152 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-05-05 17:26:04 +00:00
cmpilato
4c81b1fd91 Note new version of ViewVC.
git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2151 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-05-05 17:25:04 +00:00
cmpilato
92a95601d1 Bump copyright years.
git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2146 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-05-05 17:08:54 +00:00
cmpilato
211bc90343 Finish issue #402: Split the 'use_pagesize' configuration directive
into two: 'log_pagesize' and 'dir_pagesize', individually controlling
the size of pages used (if at all) for the revision log and directory
views, respectively.

* conf/viewvc.conf.dist
  (use_pagesize): Removed, in favor of...
  (dir_pagesize, log_pagesize): ...these.

* lib/viewvc.py,
* lib/config.py,
* bin/standalone.py
  Replace the use and tooling around 'use_pagesize' with
  'dir_pagesize' and 'log_pagesize' as appropriate.

* templates/include/paging.ezt,
* templates/include/dir_header.ezt
  Stop using the option value to determine whether or not to show
  pagination UI.  Use the presence of some pages instead.
  
* docs/upgrading-howto.html
  Note the changes in options.

Patch by: Lei Zhang <thestig{_AT_}google.com>
          (Tweaked by me.)


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2142 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-05-05 15:45:25 +00:00
cmpilato
fdff86c5f4 Fix the GUI mode of standalone.py -- it wasn't even starting
correctly, and we don't need a toggle for 'enscript' any more.

* bin/standalone.py
  (GUI.__init__): Pass the configuration file to handle_config().
    Lose 'enscript'-related stuff.
  (GUI.toggle_use_enscript): Remove.
  (cli): Fix call to gui(), dropping bogus parameter.


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2140 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-05-05 15:34:11 +00:00
cmpilato
7ca7528869 Fix issue #409, an exception thrown when sorting by revision in a
remote Subversion directory view.

* lib/vclib/svn/svn_ra.py
  (RemoteSubversionRepository.dirlogs): Store the entry's revision as
    a string, for consistency with other vclib modules.

Reported by: Wojciech Wróblewski <wojtek{_AT_}elmi.pl>


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2137 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-05-05 14:52:35 +00:00
cmpilato
dfa98b490f Fix an exception in log views of Subversion repositories with 0
revisions.

* lib/vclib/svn/svn_repos.py
  (_get_history): Add easy-out for repositories with 0 revisions.

Reported by: Wojciech Wróblewski <wojtek{_AT_}elmi.pl>


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2134 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-05-04 14:53:24 +00:00
cmpilato
bacb71b1d2 Call make-release correctly.
git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2132 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-04-20 17:47:50 +00:00
cmpilato
3da11f485a Slight terminology tweak.
git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2129 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-04-20 17:40:51 +00:00
cmpilato
a8e6f976ef * tools/make-release
Make this able to build any branch, not just trunk and tag names.

* notes/releases.txt
  Update example of using make-release.


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2128 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-04-20 17:38:57 +00:00
cmpilato
6d6a0287ac * lib/viewvc.py
(view_directory, view_log): Add some comments explaining the
    presence of certain data dictionary dummy values.


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2124 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-03-24 17:01:53 +00:00
cmpilato
63af297920 Try to make ViewVC provide a consistent, predictable data dictionary
in all of its templated views.  Do this with a custom, dictionary-like
class that prevents the creation of new keys after an initial
instantiation of keys and (possibly dummy) values.

* lib/ezt.py
  (TemplateData): New.

* lib/viewvc.py
  (common_template_data): Now return an ezt.TemplateData() object.
  (make_comma_sep_list_string): New.
  (markup_or_annotate): Use new ezt.TemplateData() interface now.  Use
    make_comma_sep_list_string() where applicable.
  (view_roots, view_log, view_cvsgraph, view_diff, view_revision,
   view_queryform, view_query): Use new ezt.TemplateData() interface now.
  (view_directory): Use new ezt.TemplateData() interface now.  Drop
    'search_re_form' dictionary item.

* lib/query.py
  (main): Use new ezt.TemplateData() interface now.  While here, drop
    'script_name' calculation (it isn't used).

* templates/include/dir_header.ezt
  Display the search form if 'search_re_action' is set, not 'search_re_form'.

* docs/template-authoring-guide.html
  Remove 'search_re_form'.  Update 'search_re_action' description.


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2123 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-03-24 16:55:25 +00:00
cmpilato
d7ac8ee2d4 * templates/include/file_header.ezt
Lose template reference of 'log_href_rev', which was removed in
  r2116 as unused.


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2121 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-03-24 16:32:29 +00:00
cmpilato
11b4c4f4f8 Clutterkiller! Put the default configuration files into a conf/
subdirectory.

* conf/
  New subdirectory.

* cvsgraph.conf.dist,
* mimetypes.conf.dist,
* viewvc.conf.dist
  Move these from here ...

* conf/cvsgraph.conf.dist,
* conf/mimetypes.conf.dist,
* conf/viewvc.conf.dist
  ... to here.

* viewvc-install
  (FILE_INFO_LIST): Track new locations of configuration files.


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2119 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-03-19 20:41:41 +00:00
cmpilato
c6671ecc50 Attempt to compensate for the fact that some versions of Subversion's
Python bindings do not correctly set the .apr_err and .message members
of SubversionException objects by patching up those exceptions using
the exception arguments.

(Unfortunately, I don't have a version of these bindings installed for
testing.)

* lib/vclib/svn/svn_repos.py
  (_fix_subversion_exception): New helper function.
  (_get_history, BlameSource.__init__, LocalSubversionRepository.rawdiff,
   LocalSubversionRepository.get_location, LocalSubversionRepository.last_rev):
    Use _fix_subversion_exception().

* lib/vclib/svn/svn_ra.py
  (): Import _fix_subversion_exception from svn_repos.
  (RemoteSubversionRepository._date_from_rev, 
   RemoteSubversionRepository.get_location): Use _fix_subversion_exception().


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2117 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-03-19 18:02:35 +00:00
cmpilato
0bcb42c158 * lib/viewvc.py
(common_template_data): Stop initializing an unused value.

* docs/template-authoring-guide.html
  Lose docs for unused (and spelled wrong, to boot) template variable.


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2116 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-03-19 17:46:54 +00:00
cmpilato
586c6bfb9e * lib/ezt.py
(Template._cmd_for): Raise a more useful exception message when the
    to-be-looped-over variable ain't a sequence.


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2115 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-03-19 17:44:07 +00:00
cmpilato
ca12b5257c * lib/ezt.py
(Template._cmd_print): Raise a more helpful exception to give some
    clues to template authors who tried to, say, print a sequence
    reference.


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2111 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-03-19 15:21:30 +00:00
cmpilato
7fd9e405a1 Update copyright years.
git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2107 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-03-18 16:43:33 +00:00
cmpilato
6361a849a6 Update release notes.
git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2106 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-03-18 16:15:49 +00:00
cmpilato
e72184e288 Fix namespace problem with raised Exception.
* lib/viewvc.py
  (view_revision): raise *debug.*ViewVCException.

Patch by: Kamesh Jayachandran <kamesh@collab.net>


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2103 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-03-18 12:45:47 +00:00
cmpilato
2dc51276ce Finish issue #401: Support MIME type overrides in ViewVC configuration.
Trade the 'mime_types_file' option for 'mime_types_files' -- an
ordered list of MIME mapping files to consult.  And provide our own
(empty) mapping file that folks can use to override the mappings
provided by other such files.

* mimetypes.conf.dist
  New file.

* viewvc.conf.dist
  (mime_types_files): Was mime_types_file, and now accepts multiple values.

* lib/config.py
  (Config._force_multi_value): Add "mime_types_files" to the list of
    multi-value configuration options.
  (Config.set_defaults): Track rename of mime_types_file parameter,
    now setting the default to a list containing only "mimetypes.conf".

* lib/viewvc.py
  (load_config): Track new name and format of mime_types_files option.

* viewvc-install
  (FILE_INFO_LIST): Also install mimetypes.conf.dist as itself and as
    mimetypes.conf.

* INSTALL
  (INSTALLING VIEWVC): Update reference to renamed configuration option.

* docs/upgrading-howto.html
  Update this document.


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2101 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-03-06 16:43:04 +00:00
cmpilato
e1575692be Finish issue #396 - Malformed accept-language header crashes viewvc
* lib/accept.py
  (AcceptLanguageParseError): Was AcceptParseError.
  (_parse): Track renamed Exception.

* lib/viewvc.py
  (Request.__init__): Catch and handle raised AcceptLanguageParseError.

Patch by: Rune Halvorsen <runefh{_AT_}gmail.com>,
          me


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2097 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-02-26 16:12:15 +00:00
cmpilato
748efe3815 Add FAQ entry about exposing ViewVC at a vhost root.
git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2096 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-02-24 13:36:41 +00:00
cmpilato
d681df85d3 Allow ViewVC to (optionally) use the 'chardet' module during syntax
coloration to perform character encoding detection (and subsequent
translation to UTF-8).

(Thanks to Jeremy Whitlock <jcscoobyrs@gmail.com> for pointing me in
this direction, if inadvertantly.)

* viewvc.conf.dist
  (options.detect_encoding): New.

* lib/config.py
  (Config.set_defaults): Initialize the 'detect_encoding' parameter.

* lib/viewvc.py
  (markup_stream_pygments): If the configuration asks for character
    encoding detection, try to import the 'chardet' module and -- if all
    goes well -- tell Pygments to use it.

* CHANGES
  Note this change.


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2095 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-02-20 17:23:27 +00:00
cmpilato
e53b3af42f ViewVC doesn't "do" directory entry sorting by revision for CVS, so
don't imply that it does in the UI.

* lib/viewvc.py
  (view_directory): Don't provide sortby_rev_href to the template.

* templates/directory.ezt
  Only offer sort links when those links are provided by ViewVC.

* templates/dir_new.ezt
  Only offer sort links when those links are provided by ViewVC.  Use
  date-based sorting if rev-based sorting isn't available.


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2090 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-02-20 15:20:15 +00:00
cmpilato
d1a7412c6d Remove dead code.
* lib/popen.py
  (pipe_cmds, _copy): Remove as unused.

* bin/standalone.py
  (StandaloneServer.run_viewvc): Tweak comment that referred to pipe_cmds().

Found by: Rune Halvorsen <runeh {AT} sanedefaults.net>


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2088 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-02-03 03:53:25 +00:00
cmpilato
ee692db2b0 Fix issue #398 (File Log Viewer Shows Wrong Log Message) by asking the
vclib layer for revision-sorted output rather than "whatever you want
to give me".

* lib/viewvc.py
  (markup_or_annotate): Pass vclib.SORTBY_REV instead of vclib.SORTBY_DEFAULT
    to the itemlog() interface.


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2086 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-02-02 18:10:59 +00:00
cmpilato
544ca74ed9 Add a skeletal version of some semblance of 1.1.0 release notes, taken
from an email response I gave on the dev@ list.  Will massage this
into something a little more ready for publicity later.

* docs/release-notes,
* docs/release-notes/1.1.0.html
  New.


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2085 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-01-15 16:56:44 +00:00
cmpilato
f6844dda91 Finish issue #334 by adding an empty CSS class def and some references
to it for line number columns in the diff view.

* templates/docroot/styles.css
  (.vc_diff_line_number): New.

* templates/diff.ezt
  Use new vc_diff_line_number class.


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2083 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-01-13 19:10:09 +00:00
cmpilato
5fdfefa137 Document the new database schema stuff.
git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2081 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-01-13 18:44:43 +00:00
cmpilato
cd64b5da8b Add some real command-line parameter handling to 'make-database',
effectively allowing for non-interactive operation.

* bin/make-database
  (INTRO_TEXT): Removed, merged into the usage message printed by...
  (usage_and_exit): ...this new function.
  (__main__): Add new command-line parsing logic, including support of
    new options (--username, --hostname, --password, --dbname) and the
    replacement of the --bonsai-compatible option with a more generic
    --version.

git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2079 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-01-13 18:18:46 +00:00
cmpilato
623ab85805 Merge to trunk all changes made on the issue-366-dev branch,
completing issue #366 (cvsdb purge operation is painfully slow).

* lib/cvsdb.py,
* bin/make-database


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2078 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-01-13 18:16:11 +00:00
cmpilato
ceb7057b9f Remove unnecessary empty svn:mergeinfo.
git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2077 8cb11bc2-c004-0410-86c3-e597b4017df7
2009-01-13 18:14:52 +00:00
cmpilato
0b1ac97f75 Try to deal with Subversion versions that lack the
SVN_ERR_CEASE_INVOCATION error code.

* lib/vclib/svn/svn_repos.py
  (_SVN_ERR_CEASE_INVOCATION): New compatibility variable.
  (NodeHistory.add_history, _get_history): Use compatibility variable
    instead of testing for SVN_ERR_CEASE_INVOCATION directly.


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2070 8cb11bc2-c004-0410-86c3-e597b4017df7
2008-12-19 19:48:43 +00:00
cmpilato
3e77755819 Document new num_changes item in upgrade notes.
git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2068 8cb11bc2-c004-0410-86c3-e597b4017df7
2008-12-19 19:45:44 +00:00
cmpilato
1433941124 Expose to revision.ezt a count of the total number of changed paths.
* lib/viewvc.py
  (view_revision): Add new 'num_changes' data dictionary item.

* templates/revision.ezt
  Expose new 'num_changes' item as a header on this page, and tweak
  the way the more/first changes links appear.

* docs/template-authoring-guide.html
  Document num_changes dictionary item.


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2067 8cb11bc2-c004-0410-86c3-e597b4017df7
2008-12-19 19:43:18 +00:00
cmpilato
c733fceb9f Rework the 'rlog-ended-early' FAQ bit with a more generic entry.
git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2066 8cb11bc2-c004-0410-86c3-e597b4017df7
2008-12-10 18:12:29 +00:00
cmpilato
ca5a2bfbc9 Fix issue #385 (Hide/show annotations links mismanaged for binary
files).

* lib/viewvc.py
  (markup_or_annotate): Make the default value for the 'annotation'
    data dictionary member 'none' (instead of None) to simplify
    template logic.

* docs/template-authoring-guide.html
  Update docs for 'annotated'.

* templates/file.ezt
  Use simplified logic to avoid missing links.  (No, not *that* kind ...)


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2064 8cb11bc2-c004-0410-86c3-e597b4017df7
2008-12-10 17:26:37 +00:00
cmpilato
77fd2759c7 Remove unnecessary module imports.
git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2063 8cb11bc2-c004-0410-86c3-e597b4017df7
2008-12-10 17:25:11 +00:00
cmpilato
08a8b110ac Allow admins to enable/disable diff/patch views via the allowed_views
configuration bit.

* lib/viewvc.py
  (view_diff, view_patch): Only show diffs if 'diff' is one of the
    allowed views.

* lib/config.py
  (Config.set_defaults): Add 'diff' to the set of allowed_views (and
    sort the values alphabetically where here).

* viewvc.conf.dist
  (allowed_views): Add 'diff' to the set of views you can specify, and
    include it in the default values.  While here, sort the values
    alphabetically.


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2058 8cb11bc2-c004-0410-86c3-e597b4017df7
2008-12-05 17:01:39 +00:00
cmpilato
38a7338c9d Add a configuration option for telling ViewVC to *not* honor the
svn:mime-type property.

* lib/config.py
  (Config.set_defaults): Set options.svn_ignore_mimetype default value.

* viewvc.conf.dist
  (svn_ignore_mimetype): New.

* lib/viewvc.py
  (calculate_mime_type): Consult cfg.options.svn_ignore_mimetype
    before looking up the 'svn:mime-type' property.

* docs/upgrading-howto.html
  Add a note about the new configuration option.

Patch (mostly) by: JJ <eggsgloriouseggs {_AT_} gmail.com>


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2055 8cb11bc2-c004-0410-86c3-e597b4017df7
2008-11-13 21:44:15 +00:00
cmpilato
bf40ef2683 It's very confusing to comment out the authorizer configuration line
and have that mean "use an authorizer".  So let's just prevent that
confusion right now, okay?

* lib/config.py
  (Config.set_defaults): Set 'authorizer' by default to None.

* viewvc.conf.dist
  (authorizer): Update comments for correctness, and don't imply that
    "forbidden" is the default authorizer.

* docs/upgrading-howto.html
  Stop saying that "forbidden" is the default authorizer.


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2053 8cb11bc2-c004-0410-86c3-e597b4017df7
2008-11-13 21:20:29 +00:00
cmpilato
11f5685955 Finish issue #384 - repos._revinfo_raw() is doing far too much work
when no authz is in use.  Vastly improves performance of
repos.itemlog() for local Subversion repositories *not* protected by
an authorizer.

* lib/vclib/svn/svn_repos.py
  (LocalSubversionRepository._revinfo): Was ._revinfo_raw().  Now
    encapsulates the caching logic that used to live in .revinfo(), plus
    the old logic of _revinfo_raw() modified to avoid changed-path
    processing when that processing isn't strictly required by callers.
  (LocalSubversionRepository.revinfo): Make this just a thin wrapper
    around ._revinfo() now.  Internal callers of this function updated
    to use ._revinfo() instead.


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2051 8cb11bc2-c004-0410-86c3-e597b4017df7
2008-11-13 21:14:14 +00:00
cmpilato
4904e03324 Minor improvements to the debug timer code.
* lib/debug.py
  (t_dump): Was dump().  Now accepts an output file handle, and sorts
    the output in a predictable fashion.

* lib/viewvc.py
  (main): Track changes to debug.dump().

git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2048 8cb11bc2-c004-0410-86c3-e597b4017df7
2008-11-13 19:45:13 +00:00
cmpilato
bd1254aa5f Avoid returning huge lists of variables from get_file_view_info(), and
use an ad-hoc class to hold all that stuff instead.

* lib/viewvc.py
  (get_file_view_info): Now return an object with interesting member variables
    instead of a nasty long list of values in an easy-to-goof-up order.
  (common_template_data, view_directory, view_log, view_diff): Update
    uses of get_file_view_info to track new calling semantics.


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2047 8cb11bc2-c004-0410-86c3-e597b4017df7
2008-11-11 16:21:58 +00:00
cmpilato
8b6e568ae1 * viewvc.org/faq.html: Minor wording tweak.
git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2046 8cb11bc2-c004-0410-86c3-e597b4017df7
2008-11-10 22:05:27 +00:00
cmpilato
bc13ce9938 * viewvc.org/faq.html: Update the answer to the authz question.
git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2045 8cb11bc2-c004-0410-86c3-e597b4017df7
2008-11-10 14:29:47 +00:00
cmpilato
0ddf057bbc Minor website tweakage.
* viewvc.org/index.html
  Lose 'Future Plans' section, and overhaul the feature and requirements lists.

* viewvc.org/contributing.html
  Fix the link to the Template Authoring Guide.

* viewvc.org/download.html
  Add a section for upgrading existing ViewVC installations.


git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2044 8cb11bc2-c004-0410-86c3-e597b4017df7
2008-11-06 20:36:37 +00:00
cmpilato
5dbdea76ce docs/upgrading-howto.html: Don't claim as removed options not in 1.0.x.
git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2043 8cb11bc2-c004-0410-86c3-e597b4017df7
2008-11-05 21:13:54 +00:00
cmpilato
8a9b9562f3 Merge r2040 from the 1.1.x branch:
* CHANGES: Combine some changes, and remove a now-bogus one.

git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2041 8cb11bc2-c004-0410-86c3-e597b4017df7
2008-11-05 16:31:47 +00:00
cmpilato
51994aabc9 Doh! Remove empty <div> section.
git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2039 8cb11bc2-c004-0410-86c3-e597b4017df7
2008-11-04 21:45:28 +00:00
cmpilato
f3edee505d Website and CHANGES file updates.
git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2038 8cb11bc2-c004-0410-86c3-e597b4017df7
2008-11-04 21:44:44 +00:00
cmpilato
bcfb8f2c97 * lib/viewvc.py (__version__): Bump to '1.2-dev'.
git-svn-id: http://viewvc.tigris.org/svn/viewvc/trunk@2034 8cb11bc2-c004-0410-86c3-e597b4017df7
2008-10-30 17:37:04 +00:00
66 changed files with 3502 additions and 3233 deletions

93
CHANGES
View File

@@ -1,95 +1,6 @@
Version 1.1.12 (released 03-Nov-2011)
Version 1.2.0 (released ??-???-????)
* fix path display in patch and certain diff views (issue #485)
* fix broken cvsdb glob searching (issue 486)
* allow svn revision specifiers to have leading r's (issue #441, #448)
* allow environmental override of configuration location (issue #494)
* fix exception HTML-escaping non-string data under WSGI (issue #454)
* add links to root logs from roots view (issue #470)
* use Pygments lexer-guessing functionality (issue #495)
Version 1.1.11 (released 17-May-2011)
* security fix: remove user-reachable override of cvsdb row limit
* fix broken standalone.py -c and -d options handling
* add --help option to standalone.py
* fix stack trace when asked to checkout a directory (issue #478)
* improve memory usage and speed of revision log markup (issue #477)
* fix broken annotation view in CVS keyword-bearing files (issue #479)
* warn users when query results are incomplete (issue #433)
* avoid parsing errors on RCS newphrases in the admin section (issue #483)
* make rlog parsing code more robust in certain error cases (issue #444)
Version 1.1.10 (released 15-Mar-2011)
* fix stack trace in Subversion revision info logic (issue #475, issue #476)
Version 1.1.9 (released 18-Feb-2011)
* vcauth universal access determinations (issue #425)
* rework svn revision info cache for performance
* make revision log "extra pages" count configurable
* fix Subversion 1.4.x revision log compatibility code regression
* display sanitized error when authzfile is malformed
* handle file:/// Subversion rootpaths as local roots (issue #446)
* restore markup of URLs in file contents (issue #455)
* optionally display last-committed metadata in roots view (issue #457)
Version 1.1.8 (released 02-Dec-2010)
* fix slowness triggered by allow_compress=1 configuration (issue #467)
* allow use of 'fcrypt' for Windows standalone.py authn support (issue #471)
* yield more useful error on directory markup/annotate request (issue #472)
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 Basic authentication support to standalone.py (Unix only) (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)
* fix exception caused by trying to HTML-escape non-string data (issue #454)
* fix incorrect RSS feed Content-Type header (issue #449)
* fix RSS <title> encoding problem (issue #451)
* allow 'svndbadmin purge' to work on missing repositories (issue #452)
Version 1.1.5 (released 29-Mar-2010)
* security fix: escape user-provided search_re input to avoid XSS attack
Version 1.1.4 (released 10-Mar-2010)
* security fix: escape user-provided query form input to avoid XSS attack
* fix standalone.py failure (when per-root options aren't used) (issue #445)
* fix annotate failure caused by ignored svn_config_dir (issue #447)
Version 1.1.3 (released 22-Dec-2009)
* security fix: add root listing support of per-root authz config
* security fix: query.py requires 'forbidden' authorizer (or none) in config
* fix URL-ification of truncated log messages (issue #3)
* fix regexp input validation (issue #426, #427, #440)
* add support for configurable tab-to-spaces conversion
* fix not-a-sequence error in diff view
* allow viewvc-install to work when templates-contrib is absent
* minor template improvements/corrections
* expose revision metadata in diff view (issue #431)
* markup file/directory item property URLs and email addresses (issue #434)
* make ViewVC cross copies in Subversion history by default
* fix bug that caused standalone.py failure under Python 1.5.2 (issue #442)
* fix support for per-vhost overrides of authorizer parameters (issue #411)
* fix root name identification in query.py interface
* allow user-configurable cvsgraph display (issue #336)
Version 1.1.2 (released 11-Aug-2009)

158
INSTALL
View File

@@ -19,7 +19,7 @@ Congratulations on getting this far. :-)
For CVS Support:
* Python 1.5.2 or later (sorry, no 3.x support yet)
* Python 1.5.2 or later
(http://www.python.org/)
* RCS, Revision Control System
(http://www.cs.purdue.edu/homes/trinkle/RCS/)
@@ -30,11 +30,11 @@ Congratulations on getting this far. :-)
For Subversion Support:
* Python 2.0 or later (sorry, no 3.x support yet)
* Python 2.0 or later
(http://www.python.org/)
* Subversion, Version Control System, 1.3.1 or later
(binary installation and Python bindings)
(http://subversion.apache.org/)
(http://subversion.tigris.org/)
Optional:
@@ -168,145 +168,72 @@ checkin database working are below.
APACHE CONFIGURATION
--------------------
1) Locate your Apache configuration file(s).
1) Find out where the web server configuration file is kept. Typical
locations are /etc/httpd/httpd.conf, /etc/httpd/conf/httpd.conf,
and /etc/apache/httpd.conf. Depending on how apache was installed,
you may also look under /usr/local/etc or /etc/local. Use the vendor
documentation or the find utility if in doubt.
Typical locations are /etc/httpd/httpd.conf,
/etc/httpd/conf/httpd.conf, and /etc/apache/httpd.conf. Depending
on how Apache was installed, you may also look under /usr/local/etc
or /etc/local. Use the vendor documentation or the find utility if
in doubt.
2) Depending on how your Apache configuration is setup by default, you
might need to explicitly allow high-level access to the ViewVC
install location.
<Directory <VIEWVC_INSTALLATION_DIRECTORY>>
Order allow,deny
Allow from all
</Directory>
For example, if ViewVC is installed in /usr/local/viewvc-1.0 on
your system:
<Directory /usr/local/viewvc-1.0>
Order allow,deny
Allow from all
</Directory>
3) Configure Apache to expose ViewVC to users at the URL of your choice.
ViewVC provides several different ways to do this. Choose one of
the following methods:
-----------------------------------
METHOD A: CGI mode via ScriptAlias
-----------------------------------
The ScriptAlias directive is very useful for pointing
Either METHOD A:
2) The ScriptAlias directive is very useful for pointing
directly to the viewvc.cgi script. Simply insert a line containing
ScriptAlias /viewvc <VIEWVC_INSTALLATION_DIRECTORY>/bin/cgi/viewvc.cgi
ScriptAlias /viewvc <VIEWVC_INSTALLATION_DIRECTORY>/bin/cgi/viewvc.cgi
into your httpd.conf file. Choose the location in httpd.conf where
also the other ScriptAlias lines reside. Some examples:
ScriptAlias /viewvc /usr/local/viewvc-1.0/bin/cgi/viewvc.cgi
ScriptAlias /query /usr/local/viewvc-1.0/bin/cgi/query.cgi
ScriptAlias /viewvc /usr/local/viewvc-1.0/bin/cgi/viewvc.cgi
ScriptAlias /query /usr/local/viewvc-1.0/bin/cgi/query.cgi
----------------------------------------
METHOD B: CGI mode in cgi-bin directory
----------------------------------------
Copy the CGI scripts from
continue with step 3).
or alternatively METHOD B:
2) Copy the CGI scripts from
<VIEWVC_INSTALLATION_DIRECTORY>/bin/cgi/*.cgi
to the /cgi-bin/ directory configured in your httpd.conf file.
You can override configuration file location using:
SetEnv VIEWVC_CONF_PATHNAME /etc/viewvc.conf
continue with step 3).
------------------------------------------
METHOD C: CGI mode in ExecCGI'd directory
------------------------------------------
Copy the CGI scripts from
and then there's METHOD C:
2) Copy the CGI scripts from
<VIEWVC_INSTALLATION_DIRECTORY>/bin/cgi/*.cgi
to the directory of your choosing in the Document Root adding the following
Apache directives for the directory in httpd.conf or an .htaccess file:
apache directives for the directory in httpd.conf or an .htaccess file:
Options +ExecCGI
AddHandler cgi-script .cgi
Options +ExecCGI
AddHandler cgi-script .cgi
Note: For this to work mod_cgi has to be loaded. And for the .htaccess file
(Note: For this to work mod_cgi has to be loaded. And for the .htaccess file
to be effective, "AllowOverride All" or "AllowOverride Options FileInfo"
needs to have been specified for the directory.
need to have been specified for the directory.)
------------------------------------------
METHOD D: Using mod_python (if installed)
------------------------------------------
Copy the Python scripts and .htaccess file from
continue with step 3).
or if you've got Mod_Python installed you can use METHOD D:
2) Copy the Python scripts and .htaccess file from
<VIEWVC_INSTALLATION_DIRECTORY>/bin/mod_python/
to a directory being served by Apache.
to a directory being served by apache.
In httpd.conf, make sure that "AllowOverride All" or at least
"AllowOverride FileInfo Options" are enabled for the directory
you copied the files to.
You can override configuration file location using:
SetEnv VIEWVC_CONF_PATHNAME /etc/viewvc.conf
Note: If you are using Mod_Python under Apache 1.3 the tarball generation
feature may not work because it uses multithreading. This works fine
under Apache 2.
----------------------------------------
METHOD E: Using mod_wsgi (if installed)
----------------------------------------
Copy the Python scripts file from
<VIEWVC_INSTALLATION_DIRECTORY>/bin/mod_python/
to the directory of your choosing. Modify httpd.conf with the
following directives:
continue with step 3).
WSGIScriptAlias /viewvc <VIEWVC_INSTALLATION_DIRECTORY>/bin/wsgi/viewvc.wsgi
WSGIScriptAlias /query <VIEWVC_INSTALLATION_DIRECTORY>/bin/wsgi/query.wsgi
3) Restart apache. The commands to do this vary. "httpd -k restart" and
"apache -k restart" are two common variants. On RedHat Linux it is
done using the command "/sbin/service httpd restart" and on SuSE Linux
it is done with "rcapache restart"
You'll probably also need the following directive because of the
not-quite-sanctioned way that ViewVC manipulates Python objects.
4) Optional: Add access control.
WSGIApplicationGroup %{GLOBAL}
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
4) [Optional] Add access control.
In your httpd.conf you can control access to certain modules by
adding directives like this:
In your httpd.conf you can control access to certain modules by adding
directives like this:
<Location "<url to viewvc.cgi>/<modname_you_wish_to_access_ctl>">
AllowOverride None
@@ -324,14 +251,7 @@ APACHE CONFIGURATION
http://<server_name>/viewvc/~checkout~/<module_name>
http://<server_name>/viewvc/<module_name>.tar.gz?view=tar
5) Restart Apache.
The commands to do this vary. "httpd -k restart" and "apache -k
restart" are two common variants. On RedHat Linux it is done using
the command "/sbin/service httpd restart" and on SuSE Linux it is
done with "rcapache restart". Other systems use "apachectl restart".
6) Optional: Protect your ViewVC instance from server-whacking webcrawlers.
5) Optional: Protect your ViewVC instance from server-whacking webcrawlers.
As ViewVC is a web-based application which each page containing various
links to other pages and views, you can expect your server's performance

View File

@@ -15,7 +15,7 @@
<blockquote>
<p><strong>Copyright &copy; 1999-2011 The ViewCVS Group. All rights
<p><strong>Copyright &copy; 1999-2009 The ViewCVS Group. All rights
reserved.</strong></p>
<p>By using ViewVC, you agree to the terms and conditions set forth
@@ -60,8 +60,6 @@
<li>April 10, 2007 &mdash; copyright years updated</li>
<li>February 22, 2008 &mdash; copyright years updated</li>
<li>March 18, 2009 &mdash; copyright years updated</li>
<li>March 29, 2010 &mdash; copyright years updated</li>
<li>February 18, 2011 &mdash; copyright years updated</li>
</ul>
</body>

View File

@@ -54,10 +54,7 @@ import query
server = sapi.AspServer(Server, Request, Response, Application)
try:
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.asp"
query.main(server, cfg, viewvc_base_url)
query.main(server, cfg, "viewvc.asp")
finally:
s.close()

View File

@@ -54,7 +54,4 @@ import query
server = sapi.CgiServer()
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.cgi"
query.main(server, cfg, viewvc_base_url)
query.main(server, cfg, "viewvc.cgi")

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -242,7 +242,6 @@ def main(command, repository, revs=[], verbose=0, force=0):
cfg = viewvc.load_config(CONF_PATHNAME)
db = cvsdb.ConnectDatabase(cfg)
# Purge what must be purged.
if command in ('rebuild', 'purge'):
if verbose:
print "Purging commit info for repository root `%s'" % repository
@@ -253,24 +252,18 @@ def main(command, repository, revs=[], verbose=0, force=0):
sys.stderr.write("ERROR: " + str(e) + "\n")
sys.exit(1)
# 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)
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)
def _rev2int(r):
if r == 'HEAD':
@@ -288,7 +281,7 @@ def usage():
located at REPOS-PATH.
Usage: 1. %s [-v] rebuild REPOS-PATH
2. %s [-v] update REPOS-PATH [REV[:REV2]] [--force]
2. %s [-v] update REPOS-PATH [REV:[REV2]] [--force]
3. %s [-v] purge REPOS-PATH
1. Rebuild the commit database information for the repository located
@@ -337,6 +330,12 @@ if __name__ == '__main__':
sys.stderr.write('ERROR: unknown command %s\n' % command)
usage()
repository = args[2]
if not os.path.exists(repository):
sys.stderr.write('ERROR: could not find repository %s\n' % args[2])
usage()
repository = vclib.svn.canonicalize_rootpath(repository)
revs = []
if len(sys.argv) > 3:
if command == 'rebuild':
@@ -359,7 +358,6 @@ if __name__ == '__main__':
rev = None
try:
repository = vclib.svn.canonicalize_rootpath(args[2])
repository = cvsdb.CleanRepository(os.path.abspath(repository))
main(command, repository, revs, verbose, force)
except KeyboardInterrupt:

View File

@@ -1,54 +0,0 @@
#!/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,45 +0,0 @@
# -*-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 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 valid wsgi entry point.
#
# -----------------------------------------------------------------------
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
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.wsgi"
query.main(server, cfg, viewvc_base_url)
return []

View File

@@ -1,50 +0,0 @@
#!/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

@@ -1,41 +0,0 @@
# -*-python-*-
#
# 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
# 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
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
def application(environ, start_response):
server = sapi.WsgiServer(environ, start_response)
cfg = viewvc.load_config(CONF_PATHNAME, server)
viewvc.main(server, cfg)
return []

View File

@@ -106,47 +106,27 @@
##
#svn_roots =
## 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").
## 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.
##
## 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.
## You can specify multiple parent paths separated by commas or new lines.
##
## 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.
## 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.
##
## Example:
## root_parents = /opt/svn: svn,
## /opt/cvs: cvs
## root_parents = /opt/svn : svn,
## /opt/cvs : cvs
##
#root_parents =
@@ -156,7 +136,7 @@
## virtue of being the basenames of repositories found in the
## root_parents option locations.
##
## NOTE: This setting is ignored when root_as_url_component is enabled.
## Note: This setting is ignored when root_as_url_component is enabled.
##
## Example:
## default_root = cvsroot
@@ -263,14 +243,9 @@
## aren't installed in the executable search path, so here's where you can
## tell ViewVC where to find them.
##
## NOTE: Options with a "_dir" suffix are for configuring the
## directories in which certain programs live. Note that this might
## not be the same directory into which the program's installer dumped
## the whole program package -- we want the deepest directory in which
## the executable program itself resides ("C:\rcstools\bin\win32"
## rather than just "C:\rcstools", for example). The values of options
## whose names lack the "_dir" suffix should point to the actual
## program itself (such as "C:\Program Files\cvsnt\cvs.exe").
## NOTE: Options with a "_dir" suffix are for configuring the directories
## in which certain programs live; otherwise, the option value should
## point to the actual program.
## rcs_dir: Directory in which the RCS utilities are installed, used
@@ -328,16 +303,14 @@
## alternative to using the "root=" query key. If ViewVC is configured
## with multiple repositories, this results in more natural looking
## ViewVC URLs.
##
## NOTE: Enabling this option will break backwards compatibility with
## Note: Enabling this option will break backwards compatibility with
## any old ViewCVS URL which doesn't have an explicit "root" parameter.
##
#root_as_url_component = 1
## checkout_magic: Use checkout links with magic /*checkout*/ prefixes so
## checked out HTML pages can have working links to other repository files
##
## NOTE: This option is DEPRECATED and should not be used in new ViewVC
## Note: This option is DEPRECATED and should not be used in new ViewVC
## installations. Setting "default_file_view = co" achieves the same effect
##
#checkout_magic = 0
@@ -345,43 +318,7 @@
## allowed_views: List the ViewVC views which are enabled. Views not
## in this comma-delited list will not be served (or, will return an
## error on attempted access).
##
## Valid items for this list include: "annotate", "co", "diff", "markup",
## "roots", "tar".
##
## ----------+---------------------------------------------------------
## VIEW | DESCRIPTION
## ----------+---------------------------------------------------------
## annotate | The 'annotate' view shows the contents of a single
## | revision of a versioned file in exactly the same way as
## | the markup view, but with additional line-by-line
## | change attribution (the revision number, author, etc.
## | the most recent edit to that line of text as of the
## | displayed version).
## ----------+---------------------------------------------------------
## co | The 'co' (aka "checkout" or "download") view isn't
## | really a branded view at all, but allows for direct
## | downloading of the contents of a single revision of a
## | versioned file.
## ----------+---------------------------------------------------------
## diff | The 'diff' view displays line-based differences between
## | two revisions of a versioned file in a variety of
## | different user-selectable formats.
## ----------+---------------------------------------------------------
## markup | The 'markup' view shows the contents of a single
## | revision of a versioned file, with syntax highlighting
## | where possible and enabled. It can also optionally
## | show change log information for that revision of the
## | file.
## ----------+---------------------------------------------------------
## roots | The 'roots' view is a simple listing of the various
## | repositories which ViewVC has been configured to serve
## | to users.
## ----------+---------------------------------------------------------
## tar | The 'tar' view isn't a branded view, but generates
## | a GNU Tar archive file containing a single versioned
## | directory and its contents (recursively).
## ----------+---------------------------------------------------------
## Possible values: "annotate", "co", "diff", "markup", "roots", "tar"
##
#allowed_views = annotate, diff, markup, roots
@@ -410,7 +347,6 @@
## hide_cvsroot: Don't show the CVSROOT directory
## 1 Hide CVSROOT directory
## 0 Show CVSROOT directory
##
## NOTE: Someday this option may be removed in favor of letting
## individual authorizer plugin hide the CVSROOT.
##
@@ -421,8 +357,7 @@
## 0 - No mangling; markup un-mangled email addresses as hyperlinks
## 1 - Obfuscation (using entity encoding); no hyperlinking
## 2 - Data-dropping address truncation; no hyperlinking
##
## NOTE: this will not effect the display of versioned file contents, only
## Note: this will not effect the display of versioned file contents, only
## addresses that appear in version control metadata (e.g. log messages).
##
#mangle_email_addresses = 0
@@ -433,11 +368,9 @@
## ViewCVS URLs, but "co" has the advantage that it allows ViewVC to serve
## static HTML pages directly from a repository with working links
## to other repository files
##
## NOTE: Changing this option may break compatibility with existing
## Note: Changing this option may break compatibility with existing
## bookmarked URLs.
##
## ALSO NOTE: If you choose one of the "co" or "markup" views, be sure
## Also note: If you choose one of the "co" or "markup" views, be sure
## to enable it (via the allowed_views option)
##
#default_file_view = log
@@ -557,7 +490,7 @@
## allow_compress: Allow compression via gzip of output if the Browser
## accepts it (HTTP_ACCEPT_ENCODING contains "gzip").
##
## NOTE: this relies on Python's gzip module, which has proven to be
## Note: this relies on Python's gzip module, which has proven to be
## not-so-performant. Enabling this feature should reduce the overall
## transfer size of ViewVC's responses to the client's request, but
## will do so with a speed penalty.
@@ -572,8 +505,7 @@
## this config file resides; absolute paths may be used as well. If
## %lang% occurs in the pathname, then the selected language will be
## substituted.
##
## SEE ALSO: the [templates] configuration section, where you can
## See Also: the [templates] configuration section, where you can
## override templates on a per-view basis.
##
#template_dir = templates
@@ -585,16 +517,9 @@
## penalty, and from the "docroot" subdirectory of the directory
## specified by the "template_dir" option).
##
## NOTE: This option is evaluated outside the context of a particular
## root. Be careful when using per-root configuration to select an
## alternate template set as the default value for this option will
## still be based on the global default template set per 'template_dir'
## above, not on 'template_dir' as overridden for a given root.
##
#docroot =
## show_subdir_lastmod: Show last changelog message for CVS subdirectories
##
## NOTE: The current implementation makes many assumptions and may show
## the incorrect file at some times. The main assumption is that the
## last modified file has the newest filedate. But some CVS operations
@@ -603,19 +528,10 @@
## the last checkin was on the same tag as you are viewing. Enable
## this if you like the feature, but don't rely on correct results.
##
## SECURITY WARNING: Enabling this will currently leak unauthorized
## path names.
## ** WARNING: Enabling this will currently leak unauthorized path names **
##
#show_subdir_lastmod = 0
## show_roots_lastmod: In the root listing view, show the most recent
## modifications made to the root. (Subversion roots only.)
##
## NOTE: Enabling this feature will significantly reduce the
## performance of the root listing view.
##
#show_roots_lastmod = 0
## show_logs: Show the most recent log entry in directory listings.
##
#show_logs = 1
@@ -639,21 +555,10 @@
#short_log_len = 80
## enable_syntax_coloration: Should we colorize known file content
## syntaxes?
##
## NOTE: This feature requires the Pygments Python module
## (http://pygments.org) and works only when ViewVC can determine the
## MIME content type of the file whose contents it wishes to colorize.
## Use the 'mime_types_files' configuration option to specify MIME
## type mapping files useful for making that determination.
## syntaxes? [Requires Pygments Python module]
##
#enable_syntax_coloration = 1
## tabsize: The number of spaces into which tabstops are converted
## when viewing file contents.
##
#tabsize = 8
## detect_encoding: Should we attempt to detect versioned file
## character encodings? [Requires 'chardet' module, and is currently
## used only by the syntax coloration logic -- if enabled -- for the
@@ -671,6 +576,28 @@
##
#cvsgraph_conf = cvsgraph.conf
## allowed_cvsgraph_useropts: A list of settings used for cvsgraph's
## user-modifiable behavior which can be changed in the graph display.
## This value is a comma-delimited list of features, taken from the
## following set:
## invert - Display graph upside down
## branchbox - Add a branchbox at the tip of each branch
## show - Display user-selected classes of revisions
## rotate - Draw the tree left-to-right or top-to-bottom [*]
## limittags - Allow limit on the maximum number of tags displayed
##
## If this option is left unset, users will not be permitted to modify
## the graph display behavior.
##
## [*] WARNING: The 'rotate' option is known to cause some browsers to
## crash due, presumably, to the display of excessively wide images.
##
## Example:
## allowed_cvsgraph_useropts = limittags, show
##
##
#allowed_cvsgraph_useropts =
## use_re_search: Enable regular expression search of files in a directory.
##
## WARNING: Enabling this option can consume HUGE amounts of server
@@ -699,26 +626,6 @@
##
#log_pagesize = 0
## log_pagesextra: Maximum number of extra pages (based on
## log_pagesize) of revision log data to fetch and present to the user
## as additional options for display. Revision log information
## "beyond" this window is still accessible, but must be navigated to
## in multiple steps.
##
## Example:
## log_pagesize = 100
## log_pagesextra = 3
##
## For a versioned file with 1000 revisions, the above settings would
## present to the user the first 100 of those 1000 revisions, with
## links to three additional pages (the 200-299th revisions, 300-399th
## revisions, and 400-499th revisions) plus a link to the 500th
## revision. Following these links slides the display "window",
## showing the requested set of revisions plus links to three
## additional pages beyond those, and so on.
##
#log_pagesextra = 3
## limit_changes: Maximum number of changed paths shown per commit in
## the Subversion revision view and in query results. This is not a
## hard limit (the UI provides options to show all changed paths), but
@@ -747,7 +654,7 @@
## If %lang% occurs in the pathname, then the selected language will be
## substituted.
##
## NOTE: the selected language is defined by the "languages" item in the
## Note: the selected language is defined by the "languages" item in the
## [general] section, and based on the request's Accept-Language
## header.
##
@@ -813,8 +720,7 @@
#port = 3306
## database_name: ViewVC database name.
##
#database_name = ViewVC
##database_name = ViewVC
## user: Username of user with read/write privileges to the database
## specified by the 'database_name' configuration option.
@@ -839,14 +745,6 @@
## row_limit: Maximum number of rows returned by a given normal query
## to the database.
##
## NOTE: This limits the amount of data provided to ViewVC by the
## database. It is from this already-reduced data set that ViewVC
## builds the query response it presents to the user, which may or may
## not include still more limiting via the query form's 'limit'
## parameter. In other words, there is no value which the user can use
## in the query form's 'limit' parameter which will cause more data to
## be returned by the database for ViewVC to process.
##
#row_limit = 1000
## rss_row_limit: Maximum number of rows returned by a given query to
@@ -854,9 +752,6 @@
## that RSS readers tend to poll regularly for new data, you might want
## to keep this set to a conservative number.)
##
## See also the `NOTE' for the 'row_limit' option, which applies here
## as well.
##
#rss_row_limit = 100
## check_database_for_root: Check if the repository is found in the
@@ -910,16 +805,6 @@
## ViewVC options typically found in the base configuration section
## named CONFIGSECTION ("general", "option", etc.)
##
## NOTE: Per-vhost overrides may only be applied to the following
## sections:
##
## general
## options
## utilities
## templates
## cvsdb
## authz-*
##
## Here is an example:
##
## [vhosts]
@@ -949,19 +834,7 @@
## basename of a root path in root_parents. Options found in this new
## configuration section override for this one root the corresponding
## options found in the base configuration section CONFIGSECTION
## ("options", "authz-*", etc.) as interpreted after per-vhost
## overrides (if any) have been applied.
##
## NOTE: Per-root overrides may only be applied to the following
## sections:
##
## options
## utilities
## authz-*
##
## WARNING: Do not use per-root overrides if your ViewVC instance is
## served via the standalone.py server option! Doing so could cause
## ViewVC to be unable to function properly (or at all).
## ("options", "authz-*", etc.)
##
## Here is an example showing how to enable Subversion authz-based
## authorization for only the single root named "svnroot":
@@ -977,15 +850,8 @@
[authz-forbidden]
## The "forbidden" authorizer forbids access to repository modules,
## defined to be top-level subdirectories in a repository.
##
## NOTE: The options in this section apply only when the 'authorizer'
## option (in the [options] section) is set to 'forbidden'.
## forbidden: A comma-delimited list of patterns which match modules
## that ViewVC should hide from users.
##
## You can use a simple list of modules, or something more complex:
## defined to be top-level subdirectories in a repository. You can use
## a simple list of modules, or something more complex:
##
## *) The "!" can be used before a module to explicitly state that it
## is NOT forbidden. Whenever this form is seen, then all modules will
@@ -1040,12 +906,6 @@
## regular expressions. Directory paths will be terminated by a forward
## slash.
##
## NOTE: The options in this section apply only when the 'authorizer'
## option (in the [options] section) is set to 'forbiddenre'.
## forbiddenre: A comma-delimited list of regular expressions which
## match paths that ViewVC should hide from users.
##
## Like the "forbidden" authorizer...
##
## *) The "!" can be used before a module to explicitly state that it
@@ -1080,9 +940,6 @@
## The "svnauthz" authorizer uses a Subversion authz configuration file
## to determine access to repository paths.
##
## NOTE: The options in this section apply only when the 'authorizer'
## option (in the [options] section) is set to 'svnauthz'.
## authzfile: Specifies the location of the authorization rules file
## (using an absolute path).
@@ -1098,30 +955,3 @@
#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

@@ -0,0 +1,211 @@
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<title>ViewVC: 1.1.0 Release Notes</title>
<style>
.h2, .h3 {
padding: 0.25em 0em;
background: white;
}
.warning {
font-style: italic;
}
</style>
</head>
<body>
<h1>ViewVC 1.1.0 Release Notes</h1>
<div class="h2">
<h2 id="introduction">Introduction</h2>
<p>ViewVC 1.1.0 is the superset of all previous ViewVC releases.</p>
</div>
<div class="h2">
<h2 id="compatibility">Compatibility</h2>
<p>Each ViewVC release strives to maintain URL stability with previous
releases, and 1.1.0 is no exception. All URLs considered valid for
previous ViewVC releases should continue to work correctly in this
release, though possibly only via the use of HTTP redirects
(generated by ViewVC itself).</p>
<p>The commits database functionality has changed in ViewVC 1.1.0 in
way that breaks compatibility with prior ViewVC releases, but only
for new database instantiations. ViewVC 1.1.0 will continue to
understand (for both read and write operations) the previous
schema, so you are not required to rebuild your commits database
for ViewVC 1.1.0 compatibility. By default, new commits databases
created using the 1.1.0 version of the <code>make-database</code>
script will use a new database schema that is unreadable by
previous ViewVC versions. However, if you need a database which
can co-exist with a previous ViewVC version, you can use
the <code>--version=1.0</code> option
to <code>make-database</code>.</p>
<p>The ViewVC configuration files and template language have changed
dramatically. See the file <code>docs/upgrading-howto.html</code>
in the release for information on porting existing versions of
those items for use with ViewVC 1.1.0.</p>
</div>
<div class="h2">
<h2 id="compatibility">Features and Fixes</h2>
<div class="h3">
<h3 id="">Extensible path-based authorization w/ Subversion authz support</h3>
<p>In a nutshell, ViewVC is now able to do path-based authorization.
ViewVC 1.0 has a configuration option for naming 'forbidden'
modules, but it is really limited &mdash; it basically just makes a
universal decision about which top-level directories in every
hosted repository should be hidden by ViewVC. People want
more, and specifically requested that ViewVC learn how to honor
Subversion's authz files and semantics. So, along with some other
types of authorization approaches, that's what ViewVC 1.1 can now
do. If you are using mod_authz_svn with Apache today, or
svnserve's built-in authorization support, then you can now point
ViewVC to the same authz configuration file and have it honor the
access rules you've defined for your repositories.</p>
<p>Note that ViewVC does <strong>not</strong> handle authentication,
though. You'll need to configure your web server to demand login
credentials from users, which the web server itself can then hand
off to ViewVC for application against the authorization rules
you've defined.</p>
<p class="warning">WARNING: The root listing view does not consult the
authorization subsystem when deciding what roots to display to a
given user. If you need to protect your root names, consider
disabling it by removing <code>roots</code> from the set of views
listed in the
<code>allowed_views</code> configuration option.</p>
<p class="warning">WARNING: Support for path-based authorization is
incomplete in the experimental version control backend modules,
including the one that permits display of remote Subversion
repositories.</p>
</div>
<div class="h3">
<h3 id="">Subversion versioned properties display</h3>
<p>ViewVC 1.1 displays the properties that Subversion lets you store
on files and directories
(<code>svn:mime-type</code>, <code>svn:mergeinfo</code>,
<code>svn:ignore</code>, etc.). Directory properties are shown by
default at the bottom of that directory's entry listing. File
properties are displayed at the bottom of that file's
markup/annotate view.</p>
</div>
<div class="h3">
<h3 id="">Unified markup and annotation views</h3>
<p>The "markup" and "annotate" views in ViewVC now have a unified look
and feel (driven by a single EZT template). Both views support
syntax highlighting and Subversion file property display.</p>
</div>
<div class="h3">
<h3 id="">Unified, hassle-free Pygments-based syntax highlighting</h3>
<p>ViewVC 1.0 does syntax highlighting by working with GNU enscript, or
highlight, or php, or py2html &mdash; all these external tools just
to accomplish a single task. But they all do things in slightly
different ways. And if you configure them wrongly, you get strange
errors. <a href="http://www.pygments.org/">Pygments</a> (which is
also used by <a href="http://trac.edgewall.org/">Trac</a> for
syntax highlighting) is a Python package that requires no
configuration, is easier to use inside ViewVC, and so on. So
ViewVC 1.1 drops support for all those various old integrations,
and just uses Pygments for everything now. This change was about
developer and administrator sanity. There will be complaints, to
be sure, about how various color schemes differ and what file types
now are and aren't understood by the syntax highlighting engine,
but this change should vastly simplify the discussions of such
things.</p>
</div>
<div class="h3">
<h3 id="">Better MIME detection and handling</h3>
<p>ViewVC typically consults a MIME types file to determine what kind
of file a given document is, based on its filename extension
(<code>.jpg</code> = <code>image/jpeg</code>, &hellip;). But
Subversion lets you dictate a file's MIME type using
the <code>svn:mime-type</code> property. ViewVC now recognizes and
honors that property as the preferred source of a file's MIME type.
This can be disabled in the configuration, though, which might be
desirable if many of your Subversion-versioned files carry the
generic <code>application/octet-stream</code> MIME type that
Subversion uses by default for non-human-readable files.</p>
<p>Also, ViewVC now allows you to specify multiple MIME type mapping
files that you'd like it to consult when determine the MIME type of
files based on their extensions. This allows administrators to
easily define their own custom mappings for ViewVC's benefit
without potentially affecting the mappings used by other site
services.</p>
</div>
<div class="h3">
<h3 id="">Support for full content diffs</h3>
<p>ViewVC 1.1 expands the previously existing options of "colored
diff" and "long colored diff" with a new "full colored diff", which
shows the full contents of the changed file (instead of only the 3
or 15 lines of context shown via the older diff display types).</p>
</div>
<div class="h3">
<h3 id="">Support for per-root configuration overrides</h3>
<p>In ViewVC 1.1, you can setup configuration option overrides on a
per-root (per-repository) basis (if you need/care to do so). See
the comments in the <code>viewvc.conf.dist</code> file for more on
how to do this.</p>
</div>
<div class="h3">
<h3 id="">Optional email address obfuscation/mangling</h3>
<p>ViewVC can, when displaying revision metadata, munge strings that
look like email addresses to protect them from screen-scraping
spammers. For example, a log message that says, "Patch by:
cmpilato@red-bean.com" can optionally be displayed by ViewVC using
HTML entity encoding for the characters (a trick that causes no
visible change to the output, but that might confuse
unsophisticated spam bot crawlers) or as "Patch by: cmpilato@..."
(which isn't a complete email address at all, but might be enough
information for the human reading the log message to know who to
blame for the patch).</p>
</div>
<div class="h3">
<h3 id="">Pagination improvements</h3>
<p>The way that ViewVC splits directory and log views across pages has
been reworked. The old way was "Fetch all the information you can
find, then display only one page's worth." The new way is "Fetch
only what you need to display the page requested, plus a little bit
of border information." This provides a large performance
enhancement for the default sort orderings.</p>
</div>
</div>
</body>
</html>

View File

@@ -1,6 +1,6 @@
<html>
<head>
<title>ViewVC 1.1 Template Authoring Guide</title>
<title>ViewVC 1.0 Template Authoring Guide</title>
<style>
body {
background-color: rgb(180,193,205);
@@ -38,13 +38,13 @@ td {
</head>
<body>
<h1>ViewVC 1.1 Template Authoring Guide</h1>
<h1>ViewVC 1.0 Template Authoring Guide</h1>
<div class="h2">
<h2 id="introduction">Introduction</h2>
<p>This document represents an (unfinished) attempt at providing
instructions for how to customize ViewVC's HTML output via
documentation for how to customize ViewVC 1.0-dev's HTML output via
modification of its templates.</p>
</div>
@@ -598,6 +598,45 @@ td {
<td colspan="3">Includes all variables from the
<a href="#variables-common">COMMON</a> variable set</td>
</tr>
<tr class="varlevel1">
<td class="varname">gbbox</td>
<td>Boolean</td>
<td>Toggle generation of a branch box at the tip of all branches in
the revision graph.</td>
</tr>
<tr class="varlevel1">
<td class="varname">gflip</td>
<td>Boolean</td>
<td>Toggle the direction of the revision graph.</td>
</tr>
<tr class="varlevel1">
<td class="varname">gleft</td>
<td>Boolean</td>
<td>Toggle the orientation of the revision graph.</td>
</tr>
<tr class="varlevel1">
<td class="varname">gmaxtag</td>
<td>String</td>
<td>Number of tags per revision to display in the revision graph.</td>
</tr>
<tr class="varlevel1">
<td class="varname">graph_action</td>
<td>String</td>
<td>Form action URL for the graph customization form.</td>
</tr>
<tr class="varlevel1">
<td class="varname">graph_hidden_values</td>
<td>String</td>
<td>Hidden value name/value pairs for the graph customization form.</td>
</tr>
<tr class="varlevel1">
<td class="varname">gshow</td>
<td>String</td>
<td>Classes of revisions to show in the revision graph. Valid values
are <tt>all</tt> (all revision), <tt>inittagged</tt> (initial
revision(s) and tagged revisions), and <tt>tagged</tt> (tagged
revisions only).</td>
</tr>
<tr class="varlevel1">
<td class="varname">imagemap</td>
<td>String</td>
@@ -610,6 +649,37 @@ td {
<td>URL of the ViewVC revision graph image for the current
resource.</td>
</tr>
<tr class="varlevel1">
<td class="varname">opt_gbbox</td>
<td>Boolean</td>
<td>Specifies whether the user is allowed to toggle the generation
of branch boxes at the tip of all branches in the revision
graph.</td>
</tr>
<tr class="varlevel1">
<td class="varname">opt_gflip</td>
<td>Boolean</td>
<td>Specifies whether the user is allowed to toggle the direction
of the revision graph.</td>
</tr>
<tr class="varlevel1">
<td class="varname">opt_gleft</td>
<td>Boolean</td>
<td>Specifies whether the user is allowed to toggle the orientation
of the revision graph.</td>
</tr>
<tr class="varlevel1">
<td class="varname">opt_gmaxtag</td>
<td>Boolean</td>
<td>Specifies whether the user is allowed to configure the maximum
number of tags per revision show in the revision graph.</td>
</tr>
<tr class="varlevel1">
<td class="varname">opt_gshow</td>
<td>Boolean</td>
<td>Specifies whether the user is allowed to configure which
classes of revisions are shown in the revision graph.</td>
</tr>
</tbody>
</table>
</div>
@@ -726,22 +796,12 @@ td {
<td>Container</td>
<td>Container object for grouping information about the left file.</td>
</tr>
<tr class="varlevel2">
<td class="varname">left.ago</td>
<td>String</td>
<td>Text description of the time elapsed since <var>left.date</date>.</td>
</tr>
<tr class="varlevel2">
<td class="varname">left.annotate_href</td>
<td>String</td>
<td>URL of the ViewVC annotation view for the left file.
Valid only when <var>entries.pathtype</var> is <tt>file</tt>.</td>
</tr>
<tr class="varlevel2">
<td class="varname">left.author</td>
<td>String</td>
<td>Author of the revision of the left file.</td>
</tr>
<tr class="varlevel2">
<td class="varname">left.date</td>
<td>String</td>
@@ -759,11 +819,6 @@ td {
<td>URL to download the HEAD revision of the left file as
<tt>text/plain</tt>.</td>
</tr>
<tr class="varlevel2">
<td class="varname">left.log</td>
<td>String</td>
<td>Log message of the left file revision.</td>
</tr>
<tr class="varlevel2">
<td class="varname">left.path</td>
<td>String</td>
@@ -787,11 +842,6 @@ td {
current revision. Valid only when <var>roottype</var> is
<tt>svn</tt>.</td>
</tr>
<tr class="varlevel2">
<td class="varname">left.size</td>
<td>String</td>
<td>Size of the left file revision, in bytes. Subversion only.</td>
</tr>
<tr class="varlevel2">
<td class="varname">left.tag</td>
<td>String</td>
@@ -802,11 +852,6 @@ td {
<td>String</td>
<td>This is a URL for the markup view of the left file.</td>
</tr>
<tr class="varlevel1">
<td class="varname">patch_href</td>
<td>String</td>
<td>URL of the patch view for the file.</td>
</tr>
<tr class="varlevel1">
<td class="varname">raw_diff</td>
<td>String</td>
@@ -818,22 +863,12 @@ td {
<td>Container</td>
<td>Container object for grouping information about the right file.</td>
</tr>
<tr class="varlevel2">
<td class="varname">right.author</td>
<td>String</td>
<td>Author of the revision of the right file.</td>
</tr>
<tr class="varlevel2">
<td class="varname">right.annotate_href</td>
<td>String</td>
<td>URL of the ViewVC annotation view for the right file.
Valid only when <var>entries.pathtype</var> is <tt>file</tt>.</td>
</tr>
<tr class="varlevel2">
<td class="varname">right.author</td>
<td>String</td>
<td>Author of the revision of the right file.</td>
</tr>
<tr class="varlevel2">
<td class="varname">right.date</td>
<td>String</td>
@@ -851,11 +886,6 @@ td {
<td>URL to download the HEAD revision of the right file as
<tt>text/plain</tt>.</td>
</tr>
<tr class="varlevel2">
<td class="varname">right.log</td>
<td>String</td>
<td>Log message of the right file revision.</td>
</tr>
<tr class="varlevel2">
<td class="varname">right.path</td>
<td>String</td>
@@ -879,11 +909,6 @@ td {
current revision. Valid only when <var>roottype</var> is
<tt>svn</tt>.</td>
</tr>
<tr class="varlevel2">
<td class="varname">right.size</td>
<td>String</td>
<td>Size of the right file revision, in bytes. Subversion only.</td>
</tr>
<tr class="varlevel2">
<td class="varname">right.tag</td>
<td>String</td>
@@ -1826,14 +1851,6 @@ td {
<td>Indicates how query results are being sorted. Possible values:
<tt>date</tt>, <tt>author</tt>, and <tt>file</tt>.</td>
</tr>
<tr class="varlevel1">
<td class="varname">row_limit_reached</td>
<td>Boolean</td>
<td>Indicates whether the internal database row limit threshold (set
via the <code>cvsdb.row_limit</code>
and <code>cvsdb.rss_row_limit</code> configuration options) was
reached by the query.</td>
</tr>
<tr class="varlevel1">
<td class="varname">show_branch</td>
<td>Boolean</td>
@@ -2157,38 +2174,6 @@ td {
<td>List</td>
<td>Set of configured viewable repositories.</td>
</tr>
<tr class="varlevel2">
<td class="varname">roots.ago</td>
<td>String</td>
<td>Textual description of the time since <var>roots.date</var>.</td>
</tr>
<tr class="varlevel2">
<td class="varname">roots.author</td>
<td>String</td>
<td>Username of the last modifier of the root.</td>
</tr>
<tr class="varlevel2">
<td class="varname">root.date</td>
<td>String</td>
<td>Date (in UTC if not otherwise configured) of the last
modification of the root.</td>
</tr>
<tr class="varlevel2">
<td class="varname">roots.href</td>
<td>String</td>
<td>URL of root directory view for a configured repository.</td>
</tr>
<tr class="varlevel2">
<td class="varname">roots.log</td>
<td>String</td>
<td>Log message of last modification to the root.</td>
</tr>
<tr class="varlevel2">
<td class="varname">roots.log_href</td>
<td>String</td>
<td>URL of log revision view for the top-most (root) directory of
the root (repository).</td>
</tr>
<tr class="varlevel2">
<td class="varname">roots.name</td>
<td>String</td>
@@ -2202,24 +2187,17 @@ td {
configuration can have negative security implications. Use this
token at your own risk.</td>
</tr>
<tr class="varlevel2">
<td class="varname">roots.rev</td>
<td>String</td>
<td>Youngest revision of the root.</td>
</tr>
<tr class="varlevel2">
<td class="varname">roots.short_log</td>
<td>String</td>
<td>Log message of last modification to the root, truncated to
contain no more than the number of characters specified by
the <code>short_log_len</code> configuration option.</td>
</tr>
<tr class="varlevel2">
<td class="varname">roots.type</td>
<td>String</td>
<td>Version control type of a configured repository. Valid
values: <tt>cvs</tt>, <tt>svn</tt>.</td>
</tr>
<tr class="varlevel2">
<td class="varname">roots.href</td>
<td>String</td>
<td>URL of root directory view for a configured repository.</td>
</tr>
</tbody>
</table>

View File

@@ -348,7 +348,7 @@ td {
all = viewvc.*
[all-options]
allowed_views = annotate, diff, markup, tar
allow_tar = 1
</pre>
</blockquote>
@@ -358,7 +358,7 @@ allowed_views = annotate, diff, markup, tar
all = viewvc.*
[vhost-all/options]
allowed_views = annotate, diff, markup, tar
allow_tar = 1
</pre>
</blockquote>

View File

@@ -654,6 +654,35 @@ th.caption {
<td>depends</td>
<td><a href="#root-param"><code>root</code> parameter</a></td>
</tr>
<tr>
<td><code>gflip=<var>GFLIP</var></code></td>
<td>optional</td>
<td>"1" if the revisions in the graph should run
youngest-to-oldest; "0" for the reverse</td>
</tr>
<tr>
<td><code>gbbox=<var>GBBOX</var></code></td>
<td>optional</td>
<td>"1" if the revision graph should contain branch boxes at the
tip of each branch; "0" otherwise</td>
</tr>
<tr>
<td><code>gleft=<var>GLEFT</var></code></td>
<td>optional</td>
<td>"1" if the revision graph should be orientated left-to-right;
"0" otherwise</td>
</tr>
<tr>
<td><code>gmaxtag=<var>GMAXTAG</var></code></td>
<td>optional</td>
<td>maximum number of per-revision tags to show in the revision graph</td>
</tr>
<tr>
<td><code>gshow=<var>GSHOW</var></code></td>
<td>optional</td>
<td>"all", "inittagged", or "tagged" &mdash; user-selected classes
of revision to show in the graph</td>
</tr>
</table>
<h3 id="graphimg-view">Graph Image View</h3>
@@ -700,6 +729,35 @@ th.caption {
<td>depends</td>
<td><a href="#root-param"><code>root</code> parameter</a></td>
</tr>
<tr>
<td><code>gflip=<var>GFLIP</var></code></td>
<td>optional</td>
<td>"1" if the revisions in the graph should run
youngest-to-oldest; "0" for the reverse</td>
</tr>
<tr>
<td><code>gbbox=<var>GBBOX</var></code></td>
<td>optional</td>
<td>"1" if the revision graph should contain branch boxes at the
tip of each branch; "0" otherwise</td>
</tr>
<tr>
<td><code>gleft=<var>GLEFT</var></code></td>
<td>optional</td>
<td>"1" if the revision graph should be orientated left-to-right;
"0" otherwise</td>
</tr>
<tr>
<td><code>gmaxtag=<var>GMAXTAG</var></code></td>
<td>optional</td>
<td>maximum number of per-revision tags to show in the revision graph</td>
</tr>
<tr>
<td><code>gshow=<var>GSHOW</var></code></td>
<td>optional</td>
<td>"all", "inittagged", or "tagged" &mdash; user-selected classes
of revision to show in the graph</td>
</tr>
</table>
<h3 id="log-view">Log View</h3>
@@ -1192,6 +1250,13 @@ th.caption {
commands to back out changes instead showing a normal query result
page</td>
</tr>
<tr>
<td><code>limit=<var>LIMIT</var></code></td>
<td>optional</td>
<td>maximum number of file-revisions to process during a
query. Default is value of <code>row_limit</code> configuration
option</td>
</tr>
<tr>
<td><code>limit_changes=<var>LIMIT_CHANGES</var></code></td>
<td>optional</td>

View File

@@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*-python-*-
#
# Copyright (C) 1999-2010 The ViewCVS Group. All Rights Reserved.
# Copyright (C) 1999-2008 The ViewCVS Group. All Rights Reserved.
# Copyright (C) 2000 Curt Hagenlocher <curt@hagenlocher.org>
#
# By using this file, you agree to the terms and conditions set forth in
@@ -32,8 +32,9 @@ import os
import re
import time
import math
import cgi
import vclib
import sapi
re_includes = re.compile('\\#(\\s*)include(\\s*)"(.*?)"')
@@ -81,7 +82,7 @@ class HTMLBlameSource:
diff_url = None
if item.prev_rev:
diff_url = '%sr1=%s&amp;r2=%s' % (self.diff_url, item.prev_rev, item.rev)
thisline = link_includes(sapi.escape(item.text), self.repos,
thisline = link_includes(cgi.escape(item.text), self.repos,
self.path_parts, self.include_url)
return _item(text=thisline, line_number=item.line_number,
rev=item.rev, prev_rev=item.prev_rev,

View File

@@ -1,6 +1,6 @@
# -*-python-*-
#
# Copyright (C) 1999-2011 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
@@ -24,148 +24,45 @@ import fnmatch
#########################################################################
#
# CONFIGURATION
# -------------
#
# There are three forms of configuration:
#
# 1. edit the viewvc.conf created by the viewvc-install(er)
# 2. as (1), but delete all unchanged entries from viewvc.conf
# 3. do not use viewvc.conf and just edit the defaults in this file
# 1) edit the viewvc.conf created by the viewvc-install(er)
# 2) as (1), but delete all unchanged entries from viewvc.conf
# 3) do not use viewvc.conf and just edit the defaults in this file
#
# Most users will want to use (1), but there are slight speed advantages
# to the other two options. Note that viewvc.conf values are a bit easier
# to work with since it is raw text, rather than python literal values.
#
#
# A WORD ABOUT OPTION LAYERING/OVERRIDES
# --------------------------------------
#
# ViewVC has three "layers" of configuration options:
#
# 1. base configuration options - very basic configuration bits
# found in sections like 'general', 'options', etc.
# 2. vhost overrides - these options overlay/override the base
# configuration on a per-vhost basis.
# 3. root overrides - these options overlay/override the base
# configuration and vhost overrides on a per-root basis.
#
# Here's a diagram of the valid overlays/overrides:
#
# PER-ROOT PER-VHOST BASE
#
# ,-----------. ,-----------.
# | vhost-*/ | | |
# | general | --> | general |
# | | | |
# `-----------' `-----------'
# ,-----------. ,-----------. ,-----------.
# | root-*/ | | vhost-*/ | | |
# | options | --> | options | --> | options |
# | | | | | |
# `-----------' `-----------' `-----------'
# ,-----------. ,-----------. ,-----------.
# | root-*/ | | vhost-*/ | | |
# | templates | --> | templates | --> | templates |
# | | | | | |
# `-----------' `-----------' `-----------'
# ,-----------. ,-----------. ,-----------.
# | root-*/ | | vhost-*/ | | |
# | utilities | --> | utilities | --> | utilities |
# | | | | | |
# `-----------' `-----------' `-----------'
# ,-----------. ,-----------.
# | vhost-*/ | | |
# | cvsdb | --> | cvsdb |
# | | | |
# `-----------' `-----------'
# ,-----------. ,-----------. ,-----------.
# | root-*/ | | vhost-*/ | | |
# | authz-* | --> | authz-* | --> | authz-* |
# | | | | | |
# `-----------' `-----------' `-----------'
# ,-----------.
# | |
# | vhosts |
# | |
# `-----------'
# ,-----------.
# | |
# | query |
# | |
# `-----------'
#
# ### TODO: Figure out what this all means for the 'kv' stuff.
#
#########################################################################
class Config:
_base_sections = (
# Base configuration sections.
'authz-*',
'cvsdb',
'general',
'options',
'query',
'templates',
'utilities',
)
_force_multi_value = (
# Configuration values with multiple, comma-separated values.
'allowed_views',
'cvs_roots',
'kv_files',
'languages',
'mime_types_files',
'root_parents',
'svn_roots',
)
_allowed_overrides = {
# Mapping of override types to allowed overridable sections.
'vhost' : ('authz-*',
'cvsdb',
'general',
'options',
'templates',
'utilities',
),
'root' : ('authz-*',
'options',
'templates',
'utilities',
)
}
_sections = ('general', 'utilities', 'options', 'cvsdb', 'templates')
_force_multi_value = ('cvs_roots', 'svn_roots', 'languages', 'kv_files',
'root_parents', 'allowed_views', 'mime_types_files')
def __init__(self):
self.root_options_overlayed = 0
for section in self._base_sections:
if section[-1] == '*':
continue
for section in self._sections:
setattr(self, section, _sub_config())
def load_config(self, pathname, vhost=None):
"""Load the configuration file at PATHNAME, applying configuration
settings there as overrides to the built-in default values. If
VHOST is provided, also process the configuration overrides
specific to that virtual host."""
def load_config(self, pathname, vhost=None, rootname=None):
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():
if self._is_allowed_section(section, self._base_sections):
for section in self._sections:
if self.parser.has_section(section):
self._process_section(self.parser, section, section)
if vhost and self.parser.has_section('vhosts'):
self._process_vhost(self.parser, vhost)
if rootname:
self._process_root_options(self.parser, rootname)
def load_kv_files(self, language):
"""Process the key/value (kv) files specified in the
configuration, merging their values into the configuration as
dotted heirarchical items."""
kv = _sub_config()
for fname in self.general.kv_files:
@@ -178,7 +75,6 @@ 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):
@@ -196,12 +92,10 @@ class Config:
return kv
def path(self, path):
"""Return PATH relative to the config file directory."""
"""Return path relative to the config file directory"""
return os.path.join(self.base, path)
def _process_section(self, parser, section, subcfg_name):
if not hasattr(self, subcfg_name):
setattr(self, subcfg_name, _sub_config())
sc = getattr(self, subcfg_name)
for opt in parser.options(section):
@@ -214,54 +108,25 @@ class Config:
except ValueError:
pass
### FIXME: This feels like unnecessary depth of knowledge for a
### semi-generic configuration object.
if opt == 'cvs_roots' or opt == 'svn_roots':
value = _parse_roots(opt, value)
setattr(sc, opt, value)
def _is_allowed_section(self, section, allowed_sections):
"""Return 1 iff SECTION is an allowed section, defined as being
explicitly present in the ALLOWED_SECTIONS list or present in the
form 'someprefix-*' in that list."""
for allowed_section in allowed_sections:
if allowed_section[-1] == '*':
if _startswith(section, allowed_section[:-1]):
return 1
elif allowed_section == section:
return 1
return 0
def _is_allowed_override(self, sectype, secspec, section):
"""Test if SECTION is an allowed override section for sections of
type SECTYPE ('vhosts' or 'root', currently) and type-specifier
SECSPEC (a rootname or vhostname, currently). If it is, return
the overridden base section name. If it's not an override section
at all, return None. And if it's an override section but not an
allowed one, raise IllegalOverrideSection."""
cv = '%s-%s/' % (sectype, secspec)
lcv = len(cv)
if section[:lcv] != cv:
return None
base_section = section[lcv:]
if self._is_allowed_section(base_section,
self._allowed_overrides[sectype]):
return base_section
raise IllegalOverrideSection(sectype, section)
def _process_vhost(self, parser, vhost):
# Find a vhost name for this VHOST, if any (else, we've nothing to do).
# find a vhost name for this vhost, if any (if not, we've nothing to do)
canon_vhost = self._find_canon_vhost(parser, vhost)
if not canon_vhost:
return
# Overlay any option sections associated with this vhost name.
# overlay any option sections associated with this vhost name
cv = 'vhost-%s/' % (canon_vhost)
lcv = len(cv)
for section in parser.sections():
base_section = self._is_allowed_override('vhost', canon_vhost, section)
if base_section:
if section[:lcv] == cv:
base_section = section[lcv:]
if base_section not in self._sections:
raise IllegalOverrideSection('vhost', section)
self._process_section(parser, section, base_section)
def _find_canon_vhost(self, parser, vhost):
@@ -276,29 +141,26 @@ class Config:
return None
def _process_root_options(self, parser, rootname):
rn = 'root-%s/' % (rootname)
lrn = len(rn)
for section in parser.sections():
if section[:lrn] == rn:
base_section = section[lrn:]
if base_section in self._sections:
if base_section == 'general':
raise IllegalOverrideSection('root', section)
self._process_section(parser, section, base_section)
elif _startswith(base_section, 'authz-'):
pass
else:
raise IllegalOverrideSection('root', section)
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."""
did_overlay = 0
"Overly per-root options atop the existing option set."
if not self.conf_path:
return
for section in self.parser.sections():
base_section = self._is_allowed_override('root', rootname, section)
if base_section:
# We can currently only deal with root overlays happening
# once, so check that we've not yet done any overlaying of
# per-root options.
assert(self.root_options_overlayed == 0)
self._process_section(self.parser, section, base_section)
did_overlay = 1
# If we actually did any overlaying, remember this fact so we
# don't do it again later.
if did_overlay:
self.root_options_overlayed = 1
self._process_root_options(self.parser, rootname)
def _get_parser_items(self, parser, section):
"""Basically implement ConfigParser.items() for pre-Python-2.3 versions."""
@@ -309,67 +171,23 @@ class Config:
for option in parser.options(section):
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)
def get_authorizer_params(self, authorizer, rootname=None):
if not self.conf_path:
return None, {}
return {}
# 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:
if section == 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)."""
params = {}
if authorizer is None:
authorizer = self.options.authorizer
if authorizer:
authz_section = 'authz-%s' % (self.options.authorizer)
if hasattr(self, authz_section):
sub_config = getattr(self, authz_section)
for attr in dir(sub_config):
params[attr] = getattr(sub_config, attr)
if rootname:
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 params
def set_defaults(self):
@@ -420,21 +238,19 @@ class Config:
self.options.template_dir = "templates"
self.options.docroot = None
self.options.show_subdir_lastmod = 0
self.options.show_roots_lastmod = 0
self.options.show_logs = 1
self.options.show_log_in_markup = 1
self.options.cross_copies = 1
self.options.cross_copies = 0
self.options.use_localtime = 0
self.options.short_log_len = 80
self.options.enable_syntax_coloration = 1
self.options.tabsize = 8
self.options.detect_encoding = 0
self.options.use_cvsgraph = 0
self.options.cvsgraph_conf = "cvsgraph.conf"
self.options.allowed_cvsgraph_useropts = []
self.options.use_re_search = 0
self.options.dir_pagesize = 0
self.options.log_pagesize = 0
self.options.log_pagesextra = 3
self.options.limit_changes = 100
self.templates.diff = None
@@ -460,8 +276,6 @@ 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

@@ -1,6 +1,6 @@
# -*-python-*-
#
# Copyright (C) 1999-2011 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
@@ -38,12 +38,13 @@ error = "cvsdb error"
## complient database interface
class CheckinDatabase:
def __init__(self, host, port, user, passwd, database):
def __init__(self, host, port, user, passwd, database, row_limit):
self._host = host
self._port = port
self._user = user
self._passwd = passwd
self._database = database
self._row_limit = row_limit
self._version = None
## database lookup caches
@@ -168,9 +169,6 @@ class CheckinDatabase:
return list
def GetCommitsTable(self):
return self._version >= 1 and 'commits' or 'checkins'
def GetTableList(self):
sql = "SHOW TABLES"
cursor = self.db.cursor()
@@ -311,7 +309,8 @@ class CheckinDatabase:
minus_count = commit.GetMinusCount() or '0'
description_id = self.GetDescriptionID(commit.GetDescription())
sql = "REPLACE INTO %s" % (self.GetCommitsTable())
commits_table = self._version >= 1 and 'commits' or 'checkins'
sql = "REPLACE INTO %s" % (commits_table)
sql = sql + \
" (type,ci_when,whoid,repositoryid,dirid,fileid,revision,"\
" stickytag,branchid,addedlines,removedlines,descid)"\
@@ -352,17 +351,9 @@ class CheckinDatabase:
match = " LIKE "
elif query_entry.match == "glob":
match = " REGEXP "
# Use fnmatch to translate the glob into a regular
# expression. Sadly, we have to account for the fact
# that in Python 2.6, fnmatch.translate() started
# sticking '\Z(?ms)' at the end of the regular
# expression instead of just '$', and doesn't prepend
# the '^'.
# use fnmatch to translate the glob into a regexp
data = fnmatch.translate(data)
if data[0] != '^':
data = '^' + data
if data[-7:] == '\Z(?ms)':
data = data[:-7] + '$'
if data[0] != '^': data = '^' + data
elif query_entry.match == "regex":
match = " REGEXP "
elif query_entry.match == "notregex":
@@ -372,8 +363,8 @@ class CheckinDatabase:
return "(%s)" % (string.join(sqlList, " OR "))
def CreateSQLQueryString(self, query, detect_leftover=0):
commits_table = self.GetCommitsTable()
def CreateSQLQueryString(self, query):
commits_table = self._version >= 1 and 'commits' or 'checkins'
tableList = [(commits_table, None)]
condList = []
@@ -453,14 +444,13 @@ class CheckinDatabase:
conditions = string.join(joinConds + condList, " AND ")
conditions = conditions and "WHERE %s" % conditions
## apply the query's row limit, if any (so we avoid really
## slamming a server with a large database)
## limit the number of rows requested or we could really slam
## a server with a large database
limit = ""
if query.limit:
if detect_leftover:
limit = "LIMIT %s" % (str(query.limit + 1))
else:
limit = "LIMIT %s" % (str(query.limit))
limit = "LIMIT %s" % (str(query.limit))
elif self._row_limit:
limit = "LIMIT %s" % (str(self._row_limit))
sql = "SELECT %s.* FROM %s %s %s %s" \
% (commits_table, tables, conditions, order_by, limit)
@@ -468,20 +458,14 @@ class CheckinDatabase:
return sql
def RunQuery(self, query):
sql = self.CreateSQLQueryString(query, 1)
sql = self.CreateSQLQueryString(query)
cursor = self.db.cursor()
cursor.execute(sql)
query.SetExecuted()
row_count = 0
while 1:
row = cursor.fetchone()
if not row:
break
row_count = row_count + 1
if query.limit and (row_count > query.limit):
query.SetLimitReached()
break
(dbType, dbCI_When, dbAuthorID, dbRepositoryID, dbDirID,
dbFileID, dbRevision, dbStickyTag, dbBranchID, dbAddedLines,
@@ -520,12 +504,13 @@ class CheckinDatabase:
if file_id == None:
return None
commits_table = self._version >= 1 and 'commits' or 'checkins'
sql = "SELECT * FROM %s WHERE "\
" repositoryid=%%s "\
" AND dirid=%%s"\
" AND fileid=%%s"\
" AND revision=%%s"\
% (self.GetCommitsTable())
% (commits_table)
sql_args = (repository_id, dir_id, file_id, commit.GetRevision())
cursor = self.db.cursor()
@@ -542,9 +527,10 @@ class CheckinDatabase:
def sql_delete(self, table, key, value, keep_fkey = None):
sql = "DELETE FROM %s WHERE %s=%%s" % (table, key)
sql_args = (value, )
commits_table = self._version >= 1 and 'commits' or 'checkins'
if keep_fkey:
sql += " AND %s NOT IN (SELECT %s FROM %s WHERE %s = %%s)" \
% (key, keep_fkey, self.GetCommitsTable(), keep_fkey)
% (key, keep_fkey, commits_table, keep_fkey)
sql_args = (value, value)
cursor = self.db.cursor()
cursor.execute(sql, sql_args)
@@ -783,9 +769,8 @@ class QueryEntry:
self.data = data
self.match = match
## CheckinDatabaseQuery is an object which contains the search
## parameters for a query to the Checkin Database and -- after the
## query is executed -- the data returned by the query.
## CheckinDatabaseQueryData is a object which contains the search parameters
## for a query to the CheckinDatabase
class CheckinDatabaseQuery:
def __init__(self):
## sorting
@@ -805,8 +790,7 @@ class CheckinDatabaseQuery:
## limit on number of rows to return
self.limit = None
self.limit_reached = 0
## list of commits -- filled in by CVS query
self.commit_list = []
@@ -814,9 +798,6 @@ class CheckinDatabaseQuery:
## are added
self.commit_cb = None
## has this query been run?
self.executed = 0
def SetRepository(self, repository, match = "exact"):
self.repository_list.append(QueryEntry(repository, match))
@@ -862,20 +843,6 @@ class CheckinDatabaseQuery:
def AddCommit(self, commit):
self.commit_list.append(commit)
def SetExecuted(self):
self.executed = 1
def SetLimitReached(self):
self.limit_reached = 1
def GetLimitReached(self):
assert self.executed
return self.limit_reached
def GetCommitList(self):
assert self.executed
return self.commit_list
##
## entrypoints
@@ -894,7 +861,7 @@ def ConnectDatabase(cfg, readonly=0):
user = cfg.cvsdb.user
passwd = cfg.cvsdb.passwd
db = CheckinDatabase(cfg.cvsdb.host, cfg.cvsdb.port, user, passwd,
cfg.cvsdb.database_name)
cfg.cvsdb.database_name, cfg.cvsdb.row_limit)
db.Connect()
return db

View File

@@ -347,7 +347,7 @@ class Template:
for_names = [ ]
if base_format:
program.append((self._cmd_format, _formatters[base_format]))
program.append((self._cmd_format, _printers[base_format]))
for i in range(len(parts)):
piece = parts[i]
@@ -405,13 +405,13 @@ class Template:
elif cmd == 'format':
if args[1][0]:
# argument is a variable reference
formatter = args[1]
printer = args[1]
else:
# argument is a string constant referring to built-in formatter
formatter = _formatters.get(args[1][1])
if not formatter:
# argument is a string constant referring to built-in printer
printer = _printers.get(args[1][1])
if not printer:
raise UnknownFormatConstantError(str(args[1:]))
program.append((self._cmd_format, formatter))
program.append((self._cmd_format, printer))
# remember the cmd, current pos, args, and a section placeholder
stack.append([cmd, len(program), args[1:], None])
@@ -465,13 +465,13 @@ class Template:
except TypeError:
raise Exception("Unprintable value type for '%s'" % (str(valrefs[0][0])))
def _cmd_format(self, formatter, ctx):
if type(formatter) is TupleType:
formatter = _get_value(formatter, ctx)
ctx.formatters.append(formatter)
def _cmd_format(self, printer, ctx):
if type(printer) is TupleType:
printer = _get_value(printer, ctx)
ctx.printers.append(printer)
def _cmd_end_format(self, valref, ctx):
ctx.formatters.pop()
ctx.printers.pop()
def _cmd_include(self, (valref, reader), ctx):
fname = _get_value(valref, ctx)
@@ -637,23 +637,14 @@ def _get_value((refname, start, rest), ctx):
# string or a sequence
return ob
def _print_formatted(formatters, ctx, chunk):
# print chunk to ctx.fp after running it sequentially through formatters
for formatter in formatters:
chunk = formatter(chunk)
ctx.fp.write(chunk)
def _write_value(value, args, ctx):
# value is a callback function, generates its own output
if callable(value):
apply(value, [ctx] + list(args))
return
# squirrel away formatters in case one of them recursively calls
# _write_value() -- we'll use them (in reverse order) to format our
# output.
formatters = ctx.formatters[:]
formatters.reverse()
# pop printer in case it recursively calls _write_value
printer = ctx.printers.pop()
try:
# if the value has a 'read' attribute, then it is a stream: copy it
@@ -662,7 +653,7 @@ def _write_value(value, args, ctx):
chunk = value.read(16384)
if not chunk:
break
_print_formatted(formatters, ctx, chunk)
printer(ctx, chunk)
# value is a substitution pattern
elif args:
@@ -675,16 +666,14 @@ def _write_value(value, args, ctx):
piece = args[idx]
else:
piece = '<undef>'
_print_formatted(formatters, ctx, piece)
printer(ctx, piece)
# plain old value, write to output
else:
_print_formatted(formatters, ctx, value)
printer(ctx, value)
finally:
# restore our formatters
formatters.reverse()
ctx.formatters = formatters
ctx.printers.append(printer)
class TemplateData:
@@ -726,7 +715,7 @@ class Context:
"""A container for the execution context"""
def __init__(self, fp):
self.fp = fp
self.formatters = []
self.printers = []
def write(self, value, args=()):
_write_value(value, args, self)
@@ -839,26 +828,20 @@ class BaseUnavailableError(EZTException):
class UnknownFormatConstantError(EZTException):
"""The format specifier is an unknown value."""
def _raw_formatter(s):
return s
def _raw_printer(ctx, s):
ctx.fp.write(s)
def _html_printer(ctx, s):
ctx.fp.write(cgi.escape(s))
def _html_formatter(s):
return cgi.escape(s)
def _uri_printer(ctx, s):
ctx.fp.write(urllib.quote(s))
def _xml_formatter(s):
s = s.replace('&', '&#x26;')
s = s.replace('<', '&#x3C;')
s = s.replace('>', '&#x3E;')
return s
def _uri_formatter(s):
return urllib.quote(s)
_formatters = {
FORMAT_RAW : _raw_formatter,
FORMAT_HTML : _html_formatter,
FORMAT_XML : _xml_formatter,
FORMAT_URI : _uri_formatter,
_printers = {
FORMAT_RAW : _raw_printer,
FORMAT_HTML : _html_printer,
FORMAT_XML : _html_printer,
FORMAT_URI : _uri_printer,
}
# --- standard test environment ---

View File

@@ -1,6 +1,6 @@
# -*-python-*-
#
# Copyright (C) 1999-2010 The ViewCVS Group. All Rights Reserved.
# Copyright (C) 1999-2006 The ViewCVS Group. All Rights Reserved.
#
# By using this file, you agree to the terms and conditions set forth in
# the LICENSE.html file which can be found at the top level of the ViewVC
@@ -20,7 +20,7 @@ import difflib
import sys
import re
import ezt
import sapi
import cgi
def sidebyside(fromlines, tolines, context):
"""Generate side by side diff"""
@@ -49,18 +49,18 @@ def _mdiff_split(flag, (line_number, text)):
while True:
m = _re_mdiff.search(text, pos)
if not m:
segments.append(_item(text=sapi.escape(text[pos:]), type=None))
segments.append(_item(text=cgi.escape(text[pos:]), type=None))
break
if m.start() > pos:
segments.append(_item(text=sapi.escape(text[pos:m.start()]), type=None))
segments.append(_item(text=cgi.escape(text[pos:m.start()]), type=None))
if m.group(1) == "+":
segments.append(_item(text=sapi.escape(m.group(2)), type="add"))
segments.append(_item(text=cgi.escape(m.group(2)), type="add"))
elif m.group(1) == "-":
segments.append(_item(text=sapi.escape(m.group(2)), type="remove"))
segments.append(_item(text=cgi.escape(m.group(2)), type="remove"))
elif m.group(1) == "^":
segments.append(_item(text=sapi.escape(m.group(2)), type="change"))
segments.append(_item(text=cgi.escape(m.group(2)), type="change"))
pos = m.end()
@@ -166,12 +166,12 @@ def _differ_split(row, guide):
for m in _re_differ.finditer(guide, pos):
if m.start() > pos:
segments.append(_item(text=sapi.escape(line[pos:m.start()]), type=None))
segments.append(_item(text=sapi.escape(line[m.start():m.end()]),
segments.append(_item(text=cgi.escape(line[pos:m.start()]), type=None))
segments.append(_item(text=cgi.escape(line[m.start():m.end()]),
type="change"))
pos = m.end()
segments.append(_item(text=sapi.escape(line[pos:]), type=None))
segments.append(_item(text=cgi.escape(line[pos:]), type=None))
return _item(gap=ezt.boolean(gap), type=type, segments=segments,
left_number=left_number, right_number=right_number)

View File

@@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*-python-*-
#
# Copyright (C) 1999-2010 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
@@ -217,9 +217,8 @@ def decode_command(cmd):
else:
return "exact"
def form_to_cvsdb_query(cfg, form_data):
def form_to_cvsdb_query(form_data):
query = cvsdb.CreateCheckinQuery()
query.SetLimit(cfg.cvsdb.row_limit)
if form_data.repository:
for cmd, str in listparse_string(form_data.repository):
@@ -276,30 +275,8 @@ def prev_rev(rev):
return string.join(r, '.')
def is_forbidden(cfg, cvsroot_name, module):
'''Return 1 if MODULE in CVSROOT_NAME is forbidden; return 0 otherwise.'''
# CVSROOT_NAME might be None here if the data comes from an
# unconfigured root. This interfaces doesn't care that the root
# isn't configured, but if that's the case, it will consult only
# 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()
# 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
# forbiddenness per the PARAMS as expected.
if not authorizer:
return 0
if authorizer != 'forbidden':
raise Exception("The 'forbidden' authorizer is the only one supported "
"by this interface. The '%s' root is configured to "
"use a different one." % (cvsroot_name))
forbidden = params.get('forbidden', '')
auth_params = cfg.get_authorizer_params('forbidden', cvsroot_name)
forbidden = auth_params.get('forbidden', '')
forbidden = map(string.strip, filter(None, string.split(forbidden, ',')))
default = 0
for pat in forbidden:
@@ -313,7 +290,11 @@ 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 string.replace(server.escape(desc), '\n', '<br />') or ''
if desc:
ob.log = string.replace(server.escape(desc), '\n', '<br />')
else:
ob.log = '&nbsp;'
for commit in files:
repository = commit.GetRepository()
@@ -347,10 +328,9 @@ 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, or we don't have a VIEWVC_LINK, then
## don't make the link.
if cvsroot_name and viewvc_link:
## 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)
@@ -378,27 +358,23 @@ def build_commit(server, cfg, desc, files, cvsroots, viewvc_link):
return ob
def run_query(server, cfg, form_data, viewvc_link):
query = form_to_cvsdb_query(cfg, form_data)
query = form_to_cvsdb_query(form_data)
db = cvsdb.ConnectDatabaseReadOnly(cfg)
db.RunQuery(query)
commit_list = query.GetCommitList()
if not commit_list:
return [ ], 0
row_limit_reached = query.GetLimitReached()
if not query.commit_list:
return [ ]
commits = [ ]
files = [ ]
cvsroots = {}
viewvc.expand_root_parents(cfg)
rootitems = cfg.general.svn_roots.items() + cfg.general.cvs_roots.items()
for key, value in rootitems:
cvsroots[cvsdb.CleanRepository(value)] = key
current_desc = commit_list[0].GetDescription()
for commit in commit_list:
current_desc = query.commit_list[0].GetDescription()
for commit in query.commit_list:
desc = commit.GetDescription()
if current_desc == desc:
files.append(commit)
@@ -421,7 +397,7 @@ def run_query(server, cfg, form_data, viewvc_link):
return len(commit.files) > 0
commits = filter(_only_with_files, commits)
return commits, row_limit_reached
return commits
def main(server, cfg, viewvc_link):
try:
@@ -430,32 +406,29 @@ def main(server, cfg, viewvc_link):
form_data = FormData(form)
if form_data.valid:
commits, row_limit_reached = run_query(server, cfg,
form_data, viewvc_link)
commits = run_query(server, cfg, form_data, viewvc_link)
query = None
else:
commits = [ ]
row_limit_reached = 0
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,
'vsn' : viewvc.__version__,
'repository' : server.escape(form_data.repository),
'branch' : server.escape(form_data.branch),
'directory' : server.escape(form_data.directory),
'file' : server.escape(form_data.file),
'who' : server.escape(form_data.who),
'docroot' : docroot,
'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,
'row_limit_reached' : ezt.boolean(row_limit_reached),
'commits' : commits,
'num_commits' : len(commits),
'rss_href' : None,

View File

@@ -1,6 +1,6 @@
# -*-python-*-
#
# Copyright (C) 1999-2010 The ViewCVS Group. All Rights Reserved.
# Copyright (C) 1999-2006 The ViewCVS Group. All Rights Reserved.
#
# By using this file, you agree to the terms and conditions set forth in
# the LICENSE.html file which can be found at the top level of the ViewVC
@@ -20,27 +20,13 @@ import string
import os
import sys
import re
import cgi
# global server object. It will be either a CgiServer, a WsgiServer,
# or a proxy to an AspServer or ModPythonServer object.
# global server object. It will be either a CgiServer or a proxy to
# an AspServer or ModPythonServer object.
server = None
# Simple HTML string escaping. Note that we always escape the
# double-quote character -- ViewVC shouldn't ever need to preserve
# that character as-is, and sometimes needs to embed escaped values
# into HTML attributes.
def escape(s):
s = str(s)
s = string.replace(s, '&', '&amp;')
s = string.replace(s, '>', '&gt;')
s = string.replace(s, '<', '&lt;')
s = string.replace(s, '"', "&quot;")
return s
class Server:
def __init__(self):
self.pageGlobals = {}
@@ -48,9 +34,6 @@ class Server:
def self(self):
return self
def escape(self, s):
return escape(s)
def close(self):
pass
@@ -146,6 +129,9 @@ class CgiServer(Server):
global server
server = self
global cgi
import cgi
def addheader(self, name, value):
self.headers.append((name, value))
@@ -174,6 +160,9 @@ class CgiServer(Server):
self.header(status='301 Moved')
sys.stdout.write('This document is located <a href="%s">here</a>.\n' % url)
def escape(self, s, quote = None):
return cgi.escape(s, quote)
def getenv(self, name, value=None):
ret = os.environ.get(name, value)
if self.iis and name == 'PATH_INFO' and ret:
@@ -186,7 +175,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)
@@ -198,63 +187,6 @@ class CgiServer(Server):
return sys.stdout
class WsgiServer(Server):
def __init__(self, environ, start_response):
Server.__init__(self)
self._environ = environ
self._start_response = start_response;
self._headers = []
self._wsgi_write = None
self.headerSent = False
global server
server = self
global cgi
import cgi
def addheader(self, name, value):
self._headers.append((name, value))
def header(self, content_type='text/html; charset=UTF-8', status=None):
if not status:
status = "200 OK"
if not self.headerSent:
self.headerSent = True
self._headers.insert(0, ("Content-Type", content_type),)
self._wsgi_write = self._start_response("%s" % status, self._headers)
def redirect(self, url):
"""Redirect client to url. This discards any data that has been queued
to be sent to the user. But there should never by any anyway.
"""
self.addheader('Location', url)
self.header(status='301 Moved')
self._wsgi_write('This document is located <a href="%s">here</a>.' % url)
def getenv(self, name, value=None):
return self._environ.get(name, value)
def params(self):
return cgi.parse(environ=self._environ, fp=self._environ["wsgi.input"])
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"], headers,
outerboundary, self._environ, keep_blank_values,
strict_parsing)
def write(self, s):
self._wsgi_write(s)
def flush(self):
pass
def file(self):
return File(self)
class AspServer(ThreadedServer):
def __init__(self, Server, Request, Response, Application):
ThreadedServer.__init__(self)
@@ -287,6 +219,9 @@ class AspServer(ThreadedServer):
def redirect(self, url):
self.response.Redirect(url)
def escape(self, s, quote = None):
return self.server.HTMLEncode(str(s))
def getenv(self, name, value = None):
ret = self.request.ServerVariables(name)()
if not type(ret) is types.UnicodeType:
@@ -348,6 +283,9 @@ class ModPythonServer(ThreadedServer):
self.request = request
self.headerSent = 0
global cgi
import cgi
def addheader(self, name, value):
self.request.headers_out.add(name, value)
@@ -370,6 +308,9 @@ class ModPythonServer(ThreadedServer):
self.request.write("You are being redirected to <a href=\"%s\">%s</a>"
% (url, url))
def escape(self, s, quote = None):
return cgi.escape(s, quote)
def getenv(self, name, value = None):
try:
return self.request.subprocess_env[name]

View File

@@ -1,6 +1,6 @@
# -*-python-*-
#
# Copyright (C) 2006-2010 The ViewCVS Group. All Rights Reserved.
# Copyright (C) 2006-2008 The ViewCVS Group. All Rights Reserved.
#
# By using this file, you agree to the terms and conditions set forth in
# the LICENSE.html file which can be found at the top level of the ViewVC
@@ -29,15 +29,7 @@ class GenericViewVCAuthorizer:
def check_root_access(self, rootname):
"""Return 1 iff the associated username is permitted to read ROOTNAME."""
pass
def check_universal_access(self, rootname):
"""Return 1 if the associated username is permitted to read every
path in the repository at every revision, 0 if the associated
username is prohibited from reading any path in the repository, or
None if no such determination can be made (perhaps because the
cost of making it is too great)."""
pass
def check_path_access(self, rootname, path_parts, pathtype, rev=None):
"""Return 1 iff the associated username is permitted to read
revision REV of the path PATH_PARTS (of type PATHTYPE) in
@@ -52,9 +44,6 @@ class ViewVCAuthorizer(GenericViewVCAuthorizer):
"""The uber-permissive authorizer."""
def check_root_access(self, rootname):
return 1
def check_universal_access(self, rootname):
return 1
def check_path_access(self, rootname, path_parts, pathtype, rev=None):
return 1

View File

@@ -1,6 +1,6 @@
# -*-python-*-
#
# Copyright (C) 2006-2010 The ViewCVS Group. All Rights Reserved.
# Copyright (C) 2006-2008 The ViewCVS Group. All Rights Reserved.
#
# By using this file, you agree to the terms and conditions set forth in
# the LICENSE.html file which can be found at the top level of the ViewVC
@@ -23,14 +23,7 @@ class ViewVCAuthorizer(vcauth.GenericViewVCAuthorizer):
def check_root_access(self, rootname):
return 1
def check_universal_access(self, rootname):
# If there aren't any forbidden paths, we can grant universal read
# access. Otherwise, we make no claim.
if not self.forbidden:
return 1
return None
def check_path_access(self, rootname, path_parts, pathtype, rev=None):
# No path? No problem.
if not path_parts:

View File

@@ -1,6 +1,6 @@
# -*-python-*-
#
# Copyright (C) 2008-2010 The ViewCVS Group. All Rights Reserved.
# Copyright (C) 2008 The ViewCVS Group. All Rights Reserved.
#
# By using this file, you agree to the terms and conditions set forth in
# the LICENSE.html file which can be found at the top level of the ViewVC
@@ -46,13 +46,6 @@ class ViewVCAuthorizer(vcauth.GenericViewVCAuthorizer):
def check_root_access(self, rootname):
return self._check_root_path_access(rootname)
def check_universal_access(self, rootname):
# If there aren't any forbidden regexps, we can grant universal
# read access. Otherwise, we make no claim.
if not self.forbidden:
return 1
return None
def check_path_access(self, rootname, path_parts, pathtype, rev=None):
root_path = rootname
if path_parts:

View File

@@ -1,6 +1,6 @@
# -*-python-*-
#
# Copyright (C) 2006-2011 The ViewCVS Group. All Rights Reserved.
# Copyright (C) 2006-2008 The ViewCVS Group. All Rights Reserved.
#
# By using this file, you agree to the terms and conditions set forth in
# the LICENSE.html file which can be found at the top level of the ViewVC
@@ -54,10 +54,7 @@ class ViewVCAuthorizer(vcauth.GenericViewVCAuthorizer):
# option names.
cp = ConfigParser()
cp.optionxform = lambda x: x
try:
cp.read(self.authz_file)
except:
raise debug.ViewVCException("Unable to parse configured authzfile file")
cp.read(self.authz_file)
# Figure out if there are any aliases for the current username
aliases = []
@@ -224,36 +221,6 @@ class ViewVCAuthorizer(vcauth.GenericViewVCAuthorizer):
paths = self._get_paths_for_root(rootname)
return (paths is not None) and 1 or 0
def check_universal_access(self, rootname):
paths = self._get_paths_for_root(rootname)
if not paths: # None or empty.
return 0
# Search the access determinations. If there's a mix, we can't
# claim a universal access determination.
found_allow = 0
found_deny = 0
for access in paths.values():
if access:
found_allow = 1
else:
found_deny = 1
if found_allow and found_deny:
return None
# We didn't find both allowances and denials, so we must have
# found one or the other. Denials only is a universal denial.
if found_deny:
return 0
# ... but allowances only is only a universal allowance if read
# access is granted to the root directory.
if found_allow and paths.has_key('/'):
return 1
# Anything else is indeterminable.
return None
def check_path_access(self, rootname, path_parts, pathtype, rev=None):
# Crawl upward from the path represented by PATH_PARTS toward to
# the root of the repository, looking for an explicitly grant or

View File

@@ -1,6 +1,6 @@
# -*-python-*-
#
# Copyright (C) 1999-2011 The ViewCVS Group. All Rights Reserved.
# Copyright (C) 1999-2008 The ViewCVS Group. All Rights Reserved.
#
# By using this file, you agree to the terms and conditions set forth in
# the LICENSE.html file which can be found at the top level of the ViewVC
@@ -76,7 +76,7 @@ class Repository:
"""
pass
def openfile(self, path_parts, rev, options):
def openfile(self, path_parts, rev):
"""Open a file object to read file contents at a given path and revision.
The return value is a 2-tuple of containg the file object and revision
@@ -86,8 +86,6 @@ class Repository:
of the repository. e.g. ["subdir1", "subdir2", "filename"]
rev is the revision of the file to check out
options is a dictionary of implementation specific options
"""
def listdir(self, path_parts, rev, options):
@@ -182,10 +180,8 @@ class Repository:
rev is the revision of the item to return information about
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.
Return value is a 4-tuple containing the date, author, log
message, and a list of ChangedPath items representing paths changed
Raise vclib.UnsupportedFeature if the version control system
doesn't support a global revision concept.

View File

@@ -1,6 +1,6 @@
# -*-python-*-
#
# Copyright (C) 1999-2011 The ViewCVS Group. All Rights Reserved.
# Copyright (C) 1999-2008 The ViewCVS Group. All Rights Reserved.
#
# By using this file, you agree to the terms and conditions set forth in
# the LICENSE.html file which can be found at the top level of the ViewVC
@@ -40,11 +40,6 @@ class BaseCVSRepository(vclib.Repository):
if not vclib.check_root_access(self):
raise vclib.ReposNotFound(name)
def open(self):
# See if a universal read access determination can be made.
if self.auth and self.auth.check_universal_access(self.name) == 1:
self.auth = None
def rootname(self):
return self.name
@@ -167,14 +162,7 @@ class BinCVSRepository(BaseCVSRepository):
return revs[-1]
return None
def openfile(self, path_parts, rev, options):
"""see vclib.Repository.openfile docstring
Option values recognized by this implementation:
cvs_oldkeywords
boolean. true to use the original keyword substitution values.
"""
def openfile(self, path_parts, rev):
if self.itemtype(path_parts, rev) != vclib.FILE: # does auth-check
raise vclib.Error("Path '%s' is not a file."
% (string.join(path_parts, "/")))
@@ -182,14 +170,12 @@ class BinCVSRepository(BaseCVSRepository):
rev_flag = '-p'
else:
rev_flag = '-p' + rev
if options.get('cvs_oldkeywords', 0):
kv_flag = '-ko'
else:
kv_flag = '-kkv'
full_name = self.rcsfile(path_parts, root=1, v=0)
used_rlog = 0
tip_rev = None # used only if we have to fallback to using rlog
fp = self.rcs_popen('co', (kv_flag, rev_flag, full_name), 'rb')
fp = self.rcs_popen('co', (rev_flag, full_name), 'rb')
try:
filename, revision = _parse_co_header(fp)
except COMissingRevision:
@@ -1036,16 +1022,16 @@ def _get_logs(repos, dir_path_parts, entries, view_tag, get_dirs):
file.errors.append("rlog error: %s" % msg)
continue
tag = None
if view_tag == 'MAIN' or view_tag == 'HEAD':
tag = Tag(None, default_branch)
elif taginfo.has_key(view_tag):
tag = Tag(None, taginfo[view_tag])
elif view_tag and (eof != _EOF_FILE):
# the tag wasn't found, so skip this file (unless we already
# know there's nothing left of it to read)
elif view_tag:
# the tag wasn't found, so skip this file
_skip_file(rlog)
eof = _EOF_FILE
eof = 1
else:
tag = None
# 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

View File

@@ -1,7 +1,7 @@
#!/usr/bin/env python
# -*-python-*-
#
# Copyright (C) 1999-2011 The ViewCVS Group. All Rights Reserved.
# Copyright (C) 1999-2008 The ViewCVS Group. All Rights Reserved.
# Copyright (C) 2000 Curt Hagenlocher <curt@hagenlocher.org>
#
# By using this file, you agree to the terms and conditions set forth in

View File

@@ -1,6 +1,6 @@
# -*-python-*-
#
# Copyright (C) 1999-2011 The ViewCVS Group. All Rights Reserved.
# Copyright (C) 1999-2008 The ViewCVS Group. All Rights Reserved.
#
# By using this file, you agree to the terms and conditions set forth in
# the LICENSE.html file which can be found at the top level of the ViewVC
@@ -127,9 +127,9 @@ class CCVSRepository(BaseCVSRepository):
% (string.join(path_parts2, "/")))
temp1 = tempfile.mktemp()
open(temp1, 'wb').write(self.openfile(path_parts1, rev1, {})[0].getvalue())
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())
open(temp2, 'wb').write(self.openfile(path_parts2, rev2)[0].getvalue())
r1 = self.itemlog(path_parts1, rev1, vclib.SORTBY_DEFAULT, 0, 0, {})[-1]
r2 = self.itemlog(path_parts2, rev2, vclib.SORTBY_DEFAULT, 0, 0, {})[-1]
@@ -152,7 +152,7 @@ class CCVSRepository(BaseCVSRepository):
def revinfo(self, rev):
raise vclib.UnsupportedFeature
def openfile(self, path_parts, rev, options):
def openfile(self, path_parts, rev=None):
if self.itemtype(path_parts, rev) != vclib.FILE: # does auth-check
raise vclib.Error("Path '%s' is not a file."
% (string.join(path_parts, "/")))

View File

@@ -1,6 +1,6 @@
# -*-python-*-
#
# Copyright (C) 1999-2011 The ViewCVS Group. All Rights Reserved.
# Copyright (C) 1999-2008 The ViewCVS Group. All Rights Reserved.
#
# By using this file, you agree to the terms and conditions set forth in
# the LICENSE.html file which can be found at the top level of the ViewVC
@@ -194,8 +194,7 @@ class _Parser:
else:
# Chew up "newphrase"
# warn("Unexpected RCS token: $token\n")
while self.ts.get() != ';':
pass
pass
else:
if f is None:
self.ts.unget(token)

View File

@@ -19,11 +19,7 @@ import string
import common
class _TokenStream:
token_term = string.whitespace + ";:"
try:
token_term = frozenset(token_term)
except NameError:
pass
token_term = string.whitespace + ';:'
# the algorithm is about the same speed for any CHUNK_SIZE chosen.
# grab a good-sized chunk, but not too large to overwhelm memory.
@@ -48,17 +44,15 @@ class _TokenStream:
# out more complex solutions.
buf = self.buf
lbuf = len(buf)
idx = self.idx
while 1:
if idx == lbuf:
if idx == len(buf):
buf = self.rcsfile.read(self.CHUNK_SIZE)
if buf == '':
# signal EOF by returning None as the token
del self.buf # so we fail if get() is called again
return None
lbuf = len(buf)
idx = 0
if buf[idx] not in string.whitespace:
@@ -66,7 +60,7 @@ class _TokenStream:
idx = idx + 1
if buf[idx] in ';:':
if buf[idx] == ';' or buf[idx] == ':':
self.buf = buf
self.idx = idx + 1
return buf[idx]
@@ -76,18 +70,17 @@ class _TokenStream:
token = ''
while 1:
# find token characters in the current buffer
while end < lbuf and buf[end] not in self.token_term:
while end < len(buf) and buf[end] not in self.token_term:
end = end + 1
token = token + buf[idx:end]
if end < lbuf:
if end < len(buf):
# we stopped before the end, so we have a full token
idx = end
break
# we stopped at the end of the buffer, so we may have a partial token
buf = self.rcsfile.read(self.CHUNK_SIZE)
lbuf = len(buf)
idx = end = 0
self.buf = buf
@@ -101,24 +94,22 @@ class _TokenStream:
chunks = [ ]
while 1:
if idx == lbuf:
if idx == len(buf):
idx = 0
buf = self.rcsfile.read(self.CHUNK_SIZE)
if buf == '':
raise RuntimeError, 'EOF'
lbuf = len(buf)
i = string.find(buf, '@', idx)
if i == -1:
chunks.append(buf[idx:])
idx = lbuf
idx = len(buf)
continue
if i == lbuf - 1:
if i == len(buf) - 1:
chunks.append(buf[idx:i])
idx = 0
buf = '@' + self.rcsfile.read(self.CHUNK_SIZE)
if buf == '@':
raise RuntimeError, 'EOF'
lbuf = len(buf)
continue
if buf[i + 1] == '@':
chunks.append(buf[idx:i+1])

View File

@@ -1,6 +1,6 @@
# -*-python-*-
#
# Copyright (C) 1999-2011 The ViewCVS Group. All Rights Reserved.
# Copyright (C) 1999-2008 The ViewCVS Group. All Rights Reserved.
#
# By using this file, you agree to the terms and conditions set forth in
# the LICENSE.html file which can be found at the top level of the ViewVC
@@ -15,7 +15,6 @@
import os
import os.path
import re
import urllib
_re_url = re.compile('^(http|https|file|svn|svn\+[^:]+)://')
@@ -24,20 +23,8 @@ def canonicalize_rootpath(rootpath):
import svn.core
return svn.core.svn_path_canonicalize(rootpath)
except:
if os.name == 'posix':
rootpath_lower = rootpath.lower()
if rootpath_lower in ['file://localhost',
'file://localhost/',
'file://',
'file:///'
]:
return '/'
if rootpath_lower.startswith('file://localhost/'):
return os.path.normpath(urllib.unquote(rootpath[16:]))
elif rootpath_lower.startswith('file:///'):
return os.path.normpath(urllib.unquote(rootpath[7:]))
if re.search(_re_url, rootpath):
return rootpath.rstrip('/')
return rootpath[-1] == '/' and rootpath[:-1] or rootpath
return os.path.normpath(rootpath)

View File

@@ -1,6 +1,6 @@
# -*-python-*-
#
# Copyright (C) 1999-2011 The ViewCVS Group. All Rights Reserved.
# Copyright (C) 1999-2009 The ViewCVS Group. All Rights Reserved.
#
# By using this file, you agree to the terms and conditions set forth in
# the LICENSE.html file which can be found at the top level of the ViewVC
@@ -18,9 +18,10 @@ 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, _split_revprops
from svn_repos import Revision, SVNChangedPath, _datestr_to_date, _compare_paths, _path_parts, _cleanup_path, _rev2optrev, _fix_subversion_exception
from svn import core, delta, client, wc, ra
@@ -51,29 +52,6 @@ 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 AttributeError:
# 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 ###
@@ -90,11 +68,7 @@ class LogCollector:
self.show_all_logs = show_all_logs
self.lockinfo = lockinfo
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)
def add_log(self, paths, revision, author, date, message, pool):
# Changed paths have leading slashes
changed_paths = paths.keys()
changed_paths.sort(lambda a, b: _compare_paths(a, b))
@@ -114,8 +88,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, date, author, msg, None, self.lockinfo,
self.path[1:], None, None)
entry = Revision(revision, _datestr_to_date(date), author, message, None,
self.lockinfo, self.path[1:], None, None)
self.logs.append(entry)
if this_path:
self.path = this_path
@@ -183,7 +157,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_create_context()
self.ctx = client.svn_client_ctx_t()
self.ctx.auth_baton = core.svn_auth_open([
client.svn_client_get_simple_provider(),
client.svn_client_get_username_provider(),
@@ -203,10 +177,6 @@ class RemoteSubversionRepository(vclib.Repository):
self.youngest = ra.svn_ra_get_latest_revnum(self.ra_session)
self._dirent_cache = { }
self._revinfo_cache = { }
# See if a universal read access determination can be made.
if self.auth and self.auth.check_universal_access(self.name) == 1:
self.auth = None
def rootname(self):
return self.name
@@ -241,7 +211,7 @@ class RemoteSubversionRepository(vclib.Repository):
raise vclib.ItemNotFound(path_parts)
return pathtype
def openfile(self, path_parts, rev, options):
def openfile(self, path_parts, rev):
path = self._getpath(path_parts)
if self.itemtype(path_parts, rev) != vclib.FILE: # does auth-check
raise vclib.Error("Path '%s' is not a file." % path)
@@ -282,7 +252,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, revprops, changes = \
entry.date, entry.author, entry.log, changes = \
self.revinfo(dirent.created_rev)
entry.rev = str(dirent.created_rev)
entry.size = dirent.size
@@ -313,8 +283,9 @@ class RemoteSubversionRepository(vclib.Repository):
log_limit = 0
if limit:
log_limit = first + limit
client_log(url, _rev2optrev(rev), _rev2optrev(1), log_limit,
cross_copies, lc.add_log, self.ctx)
client.svn_client_log2([url], _rev2optrev(rev), _rev2optrev(1),
log_limit, 1, not cross_copies,
lc.add_log, self.ctx)
revs = lc.logs
revs.sort()
prev = None
@@ -366,7 +337,7 @@ class RemoteSubversionRepository(vclib.Repository):
if not cached_info:
cached_info = self._revinfo_raw(rev)
self._revinfo_cache[rev] = cached_info
return tuple(cached_info)
return cached_info[0], cached_info[1], cached_info[2], cached_info[3]
def rawdiff(self, path_parts1, rev1, path_parts2, rev2, type, options={}):
p1 = self._getpath(path_parts1)
@@ -381,7 +352,7 @@ class RemoteSubversionRepository(vclib.Repository):
args = vclib._diff_args(type, options)
def _date_from_rev(rev):
date, author, msg, revprops, changes = self.revinfo(rev)
date, author, msg, changes = self.revinfo(rev)
return date
try:
@@ -407,11 +378,8 @@ class RemoteSubversionRepository(vclib.Repository):
if rev is None or rev == 'HEAD':
return self.youngest
try:
if type(rev) == type(''):
while rev[0] == 'r':
rev = rev[1:]
rev = int(rev)
except:
except ValueError:
raise vclib.InvalidRevision(rev)
if (rev < 0) or (rev > self.youngest):
raise vclib.InvalidRevision(rev)
@@ -449,54 +417,29 @@ class RemoteSubversionRepository(vclib.Repository):
return revisions[0]
def _revinfo_raw(self, rev):
# return 5-tuple (date, author, msg, revprops, changes)
# return 5-tuple (date, author, message, changes)
optrev = _rev2optrev(rev)
revs = []
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)
def _log_cb(changed_paths, revision, author,
datestr, message, pool, retval=revs):
date = _datestr_to_date(datestr)
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:
change = changed_paths[path]
### svn_log_changed_path_t (which we might get instead of the
### svn_log_changed_path2_t we'd prefer) doesn't have the
### 'node_kind' member.
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
change = changed_paths[path]
action = action_map.get(change.action, vclib.MODIFIED)
### 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
@@ -519,21 +462,21 @@ class RemoteSubversionRepository(vclib.Repository):
base_path = None
base_rev = None
changes.append(SVNChangedPath(path, revision, pathtype, base_path,
base_rev, action, is_copy,
text_modified, props_modified))
base_rev, action, is_copy, 0, 0))
found_readable = 1
else:
found_unreadable = 1
if found_unreadable:
msg = None
message = None
if not found_readable:
author = None
date = None
revs.append([date, author, msg, revprops, changes])
revs.append([date, author, message, changes])
client_log(self.rootpath, optrev, optrev, 1, 0, _log_cb, self.ctx)
return tuple(revs[0])
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]
##--- custom --##

View File

@@ -1,6 +1,6 @@
# -*-python-*-
#
# Copyright (C) 1999-2011 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
@@ -115,27 +115,6 @@ 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
@@ -204,6 +183,59 @@ class NodeHistory:
def __getitem__(self, idx):
return self.histories[idx]
def _get_history(svnrepos, path, rev, path_type, limit=0, options={}):
if svnrepos.youngest == 0:
return []
rev_paths = []
fsroot = svnrepos._getroot(rev)
show_all_logs = options.get('svn_show_all_dir_logs', 0)
if not show_all_logs:
# See if the path is a file or directory.
kind = fs.check_path(fsroot, path)
if kind is core.svn_node_file:
show_all_logs = 1
# Instantiate a NodeHistory collector object, and use it to collect
# history items for PATH@REV.
history = NodeHistory(svnrepos.fs_ptr, show_all_logs, limit)
try:
repos.svn_repos_history(svnrepos.fs_ptr, path, history.add_history,
1, rev, options.get('svn_cross_copies', 0))
except core.SubversionException, e:
_fix_subversion_exception(e)
if e.apr_err != _SVN_ERR_CEASE_INVOCATION:
raise
# Now, iterate over those history items, checking for changes of
# location, pruning as necessitated by authz rules.
for hist_rev, hist_path in history:
path_parts = _path_parts(hist_path)
if not vclib.check_path_access(svnrepos, path_parts, path_type, hist_rev):
break
rev_paths.append([hist_rev, hist_path])
return rev_paths
def _log_helper(svnrepos, path, rev, lockinfo):
rev_root = fs.revision_root(svnrepos.fs_ptr, rev)
# Was this path@rev the target of a copy?
copyfrom_rev, copyfrom_path = fs.copied_from(rev_root, path)
# Assemble our LogEntry
date, author, msg, changes = svnrepos._revinfo(rev)
if fs.is_file(rev_root, path):
size = fs.file_length(rev_root, path)
else:
size = None
entry = Revision(rev, date, author, msg, size, lockinfo, path,
copyfrom_path and _cleanup_path(copyfrom_path),
copyfrom_rev)
return entry
def _get_last_history_rev(fsroot, path):
history = fs.node_history(fsroot, path)
history = fs.history_prev(history, 0)
@@ -282,14 +314,14 @@ class FileContentsPipe:
class BlameSource:
def __init__(self, local_url, rev, first_rev, config_dir):
def __init__(self, local_url, rev, first_rev):
self.idx = -1
self.first_rev = first_rev
self.blame_data = []
ctx = client.svn_client_create_context()
core.svn_config_ensure(config_dir)
ctx.config = core.svn_config_get_config(config_dir)
ctx = client.ctx_t()
core.svn_config_ensure(None)
ctx.config = core.svn_config_get_config(None)
ctx.auth_baton = core.svn_auth_open([])
try:
### TODO: Is this use of FIRST_REV always what we want? Should we
@@ -344,7 +376,7 @@ class LocalSubversionRepository(vclib.Repository):
self.auth = authorizer
self.svn_client_path = utilities.svn or 'svn'
self.diff_cmd = utilities.diff or 'diff'
self.config_dir = config_dir or None
self.config_dir = config_dir
# See if this repository is even viewable, authz-wise.
if not vclib.check_root_access(self):
@@ -374,10 +406,6 @@ class LocalSubversionRepository(vclib.Repository):
self._fsroots = {}
self._revinfo_cache = {}
# See if a universal read access determination can be made.
if self.auth and self.auth.check_universal_access(self.name) == 1:
self.auth = None
def rootname(self):
return self.name
@@ -393,14 +421,19 @@ class LocalSubversionRepository(vclib.Repository):
def itemtype(self, path_parts, rev):
rev = self._getrev(rev)
basepath = self._getpath(path_parts)
pathtype = self._gettype(basepath, rev)
if pathtype is None:
kind = fs.check_path(self._getroot(rev), basepath)
pathtype = None
if kind == core.svn_node_dir:
pathtype = vclib.DIR
elif kind == core.svn_node_file:
pathtype = vclib.FILE
else:
raise vclib.ItemNotFound(path_parts)
if not vclib.check_path_access(self, path_parts, pathtype, rev):
raise vclib.ItemNotFound(path_parts)
return pathtype
def openfile(self, path_parts, rev, options):
def openfile(self, path_parts, rev):
path = self._getpath(path_parts)
if self.itemtype(path_parts, rev) != vclib.FILE: # does auth-check
raise vclib.Error("Path '%s' is not a file." % path)
@@ -439,7 +472,7 @@ class LocalSubversionRepository(vclib.Repository):
continue
path = self._getpath(entry_path_parts)
entry_rev = _get_last_history_rev(fsroot, path)
date, author, msg, revprops, changes = self._revinfo(entry_rev)
date, author, msg, changes = self._revinfo(entry_rev)
entry.rev = str(entry_rev)
entry.date = date
entry.author = author
@@ -488,19 +521,20 @@ class LocalSubversionRepository(vclib.Repository):
# 'limit' parameter here as numeric cut-off for the depth of our
# history search.
if options.get('svn_latest_log', 0):
revision = self._log_helper(path, rev, lockinfo)
revision = _log_helper(self, path, rev, lockinfo)
if revision:
revision.prev = None
revs.append(revision)
else:
history = self._get_history(path, rev, path_type, first + limit, options)
history = _get_history(self, path, rev, path_type,
first + limit, options)
if len(history) < first:
history = []
if limit:
history = history[first:first+limit]
for hist_rev, hist_path in history:
revision = self._log_helper(hist_path, hist_rev, lockinfo)
revision = _log_helper(self, hist_path, hist_rev, lockinfo)
if revision:
# If we have unreadable copyfrom data, obscure it.
if revision.copy_path is not None:
@@ -528,56 +562,36 @@ class LocalSubversionRepository(vclib.Repository):
raise vclib.Error("Path '%s' is not a file." % path)
rev = self._getrev(rev)
fsroot = self._getroot(rev)
history = self._get_history(path, rev, path_type, 0,
{'svn_cross_copies': 1})
history = _get_history(self, path, rev, path_type, 0,
{'svn_cross_copies': 1})
youngest_rev, youngest_path = history[0]
oldest_rev, oldest_path = history[-1]
source = BlameSource(_rootpath2url(self.rootpath, path),
youngest_rev, oldest_rev, self.config_dir)
youngest_rev, oldest_rev)
return source, youngest_rev
def revinfo(self, rev):
return self._revinfo(rev, 1)
def rawdiff(self, path_parts1, rev1, path_parts2, rev2, type, options={}):
p1 = self._getpath(path_parts1)
p2 = self._getpath(path_parts2)
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)
args = vclib._diff_args(type, options)
def _date_from_rev(rev):
date, author, msg, revprops, changes = self._revinfo(rev)
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
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
def isexecutable(self, path_parts, rev):
props = self.itemprops(path_parts, rev) # does authz-check
return props.has_key(core.SVN_PROP_EXECUTABLE)
##--- helpers ---##
def _revinfo(self, rev, include_changed_paths=0):
"""Internal-use, cache-friendly revision information harvester."""
def _get_changed_paths(fsroot):
"""Return a 3-tuple: found_readable, found_unreadable, changed_paths."""
def _revinfo_helper(rev, include_changed_paths):
# Get the revision property info. (Would use
# editor.get_root_props(), but something is broken there...)
revprops = fs.revision_proplist(self.fs_ptr, rev)
msg = revprops.get(core.SVN_PROP_REVISION_LOG)
author = revprops.get(core.SVN_PROP_REVISION_AUTHOR)
datestr = revprops.get(core.SVN_PROP_REVISION_DATE)
date = _datestr_to_date(datestr)
# Optimization: If our caller doesn't care about the changed
# paths, and we don't need them to do authz determinations, let's
# get outta here.
if self.auth is None and not include_changed_paths:
return date, author, msg, None
# If we get here, then we either need the changed paths because we
# were asked for them, or we need them to do authorization checks.
# Either way, we need 'em, so let's get 'em.
fsroot = self._getroot(rev)
editor = repos.ChangeCollector(self.fs_ptr, fsroot)
e_ptr, e_baton = delta.make_editor(editor)
repos.svn_repos_replay(fsroot, e_ptr, e_baton)
@@ -630,8 +644,7 @@ class LocalSubversionRepository(vclib.Repository):
if vclib.check_path_access(self, parts, pathtype, rev):
if is_copy and change.base_path and (change.base_path != path):
parts = _path_parts(change.base_path)
if not vclib.check_path_access(self, parts, pathtype,
change.base_rev):
if not vclib.check_path_access(self, parts, pathtype, change.base_rev):
is_copy = 0
change.base_path = None
change.base_rev = None
@@ -643,108 +656,24 @@ class LocalSubversionRepository(vclib.Repository):
found_readable = 1
else:
found_unreadable = 1
return found_readable, found_unreadable, changedpaths.values()
def _get_change_copyinfo(fsroot, path, change):
if hasattr(change, 'copyfrom_known') and change.copyfrom_known:
copyfrom_path = change.copyfrom_path
copyfrom_rev = change.copyfrom_rev
else:
copyfrom_rev, copyfrom_path = fs.copied_from(fsroot, path)
return copyfrom_path, copyfrom_rev
def _simple_auth_check(fsroot):
"""Return a 2-tuple: found_readable, found_unreadable."""
found_unreadable = found_readable = 0
if hasattr(fs, 'paths_changed2'):
changes = fs.paths_changed2(fsroot)
else:
changes = fs.paths_changed(fsroot)
paths = changes.keys()
for path in paths:
change = changes[path]
pathtype = None
if hasattr(change, 'node_kind'):
if change.node_kind == core.svn_node_file:
pathtype = vclib.FILE
elif change.node_kind == core.svn_node_dir:
pathtype = vclib.DIR
parts = _path_parts(path)
if pathtype is None:
# Figure out the pathtype so we can query the authz subsystem.
if change.change_kind == fs.path_change_delete:
# Deletions are annoying, because they might be underneath
# copies (make their previous location non-trivial).
prev_parts = parts
prev_rev = rev - 1
parent_parts = parts[:-1]
while parent_parts:
parent_path = '/' + self._getpath(parent_parts)
parent_change = changes.get(parent_path)
if not (parent_change and \
(parent_change.change_kind == fs.path_change_add or
parent_change.change_kind == fs.path_change_replace)):
del(parent_parts[-1])
continue
copyfrom_path, copyfrom_rev = \
_get_change_copyinfo(fsroot, parent_path, parent_change)
if copyfrom_path:
prev_rev = copyfrom_rev
prev_parts = _path_parts(copyfrom_path) + \
parts[len(parent_parts):]
break
del(parent_parts[-1])
pathtype = self._gettype(self._getpath(prev_parts), prev_rev)
else:
pathtype = self._gettype(self._getpath(parts), rev)
if vclib.check_path_access(self, parts, pathtype, rev):
found_readable = 1
copyfrom_path, copyfrom_rev = \
_get_change_copyinfo(fsroot, path, change)
if copyfrom_path and copyfrom_path != path:
parts = _path_parts(copyfrom_path)
if not vclib.check_path_access(self, parts, pathtype,
copyfrom_rev):
found_unreadable = 1
else:
found_unreadable = 1
if found_readable and found_unreadable:
break
return found_readable, found_unreadable
def _revinfo_helper(rev, include_changed_paths):
# Get the revision property info. (Would use
# editor.get_root_props(), but something is broken there...)
revprops = fs.revision_proplist(self.fs_ptr, rev)
msg, 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, 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.
#
# If we only need them for authorization checks, though, we
# won't bother generating fully populated ChangedPath items (the
# cost is too great).
fsroot = self._getroot(rev)
if include_changed_paths:
found_readable, found_unreadable, changedpaths = \
_get_changed_paths(fsroot)
else:
changedpaths = None
found_readable, found_unreadable = _simple_auth_check(fsroot)
# If our caller doesn't care about changed paths, we must be
# here for authz reasons only. That means the minute we've
# found both a readable and an unreadable path, we can bail out.
if (not include_changed_paths) and found_readable and found_unreadable:
return date, author, None, None
# Filter our metadata where necessary, and return the requested data.
# Okay, we've process all our paths. Let's filter our metadata,
# and return the requested data.
if found_unreadable:
msg = None
if not found_readable:
author = None
date = None
return date, author, msg, revprops, changedpaths
if include_changed_paths:
return date, author, msg, changedpaths.values()
else:
return date, author, msg, 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
@@ -752,55 +681,45 @@ 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[4] is None):
or (include_changed_paths and cached_info[3] is None):
cached_info = _revinfo_helper(rev, include_changed_paths)
self._revinfo_cache[rev] = cached_info
return tuple(cached_info)
return cached_info[0], cached_info[1], cached_info[2], cached_info[3]
def _log_helper(self, path, rev, lockinfo):
rev_root = fs.revision_root(self.fs_ptr, rev)
copyfrom_rev, copyfrom_path = fs.copied_from(rev_root, path)
date, author, msg, revprops, changes = self._revinfo(rev)
if fs.is_file(rev_root, path):
size = fs.file_length(rev_root, path)
else:
size = None
return Revision(rev, date, author, msg, size, lockinfo, path,
copyfrom_path and _cleanup_path(copyfrom_path),
copyfrom_rev)
def revinfo(self, rev):
return self._revinfo(rev, 1)
def rawdiff(self, path_parts1, rev1, path_parts2, rev2, type, options={}):
p1 = self._getpath(path_parts1)
p2 = self._getpath(path_parts2)
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)
args = vclib._diff_args(type, options)
def _get_history(self, path, rev, path_type, limit=0, options={}):
if self.youngest == 0:
return []
def _date_from_rev(rev):
date, author, msg, changes = self._revinfo(rev)
return date
rev_paths = []
fsroot = self._getroot(rev)
show_all_logs = options.get('svn_show_all_dir_logs', 0)
if not show_all_logs:
# See if the path is a file or directory.
kind = fs.check_path(fsroot, path)
if kind is core.svn_node_file:
show_all_logs = 1
# Instantiate a NodeHistory collector object, and use it to collect
# history items for PATH@REV.
history = NodeHistory(self.fs_ptr, show_all_logs, limit)
try:
repos.svn_repos_history(self.fs_ptr, path, history.add_history,
1, rev, options.get('svn_cross_copies', 0))
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
return vclib._diff_fp(temp1, temp2, info1, info2, self.diff_cmd, args)
except core.SubversionException, e:
_fix_subversion_exception(e)
if e.apr_err != _SVN_ERR_CEASE_INVOCATION:
raise
if e.apr_err == core.SVN_ERR_FS_NOT_FOUND:
raise vclib.InvalidRevision
raise
# Now, iterate over those history items, checking for changes of
# location, pruning as necessitated by authz rules.
for hist_rev, hist_path in history:
path_parts = _path_parts(hist_path)
if not vclib.check_path_access(self, path_parts, path_type, hist_rev):
break
rev_paths.append([hist_rev, hist_path])
return rev_paths
def isexecutable(self, path_parts, rev):
props = self.itemprops(path_parts, rev) # does authz-check
return props.has_key(core.SVN_PROP_EXECUTABLE)
def _getpath(self, path_parts):
return string.join(path_parts, '/')
@@ -809,11 +728,8 @@ class LocalSubversionRepository(vclib.Repository):
if rev is None or rev == 'HEAD':
return self.youngest
try:
if type(rev) == type(''):
while rev[0] == 'r':
rev = rev[1:]
rev = int(rev)
except:
except ValueError:
raise vclib.InvalidRevision(rev)
if (rev < 0) or (rev > self.youngest):
raise vclib.InvalidRevision(rev)
@@ -826,20 +742,7 @@ class LocalSubversionRepository(vclib.Repository):
r = self._fsroots[rev] = fs.revision_root(self.fs_ptr, rev)
return r
def _gettype(self, path, rev):
# Similar to itemtype(), but without the authz check. Returns
# None for missing paths.
try:
kind = fs.check_path(self._getroot(rev), path)
except:
return None
if kind == core.svn_node_dir:
return vclib.DIR
if kind == core.svn_node_file:
return vclib.FILE
return None
##--- custom ---##
##--- custom --##
def get_youngest_revision(self):
return self.youngest

File diff suppressed because it is too large Load Diff

View File

@@ -27,9 +27,7 @@ numbers, and not literal):
3. Verify that copyright years are correct in both the license-1.html
file and the source code.
4. Update and commit the 'CHANGES' file, using any available crystal
balls or other forward-looking devices to take a stab at the
release date.
4. Update and commit the 'CHANGES' file.
5. Test, test, test! There is no automatic testsuite available. So
just run with permuting different `viewvc.conf' settings... and
@@ -40,76 +38,50 @@ numbers, and not literal):
should exactly reflect what you wish to distribute and dub "the
release".
7. Update your release branch working copy to HEAD.
svn up
8. Edit the file 'lib/viewvc.py' and remove the "-dev" suffix from
7. 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.
Y, and Z are positive integers. Do NOT commit this change.
*** Do NOT commit this change. ***
8. Update your working copy to HEAD, and tag the release:
9. "Peg" the contributed templates externals definition to the
current HEAD revision:
svn update
svn cp -m "Tag the X.Y.Z final release." . \
http://viewvc.tigris.org/svn/viewvc/tags/X.Y.Z
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:
9. Go into an empty directory and run the 'make-release' script:
tools/make-release viewvc-X.Y.Z tags/X.Y.Z
13. Verify the archive files:
10. 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?
14. Upload the created archive files (tar.gz and zip) into the Files
11. 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:
CHECKSUMS document there accordingly. Also, drop a copy of the
archive files into the root directory of the viewvc.org website
(unversioned).
http://viewvc.tigris.org/servlets/ProjectDocumentList?folderID=6004
Also, drop a copy of the archive files into the root directory of
the viewvc.org website (unversioned).
15. On trunk, update the websites (both the viewvc.org/ and www/ ones)
12. 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.
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:
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:
svn ci -m "Begin a new release cycle."
17. Edit the Issue Tracker configuration options, adding a new Version
14. 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.)
http://viewvc.tigris.org/issues/editversions.cgi?component=viewvc&action=add
http://viewvc.tigris.org/issues/editmilestones.cgi?component=viewvc&action=add
18. Send to the announce@ list a message explaining all the cool new
features, and post similar announcements to other places interested
in this sort of stuff, such as Freshmeat (http://www.freshmeat.net).
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).

View File

@@ -21,13 +21,13 @@
<th style="width:6%;"></th>
<th style="width:47%; vertical-align:top;">
[is left.path right.path][else][left.path][end]
revision [if-any left_view_href]<a href="[left_view_href]">[end][left.rev][if-any left_view_href]</a>[end][if-any left.author] by <em>[left.author]</em>[end],
revision [if-any left_view_href]<a href="[left_view_href]">[end][left.rev][if-any left_view_href]</a>[end],
[left.date]
[if-any left.tag]<br />Tag: [left.tag][end]
</th>
<th style="width:47%; vertical-align:top;">
[is left.path right.path][else][right.path][end]
revision [if-any right_view_href]<a href="[right_view_href]">[end][right.rev][if-any right_view_href]</a>[end][if-any right.author] by <em>[right.author]</em>[end],
revision [if-any right_view_href]<a href="[right_view_href]">[end][right.rev][if-any right_view_href]</a>[end],
[right.date]
[if-any right.tag]<br />Tag: [right.tag][end]
</th>

View File

@@ -94,6 +94,9 @@ form { margin: 0; }
.vc_properties {
margin: 1em 0;
}
.vc_properties h2 {
font-size: 115%;
}
/*** File Content Markup Styles ***/
@@ -271,12 +274,6 @@ table.vc_idiff tbody th {
}
/*** Warning! ***/
.vc_warning {
border-width: 1px 2px 2px 2px;
border-color: black;
border-style: solid;
background-color: red;
color: white;
padding: 0.5em;
/*** Graph Display Form ***/
.vc_graph_form {
}

View File

@@ -71,9 +71,9 @@ Revision [if-any revision_href]<a href="[revision_href]"><strong>[rev]</strong><
[if-any image_src_href][define hide_binary_garbage]0[end][end]
[is hide_binary_garbage "1"]
<p><strong>This file's contents are not viewable.
[if-any download_href]Please <a href="[download_href]">download</a>
this version of the file in order to view it.[end]</strong></p>
<p><strong>This file's contents are not viewable. Please
<a href="[download_href]">download</a> this version of the
file in order to view it.</strong></p>
[else]
[define last_rev]0[end]

View File

@@ -15,4 +15,78 @@
alt="Revisions of [where]" />
</div>
[define graph_disp_opts][end]
[if-any opt_gflip][define graph_disp_opts]1[end][end]
[if-any opt_gbbox][define graph_disp_opts]1[end][end]
[if-any opt_gleft][define graph_disp_opts]1[end][end]
[define graph_user_opts][end]
[if-any graph_disp_opts][define graph_user_opts]1[end][end]
[if-any opt_gshow][define graph_user_opts]1[end][end]
[if-any opt_gmaxtag][define graph_user_opts]1[end][end]
[if-any graph_user_opts]
<form method="get" action="[graph_action]">
<div class="vc_graph_form">
[for graph_hidden_values]<input type="hidden" name="[graph_hidden_values.name]" value="[graph_hidden_values.value]"/>[end]
[is graph_disp_opts "1"]
<p><strong>Graph display options:</strong></p>
<table class="auto">
[if-any opt_gflip]
<tr>
<td><input id="gflip" type="checkbox" name="gflip" value="1"[if-any gflip] checked="checked"[end] /></td>
<td style="text-align: left;"><label for="gflip">Flip the graph</label></td>
</tr>
[end]
[if-any opt_gbbox]
<tr>
<td><input id="gbbox" type="checkbox" name="gbbox" value="1"[if-any gbbox] checked="checked"[end] /></td>
<td style="text-align: left;"><label for="gbbox">Add a branch box at the tip of each branch</label></td>
</tr>
[end]
[if-any opt_gleft]
<tr>
<td><input id="gleft" type="checkbox" name="gleft" value="1"[if-any gleft] checked="checked"[end] /></td>
<td style="text-align: left;"><label for="gleft">Draw tree left-to-right (instead of top-to-bottom)</label></td>
</tr>
[end]
</table>
[end]
[if-any opt_gshow]
<p><strong>Revision display options:</strong></p>
<table class="auto">
<tr>
<td><input id="gshow_all" type="radio" name="gshow" value="all"[is gshow "all"] checked="checked"[end] /></td>
<td style="text-align: left;"><label for="gshow_all">Show all revisions</label></td>
</tr>
<tr>
<td><input id="gshow_inittagged" type="radio" name="gshow" value="inittagged"[is gshow "inittagged"] checked="checked"[end] /></td>
<td style="text-align: left;"><label for="gshow_inittagged">Show only tagged and initial untagged revisions</label></td>
</tr>
<tr>
<td><input id="gshow_tagged" type="radio" name="gshow" value="tagged"[is gshow "tagged"] checked="checked"[end] /></td>
<td style="text-align: left;"><label for="gshow_tagged">Show only tagged revisions</label></td>
</tr>
</table>
[end]
[if-any opt_gmaxtag]
<p><strong>Tag limitation:</strong></p>
<table class="auto">
<tr>
<td><input id="gmaxtag" type="text" size="3" name="gmaxtag" value="[gmaxtag]" /></td>
<td style="text-align: left;"><label for="gmaxtag">Maximum number of tags to display (0=all)</label></td>
</tr>
</table>
[end]
<input type="submit" value="Refresh" />
</div>
</form>
[end]
[include "include/footer.ezt"]

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;">[if-any help_href]<strong><a href="[help_href]">ViewVC Help</a></strong>[else]&nbsp;[end]</td>
<td style="text-align: right;"><strong><a href="[help_href]">ViewVC Help</a></strong></td>
</tr>
<tr>
<td>Powered by <a href="http://viewvc.tigris.org/">ViewVC [vsn]</a></td>

View File

@@ -5,7 +5,7 @@
<head>
<title>[if-any rootname][[][rootname]][else]ViewVC[end] [page_title]</title>
<meta name="generator" content="ViewVC [vsn]" />
<link rel="shortcut icon" href="[docroot]/images/favicon.ico" />
<link rel="shortcut icon" href="[docroot]/images/favicon.ico" type="image/x-icon" />
<link rel="stylesheet" href="[docroot]/styles.css" type="text/css" />
[if-any rss_href]<link rel="alternate" type="application/rss+xml" title="RSS [[][rootname]][where]" href="[rss_href]" />[end]
</head>

View File

@@ -4,13 +4,13 @@
<!-- ViewVC :: http://www.viewvc.org/ -->
<head>
<title>Checkin Database Query</title>
[if-any docroot]<link rel="stylesheet" href="[docroot]/styles.css" type="text/css" />[end]
<link rel="stylesheet" href="[docroot]/styles.css" type="text/css" />
</head>
<body>
[# setup page definitions]
[define help_href][if-any docroot][docroot]/help_query.html[end][end]
[define help_href][docroot]/help_query.html[end]
[# end]
<p>
@@ -158,15 +158,7 @@
[is query "skipped"]
[else]
<p><strong>[num_commits]</strong> matches found.</p>
[if-any row_limit_reached]
<p class="vc_warning">WARNING: These query results have been
artificially limited by an administrative threshold value and do
<em>not</em> represent the entirety of the data set which matches
the query. Consider modifying your query to be more specific</a>,
using your version control tool's query capabilities, or asking
your administrator to raise the database response size
threshold.</p>
[end]
[if-any commits]
<table cellspacing="0" cellpadding="2">
<thead>
@@ -210,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}">
{if-any commits.log}{commits.log}{else}&nbsp;{end}
{commits.log}
</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">[if-any commits.log][commits.log][else]&nbsp;[end]</pre></td>
<pre class="vc_log">[commits.log]</pre></td>
</tr>
[end]
[# ---]

View File

@@ -7,15 +7,6 @@
<p><strong>[english_query]</strong></p>
[# <!-- {sql} --> ]
[if-any row_limit_reached]
<p class="vc_warning">WARNING: These query results have been
artificially limited by an administrative threshold value and do
<em>not</em> represent the entirety of the data set which matches
the query. Consider <a href="[queryform_href]">modifying your
query to be more specific</a>, using your version control tool's
query capabilities, or asking your administrator to raise the
database response size threshold.</p>
[end]
<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>

View File

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

View File

@@ -9,12 +9,6 @@
<thead>
<tr>
<th class="vc_header_sort">Name</th>
[is cfg.options.show_roots_lastmod "1"]
<th class="vc_header">Revision</th>
<th class="vc_header">Age</th>
<th class="vc_header">Author</th>
<th class="vc_header">Log</th>
[end]
</tr>
</thead>
@@ -26,12 +20,6 @@
<img src="[docroot]/images/dir.png" alt="" class="vc_icon" />
[roots.name]</a>
</td>
[is cfg.options.show_roots_lastmod "1"]
<td style="width:20">&nbsp;[if-any roots.log_href]<a href="[roots.log_href]">[roots.rev]</a>[else][roots.rev][end]</td>
<td style="width:20">&nbsp;[roots.ago]</td>
<td style="width:20">&nbsp;[roots.author]</td>
<td style="width:20">&nbsp;[roots.short_log]</td>
[end]
</tr>
[end]
</tbody>

View File

@@ -7,11 +7,11 @@
<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]] [format "xml"][commits.short_log][end]</title>
<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>&#x3C;pre&#x3E;[format "xml"][format "html"][commits.log][end][end]&#x3C;/pre&#x3E;</description>
<description>&lt;pre&gt;[format "xml"][commits.log][end]&lt;/pre&gt;</description>
</item>[end]
</channel>
</rss>

View File

@@ -49,10 +49,6 @@ CLEAN_MODE = None
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),
@@ -79,12 +75,11 @@ if sys.platform == "win32":
## List of directories for installation.
## type (source path,
## destination path,
## boolean -- optional item?,
## boolean -- prompt before replacing?)
TREE_LIST = [
("lib", "lib", 0, 0),
("templates", "templates", 0, 1),
("templates-contrib", "templates-contrib", 1, 1),
("lib", "lib", 0),
("templates", "templates", 1),
("templates-contrib", "templates-contrib", 1),
]
@@ -209,8 +204,6 @@ def install_file(src_path, dst_path, mode, subst_path_vars,
temp = raw_input("Do you want to [O]verwrite, [D]o "
"not overwrite, or [V]iew "
"differences? ")
if len(temp) == 0:
continue
temp = string.lower(temp[0])
if temp == "v" and ext not in BINARY_FILE_EXTS:
print """
@@ -282,22 +275,18 @@ LEGEND
py_compile.compile(destdir_path, destdir_path + "c" , dst_path)
def install_tree(src_path, dst_path, is_optional, prompt_replace):
def install_tree(src_path, dst_path, prompt_replace):
"""Install a tree whose source is at SRC_PATH (which is relative
to the ViewVC source directory) into the location DST_PATH (which
is relative both to the global ROOT_DIR and DESTDIR settings). If
PROMPT_REPLACE is set (and is not overridden by global setting
CLEAN_MODE), prompt the user for how to deal with already existing
files that differ from the to-be-installed version. If
IS_OPTIONAL is set, don't fuss about a missing source item."""
files that differ from the to-be-installed version."""
orig_src_path = src_path
orig_dst_path = dst_path
src_path = _actual_src_path(src_path)
dst_path = os.path.join(ROOT_DIR, string.replace(dst_path, '/', os.sep))
if not os.path.isdir(src_path):
print " skipping %s" % (dst_path)
return
destdir_path = os.path.join(DESTDIR + dst_path)
# Get a list of items in the directory.
@@ -317,7 +306,7 @@ def install_tree(src_path, dst_path, is_optional, prompt_replace):
# If the item is a subdirectory, recurse. Otherwise, install the file.
if os.path.isdir(os.path.join(src_path, fname)):
install_tree(orig_src_child, orig_dst_child, 0, prompt_replace)
install_tree(orig_src_child, orig_dst_child, prompt_replace)
else:
set_paths = 0
compile_it = fname[-3:] == '.py'

9
viewvc.org/.htaccess Normal file
View File

@@ -0,0 +1,9 @@
# Old documents.
RedirectPermanent /upgrading.html http://viewvc.tigris.org/nonav/source/browse/*checkout*/viewvc/trunk/docs/upgrading-howto.html
RedirectPermanent /template-authoring-guide.html http://viewvc.tigris.org/nonav/source/browse/*checkout*/viewvc/trunk/docs/template-authoring-guide.html
RedirectPermanent /url-reference.html http://viewvc.tigris.org/nonav/source/browse/*checkout*/viewvc/trunk/docs/url-reference.html
# The license-1.html file.
RedirectPermanent /license-1.html http://viewvc.tigris.org/nonav/source/browse/*checkout*/viewvc/trunk/LICENSE.html

93
viewvc.org/contact.html Normal file
View File

@@ -0,0 +1,93 @@
<!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">
<head>
<title>ViewVC: Contact</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<link rel="stylesheet" type="text/css" href="./styles.css"/>
<link rel="shortcut icon" href="./favicon.ico" type="image/x-icon" />
</head>
<body>
<div id="title">
<a href="http://www.viewvc.org/"><img
src="./images/title.jpg" alt="ViewVC: Repository Browsing"/></a>
</div>
<div id="menu">
<p><a href="./index.html">Home</a> |
<a href="http://viewvc.tigris.org/">Project Page</a> |
<a href="./download.html">Download</a> |
<a href="./contributing.html">Contributing</a> |
<a href="./faq.html">FAQ</a> |
<a href="http://viewvc.tigris.org/nonav/source/browse/*checkout*/viewvc/trunk/LICENSE.html">License</a> |
<a href="./contact.html">Contact</a> |
<a href="./who.html">About</a>
</p>
</div>
<table id="pagetable">
<tr>
<td id="pagecolumn1">
<h4>On this page:</h4>
<ul id="bookmarks">
<li><a href="#sec-contacting-us">Contacting Us</a></li>
</ul>
<p><a href="http://validator.w3.org/check?uri=referer"><img
src="http://www.w3.org/Icons/valid-xhtml10"
alt="Valid XHTML 1.0 Strict" height="31" width="88" /></a>
</p>
</td>
<td id="pagecolumn2">
<div class="section">
<h2 id="sec-contacting-us">Contacting Us</h2>
<div class="section-body">
<p>ViewVC is an <a href="http://www.opensource.org/">Open Source</a>
project, and all <a href="./contributing.html">contributions</a>
are welcome. Please send any comments, questions, or suggestions
to the <a
href="mailto:&#117;&#115;&#101;&#114;&#115;&#64;&#118;&#105;&#101;&#119;&#118;&#99;&#46;&#116;&#105;&#103;&#114;&#105;&#115;&#46;&#111;&#114;&#103;">ViewVC
users mailing list</a>. There is also a <a
href="mailto:&#100;&#101;&#118;&#64;&#118;&#105;&#101;&#119;&#118;&#99;&#46;&#116;&#105;&#103;&#114;&#105;&#115;&#46;&#111;&#114;&#103;">mailing
list specifically for ViewVC developers</a>. You can subscribe to
these lists (and other project lists), as well view the list
archives, <a
href="http://viewvc.tigris.org/servlets/ProjectMailingListList"
>here</a>. If you are having problems with ViewVC, consider
checking our <a href="./faq.html">Frequently Asked Questions</a>
page and list of <a
href="http://viewvc.tigris.org/issues/buglist.cgi?component=viewvc&amp;issue_status=UNCONFIRMED&amp;issue_status=NEW&amp;issue_status=STARTED&amp;issue_status=REOPENED"
>open issues</a> before mail our users@ list &mdash; perhaps the
information you need is already available in one of those
places.</p>
<p>If you prefer interaction that's a little more real-time, use your
favorite IRC client to pop into <tt><a
href="irc://irc.freenode.net/viewvc">#viewvc</a></tt> on
irc.freenode.net.</p>
<p>So, to summarize:</p>
<ul>
<li>To discuss ViewVC installation, configuration, and behavior: &#117;&#115;&#101;&#114;&#115;&#64;&#118;&#105;&#101;&#119;&#118;&#99;&#46;&#116;&#105;&#103;&#114;&#105;&#115;&#46;&#111;&#114;&#103;</li>
<li>To discuss the development of ViewVC itself or submit patches: &#100;&#101;&#118;&#64;&#118;&#105;&#101;&#119;&#118;&#99;&#46;&#116;&#105;&#103;&#114;&#105;&#115;&#46;&#111;&#114;&#103;</li>
<li>To discussion anything ViewVC-related in real time: irc.freenode.net, #viewvc</li>
</ul>
</div> <!-- section-body -->
</div> <!-- section -->
</td>
</tr>
</table>
</body>
</html>

View File

@@ -0,0 +1,242 @@
<!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">
<head>
<title>ViewVC: Contributing</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<link rel="stylesheet" type="text/css" href="./styles.css"/>
<link rel="shortcut icon" href="./favicon.ico" type="image/x-icon" />
</head>
<body>
<div id="title">
<a href="http://www.viewvc.org/"><img
src="./images/title.jpg" alt="ViewVC: Repository Browsing"/></a>
</div>
<div id="menu">
<p><a href="./index.html">Home</a> |
<a href="http://viewvc.tigris.org/">Project Page</a> |
<a href="./download.html">Download</a> |
<a href="./contributing.html">Contributing</a> |
<a href="./faq.html">FAQ</a> |
<a href="http://viewvc.tigris.org/nonav/source/browse/*checkout*/viewvc/trunk/LICENSE.html">License</a> |
<a href="./contact.html">Contact</a> |
<a href="./who.html">About</a>
</p>
</div>
<table id="pagetable">
<tr>
<td id="pagecolumn1">
<h4>On this page:</h4>
<ul id="bookmarks">
<li><a href="#sec-getting-started">Getting Started</a></li>
<li><a href="#sec-testing">Testing and Reporting</a></li>
<li><a href="#sec-coding-style">Coding Style</a></li>
<li><a href="#sec-patches">Submitting Patches</a></li>
<li><a href="#sec-security">Security</a></li>
<li><a href="#sec-adding-features">Adding Features</a></li>
<li><a href="#sec-templates">Hacking on Templates</a></li>
</ul>
<p><a href="http://validator.w3.org/check?uri=referer"><img
src="http://www.w3.org/Icons/valid-xhtml10"
alt="Valid XHTML 1.0 Strict" height="31" width="88" /></a>
</p>
</td>
<td id="pagecolumn2">
<div class="section">
<h2 id="sec-getting-started">Getting Started</h2>
<div class="section-body">
<p>Some basic knowledge about <a
href="http://www.python.org">Python</a> and development tools like
<code>diff</code> is required. Your best bet is to start with a
fresh source code snapshot, which you may obtain from our
Subversion repository (see instructions <a
href="./download.html#sec-subversion">here</a>).</p>
<p>Version control history can be obtained using Subversion clients,
but is also browsable using <a
href="http://viewvc.tigris.org/source/browse/viewvc/trunk/"
>tigris.org's integrated ViewVC tool</a>.</p>
</div> <!-- section-body -->
</div> <!-- section -->
<div class="section">
<h2 id="sec-testing">Testing and Reporting</h2>
<div class="section-body">
<p>Testing usability and the installation process on different
platforms is also a valuable contribution. Please report your
results back to us developers. Bandwidth is getting cheaper daily,
so don't be afraid &mdash; in fact, feel encouraged &mdash; to dump
as much detail about the problems you are seeing as possible into
your bug reports. Here are some things you definitely should
try to include:</p>
<ul>
<li>What version of ViewVC you are using (if you are using a source
snapshot, tell us the date of that snapshot).</li>
<li>What operating system your ViewVC is running on.</li>
<li>What version of Python you are using.</li>
<li>Whether you are running ViewVC standalone, or as a CGI program
under a web server (and if so, what web server).</li>
<li>The URL of your ViewVC instantiation, if it is public.
Sometimes, letting developers see the problem for themselves can
save everyone alot of time.</li>
</ul>
</div> <!-- section-body -->
</div> <!-- section -->
<div class="section">
<h2 id="sec-coding-style">Coding Style</h2>
<div class="section-body">
<p>Unlike its predecessor, CvsWeb, ViewVC is written in Python, so it
doesn't suffer from the "unmaintainable code effect" that hits most
Perl projects sooner or later:</p>
<blockquote>
<p>&quot;[Perl] combines all the worst aspects of C and Lisp: a
billion different sublanguages in one monolithic executable. It
combines the power of C with the readability of
PostScript.&quot; &mdash;&nbsp;Jamie&nbsp;Zawinski
</p>
</blockquote>
<p>Of course, a symphony of insanity can be composed in any language,
so we do try to stick to some basic guiding principles. Maintain
whatever style is present in the code being modified. New code can
use anything sane (which generally means <a
href="http://www.python.org/dev/peps/pep-0008/">PEP&nbsp;8</a>).
Our only real peeve is if someone writes a function call as:
<code>some_func&nbsp;(args)</code> &mdash; that space between the
function name and opening parenthesis is Huge Badness. Oh, and we
do <strong>not</strong> use Subversion keywords (such as
<code>$</code><code>Id$</code>) within the source.</p>
<p>Otherwise&hellip; <em>shrug</em>.</p>
</div> <!-- section-body -->
</div> <!-- section -->
<div class="section">
<h2 id="sec-patches">Submitting Patches</h2>
<div class="section-body">
<p>Nothing speaks more loudly when bugs or features are the topic than
a patch. And quite frankly, sometimes if you want something done,
you gotta do it yourself. So, patches are always welcome. If you
aren't sure what exactly a &quot;patch&quot; is, or don't know how
to generate one, but you've got code contributions to make, please
don't hesitate to ask questions on the mailing lists. Patch
generation and application are pretty easy thing to get the hang of,
and drastically simplify code submission and review.</p>
<p>Please use the <a
href="http://viewvc.tigris.org/servlets/ProjectIssues">Issue
Tracker</a> to submit your patches. Unified contextual diffs
against the latest development snapshot are preferred.</p>
<p>If you have commit access, then you should know what you're doing.
Just make changes directly. Subscribing to the <a
href="http://viewvc.tigris.org/servlets/ProjectMailingListList"
><tt>dev@</tt> developer mailing list</a> is recommended in any
case.</p>
</div> <!-- section-body -->
</div> <!-- section -->
<div class="section">
<h2 id="sec-security">Security</h2>
<div class="section-body">
<p>Since ViewVC is used on the Internet, security is a major concern.
If you need to pass data from the request into an external program,
please don't use <code>os.system()</code> or
<code>os.popen()</code>. Please use the module
<code>lib/popen.py</code> that is included in the ViewVC
distribution instead.</p>
</div> <!-- section-body -->
</div> <!-- section -->
<div class="section">
<h2 id="sec-adding-features">Adding Features</h2>
<div class="section-body">
<p>If you need a new configuration option think carefully, into which
section it belongs. Try to keep the content of
<code>cgi/viewvc.conf.dist</code> file and the library module
<code>lib/config.py</code> in sync.</p>
<p>Because ViewVC is a Web-based application, people will have ViewVC
URLs hyperlinked from other sites, embedded in emails, bookmarked
in their browsers, etc. It is very important to ensure that those
URLs continue to retrieve the information they were intended to
retrieve even if ViewVC is upgraded on the hosting server. In
other words, as new features require modifications to the <a
href="./url-reference.html">ViewVC URL schema</a>, make sure those
modifications preserve the existing functionality of all ViewVC
URLs.</p>
<p>The library subdirectory contains a module <code>debug.py</code>,
which you may find useful for performance testing.</p>
<p>If a new file or module is added, a new line in the installer
program <code>viewvc-install</code> is required.</p>
</div> <!-- section-body -->
</div> <!-- section -->
<div class="section">
<h2 id="sec-templates">Hacking on Templates</h2>
<div class="section-body">
<p>The library module <code>ezt.py</code> contains a module docstring
which describes the directives used in the HTML templates used by
ViewVC. The templates themselves can be found in the
<code>templates</code> subdirectory. We're currently developing a
how-to guide for
<a href="http://viewvc.tigris.org/source/browse/viewvc/trunk/docs/template-authoring-guide.html?rev=HEAD"
>ViewVC template customization</a>.</p>
</div> <!-- section-body -->
</div> <!-- section -->
</td>
</tr>
</table>
</body>
</html>

121
viewvc.org/download.html Normal file
View File

@@ -0,0 +1,121 @@
<!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">
<head>
<title>ViewVC: Download</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<link rel="stylesheet" type="text/css" href="./styles.css"/>
<link rel="shortcut icon" href="./favicon.ico" type="image/x-icon" />
</head>
<body>
<div id="title">
<a href="http://www.viewvc.org/"><img
src="./images/title.jpg" alt="ViewVC: Repository Browsing"/></a>
</div>
<div id="menu">
<p><a href="./index.html">Home</a> |
<a href="http://viewvc.tigris.org/">Project Page</a> |
<a href="./download.html">Download</a> |
<a href="./contributing.html">Contributing</a> |
<a href="./faq.html">FAQ</a> |
<a href="http://viewvc.tigris.org/nonav/source/browse/*checkout*/viewvc/trunk/LICENSE.html">License</a> |
<a href="./contact.html">Contact</a> |
<a href="./who.html">About</a>
</p>
</div>
<table id="pagetable">
<tr>
<td id="pagecolumn1">
<h4>On this page:</h4>
<ul id="bookmarks">
<li><a href="#sec-download">Downloading</a></li>
<li><a href="#sec-subversion">Subversion Checkout</a></li>
<li><a href="#sec-upgrading">Upgrading</a></li>
</ul>
<p><a href="http://validator.w3.org/check?uri=referer"><img
src="http://www.w3.org/Icons/valid-xhtml10"
alt="Valid XHTML 1.0 Strict" height="31" width="88" /></a>
</p>
</td>
<td id="pagecolumn2">
<div class="section">
<h2 id="sec-download">Downloading</h2>
<div class="section-body">
<p>You can download the latest release of ViewVC (and the older ViewVC
and ViewCVS releases, too) from our <a
href="http://viewvc.tigris.org/servlets/ProjectDocumentList?folderID=6004"
>Documents &amp; Files</a> area. For information about what has
changed in each release, see the <a
href="http://viewvc.tigris.org/source/browse/viewvc/trunk/CHANGES?rev=HEAD"
>CHANGES</a> file.</p>
<p>We are also making <a href="./nightly/">nightly snapshots</a>
available in tar.gz and zip formats.</p>
</div> <!-- section-body -->
</div> <!-- section -->
<div class="section">
<h2 id="sec-subversion">Subversion Checkout</h2>
<div class="section-body">
<p>The source code for ViewVC is maintained in a Subversion repository
at Tigris.org. You can checkout the trunk of our development tree
from <a href="http://viewvc.tigris.org/svn/viewvc/trunk/"
>http://viewvc.tigris.org/svn/viewvc/trunk/</a>. You'll
need to provide your Tigris.org username and password when so
prompted, or, if you don't have a Tigris.org account, use "guest"
as the username (with no, or an empty, password).</p>
</div> <!-- section-body -->
</div> <!-- section -->
<div class="section">
<h2 id="sec-upgrading">Upgrading</h2>
<div class="section-body">
<p>We've tried to ensure that ViewVC URLs are stable, and that even
when we deprecate a particular URL syntax, we continue to support
the handling of it (using HTTP redirects to point browsers to the
new form of that URL). We know that ViewVC URLs get bookmarked,
and nobody likes when their bookmarked URLs suddenly stop working.</p>
<p>Across patch releases of ViewVC (when only the <em>Z</em> component
of <em>version X.Y.Z</em> changes), we do our best to keep the
configuration file syntax and template data dictionary unchanged,
too. This makes it much easier for folks who need to upgrade
quickly to get security or other bug fixes. But across major and
minor releases, all bets are off, and chances are good that we've
done some major plumbing. When upgrading your ViewVC instance
across major or minor version numbers, you'll almost certainly want
to consult our
<a href="http://viewvc.tigris.org/source/browse/viewvc/trunk/docs/upgrading-howto.html?rev=HEAD"
>upgrading HOWTO</a> for tips on how to migrate your configuration
files and any template customizations you've made into their new
formats.</p>
</div> <!-- section-body -->
</div> <!-- section -->
</td>
</tr>
</table>
</body>
</html>

394
viewvc.org/faq.html Normal file
View File

@@ -0,0 +1,394 @@
<!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">
<head>
<title>ViewVC: Frequently Asked Questions (FAQ)</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<link rel="stylesheet" type="text/css" href="./styles.css"/>
<link rel="shortcut icon" href="./favicon.ico" type="image/x-icon" />
</head>
<body>
<div id="title">
<a href="http://www.viewvc.org/"><img
src="./images/title.jpg" alt="ViewVC: Frequently Asked Questions (FAQ)"/></a>
</div>
<div id="menu">
<p><a href="./index.html">Home</a> |
<a href="http://viewvc.tigris.org/">Project Page</a> |
<a href="./download.html">Download</a> |
<a href="./contributing.html">Contributing</a> |
<a href="./faq.html">FAQ</a> |
<a href="http://viewvc.tigris.org/nonav/source/browse/*checkout*/viewvc/trunk/LICENSE.html">License</a> |
<a href="./contact.html">Contact</a> |
<a href="./who.html">About</a>
</p>
</div>
<table id="pagetable">
<tr>
<td id="pagecolumn1">
<h4>On this page:</h4>
<ul id="bookmarks">
<li><a href="#faq-q">Questions</a></li>
<li><a href="#faq-a">Answers</a></li>
</ul>
<p><a href="http://validator.w3.org/check?uri=referer"><img
src="http://www.w3.org/Icons/valid-xhtml10"
alt="Valid XHTML 1.0 Strict" height="31" width="88" /></a>
</p>
</td>
<td id="pagecolumn2">
<div class="section">
<!-- ##################################################################### -->
<h2 id="faq-q">Questions</h2>
<!-- ##################################################################### -->
<div class="section-body">
<!-- #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# -->
<h3 class="faq-section" id="faq-q-general">General Usage</h3>
<!-- #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# -->
<ul>
<li><a href="#installation">Where does the installation documentation,
if any, live?</a></li>
<li><a href="#vhost-root">How can I expose ViewVC at the root of a
virtual host on my webserver?</a></li>
<li><a href="#authz-support">Does ViewVC support path-based
authorization, such as Subversion's authz-file mechanism?</a></li>
<li><a href="#missing-tmpdir">What causes "Error: OSError: [Errno 2] No such file
or directory: '/tmp/tmpGc-Ztj'"?</a></li>
<li><a href="#standalone-only">Why does <em>SOME-FEATURE</em>
work under standalone.py, but not under Apache (or IIS or
&hellip;)?</a></li>
<li><a href="#rss-support">How do I enable ViewVC's RSS feed
capabilities?</a></li>
</ul>
<!-- #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# -->
<h3 class="faq-section" id="faq-q-cvs">CVS Browsing</h3>
<!-- #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# -->
<ul>
<li><a href="#error-displaying-cvs-files">Why can I navigate only those CVS
directories that have no files in them?</a></li>
<li><a href="#rlog-output-ended-early">What causes "Error: Rlog output ended
early. Expected RCS file "/opt/cvs/project/file,v""?</a></li>
<li><a href="#comalformedoutput">What causes "Error: COMalformedOutput: Unable to
find filename in co output stream"?</a></li>
<li><a href="#error-during-rlog">What causes "Error: error during
rlog: 0x100"?</a></li>
<li><a href="#missing-files">Why do my directories have no files in them?</a></li>
<li><a href="#none-match">ViewVC doesn't show files I'm looking for,
and instead displays the message "NOTE: There are N files, but
none match the current selection criteria". How can I fix this?</a></li>
</ul>
<!-- #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# -->
<h3 class="faq-section" id="faq-q-svn">Subversion Browsing</h3>
<!-- #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# -->
<ul>
<li><a href="#no-module-named-svn">What causes "Error: ImportError: No module named
svn"?</a></li>
<li><a href="#remote-svn-access">Can I use ViewVC with remote
Subversion repositories?</a></li>
</ul>
<!-- #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# -->
</div>
</div>
<div class="section">
<!-- ##################################################################### -->
<h2 id="faq-a">Answers</h2>
<!-- ##################################################################### -->
<div class="section-body">
<!-- #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# -->
<h3 class="faq-section" id="faq-a-general">General Usage</h3>
<!-- #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# -->
<div id="installation">
<p class="faq-atitle">Where does the installation documentation, if
any, live?</p>
<p>ViewVC's installation how-to documentation lives in the INSTALL
file located in the root of the ViewVC source code distribution.
The most recent version of this document (which may cover
unreleased ViewVC versions) can be found
at <a href="http://viewvc.tigris.org/source/browse/*checkout*/viewvc/trunk/INSTALL"
>http://viewvc.tigris.org/source/browse/*checkout*/viewvc/trunk/INSTALL</a>.
If you are upgrading an existing ViewVC instance, you'll also want
to read the upgrade documentation, found
at <a href="http://viewvc.tigris.org/source/browse/*checkout*/viewvc/trunk/docs/upgrading-howto.html"
>http://viewvc.tigris.org/source/browse/*checkout*/viewvc/trunk/docs/upgrading-howto.html</a>.</p>
</div>
<div id="vhost-root">
<p class="faq-atitle">How can I expose ViewVC at the root of a virtual
host on my webserver?</p>
<p>If you want to dedicate a virtual host on your server just to
ViewVC, such the root directory of that host maps to ViewVC's root
display, you can do so by placing the following lines inside
the <code>VirtualHost</code>Apache configuration:</p>
<blockquote><pre>Alias /docroot /usr/local/viewvc/templates/docroot
ScriptAlias / /usr/local/viewvc/bin/cgi/viewvc.cgi/</pre></blockquote>
<p>The trick appears to be the presence of the trailing slash
character on the <code>ScriptAlias</code> directive.</p>
</div>
<div id="authz-support">
<p class="faq-atitle">Does ViewVC support path-based authorization,
such as Subversion's authz-file mechanism?</p>
<p>This feature is available in ViewVC 1.1.0, which you can get from
our <a href="http://viewvc.org/download.html" >Download</a>
page.</p>
<p>If you prefer to use only final releases, there are some available
workarounds. For example, if you are running ViewVC under Apache,
you can use regular Apache configuration directives to
authz-protect areas of your repository &mdash; see
the <a href="http://httpd.apache.org/docs/2.2/mod/core.html#location"
>Location</a>
and <a href="http://httpd.apache.org/docs/2.2/mod/core.html#locationmatch"
>LocationMatch</a> directives, as well as
the <a href="http://httpd.apache.org/docs/2.2/howto/auth.html"
>Authentication, Authorization and Access Control</a> portions of
the Apache HTTP Server documentation. This works best when ViewVC
is only serving up a single repository, or when the
<code>root_as_url_component</code> option is enabled otherwise.
And you might have to disable the checkout view, or at least turn
off the use of <code>checkout_magic</code> (see
<code>viewvc.conf</code> for details).</p>
</div>
<div id="missing-tmpdir">
<p class="faq-atitle">What causes "Error: OSError: [Errno 2] No such
file or directory: '/tmp/tmpGc-Ztj'"?</p>
<p>This is tracked in <a
href="http://viewvc.tigris.org/issues/show_bug.cgi?id=282">issue
#282</a>. While we haven't figured out how to make the error
message more graceful or helpful, the basic problem seems to
generally boil down to a misconfiguration of ViewVC. Make sure
your helper applications are in the program search path
(<code>$PATH</code>, e.g.) on your ViewVC server, or accurately
specified in <code>viewvc.conf</code>.</p>
</div>
<div id="standalone-only">
<p class="faq-atitle">Why does <em>SOME-FEATURE</em> work under
standalone.py, but not under Apache (or IIS or &hellip;)?</p>
<p>Most of the time folks run standalone.py, they do so as a regular
system user, from a shell running with any and all the
environmental customizations present in their shell startup
scripts. But most web server packages (like Apache) run as a
different, often underprivileged, user, whose environment is
stripped down to just the system-wide default state. This can
cause problems for ViewVC's various helper applications, which
might reside in a location that's included as part of your (and
thus standalone.py's) <code>$PATH</code>, but not that of the user
as whom the web server package runs. The solution might be as
simple explicitly configuring the paths of the helper applications
in <code>viewvc.conf</code>, or as complex as expanding the program
search path used by your web server software.</p>
</div>
<div id="rss-support">
<p class="faq-atitle">How do I enable ViewVC's RSS feed capabilities?</p>
<p>ViewVC generates its RSS feeds from repository data mirrored in a
database as part of its MySQL integration. Follow the steps in
ViewVC's <code>INSTALL</code> file to setup and configure the MySQL
integration and begin mirroring your commit metadata in the
database &mdash; the RSS feed feature will then be enabled with no
additional configuration.</p>
</div>
<!-- #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# -->
<h3 class="faq-section" id="faq-a-cvs">CVS Browsing</h3>
<!-- #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# -->
<div id="error-displaying-cvs-files">
<p class="faq-atitle">Why can I navigate only those CVS directories
that have no files in them?</p>
<p>ViewVC can generally display CVS directories without the use of any
external tools. But unless configured to use the incomplete,
experimental rcsparse module (via the <code>use_rcsparse</code>
configuration option), it relies on either the RCS toolchain or the
CVSNT tool (on Windows) to get information about versioned files.
If the system is missing both of these, you'll need to remedy that.
If ViewVC simply cannot find the installed tools, ensure that they
are available in the system <code>$PATH</code>, or specify their
location in the <code>viewvc.conf</code> file using
the <code>utilities/rcs_dir</code> or <code>utilities/cvsnt</code>
options. (Note that prior to ViewVC 1.1.0, these options were found
at <code>general/rcs_path</code>
and <code>general/cvsnt_exe_path</code>.)</p>
</div>
<div id="rlog-output-ended-early">
<p class="faq-atitle">What causes "Error: Rlog output ended
early. Expected RCS file "/opt/cvs/project/file,v""?</p>
<p>This is another symptom of the basic problem described <a
href="#error-displaying-cvs-files">here</a>.</p>
</div>
<div id="comalformedoutput">
<p class="faq-atitle">What causes "Error: COMalformedOutput: Unable to
find filename in co output stream"?</p>
<p>This is another symptom of the basic problem described <a
href="#error-displaying-cvs-files">here</a>.</p>
</div>
<div id="error-during-rlog">
<p class="faq-atitle">What causes "Error: error during rlog:
0x100"?</p>
<p>### TODO ###</p>
</div>
<div id="missing-files">
<p class="faq-atitle">Why do my directories have no files in them?</p>
<p>There are a few reasons why this can happen. Here are some of the
most common ones:</p>
<ul>
<li>Some folks mistakenly point ViewVC's configuration bits to their
CVS working copies. But ViewVC isn't a working copy browser
&mdash; it's a <em>repository</em> browser. If you don't know
the difference, here's a tip that might help: CVS repositories
are directories trees filled with files that end with
"<code>,v</code>". If your directory isn't filled with "comma
vee" files, it probably is <em>not</em> a CVS repository.</li>
<li>&hellip; <!-- TODO --></li>
</ul>
</div>
<div id="none-match">
<p class="faq-atitle">ViewVC doesn't show files I'm looking for, and
instead displays the message "NOTE: There are N files, but none
match the current selection criteria". How can I fix this?</p>
<p>From time to time, CVS and CVSNT add support for new keywords to
the RCS backend used to house repository data. If you're running a
version of ViewVC or ViewCVS that hasn't yet learned to handle
those new keywords, you might get the error you're seeing. The
solution is to try to get versions of CVS/CVSNT and ViewVC which
are better aligned, which generally means upgrading ViewVC (which
is probably less disruptive than downgrading your version control
system).</p>
</div>
<!-- #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# -->
<h3 class="faq-section" id="faq-a-svn">Subversion Browsing</h3>
<!-- #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# -->
<div id="no-module-named-svn">
<p class="faq-atitle">What causes "Error: ImportError: No module named
svn"?</p>
<p>ViewVC uses Subversion's Python bindings to interact with and pull
information out of your Subversion repositories. These bindings
are not, however, generally provided as part of the ViewVC
distribution &mdash; you have to install them yourself some other
way. (For more information, contact the <a
href="http://subversion.tigris.org">Subversion</a> community.) The
error you see is Python being asked to import the Subversion Python
bindings and being unable to do so, typically because the bindings
modules aren't found in the Python library search path.</p>
</div>
<div id="remote-svn-access">
<p class="faq-atitle">Can I use ViewVC with remote Subversion
repositories?</p>
<p>ViewVC prefers to have direct access to the repository (and in
fact, <em>must</em> have that for CVS repositories), but there does
exist experimental support for remote Subversion repositories.
Enabling this is a fairly simple &mdash; just use the URL of the
repository where you would use its path in the
<code>svn_roots</code> configuration options (sorry, you can't use
<code>root_parents</code> for remote repositories because
Subversion doesn't expose a repository-listing repository access
API).</p>
<p>What you should expect:</p>
<ul>
<li><p>Near parity with local-access Subversion in terms of
functionality.</p></li>
<li><p>Known shortcomings:</p>
<ul>
<li>file sizes aren't reported everywhere</li>
<li>the "revision" view lacks/botches some information</li>
<li>she ain't the fastest horse on the track&hellip;</li>
</ul>
</li>
<li><p>Lack of configury for dealing with the intricacies of remote
access. If the auth credentials and such you need to access
the remote repository aren't cached in
<code>~VIEWVC_USER/.subversion</code> (where
<code>VIEWVC_USER</code> is the system user as whom ViewVC
runs), stuff won't work.</p></li>
</ul>
<!-- #- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -# -->
</div>
</div>
</div> <!-- section -->
</td>
</tr>
</table>
</body>
</html>

BIN
viewvc.org/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

BIN
viewvc.org/images/title.jpg Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
viewvc.org/images/title.xcf Normal file

Binary file not shown.

186
viewvc.org/index.html Normal file
View File

@@ -0,0 +1,186 @@
<!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">
<head>
<title>ViewVC: Repository Browsing</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<link rel="stylesheet" type="text/css" href="./styles.css"/>
<link rel="shortcut icon" href="./favicon.ico" type="image/x-icon" />
</head>
<body>
<div id="title">
<a href="http://www.viewvc.org/"><img
src="./images/title.jpg" alt="ViewVC: Repository Browsing"/></a>
</div>
<div id="menu">
<p><a href="./index.html">Home</a> |
<a href="http://viewvc.tigris.org/">Project Page</a> |
<a href="./download.html">Download</a> |
<a href="./contributing.html">Contributing</a> |
<a href="./faq.html">FAQ</a> |
<a href="http://viewvc.tigris.org/nonav/source/browse/*checkout*/viewvc/trunk/LICENSE.html">License</a> |
<a href="./contact.html">Contact</a> |
<a href="./who.html">About</a>
</p>
</div>
<table id="pagetable">
<tr>
<td id="pagecolumn1">
<h4>On this page:</h4>
<ul id="bookmarks">
<li><a href="#sec-what-is-viewvc">What Is ViewVC?</a></li>
<li><a href="#sec-requirements">Requirements</a></li>
</ul>
<p><a href="http://validator.w3.org/check?uri=referer"><img
src="http://www.w3.org/Icons/valid-xhtml10"
alt="Valid XHTML 1.0 Strict" height="31" width="88" /></a>
</p>
</td>
<td id="pagecolumn2">
<div class="section">
<h2 id="sec-what-is-viewvc">What Is ViewVC?</h2>
<div class="section-body">
<p>ViewVC is a browser interface for CVS and Subversion version
control repositories. It generates templatized HTML to present
navigable directory, revision, and change log listings. It can
display specific versions of files as well as diffs between those
versions. Basically, ViewVC provides the bulk of the report-like
functionality you expect out of your version control tool, but much
more prettily than the average textual command-line program
output.</p>
<p>Here are some of the additional features of ViewVC:</p>
<ul>
<li>Support for filesystem-accessible CVS and Subversion
repositories.</li>
<li>Support for path-based authorization, including parsing and
honoring Subversion authz configuration files.</li>
<li>RSS feed generation for tracking changes to repositories or
individual items within repositories.</li>
<li>Individually configurable virtual host support.</li>
<li>Line-based annotation/blame display.</li>
<li>Revision graph capabilities (via integration with <a
href="http://www.akhphd.au.dk/~bertho/cvsgraph/">CvsGraph</a>)
(<em>CVS only</em>).</li>
<li>Syntax highlighting support.</li>
<li><a href="http://www.mozilla.org/projects/bonsai/">Bonsai</a>-like
repository query facilities.</li>
<li>Template-driven output generation.</li>
<li>Colorized, side-by-side differences.</li>
<li>Tarball generation (by tag/branch for CVS, by revision for
Subversion).</li>
<li>Localization support based on the Accept-Language request
header.</li>
<li>Ability to run either as CGI script or as a standalone
server.</li>
<li>Regexp-based file searching.</li>
<li>INI-like configuration file (as opposed to requiring actual code
tweaks).</li>
</ul>
<p>For a complete list of changes present in each release, see
ViewVC's <a
href="http://viewvc.tigris.org/source/browse/viewvc/trunk/CHANGES?rev=HEAD"
>CHANGES</a> file.</p>
</div> <!-- section-body -->
</div> <!-- section -->
<div class="section">
<h2 id="sec-requirements">Requirements</h2>
<div class="section-body">
<p>The only hard software requirement for running ViewVC is <a
href="http://www.python.org/">Python 1.5.2</a> or later. All other
requirements depend on what you want to do with the tool.</p>
<p>For use with Subversion repositories, you need these things:</p>
<ul>
<li><a href="http://subversion.tigris.org/">Subversion</a> 1.2 or
later and its SWIG Python bindings.</li>
<li><a href="http://www.gnu.org/software/diffutils/diffutils.html">GNU
diff</a></li>
<li>Physical access to a Subversion repository (though there is
limited, use-at-your-risk support for remote access, too).</li>
</ul>
<p>If you plan to use ViewVC with CVS repositories, you need the
following things:</p>
<ul>
<li><a href="http://www.cs.purdue.edu/homes/trinkle/RCS/">RCS</a>
(Revision Control System)</li>
<li><a href="http://www.gnu.org/software/diffutils/diffutils.html">GNU
diff</a></li>
<li>Read-only, physical access to a CVS repository.</li>
</ul>
<p>ViewVC integrates with additional pieces of software to provide
certain bits of optional functionality:</p>
<ul>
<li><a href="http://httpd.apache.org/">Apache HTTP Server</a>, or
another server capable of running CGI programs &mdash; unless
you just want ViewVC to run in standalone server mode.</li>
<li><a href="http://www.mysql.com/">MySQL</a> &mdash; Needed to use
the commit database query functionality.</li>
<li><a href="http://pygments.org/">Pygments</a> &mdash; Needed for
syntax highlighting in versioned file contents
displays.</li>
<li><a href="http://www.akhphd.au.dk/~bertho/cvsgraph/">CvsGraph</a>
&mdash; Needed for version graph displays.</li>
</ul>
</div> <!-- section-body -->
</div> <!-- section -->
</td>
</tr>
</table>
</body>
</html>

View File

@@ -0,0 +1,219 @@
#!/usr/bin/env python
import sys
import os
import time
import urllib
import shutil
import getopt
import tempfile
class BuildError(Exception):
def __init__(self, message):
self.message = message
def __str__(self):
return self.message
def make_release(branch, export_dir, publish_dir, root_url, username, password):
# Export the requested ViewVC source tree.
cmd = "svn export --quiet '%s/%s' %s " \
"--username '%s' --password '%s' --non-interactive --force" \
% (root_url, urllib.quote(branch), export_dir, username, password)
sys.stdout.write("Running: %s\n" % (cmd))
os.system(cmd)
# Get the version number from ViewVC itself.
sys.path.insert(0, os.path.join(export_dir, 'lib'))
try:
import viewvc
except ImportError:
raise BuildError("Unable to import viewvc module; export failed?")
version = viewvc.__version__
del sys.modules['viewvc']
del viewvc
del sys.path[0]
# Now, use ViewVC tools to make the distribution archives.
localtime = time.localtime()
date = "%4d%02d%02d" % (localtime[0], localtime[1], localtime[2])
distversion = "viewvc-%s" % (version)
distname = "%s-%s" % (distversion, date)
gzip_name = distname + '.tar.gz'
zip_name = distname + '.zip'
curdir = os.getcwd()
try:
os.chdir(os.path.join(export_dir, 'tools'))
os.system('./make-release %s %s' % (distname, branch))
finally:
os.chdir(curdir)
# Finally, return the locations of the archive files we've built.
gzip_file = os.path.join(export_dir, 'tools', gzip_name)
if not os.path.exists(gzip_file):
gzip_file = None
zip_file = os.path.join(export_dir, 'tools', zip_name)
if not os.path.exists(zip_file):
zip_file = None
# Remove superceded archives.
if gzip_file or zip_file:
dirents = os.listdir(publish_dir)
for dirent in dirents:
if dirent.startswith(distversion) \
and ((dirent.endswith('.tar.gz') and gzip_file) \
or (dirent.endswith('.zip') and zip_file)):
os.unlink(dirent)
# Install the new archives.
if gzip_file:
os.rename(gzip_file, os.path.join(publish_dir, gzip_name))
if zip_file:
os.rename(zip_file, os.path.join(publish_dir, zip_name))
# Return our archive names.
return gzip_file and gzip_name or None, zip_file and zip_name or None
def publish_releases(branches, publish_dir, root_url, username, password):
new_index_contents = get_html_index_header()
for branch in branches:
sys.stdout.write("Beginning build for branch '%s'.\n" % (branch))
export_dir = None
try:
export_dir = tempfile.mkdtemp("", "viewvc-nightly-")
gzip_file, zip_file = make_release(branch, export_dir, publish_dir,
root_url, username, password)
new_index_contents = new_index_contents + """
<p>Build of %s:</p>
<ul>
<li><a href="%s">%s</a></li>
<li><a href="%s">%s</a></li>
</ul>
""" % (branch, urllib.quote(gzip_file), gzip_file,
urllib.quote(zip_file), zip_file)
finally:
if export_dir:
sys.stdout.write("Removing temporary directory '%s'.\n" % (export_dir))
shutil.rmtree(export_dir)
sys.stdout.write("Finished build for branch '%s'.\n" % (branch))
new_index_contents = new_index_contents + get_html_index_footer()
open(os.path.join(publish_dir, 'index.html'), 'w').write(new_index_contents)
def get_html_index_header():
return """
<!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">
<head>
<title>ViewVC: Nightly Snapshots</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<link rel="stylesheet" type="text/css" href="../styles.css"/>
<link rel="shortcut icon" href="../favicon.ico" type="image/x-icon" />
</head>
<body>
<div id="title">
<a href="http://www.viewvc.org/"><img
src="../images/title.jpg" alt="ViewVC: Repository Browsing"/></a>
</div>
<div id="menu">
<p><a href="../index.html">Home</a> |
<a href="http://viewvc.tigris.org/">Project Page</a> |
<a href="../download.html">Download</a> |
<a href="../contributing.html">Contributing</a> |
<a href="./faq.html">FAQ</a> |
<a href="http://viewvc.tigris.org/nonav/source/browse/*checkout*/viewvc/trunk/LICENSE.html">License</a> |
<a href="../contact.html">Contact</a> |
<a href="../who.html">About</a>
</p>
</div>
<table id="pagetable">
<tr>
<td id="pagecolumn1">
<h4>On this page:</h4>
<ul id="bookmarks">
<li><a href="%s">Snapshots</a></li>
</ul>
<p><a href="http://validator.w3.org/check?uri=referer"><img
src="http://www.w3.org/Icons/valid-xhtml10"
alt="Valid XHTML 1.0 Strict" height="31" width="88" /></a>
</p>
</td>
<td id="pagecolumn2">
<div class="section">
<h2 id="sec-snapshots">Snapshots</h2>
<div class="section-body">
""" % ("#sec-snapshots")
def get_html_index_footer():
return """
</div> <!-- section-body -->
</div> <!-- section -->
</td>
</tr>
</table>
</body>
</html>
"""
def usage_and_exit(errmsg=None):
stream = errmsg and sys.stderr or sys.stdout
progname = os.path.basename(sys.argv[0])
stream.write("""%s -- nightly ViewVC build generation
Usage: %s [OPTIONS] PUBLISH-DIR BRANCH ...
Build an archive from one or more BRANCH in the ViewVC source
repository, dropping them into PUBLISH-DIR alongside an index.html
file that name and links to them.
Options:
--help (-h, -?) : Show this usage message
--username : Username used for source export
--password : Password used for source export
--root-url : Alternative source repository root URL
""" % (progname, progname))
if errmsg:
stream.write("ERROR: %s\n" % (errmsg))
sys.exit(errmsg and 1 or 0)
if __name__ == "__main__":
root_url = "http://viewvc.tigris.org/svn/viewvc"
username = password = ""
opts, args = getopt.getopt(sys.argv[1:], 'h?',
['help', 'username=', 'password=', 'root-url='])
for name, value in opts:
if name == '-h' or name == '-?' or name == '--help':
usage_and_exit()
elif name == '--username':
username = value
elif name == '--password':
password = value
elif name == '--root-url':
root_url = value
argc = len(args)
if argc < 2:
usage_and_exit("Not enough arguments")
try:
publish_releases(args[1:], args[0], root_url, username, password)
except BuildError, e:
sys.stderr.write(str(e) + "\n")
sys.exit(1)

169
viewvc.org/styles.css Normal file
View File

@@ -0,0 +1,169 @@
body {
background-color: #b2d388;
color: black;
font-family: trebuchet ms, arial, sans-serif;
margin: 0;
}
#title {
background-color: #739c3e;
height: 70px;
}
img {
border: none;
}
hr {
width: 95%;
height: 1px;
}
address {
font-size: 60%;
font-style: normal;
}
h2 {
background-color: #94bd5e;
padding: 2px 0.5em 2px 0.5em;
margin: 0;
border-bottom: dotted 1px rgb(180,193,205);
font-size: 110%;
}
h3 {
margin: 0;
font-size: 100%;
font-weight: bold;
border-bottom: dotted 1px rgb(180,193,205);
}
h4 {
padding: 2px 0.5em 2px 0.5em;
margin: 0;
font-size: 90%;
font-weight: bold;
}
p, dl {
padding: 0.5em;
margin: 0;
font-size: 90%;
}
ul, ol {
font-size: 90%;
padding: 0.5em;
margin: 0 0 0 0.25in;
}
code {
font-size: 105%;
font-style: italic;
font-family: monospace;
}
blockquote {
text-align: justify;
font-style: italic;
margin: 0 0.5in 0 0.5in;
padding: 5px;
border: 1px dotted black;
}
.section {
background: white;
border-color: rgb(24,24,24);
border-width: 1px;
border-style: solid;
padding: 0;
margin-bottom: 0.5em;
}
.section-body {
padding: 0 1em;
}
.section p, .section dl, .section ul, .section ol {
padding: 0.5em 0;
}
#menu {
background: black;
color: white;
}
#menu a, #menu a:visited {
background: black;
color: white;
text-decoration: none;
}
#menu a:hover {
background: black;
color: white;
text-decoration: underline;
}
#submenu {
background: rgb(90%,97%,99%);
font-size: 80%;
}
#pagetable tr {
vertical-align: top;
}
#pagetable {
width: 100%;
}
#pagecolumn1 {
width: 175px;
padding: 1em 0 0 0;
}
#pagecolumn1 a, #pagecolumn1 a:visited {
color: rgb(0,0,164);
text-decoration: none;
}
#pagecolumn1 a:hover {
text-decoration: underline;
}
#pagecolumn2 {
padding: 1em 2em;
}
#pagecolumn2 a, #pagecolumn2 a:visited {
color: rgb(0,0,164);
text-decoration: underline;
}
#pagecolumn2 a:hover {
background-color: rgb(180,193,205);
text-decoration: underline;
}
#bookmarks {
padding-left: 0.5em;
font-size: 80%;
white-space: nowrap;
}
.notice {
border: 1px solid black;
margin-bottom: 0.5em;
background: yellow;
}
.faq-section {
margin-top: 1em;
}
.faq-atitle {
font-weight: bold;
}

181
viewvc.org/who.html Normal file
View File

@@ -0,0 +1,181 @@
<!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">
<head>
<title>ViewVC: About</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
<link rel="stylesheet" type="text/css" href="./styles.css"/>
<link rel="shortcut icon" href="./favicon.ico" type="image/x-icon" />
</head>
<body>
<div id="title">
<a href="http://www.viewvc.org/"><img
src="./images/title.jpg" alt="ViewVC: Repository Browsing"/></a>
</div>
<div id="menu">
<p><a href="./index.html">Home</a> |
<a href="http://viewvc.tigris.org/">Project Page</a> |
<a href="./download.html">Download</a> |
<a href="./contributing.html">Contributing</a> |
<a href="./faq.html">FAQ</a> |
<a href="http://viewvc.tigris.org/nonav/source/browse/*checkout*/viewvc/trunk/LICENSE.html">License</a> |
<a href="./contact.html">Contact</a> |
<a href="./who.html">About</a>
</p>
</div>
<table id="pagetable">
<tr>
<td id="pagecolumn1">
<h4>On this page:</h4>
<ul id="bookmarks">
<li><a href="#sec-history">The History of ViewVC</a></li>
<li><a href="#sec-viewcvs-group">The ViewCVS Group</a></li>
<li><a href="#sec-site-credits">About This Site</a></li>
</ul>
<p><a href="http://validator.w3.org/check?uri=referer"><img
src="http://www.w3.org/Icons/valid-xhtml10"
alt="Valid XHTML 1.0 Strict" height="31" width="88" /></a>
</p>
</td>
<td id="pagecolumn2">
<div class="section">
<h2 id="sec-history">The History of ViewVC</h2>
<div class="section-body">
<p>The ViewVC software was inspired by early versions of cvsweb
(originally written by Bill Fenner, further developed by Henner
Zeller, and now maintained as <a
href="http://www.freebsd.org/projects/cvsweb.html">CVSweb</a> by
the FreeBSD community). Greg Stein wanted to make some changes and
updates, but cvsweb was implemented in Perl. He wrote:</p>
<blockquote>
<p>&quot;While I can manage some Perl, cvsweb was rather
unmaintainable for me. So I undertook the task to convert the
software to Python. As a result, I've actually been able to go
<strong>way</strong> beyond the simple changes that I had
envisioned.&quot;
</p>
</blockquote>
<p>So ViewVC started out as just a port of the cvsweb script,
originally called ViewCVS. Along the way, it has had numerous
cleanups and other modifications, a process simplified by the
elegance of the <a href="http://www.python.org/">Python</a>
language.</p>
<p>In 2001, the ViewCVS project was moved to <a
href="http://www.sourceforge.net">SourceForge</a>, a popular
software collaboration environment. There the project continued to
mature, releasing several stable-yet-pre-1.0 versions. In 2002,
C. Michael Pilato began implementing support for Subversion in
ViewCVS, taking advantage of a version control abstraction layer
begun by Lucas Bruand. Along the way, Russell Yanofsky delivered
large improvements to that abstraction, and to ViewCVS as whole.
ViewCVS was well on its way to releasing a 1.0 version.</p>
<p>Of course, now that ViewCVS could browse Subversion repositories as
easily as CVS ones, the ViewCVS name seemed inappropriate. Also,
the active ViewCVS developers at the time were growing frustrated
with SourceForge as a project hosting environment &mdash;
Subversion wasn't yet available as an option for version control,
the CVS service was always down at just the wrong moment, the bug
trackers were painful to use, and so on. So in late 2005, the
decision was made to rename the project to ViewVC, to convert the
project's CVS data to Subversion, and to move the project and its
version controlled and open issue data to <a
href="http://www.tigris.org">Tigris.org</a>.</p>
<p>Today, ViewVC is being developed at <a
href="http://viewvc.tigris.org">http://viewvc.tigris.org</a> by a
small community of folks.</p>
</div> <!-- section-body -->
</div> <!-- section -->
<div class="section">
<h2 id="sec-viewcvs-group">The ViewCVS Group</h2>
<div class="section-body">
<p>The ViewCVS Group is an informal group of people working on and
developing the ViewVC package. The current set of members are
listed below with some of their notable contributions:</p>
<dl>
<dt><a href="http://www.lyra.org/greg/">Greg Stein</a></dt>
<dd>original python port of Henner Zeller's cvsweb, secure popen
implementation, configuration file implementation, rcsparse
module, and EZT template engine</dd>
<dt>Jay Painter</dt>
<dd>CVSdb query engine</dd>
<dt>Tanaka Akira</dt>
<dd>enscript colorization and tarball generation</dd>
<dt>Tim Cera</dt>
<dd>CvsGraph support, log_table template, regular expression search,
and paging capability</dd>
<dt>Peter Funk</dt>
<dd>standalone server, blimp logo, and numerous improvements to
ViewVC's interfaces and documentation</dd>
<dt>Lucas Bruand</dt>
<dd>C++ RCS parser (tparse) and vclib module for supporting new
version control systems</dd>
<dt><a href="http://www.cmichaelpilato.com/">C. Michael Pilato</a></dt>
<dd>Subversion support, root_as_url alternative URL scheme,
templatization work, website design, documentation</dd>
<dt>Russell Yanofsky</dt>
<dd>Windows support and the sapi module for supporting multiple web
server interfaces, sweeping abstraction and UI improvements</dd>
<dt>James Henstridge</dt>
<dd>integrated query interface, support for querying Subversion
repositories, caching support, CSS formatting, and the EZT
&quot;define&quot; directive</dd>
</dl>
</div> <!-- section-body -->
</div> <!-- section -->
<div class="section">
<h2 id="sec-site-credits">About This Site</h2>
<div class="section-body">
<p>The ViewVC website was designed by <a
href="http://www.cmichaelpilato.com/">C. Michael Pilato</a>. All
HTML was hand-edited in Emacs, and the little splashes of graphical
goodness owe their existence to Open Office and the Gimp. Textual
content for the site is mostly the work of Greg Stein, but has been
tweaked through the ages by various ViewVC contributors.</p>
</div> <!-- section-body -->
</div> <!-- section -->
</td>
</tr>
</table>
</body>
</html>

View File

@@ -8,6 +8,7 @@
#longdescription { border: none; }
#longdescription h2 { display: none; }
#customcontent h2 { display: block; }
.h2 { margin-bottom: 2em; }
</style>
<!-- End custom stylations -->
</head>
@@ -18,10 +19,27 @@
<h1>ViewVC &mdash; Web-based Version Control Repository Browsing</h1>
<div class="h2">
<h2>Latest Release</h2>
<div class="h2"
style="border-style: solid;
border-width: 1px 2px 2px 1px;
border-color: black;
background: #eed;
padding: 0.5em;">
<p>The most recent release of ViewVC is: <strong>1.0.7</strong></p>
<h2>Latest Release(s)</h2>
<p>The most recent stable release of ViewVC is: <strong>1.1.2</strong></p>
<ul>
<li><a href="http://www.viewvc.org/download.html"
>Download or checkout</a> this release</li>
<li>See the
<a href="http://viewvc.tigris.org/source/browse/*checkout*/viewvc/tags/1.1.2/CHANGES"
>CHANGES</a> in this release.</li>
<li>Read the
<a href="http://viewvc.tigris.org/source/browse/*checkout*/viewvc/trunk/docs/release-notes/1.1.0.html"
>release notes</a> for this version line.</li>
</ul>
</div>
@@ -45,15 +63,16 @@
<li>Line-based annotation/blame display</li>
<li>Revision graph capabilities (<em>CVS only</em>)</li>
<li>Syntax highlighting support</li>
<li>Path-based authorization</li>
<li>Commit metadata query facilities</li>
<li>Template-driven output generation</li>
<li>Colorized, side-by-side differences</li>
<li>Tarball generation (by tag for CVS, by revision for Subversion)</li>
<li>Localization support based on the Accept-Language request header</li>
<li>Ability to run either as CGI script or as a standalone server</li>
<li>Ability to run as CGI script, under mod_python, or as a
standalone server application</li>
<li>Regexp-based file searching</li>
<li>INI-like configuration file (as opposed to requiring actual code
tweaks)</li>
<li>INI-like configuration file (no code tweaking required)</li>
<li>Localization support based on the Accept-Language request header</li>
</ul>
<p>For a complete list of changes present in each release, see
@@ -66,20 +85,28 @@
<div class="h2">
<h2>Wanna Talk About ViewVC?</h2>
<p>If you have questions about ViewVC &mdash; how to configure it, if
some behavior you are seeing is expected or not, and so on &mdash;
send email to our users list: <a
href="mailto:users@viewvc.tigris.org"
>users@viewvc.tigris.org</a>.</p>
<p>If you'd like to discuss the actual development of ViewVC itself,
or submit a patch to ViewVC's sources, you can do so on our
development list: <a href="mailto:dev@viewvc.tigris.org"
>dev@viewvc.tigris.org</a>.</p>
<p>Finally, if you prefer realtime chatter, use your favorite IRC
client to pop into <tt><a href="irc://irc.freenode.net/viewvc"
>#viewvc</a></tt> on irc.freenode.net.</p>
<table border="0" cellpadding="10" cellspacing="10" style="margin: 0 5%;">
<thead>
<tr style="vertical-align: top;">
<th style="width: 50%;">User/Admin Discussion</th>
<th style="width: 50%;">Developer Discussion</th>
</tr>
</thead>
<tbody>
<tr style="vertical-align: top;">
<td>If you have questions about ViewVC &mdash; how to configure it, if
some behavior you are seeing is expected or not, and so on &mdash;
send email to <a href="mailto:users@viewvc.tigris.org"
>users@viewvc.tigris.org</a> or use your favorite IRC client to
pop into <tt><a href="irc://irc.freenode.net/viewvc"
>#viewvc</a></tt> on irc.freenode.net.</td>
<td>If you'd like to discuss the actual development of ViewVC itself,
or submit a patch to ViewVC's sources, you can do so on our
development list, <a href="mailto:dev@viewvc.tigris.org"
>dev@viewvc.tigris.org</a>.</td>
</tr>
</tbody>
</table>
</div>

View File

@@ -13,12 +13,14 @@
<li><a href="http://viewvc.tigris.org/servlets/ProjectNewsList"
>Announcements</a></li>
<li><a href="http://viewvc.tigris.org/servlets/ProjectMailingListList"
>Mailing lists</a></li>
<li><a href="http://viewvc.tigris.org/ds/viewForums.do"
>Discussions</a></li>
<li><a href="http://viewvc.tigris.org/source/browse/viewvc/"
>Subversion</a></li>
>Source Code</a></li>
<li><a href="http://viewvc.tigris.org/issues/buglist.cgi?component=viewvc&amp;issue_status=UNCONFIRMED&amp;issue_status=NEW&amp;issue_status=STARTED&amp;issue_status=REOPENED"
>Issue tracker</a></li>
<li><a href="http://viewvc.tigris.org/servlets/ProjectDocumentList?folderID=6004"
>Downloads</a></li>
</ul></dd>
<!-- .................................................................. -->