Edgewall Software

Ticket #1781: 1781-repository-url-r8398.patch

File 1781-repository-url-r8398.patch, 8.1 KB (added by rblank, 3 years ago)

Patch against MultiRepos adding a "Repository URL" link in the browser.

  • trac/versioncontrol/admin.py

    diff --git a/trac/versioncontrol/admin.py b/trac/versioncontrol/admin.py
    a b  
    187187                    # Modify repository 
    188188                    changed = False 
    189189                    changes = {} 
    190                     for field in ['alias', 'dir', 'type']: 
     190                    for field in db_provider.repository_attrs: 
    191191                        value = req.args.get(field) 
    192192                        if value is not None and value != info.get(field): 
    193193                            changes[field] = value 
  • trac/versioncontrol/api.py

    diff --git a/trac/versioncontrol/api.py b/trac/versioncontrol/api.py
    a b  
    9595 
    9696    implements(IRepositoryProvider, IAdminCommandProvider) 
    9797 
     98    repository_attrs = ('alias', 'dir', 'type', 'url') 
     99     
    98100    # IRepositoryProvider methods 
    99101 
    100102    def get_repositories(self): 
     
    102104        db = self.env.get_db_cnx() 
    103105        cursor = db.cursor() 
    104106        cursor.execute("SELECT id,name,value FROM repository " 
    105                        "WHERE name IN ('dir', 'alias', 'type')") 
     107                       "WHERE name IN (%s)" % ",".join( 
     108                           "'%s'" % each for each in self.repository_attrs)) 
    106109        reponames = {} 
    107110        for (id, name, value) in cursor: 
    108111            if value is not None: 
    109112                reponames.setdefault(id, {})[name] = value 
    110          
    111         for reponame, info in reponames.iteritems(): 
    112             yield (reponame, info) 
     113        return reponames.iteritems() 
    113114 
    114115    # IAdminCommandProvider methods 
    115116     
     
    229230        db = self.env.get_db_cnx() 
    230231        cursor = db.cursor() 
    231232        for (k, v) in changes.iteritems(): 
     233            if k not in self.repository_attrs: 
     234                continue 
    232235            cursor.execute("UPDATE repository SET value=%s " 
    233236                           "WHERE id=%s AND name=%s", (v, reponame, k)) 
     237            cursor.execute("SELECT value FROM repository " 
     238                           "WHERE id=%s AND name=%s", (reponame, k)) 
     239            if not cursor.fetchone(): 
     240                cursor.execute("INSERT INTO repository VALUES (%s, %s, %s)", 
     241                               (reponame, k, v)) 
    234242        db.commit() 
    235243        RepositoryManager(self.env).reload_repositories() 
    236244 
     
    257265        This means that if you want to use Trac without the source browser, 
    258266        simply remove that entry from the [trac] section.""") 
    259267 
     268    repository_url = Option('trac', 'repository_url', '', 
     269        """Base URL of the default repository. (''since 0.12'')""") 
     270 
    260271    repository_sync_per_request = ListOption('trac', 
    261272        'repository_sync_per_request', '(default)', 
    262273        doc="""List of repositories that should be synchronized on every page 
     
    364375                name, detail = option[:dotindex], option[dotindex+1:] 
    365376                if name in reponames: 
    366377                    reponames[name][detail] = repositories.get(option) 
    367                 else: # alias? 
     378                elif detail == 'alias': 
    368379                    alias = repositories.get(option) 
    369380                    if alias in reponames: 
    370381                        reponames[option] = {'alias': alias} 
    371382        # eventually add pre-0.12 default repository 
    372383        if '' not in reponames and self.repository_dir: 
    373             reponames[''] = {'dir': self.repository_dir} 
     384            reponames[''] = {'dir': self.repository_dir, 
     385                             'url': self.repository_url} 
    374386 
    375387        for reponame, info in reponames.iteritems(): 
    376388            yield (reponame, info) 
     
    461473                 been truncated, if needed. 
    462474        """ 
    463475        matches = [] 
    464         path = path and path.strip('/')+'/' or '/' 
     476        path = path and path.strip('/') + '/' or '/' 
    465477        for reponame in self.get_all_repositories().keys(): 
    466             stripped_reponame = reponame.strip('/')+'/' 
     478            stripped_reponame = reponame.strip('/') + '/' 
    467479            if path.startswith(stripped_reponame): 
    468480                matches.append((len(stripped_reponame), reponame)) 
    469481        if matches: 
     
    472484            path = path[length:] 
    473485        else: 
    474486            reponame = '' 
    475         return (reponame, self.get_repository(reponame, authname), path or '/') 
     487        return (reponame, self.get_repository(reponame, authname), 
     488                path.rstrip('/') or '/') 
    476489 
    477490    def get_default_repository(self, context): 
    478491        """Recover the appropriate repository from the current context. 
     
    681694        """ 
    682695        return [] 
    683696     
     697    def get_path_url(self, path, rev): 
     698        """Return the repository URL for the given path and revision. 
     699         
     700        The returned URL can be `None`, meaning that no URL has been specified 
     701        for the repository, an absolute URL, or a scheme-relative URL starting 
     702        with `//`, in which case the scheme of the request should be prepended. 
     703        """ 
     704        return None 
     705     
    684706    def get_changeset(self, rev): 
    685707        """Retrieve a Changeset corresponding to the given revision `rev`.""" 
    686708        raise NotImplementedError 
  • trac/versioncontrol/cache.py

    diff --git a/trac/versioncontrol/cache.py b/trac/versioncontrol/cache.py
    a b  
    7070    def get_quickjump_entries(self, rev): 
    7171        return self.repos.get_quickjump_entries(self.normalize_rev(rev)) 
    7272 
     73    def get_path_url(self, path, rev): 
     74        return self.repos.get_path_url(path, rev) 
     75 
    7376    def get_changeset(self, rev): 
    7477        return CachedChangeset(self.repos, self.normalize_rev(rev), 
    7578                               self.env, self.authz) 
  • trac/versioncontrol/svn_fs.py

    diff --git a/trac/versioncontrol/svn_fs.py b/trac/versioncontrol/svn_fs.py
    a b  
    280280            self.env.systeminfo.append(('Subversion', self._version)) 
    281281        fs_repos = SubversionRepository(dir, None, self.log, 
    282282                                        {'tags': self.tags, 
    283                                          'branches': self.branches}) 
     283                                         'branches': self.branches, 
     284                                         'url': options.get('url')}) 
    284285        if type == 'direct-svnfs': 
    285286            repos = fs_repos 
    286287        else: 
     
    422423        for n in self._get_tags_or_branches('tags'): 
    423424            yield 'tags', n.path, n.created_path, n.created_rev 
    424425 
     426    def get_path_url(self, path, rev): 
     427        url = self.options.get('url', '').rstrip('/') 
     428        if url: 
     429            if not path or path == '/': 
     430                return url 
     431            return url + '/' + path.lstrip('/') 
     432     
    425433    def get_changeset(self, rev): 
    426434        rev = self.normalize_rev(rev) 
    427435        return SubversionChangeset(rev, self.authz, self.scope, 
  • trac/versioncontrol/templates/admin_repositories.html

    diff --git a/trac/versioncontrol/templates/admin_repositories.html b/trac/versioncontrol/templates/admin_repositories.html
    a b  
    5757              <div class="field"> 
    5858                <label>Directory:<br/><input type="text" name="dir" size="48" value="$info.dir" readonly="$readonly"/></label> 
    5959              </div> 
     60              <div class="field"> 
     61                <label>URL:<br/><input type="text" name="url" size="48" value="$info.url" readonly="$readonly"/></label> 
     62              </div> 
    6063            </py:otherwise> 
    6164          </py:choose> 
    6265          <div class="buttons"> 
  • trac/versioncontrol/web_ui/browser.py

    diff --git a/trac/versioncontrol/web_ui/browser.py b/trac/versioncontrol/web_ui/browser.py
    a b  
    408408 
    409409        # Links for contextual navigation 
    410410        if node: 
     411            path_url = repos.get_path_url(path, rev) 
     412            if path_url: 
     413                if path_url.startswith('//'): 
     414                    path_url = req.scheme + ':' + path_url 
     415                add_ctxtnav(req, _('Repository URL'), href=path_url) 
    411416            add_ctxtnav(req, tag.a(_('Last Change'),  
    412417                        href=req.href.changeset(node.rev, reponame, 
    413418                                                node.created_path)))