def process_request(self, req): req.perm.require('TRAC_ADMIN') self.data = {} self.args = {} self.req = req self.per_page = int(req.args.get('per-page', self.COMMENTS_PER_PAGE)) self.page = int(req.args.get('page', 1)) self.order_by = req.args.get('orderby', 'id') self.order = req.args.get('order', 'DESC') self.add_path_and_author_filters() self.comments = Comments(req, self.env) self.data['comments'] = self.comments.search(self.args, self.order, self.per_page, self.page, self.order_by) self.data['reponame'], repos, path = RepositoryManager( self.env).get_repository_by_path('/') self.data['can_delete'] = 'TRAC_ADMIN' in req.perm self.data['paginator'] = self.get_paginator() self.data['current_sorting_method'] = self.order_by self.data['current_order'] = self.order self.data['sortable_headers'] = [] self.data.update(self.comments.get_filter_values()) self.prepare_sortable_headers() return 'comments.html', self.data, None
def test_repository_sync_per_request_default_value_with_db(self): """The default repository sync_per_request attribute is set to true when repository_sync_per_request is not set in trac.ini. """ self.env.config.remove('trac', 'repository_sync_per_request') # directly insert repository records instead of DbRepositoryProvider # to avoid a TracError "The repository type 'svn' is not supported" with self.env.db_transaction as db: db.executemany( """INSERT INTO repository (id,name,value) VALUES (%s,%s,%s)""", [(1, 'name', ''), (1, 'dir', '/var/svn'), (1, 'type', 'svn'), (2, 'name', 'git'), (2, 'dir', '/var/git'), (2, 'type', 'git')]) db32.do_upgrade(self.env, VERSION, None) repos = RepositoryManager(self.env).get_all_repositories() self.assertIn('', repos) self.assertTrue(repos['']['sync_per_request']) self.assertEqual( '1', self.env.db_query(""" SELECT value FROM repository WHERE id=1 AND name='sync_per_request'""")[0][0]) self.assertIn('git', repos) self.assertFalse(repos['git']['sync_per_request']) self.assertIsNone( self.env.db_query(""" SELECT value FROM repository WHERE id=2 AND name='sync_per_request'""")[0][0])
def setUp(self): super(ChangesetIndexerEventsTestCase, self).setUp() self.whoosh_backend = WhooshBackend(self.env) self.whoosh_backend.recreate_index() self.search_api = BloodhoundSearchApi(self.env) self.repository_manager = RepositoryManager(self.env) self.inject_dummy_repository()
def _format_link_file(self, formatter, ns, target, label, fullmatch=None): """ returns a tag for org.example.package.Class.method(Class.java:123) """ fqcn = fullmatch.group("fqcn") classname = fullmatch.group("classname") line = fullmatch.group("lineno") line = line and '#L%s' % line or "" rm = RepositoryManager(self.env) self.get_psf() # force parse # search repositories by fully qualified class name if fqcn: fqcn_filename = fqcn.replace('.', '/') + ".java" for reponame in self._srcpathes.keys(): repo = rm.get_repository(reponame) if not repo: continue for srcpath in self._srcpathes[reponame]: try: if repo.has_node(srcpath + fqcn_filename, None): return tag.a( label, href=formatter.href.browser(reponame + '/' + srcpath + fqcn_filename) + line, class_="source") except Exception, e: # GIT throws exception if MBCS used in fqcn self.env.log.error(e) pass # implemented but not fit i feel # for prefix in self._prefixes.keys(): # if fqcn.startswith(prefix): # href = self._prefixes[prefix] + fqcn.replace('.', '/') + '.html' # return tag.a(label, href=href, class_="file") return label # not missing resource
def _get_authz_info(self): try: mtime = os.path.getmtime(self.authz_file) except OSError as e: if self._authz is not None: self.log.error('Error accessing authz file: %s', exception_to_unicode(e)) self._mtime = mtime = 0 self._authz = None self._users = set() if mtime != self._mtime: self._mtime = mtime rm = RepositoryManager(self.env) modules = set(repos.reponame for repos in rm.get_real_repositories()) if '' in modules and self.authz_module_name: modules.add(self.authz_module_name) modules.add('') self.log.info('Parsing authz file: %s', self.authz_file) try: self._authz = parse(read_file(self.authz_file), modules) self._users = set(user for paths in self._authz.itervalues() for path in paths.itervalues() for user, result in path.iteritems() if result) except Exception as e: self._authz = None self._users = set() self.log.error('Error parsing authz file: %s', exception_to_unicode(e)) return self._authz, self._users
def _get_authz_info(self): if not self.authz_file: self.log.error("The [svn] authz_file configuration option in " "trac.ini is empty or not defined") raise ConfigurationError() try: mtime = os.path.getmtime(self.authz_file) except OSError as e: self.log.error("Error accessing svn authz permission policy " "file: %s", exception_to_unicode(e)) raise ConfigurationError() if mtime != self._mtime: self._mtime = mtime rm = RepositoryManager(self.env) modules = set(repos.reponame for repos in rm.get_real_repositories()) if '' in modules and self.authz_module_name: modules.add(self.authz_module_name) modules.add('') self.log.info("Parsing authz file: %s", self.authz_file) try: self._authz = parse(self.authz_file, modules) except ParsingError as e: self.log.error("Error parsing svn authz permission policy " "file: %s", exception_to_unicode(e)) raise ConfigurationError() else: self._users = {user for paths in self._authz.itervalues() for path in paths.itervalues() for user, result in path.iteritems() if result} return self._authz, self._users
def _read_source_from_repos(self, formatter, src_path): repos_mgr = RepositoryManager(self.env) try: #0.12+ repos_name, repos, source_obj = repos_mgr.get_repository_by_path( src_path) except AttributeError, e: #0.11 repos = repos_mgr.get_repository(formatter.req.authname)
def _get_source(self, formatter, source_obj, dest_format): repos_mgr = RepositoryManager(self.env) try: #0.12+ repos_name, repos, source_obj = repos_mgr.get_repository_by_path( source_obj) except AttributeError, e: #0.11 repos = repos_mgr.get_repository(formatter.req.authname)
def shutdown(self, tid=None): """Close the environment.""" from trac.versioncontrol.api import RepositoryManager RepositoryManager(self).shutdown(tid) DatabaseManager(self).shutdown(tid) if tid is None: log.shutdown(self.log)
def _format_sha_link(self, formatter, sha, label): # FIXME: this function needs serious rethinking... reponame = '' context = formatter.context while context: if context.resource.realm in ('source', 'changeset'): reponame = context.resource.parent.id break context = context.parent try: repos = RepositoryManager(self.env).get_repository(reponame) if not repos: raise Exception("Repository '%s' not found" % reponame) sha = repos.normalize_rev(sha) # in case it was abbreviated changeset = repos.get_changeset(sha) return tag.a(label, class_='changeset', title=shorten_line(changeset.message), href=formatter.href.changeset(sha, repos.reponame)) except Exception as e: return tag.a(label, class_='missing changeset', title=to_unicode(e), rel='nofollow')
def get_navigation_items(self, req): rm = RepositoryManager(self.env) if any( repos.is_viewable(req.perm) for repos in rm.get_real_repositories()): yield ('mainnav', 'browser', tag.a(_('Browse Source'), href=req.href.browser()))
def _format_link(self, formatter, ns, match, label, fullmatch=None): if ns == 'log1': groups = fullmatch.groupdict() it_log = groups.get('it_log') revs = groups.get('log_revs') path = groups.get('log_path') or '/' target = '%s%s@%s' % (it_log, path, revs) # prepending it_log is needed, as the helper expects it there intertrac = formatter.shorthand_intertrac_helper( 'log', target, label, fullmatch) if intertrac: return intertrac path, query, fragment = formatter.split_link(path) else: assert ns in ('log', 'log2') if ns == 'log': match, query, fragment = formatter.split_link(match) else: query = fragment = '' match = ''.join(reversed(match.split('/', 1))) path = match revs = '' if self.LOG_LINK_RE.match(match): indexes = [sep in match and match.index(sep) for sep in ':@'] idx = min([i for i in indexes if i is not False]) path, revs = match[:idx], match[idx+1:] rm = RepositoryManager(self.env) try: reponame, repos, path = rm.get_repository_by_path(path) if not reponame: reponame = rm.get_default_repository(formatter.context) if reponame is not None: repos = rm.get_repository(reponame) if repos: if 'LOG_VIEW' in formatter.perm(repos.resource): reponame = repos.reponame or None path = path or '/' revranges = RevRanges(repos, revs) if revranges.has_ranges(): href = formatter.href.log(reponame, path, revs=unicode(revranges)) else: # try to resolve if single rev repos.normalize_rev(revs) href = formatter.href.log(reponame, path, rev=revs or None) if query and '?' in href: query = '&' + query[1:] return tag.a(label, class_='source', href=href + query + fragment) errmsg = _("No permission to view change log") elif reponame: errmsg = _("Repository '%(repo)s' not found", repo=reponame) else: errmsg = _("No default repository defined") except TracError as e: errmsg = to_unicode(e) return tag.a(label, class_='missing source', title=errmsg)
def _get_repository(env, req): '''From env and req identify and return (reponame, repository, path), removing reponame from path in the process. ''' path = req.args.get('path') repo_mgr = RepositoryManager(env) reponame, repos, path = repo_mgr.get_repository_by_path(path) return reponame, repos, path
def test_get_system_info_repository_initialized(self): # SubversionConnector is a required component when there are # Subversion repositories configured, and the Subversion version is # returned in system info. RepositoryManager(self.env).get_repository(REPOS_NAME) self.assertTrue(svn_fs.SubversionConnector(self.env).required) self.assertIsNotNone(self._svn_version_from_system_info())
def _render_repository_index(self, context, all_repositories, order, desc): # Color scale for the age column timerange = custom_colorizer = None if self.color_scale: custom_colorizer = self.get_custom_colorizer() rm = RepositoryManager(self.env) repositories = [] for reponame, repoinfo in all_repositories.iteritems(): if not reponame or as_bool(repoinfo.get('hidden')): continue try: repos = rm.get_repository(reponame) except TracError as err: entry = (reponame, repoinfo, None, None, exception_to_unicode(err), None) else: if repos: if not repos.is_viewable(context.perm): continue try: youngest = repos.get_changeset(repos.youngest_rev) except NoSuchChangeset: youngest = None if self.color_scale and youngest: if not timerange: timerange = TimeRange(youngest.date) else: timerange.insert(youngest.date) raw_href = self._get_download_href(context.href, repos, None, None) entry = (reponame, repoinfo, repos, youngest, None, raw_href) else: entry = (reponame, repoinfo, None, None, u"\u2013", None) if entry[4] is not None: # Check permission in case of error root = Resource('repository', reponame).child('source', '/') if 'BROWSER_VIEW' not in context.perm(root): continue repositories.append(entry) # Ordering of repositories if order == 'date': def repo_order((reponame, repoinfo, repos, youngest, err, href)): return (youngest.date if youngest else to_datetime(0), embedded_numbers(reponame.lower())) elif order == 'author': def repo_order((reponame, repoinfo, repos, youngest, err, href)): return (youngest.author.lower() if youngest else '', embedded_numbers(reponame.lower())) else: def repo_order((reponame, repoinfo, repos, youngest, err, href)): return embedded_numbers(reponame.lower()) repositories = sorted(repositories, key=repo_order, reverse=desc) return {'repositories' : repositories, 'timerange': timerange, 'colorize_age': custom_colorizer}
def tearDown(self): self.repos.close() self.repos = None # clear cached repositories to avoid TypeError on termination (#11505) RepositoryManager(self.env).reload_repositories() self.env.reset_db() # needed to avoid issue with 'WindowsError: The process cannot access # the file ... being used by another process: ...\rep-cache.db' self.env.shutdown(get_thread_id())
def _get_source(self, formatter, source_obj, dest_format, start, end, lineno): repos_mgr = RepositoryManager(self.env) repos_name, repos, source_obj = \ repos_mgr.get_repository_by_path(source_obj) path, rev = _split_path(source_obj) try: node = repos.get_node(path, rev) except (NoSuchChangeset, NoSuchNode), e: return system_message(e), None, None, None
def macro_setup(tc): tc.env = EnvironmentStub(enable=('trac.*', 'tracopt.ticket.commit_updater.*',)) insert_ticket(tc.env, summary='the summary', status='new') def _get_repository(reponame): return Mock(get_changeset=_get_changeset, resource=None) def _get_changeset(rev=None): return Mock(message="the message. refs #1. ", rev=rev) setattr(RepositoryManager(tc.env), 'get_repository', _get_repository)
def process_request(self, req): req.perm.require('BROWSER_VIEW') presel = req.args.get('preselected') if presel and (presel + '/').startswith(req.href.browser() + '/'): req.redirect(presel) path = req.args.get('path', '/') rev = req.args.get('rev', '') if rev in ('', 'HEAD'): rev = None order = req.args.get('order', 'name').lower() desc = req.args.has_key('desc') xhr = req.get_header('X-Requested-With') == 'XMLHttpRequest' rm = RepositoryManager(self.env) all_repositories = rm.get_all_repositories() reponame, repos, path = rm.get_repository_by_path(path) # Repository index show_index = not reponame and path == '/' if show_index: if repos and (as_bool(all_repositories[''].get('hidden')) or not repos.can_view(req.perm)): repos = None if not repos and reponame: raise ResourceNotFound( _("Repository '%(repo)s' not found", repo=reponame)) if reponame and reponame != repos.reponame: # Redirect alias qs = req.query_string req.redirect( req.href.browser(repos.reponame or None, path) + (qs and '?' + qs or '')) reponame = repos and repos.reponame or None # Find node for the requested path/rev context = Context.from_request(req) node = None display_rev = lambda rev: rev if repos: try: if rev: rev = repos.normalize_rev(rev) # If `rev` is `None`, we'll try to reuse `None` consistently, # as a special shortcut to the latest revision. rev_or_latest = rev or repos.youngest_rev node = get_existing_node(req, repos, path, rev_or_latest) except NoSuchChangeset, e: raise ResourceNotFound(e.message, _('Invalid changeset number')) context = context( repos.resource.child('source', path, version=rev_or_latest)) display_rev = repos.display_rev
def check_permission(self, action, username, resource, perm): realm = resource.realm if resource else None if (realm, action) in self._handled_perms: authz, users = self._get_authz_info() if authz is None: return False if username == 'anonymous': usernames = ('$anonymous', '*') else: usernames = (username, '$authenticated', '*') if resource is None: return True if users & set(usernames) else None rm = RepositoryManager(self.env) try: repos = rm.get_repository(resource.parent.id) except TracError: return True # Allow error to be displayed in the repo index if repos is None: return True modules = [resource.parent.id or self.authz_module_name] if modules[0]: modules.append('') def check_path(path): path = '/' + join(repos.scope, path) if path != '/': path += '/' # Allow access to parent directories of allowed resources if any( section.get(user) is True for module in modules for spath, section in authz.get( module, {}).iteritems() if spath.startswith(path) for user in usernames): return True # Walk from resource up parent directories for spath in parent_iter(path): for module in modules: section = authz.get(module, {}).get(spath) if section: for user in usernames: result = section.get(user) if result is not None: return result if realm == 'source': return check_path(resource.id) elif realm == 'changeset': changes = list(repos.get_changeset(resource.id).get_changes()) if not changes or any( check_path(change[0]) for change in changes): return True
def shutdown(self, tid=None): """Close the environment.""" from trac.versioncontrol.api import RepositoryManager RepositoryManager(self).shutdown(tid) DatabaseManager(self).shutdown(tid) if tid is None and self._log_handler is not None: self.log.removeHandler(self._log_handler) self._log_handler.flush() self._log_handler.close() del self._log_handler
def _get_password_file(self): repos = RepositoryManager(self.env).get_repository('') if not repos: return None if isinstance(repos, CachedRepository): repos = repos.repos if repos.params['type'] in ('svn', 'svnfs', 'direct-svnfs'): conf = Configuration(os.path.join(repos.path, 'conf', 'svnserve.conf')) return conf['general'].getpath('password-db')
def get_psf(self): """ parse attached "team project set" for Eclipse IDE returns a-list as [ Eclipse project name -> repository URL ] """ if self._psf is None: self._psf = {} psfResource = Resource('wiki', 'TeamProjectSet').child( 'attachment', 'projectSet.psf') if (self.compmgr[AttachmentModule].resource_exists(psfResource)): psf = Attachment(self.env, psfResource) def startElement(name, attrs): if name == 'project': attr = attrs.get('reference', "").split(',') self._psf[attr[2]] = urlparse( attr[1]).path # trim leading scheme/port reader = expat.ParserCreate() reader.StartElementHandler = startElement reader.ParseFile(psf.open()) # specify checkout dir in server subversion directory rm = RepositoryManager(self.env) repos = rm.get_all_repositories() for projectname in self._psf.keys(): path = self._psf.get(projectname) + '/.project' for reponame in repos: repo = rm.get_repository(reponame) if not repo: continue for npath in self.iter_lstrip(path): if not repo.has_node(npath, None): continue self._psf[projectname] = npath[:-9] # search .classpath here npath = npath[:-9] + '/.classpath' if not repo.has_node(npath, None): continue node = repo.get_node(npath, None) srcpathes = self.parse_classpath( node.get_content()) self._srcpathes[repo.reponame] = map( lambda x: npath[:-10] + x, srcpathes) else: # TeamProjectSet not found for repo in self.config.getlist('wiki', 'source_path', sep=';'): # expected: "svn: trunk/theproject/src/main/java trunk/theproject/src/test/java;" repo = repo.split(':') repo, srcpaths = len(repo) < 2 and ( "", repo[0] ) or repo # no leading reponame, use default repo self._srcpathes[repo] = self._srcpathes.get(repo, []) self._srcpathes[repo].extend([ s.rstrip('/') + '/' for s in srcpaths.split(' ') if s ]) return self._psf # { project_name: repository_url, ... }
def expand_macro(self, formatter, name, content): args, kwargs = parse_args(content) format = kwargs.get('format', 'compact') glob = kwargs.get('glob', '*') order = kwargs.get('order') desc = as_bool(kwargs.get('desc', 0)) rm = RepositoryManager(self.env) all_repos = dict(rdata for rdata in rm.get_all_repositories().items() if fnmatchcase(rdata[0], glob)) if format == 'table': repo = self._render_repository_index(formatter.context, all_repos, order, desc) add_stylesheet(formatter.req, 'common/css/browser.css') wiki_format_messages = self.config['changeset'] \ .getbool('wiki_format_messages') data = {'repo': repo, 'order': order, 'desc': 1 if desc else None, 'reponame': None, 'path': '/', 'stickyrev': None, 'wiki_format_messages': wiki_format_messages} from trac.web.chrome import Chrome return Chrome(self.env).render_template( formatter.req, 'repository_index.html', data, None, fragment=True) def get_repository(reponame): try: return rm.get_repository(reponame) except TracError: return all_repos = [(reponame, get_repository(reponame)) for reponame in all_repos] all_repos = sorted(((reponame, repos) for reponame, repos in all_repos if repos and not as_bool(repos.params.get('hidden')) and repos.is_viewable(formatter.perm)), reverse=desc) def repolink(reponame, repos): label = reponame or _('(default)') return Markup(tag.a(label, title=_('View repository %(repo)s', repo=label), href=formatter.href.browser(repos.reponame or None))) if format == 'list': return tag.dl([ tag(tag.dt(repolink(reponame, repos)), tag.dd(repos.params.get('description'))) for reponame, repos in all_repos]) else: # compact return Markup(', ').join([repolink(reponame, repos) for reponame, repos in all_repos])
def expand_macro(self, formatter, name, args): path = unicode(args) rm = RepositoryManager(self.env) for repo_name in rm.get_all_repositories(): repo = rm.get_repository(repo_name) if repo.has_node(path): return self.get_javadoc(repo, repo_name, path) return "No file found for %s" % (path)
def get_entries_for_index(self): repository_manager = RepositoryManager(self.env) for repository in repository_manager.get_real_repositories(): rev = repository.oldest_rev stop = repository.youngest_rev while True: changeset = repository.get_changeset(rev) yield self.build_doc(changeset) if rev == stop: break rev = repository.next_rev(rev)
def get(self, tkt_id): """Return a sorted list of tuples (reponame, changesets) for a ticket. """ changesets = [] # [(reponame, Changesets)] repos = RepositoryManager(self.env).get_real_repositories() for repo in sorted(repos, key=lambda r: r.reponame): c = self._read(tkt_id, repo.id) if c.exists: changesets.append((repo.reponame, c)) return changesets
def process_request(self, req): if req.method != 'POST': msg = u'Method not allowed (%s)\n' % req.method self.log.warning(msg.rstrip('\n')) req.send(msg.encode('utf-8'), 'text/plain', 405) path = req.args['path'] rm = RepositoryManager(self.env) reponame, repos, path = rm.get_repository_by_path(path) if path != '/': msg = u'No such repository (%s)\n' % path self.log.warning(msg.rstrip('\n')) req.send(msg.encode('utf-8'), 'text/plain', 400) output = u'Running hook on %s\n' % (reponame or '(default)') output += u'* Updating clone\n' repos.git.repo.remote('update', '--prune') output += u'* Synchronizing with clone\n' repos.git.sync() try: payload = json.loads(req.args['payload']) revs = [ commit['id'] for commit in payload['commits'] if commit['distinct'] ] except (ValueError, KeyError): msg = u'Invalid payload\n' self.log.warning(msg.rstrip('\n')) req.send(msg.encode('utf-8'), 'text/plain', 400) branches = self.get_branches(reponame) added, skipped, unknown = classify_commits(revs, repos, branches) if added: output += u'* Adding %s\n' % describe_commits(added) # This is where Trac gets notified of the commits in the changeset rm.notify('changeset_added', reponame, added) if skipped: output += u'* Skipping %s\n' % describe_commits(skipped) if unknown: output += u'* Unknown %s\n' % describe_commits(unknown) self.log.error(u'Payload contains unknown %s', describe_commits(unknown)) for line in output.splitlines(): self.log.debug(line) req.send(output.encode('utf-8'), 'text/plain', 200 if output else 204)
def get_repo_name(self): all_repos = RepositoryManager(self.env).get_all_repositories() http_ref = self.req.environ["HTTP_REFERER"] browser_and_repo_name = re.search('(browser\/)\w+', http_ref) if browser_and_repo_name is not None: browser_and_repo_name = browser_and_repo_name.group(0) repo_name = browser_and_repo_name.rsplit('/', 1)[1] if repo_name not in all_repos: repo_name = '' else: repo_name = 'None' return repo_name
def test_add_alias(self): self.db_provider.add_repository('', '/path/to/repos') self.db_provider.add_repository('target', '/path/to/repos') self.db_provider.add_alias('blah1', '') self.db_provider.add_alias('blah2', '(default)') self.db_provider.add_alias('blah3', 'target') repositories = RepositoryManager(self.env).get_all_repositories() self.assertEqual(['', 'blah1', 'blah2', 'blah3', 'target'], sorted(repositories)) self.assertEqual('', repositories['blah1']['alias']) self.assertEqual('', repositories['blah2']['alias']) self.assertEqual('target', repositories['blah3']['alias'])