Edgewall Software

Ticket #1132: svn-wiki-backend-patch-0.11.4.patch

File svn-wiki-backend-patch-0.11.4.patch, 15.1 KB (added by Gregory Hart <greg@…>, 3 years ago)

Updated patch for 0.11.4 release

  • trac/versioncontrol/api.py

     
    380380        """ 
    381381        raise NotImplementedError 
    382382 
     383    def set_content(self, content, commitmsg=None): 
     384        """ 
     385        Set the content of the node. Add the commitmsg to the logs. If Node is 
     386        of type DIRECTORY this method raise an Error. 
     387         
     388        If the Node doesn't exist it's created.  
     389 
     390        Returns the revision Number that tags the commit. 
     391        """ 
     392        raise NotImplementedError 
     393 
    383394    def get_entries(self): 
    384395        """Generator that yields the immediate child entries of a directory. 
    385396 
     
    519530    access to view certain parts of a repository. 
    520531    """ 
    521532 
    522     def assert_permission(self, path): 
     533    def assert_permission(self, path, perm='r'): 
    523534        if not self.has_permission(path): 
    524535            raise PermissionDenied(_('Insufficient permissions to access ' 
    525536                                     '%(path)s', path=path)) 
     
    529540            raise PermissionDenied(_('Insufficient permissions to access ' 
    530541                                     'changeset %(id)s', id=rev)) 
    531542 
    532     def has_permission(self, path): 
     543    def has_permission(self, path, perm='r'): 
    533544        return True 
    534545 
    535546    def has_permission_for_changeset(self, rev): 
  • trac/versioncontrol/svn_authz.py

     
    8989 
    9090        self.groups = self._groups() 
    9191 
    92     def has_permission(self, path): 
     92    def has_permission(self, path, perm='r'): 
    9393        if path is None: 
    9494            return 1 
    9595 
    9696        for p in parent_iter(path): 
    9797            if self.module_name: 
    98                 for perm in self._get_section(self.module_name + ':' + p): 
     98                for perm in self._get_section(self.module_name + ':' + p, perm): 
    9999                    if perm is not None: 
    100100                        return perm 
    101101            for perm in self._get_section(p): 
     
    144144        # expand groups 
    145145        return expanded.keys() 
    146146 
    147     def _get_section(self, section): 
     147    def _get_section(self, section, perm='r'): 
    148148        if not self.conf_authz.has_section(section): 
    149149            return 
    150150 
    151         yield self._get_permission(section, self.auth_name) 
     151        yield self._get_permission(section, self.auth_name, perm) 
    152152 
    153153        group_perm = None 
    154154        for g in self.groups: 
    155             p = self._get_permission(section, '@' + g) 
     155            p = self._get_permission(section, '@' + g, perm) 
    156156            if p is not None: 
    157157                group_perm = p 
    158158 
     
    161161 
    162162        yield group_perm 
    163163 
    164         yield self._get_permission(section, '*') 
     164        yield self._get_permission(section, '*', perm) 
    165165 
    166     def _get_permission(self, section, subject): 
     166    def _get_permission(self, section, subject, perm='r'): 
    167167        if self.conf_authz.has_option(section, subject): 
    168             return 'r' in self.conf_authz.get(section, subject) 
     168            return perm in self.conf_authz.get(section, subject) 
    169169        return None 
  • trac/versioncontrol/svn_fs.py

     
    519519 
    520520        return SubversionNode(path, rev, self, self.pool) 
    521521 
     522    def delete_node(self, path, commitmsg): 
     523        return NotImplementedError 
     524 
    522525    def _history(self, path, start, end, pool): 
    523526        """`path` is a unicode path in the scope. 
    524527 
     
    739742        else: 
    740743            self.root = fs.revision_root(self.fs_ptr, rev, self.pool()) 
    741744        node_type = fs.check_path(self.root, self._scoped_path_utf8, pool) 
    742         if not node_type in _kindmap: 
     745        if node_type == core.svn_node_none: 
     746            self.created_rev = 0 
     747            self.created_path = self.scoped_path 
     748            self.rev = self.created_rev 
     749            node_type = core.svn_node_file 
     750        elif not node_type in _kindmap: 
    743751            raise NoSuchNode(path, rev) 
    744752        cp_utf8 = fs.node_created_path(self.root, self._scoped_path_utf8, pool) 
    745753        cp = _from_svn(cp_utf8) 
     
    769777        # is not destroyed before the stream object. 
    770778        s._pool = self.pool 
    771779        return s 
     780    def set_content(self,content,commitmsg="changed by trac",uname=""): 
     781        # this check is untested!  
     782        self.authz.assert_permission(self.scoped_path, 'w') 
    772783 
     784        # based on the putfile.py example of the subversion dist. 
     785        # open a transaction against HEAD. 
     786        rev = fs.youngest_rev(repos.fs(self.repos),self.pool()) 
     787        txn = repos.fs_begin_txn_for_commit(self.repos, rev, uname, 
     788                                            commitmsg, self.pool()) 
     789 
     790        root = fs.txn_root(txn,self.pool()) 
     791        kind = fs.check_path(root,self.scoped_path,self.pool()) 
     792 
     793        if kind == core.svn_node_none: 
     794            fs.make_file(root,self.scoped_path,self.pool()) 
     795        elif not kind == core.svn_node_file: 
     796            raise TracError("Node is not a File.") 
     797         
     798        handler, baton = fs.apply_textdelta(root,self.scoped_path,  
     799                                            None, None, self.pool()) 
     800 
     801        delta.svn_txdelta_send_string(content,handler,baton,self.pool()) 
     802        return repos.fs_commit_txn(self.repos,txn,self.pool()) 
     803 
    773804    def get_entries(self): 
    774805        if self.isfile: 
    775806            return 
  • trac/versioncontrol/tests/svn_fs.py

     
    195195        self.assertEqual('text/plain', node.content_type) 
    196196        self.assertEqual('A test.\n', node.get_content().read()) 
    197197 
     198    def test_set_file_content(self): 
     199        node = self.repos.get_node('/trunk/README.txt') 
     200        node.set_content('This is the test Content\n', 'change.') 
     201 
     202        # reload the repository for the newly commited change.  
     203        self.repos = SubversionRepository(REPOS_PATH, None, 
     204                                          logger_factory('test')) 
     205 
     206        node = self.repos.get_node('/trunk/README.txt') 
     207        chgset = self.repos.get_changeset(self.repos.get_youngest_rev()) 
     208 
     209        self.assertEqual('This is the test Content\n',  
     210            node.get_content().read()) 
     211        self.assertEqual('change.', chgset.message ) 
     212 
     213    def test_delete_node(self): 
     214        node = self.repos.delete_node('/trunk/README.txt', "delete.") 
     215         
     216        self.repos = SubversionRepository(REPOS_PATH, None, 
     217                                          logger_factory('test')) 
     218 
     219        node = self.repos.get_node('/trunk/README.txt') 
     220        chgset = self.repos.get_changeset(self.repos.get_youngest_rev()) 
     221 
     222        self.assertNotEqual(Node.DIRECTORY, node.kind) 
     223        self.assertNotEqual(Node.FILE, node.kind) 
     224        self.assertEqual('delete.', chgset.message ) 
     225 
    198226    def test_get_dir_properties(self): 
    199227        f = self.repos.get_node(u'/tête') 
    200228        props = f.get_properties() 
  • trac/wiki/api.py

     
    3535from trac.util.translation import _ 
    3636from trac.wiki.parser import WikiParser 
    3737 
     38from trac.wiki.model_svn import WikiPage 
    3839 
    3940class IWikiChangeListener(Interface): 
    4041    """Extension point interface for components that should get notified about 
     
    198199                cursor = db.cursor() 
    199200                cursor.execute("SELECT DISTINCT name FROM wiki") 
    200201                self._index = {} 
    201                 for (name,) in cursor: 
    202                     self._index[name] = True 
     202                for page in WikiPage.select(self.env): 
     203                    self._index[page.name] = True 
     204 
    203205                self._last_index_update = now 
    204206        finally: 
    205207            self._index_lock.release() 
  • trac/wiki/macros.py

     
    3434from trac.wiki.api import IWikiMacroProvider, WikiSystem, parse_args 
    3535from trac.wiki.formatter import format_to_html, format_to_oneliner, \ 
    3636                                extract_link, OutlineFormatter 
    37 from trac.wiki.model import WikiPage 
     37from trac.wiki.model_svn import WikiPage 
    3838from trac.web.chrome import add_stylesheet 
    3939 
    4040 
  • trac/wiki/model.py

     
    169169        for version,ts,author,comment,ipnr in cursor: 
    170170            time = datetime.fromtimestamp(ts, utc) 
    171171            yield version,time,author,comment,ipnr 
     172 
     173    def select(cls, env, db=None): 
     174        if not db: 
     175            db = env.get_db_cnx() 
     176 
     177        cursor = db.cursor() 
     178        cursor.execute("SELECT DISTINCT name FROM wiki") 
     179        for (name,) in cursor: 
     180            yield WikiPage(env,name) 
     181 
     182    select = classmethod(select) 
     183 
     184 
  • trac/wiki/model_svn.py

     
     1# -*- coding: iso8859-1 -*- 
     2# 
     3# Copyright (C) 2003-2005 Edgewall Software 
     4# Copyright (C) 2005 Philipp Scholl <pscholl@bawue.de> 
     5# All rights reserved. 
     6# 
     7# This software is licensed as described in the file COPYING, which 
     8# you should have received as part of this distribution. The terms 
     9# are also available at http://trac.edgewall.com/license.html. 
     10# 
     11# This software consists of voluntary contributions made by many 
     12# individuals. For the exact contribution history, see the revision 
     13# history and logs, available at http://projects.edgewall.com/trac/. 
     14# 
     15# Author: Philipp Scholl <pscholl@bawue.de> 
     16 
     17from __future__ import generators 
     18import time 
     19 
     20from trac.core import * 
     21from trac.resource import Resource 
     22#from trac.wiki.api import WikiSystem 
     23from trac.versioncontrol.api import Node 
     24 
     25 
     26class WikiPage(object): 
     27    """Represents a wiki page (new or existing).""" 
     28 
     29    def __init__(self, env, name=None, version=None, db=None): 
     30        self.env = env 
     31        self.root = env.config.get( 'wiki', 'svn_root' ) 
     32        if not env.get_repository().get_node(self.root).kind in (Node.DIRECTORY, Node.FILE): 
     33            raise TracError( "wiki root couldn't be found!" ) 
     34        if self.root[:-1] != '/': self.root += '/' 
     35        if isinstance(name, Resource): 
     36            self.resource = name 
     37            name = self.resource.id 
     38        else: 
     39            self.resource = Resource('wiki', name, version) 
     40        self.name = name 
     41        if name: 
     42            self._fetch(name, version, db) 
     43        else: 
     44            self.version = 0 
     45            self.text = '' 
     46            self.readonly = 0 
     47        self.old_text = self.text 
     48        self.old_readonly = self.readonly 
     49 
     50    def _fetch(self, name, version=None, db=None): 
     51        repos = self.env.get_repository() 
     52        try: 
     53            if version: 
     54                node = repos.get_node(self.root+name,version) 
     55                self.text = node.get_content().read() 
     56                self.version = version 
     57                self.readonly = 0 
     58            else: 
     59                node = repos.get_node(self.root+name) 
     60                self.text = node.get_content().read() 
     61                history = node.get_history() 
     62                self.version = 0 
     63                for path, rev, chg in history: 
     64                    if self.version < rev: self.version = rev 
     65                self.readonly = 0 
     66        except Exception: 
     67            self.version = 0 
     68            self.text = '' 
     69            self.readonly = 0 
     70        except: 
     71            repos.close() 
     72 
     73    exists = property(fget=lambda self: self.version > 0) 
     74 
     75    def delete(self, version=None, db=None): 
     76        assert self.exists, 'Cannot delete non-existent page' 
     77        if version: 
     78            raise NotImplementedError( "deletion of versions not supported in \ 
     79            wiki_svn" ) 
     80        repos = self.env.get_repository() 
     81        repos.delete_node(self.root+self.name) 
     82 
     83    def save(self, author, comment, remote_addr, t=None, db=None): 
     84        repos = self.env.get_repository() 
     85         
     86        # make sure that noone can escape the wiki root. 
     87        if self.name.find( "..") != -1: 
     88            raise TracError( ".. not allowed in wiki names." ) 
     89 
     90        node = repos.get_node(self.root+self.name) 
     91 
     92        commitmsg  = self.name+" edited by "+author+" from "+remote_addr+"\n" 
     93        commitmsg += comment 
     94        self.version = node.set_content(self.text, commitmsg, author) 
     95        self.resource = self.resource(version=self.version) 
     96 
     97        if t is None: 
     98            t = time.time() 
     99             
     100#        for listener in WikiSystem(self.env).change_listeners: 
     101#            if self.version == repos.get_youngest_rev(): 
     102#                listener.wiki_page_added(self) 
     103#            else: 
     104#                listener.wiki_page_changed(self, self.version, t, author, 
     105#                                           comment, remote_addr) 
     106 
     107    def get_history(self, db=None): 
     108        repos = self.env.get_repository() 
     109 
     110        history = repos.get_path_history(self.root+self.name) 
     111 
     112        for path, rev, kind in history: 
     113            chgset = repos.get_changeset(rev) 
     114            yield rev,chgset.date,chgset.author,chgset.message,"missing" 
     115 
     116    def select(cls, env, db=None): 
     117        if not 'get_repository' in dir(env): 
     118            return 
     119        repos = env.get_repository() 
     120        dnode = repos.get_node( env.config.get('wiki', 'svn_root') ) 
     121         
     122        for node in dnode.get_entries(): 
     123            yield WikiPage(env,node.get_name()) 
     124 
     125    select = classmethod(select) 
     126 
     127 
  • trac/wiki/web_ui.py

     
    11# -*- coding: utf-8 -*- 
    22# 
    33# Copyright (C) 2003-2009 Edgewall Software 
    4 # Copyright (C) 2003-2005 Jonas Borgström <jonas@edgewall.com> 
     4# Copyright (C) 2003-2005 Jonas Borgström <jonas@edgewall.com> 
    55# Copyright (C) 2004-2005 Christopher Lenz <cmlenz@gmx.de> 
    66# All rights reserved. 
    77# 
     
    1313# individuals. For the exact contribution history, see the revision 
    1414# history and logs, available at http://trac.edgewall.org/log/. 
    1515# 
    16 # Author: Jonas Borgström <jonas@edgewall.com> 
     16# Author: Jonas Borgström <jonas@edgewall.com> 
    1717#         Christopher Lenz <cmlenz@gmx.de> 
    1818 
    1919from datetime import datetime 
     
    4242from trac.web import IRequestHandler 
    4343from trac.wiki.api import IWikiPageManipulator, WikiSystem 
    4444from trac.wiki.formatter import format_to 
    45 from trac.wiki.model import WikiPage 
     45from trac.wiki.model_svn import WikiPage 
    4646  
    4747class InvalidWikiPage(TracError): 
    4848    """Exception raised when a Wiki page fails validation.