def from_comment(cls, env, comment, user=None, notify=True):
        """
        Creates a subscription from a Comment object.
        """
        sub = {
            'user': user or comment.author,
            'type': comment.type,
            'notify': notify,
        }

        # Munge attachments
        if comment.type == 'attachment':
            sub['path'] = comment.path.split(':')[1]
            sub['repos'] = ''
            sub['rev'] = ''

        # Munge changesets and browser
        if comment.type in ('changeset', 'browser'):
            if comment.type == 'browser':
                sub['path'] = comment.path
            else:
                sub['path'] = ''
            repo = RepositoryManager(env).get_repository(None)
            try:
                sub['repos'] = repo.reponame
                try:
                    _cs = repo.get_changeset(comment.revision)
                    sub['rev'] = _cs.rev
                except NoSuchChangeset:
                    # Invalid changeset
                    return None
            finally:
                repo.close()

        return cls._from_dict(env, sub)
Пример #2
0
    def for_request(cls, env, req, create=False):
        """
        Return a **single** subscription for a HTTP request.
        """
        reponame = req.args.get('reponame')
        rm = RepositoryManager(env)
        repos = rm.get_repository(reponame)

        path = req.args.get('path') or ''
        rev = req.args.get('rev') or repos.youngest_rev

        dict_ = {
            'user': req.authname,
            'type': req.args.get('realm'),
            'path': '',
            'rev': '',
            'repos': '',
        }

        if dict_['type'] == 'attachment':
            dict_['path'] = path

        if dict_['type'] == 'changeset':
            dict_['rev'] = path[1:]
            dict_['repos'] = repos.reponame

        if dict_['type'] == 'browser':
            if len(path) == 0:
                dict_['path'] = '/'
            else:
                dict_['path'] = path[1:]
            dict_['rev'] = rev
            dict_['repos'] = repos.reponame

        return cls._from_dict(env, dict_, create=create)
Пример #3
0
 def _do_changeset_added(self, reponame, *revs):
     if is_default(reponame):
         reponame = ""
     rm = RepositoryManager(self.env)
     errors = rm.notify("changeset_added", reponame, revs)
     for error in errors:
         printout(error)
Пример #4
0
 def expand_macro(self, formatter, name, content, args={}):
     reponame = args.get('repository') or ''
     rev = args.get('revision')
     repos = RepositoryManager(self.env).get_repository(reponame)
     try:
         changeset = repos.get_changeset(rev)
         message = changeset.message
         rev = changeset.rev
         resource = repos.resource
     except Exception:
         message = content
         resource = Resource('repository', reponame)
     if formatter.context.resource.realm == 'ticket':
         ticket_re = CommitTicketUpdater.ticket_re
         if not any(
                 int(tkt_id) == int(formatter.context.resource.id)
                 for tkt_id in ticket_re.findall(message)):
             return tag.p(
                 "(The changeset message doesn't reference this "
                 "ticket)",
                 class_='hint')
     if ChangesetModule(self.env).wiki_format_messages:
         return tag.div(format_to_html(self.env,
                                       formatter.context.child(
                                           'changeset',
                                           rev,
                                           parent=resource),
                                       message,
                                       escape_newlines=True),
                        class_='message')
     else:
         return tag.pre(message, class_='message')
Пример #5
0
def _process_browser_view(self, request):
    request.perm.require('BROWSER_VIEW')

    preselected = request.args.get('preselected')
    if preselected and (preselected + '/').startswith(request.href.browser() + '/'):
        request.redirect(preselected)

    elif request.path_info.startswith('/browser') and _valid_github_request(request):
        path = request.args.get('path', '/')
        rev = request.args.get('rev', '')
        if rev.lower() in ('', 'head'):
            rev = 'master'

        manager = RepositoryManager(self.env)
        repository_name, repository, path = manager.get_repository_by_path(path)
        repository_url = repository.params.get('url', '')

        if re.match(r'^https?://(?:www\.)?github\.com/', repository_url):
            url = repository_url.rstrip('/') + '/blob/' + rev + '/' + path
            request.redirect(url)
        else:
            return _old_process_browser_view(self, request)

    else:
        return _old_process_browser_view(self, request)
Пример #6
0
 def expand_macro(self, formatter, name, content, args={}):
     reponame = args.get("repository") or ""
     rev = args.get("revision")
     repos = RepositoryManager(self.env).get_repository(reponame)
     try:
         changeset = repos.get_changeset(rev)
         message = changeset.message
         rev = changeset.rev
         resource = repos.resource
     except Exception:
         message = content
         resource = Resource("repository", reponame)
     if formatter.context.resource.realm == "ticket":
         ticket_re = CommitTicketUpdater.ticket_re
         if not any(int(tkt_id) == int(formatter.context.resource.id) for tkt_id in ticket_re.findall(message)):
             return tag.p("(The changeset message doesn't reference this " "ticket)", class_="hint")
     if ChangesetModule(self.env).wiki_format_messages:
         return tag.div(
             format_to_html(
                 self.env, formatter.context.child("changeset", rev, parent=resource), message, escape_newlines=True
             ),
             class_="message",
         )
     else:
         return tag.pre(message, class_="message")
Пример #7
0
 def _do_changeset_modified(self, reponame, *revs):
     if is_default(reponame):
         reponame = ''
     rm = RepositoryManager(self.env)
     errors = rm.notify('changeset_modified', reponame, revs)
     for error in errors:
         printout(error)
Пример #8
0
    def match_request(self, request):
        """Match requests which are POST, include a 'commit' argument, and point at an existing repo"""
        if request.method != 'POST':
            return False

        repo_name = _get_repo_name(request.path_info)
        if repo_name is None:
            return False

        repo = RepositoryManager(self.env).get_repository(repo_name)
        if repo is None:
            return False
        repo.close()

        from cgi import parse_qs
        request.args = parse_qs(request.read())
        if request.args.get('commit', request.args.get('payload', None)) is None:
            return False

        ## XXX: evil hack to disable CSRF checking (is there a better way?)
        request._inheaders.insert(0, ('content-type', 'xx'))

        ## Go!
        self.log.info('Handling a beanstalk hook callback for repository [%s]' % repo_name)
        return True
Пример #9
0
    def add_repository(self, name):
        """Add a repository."""
        dir = os.path.join(self.parentpath, name)
        if not os.path.isabs(dir):
            raise TracError(_("The repository directory must be absolute"))
        trunk = os.path.join(dir, 'trunk')
        branches = os.path.join(dir, 'branches')
        tags = os.path.join(dir, 'tags')
        command = '"%(svnadmin)s" create "%(dir)s"; "%(svn)s" mkdir --parents -q -m "Created Folders" "file://%(trunk)s" "file://%(branches)s" "file://%(tags)s"' % {
            'svnadmin': self.admin,
            'dir': dir,
            'svn': self.client,
            'trunk': trunk,
            'branches': branches,
            'tags': tags
        }
        process = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
        (result, error) = process.communicate()
        if error is not None and error != "":
            if error.find('E165002') > -1:
                raise TracError(_('The repository "%(name)s" already exists.', name=name))
            elif error.find('E000002') > -1 or error.find('E000013') > -1:
                raise TracError(_("Can't create the repository '%(name)s.' "
                                  "Make sure the parent directory '%(parentpath)s' exists "
                                  "and the web server has write permissions for it.", name=name, parentpath=self.parentpath))
            else:
                raise TracError(error)
        if self.hookspath and os.path.exists(self.hookspath):
	        hooksdir = os.path.join(dir, 'hooks/')
	        files = os.listdir(self.hookspath)
	        files = [self.hookspath + '/' + filename for filename in files]
	        for file in files:
	        	shutil.copy2(file, hooksdir)
        rm = RepositoryManager(self.env)
        rm.reload_repositories()
Пример #10
0
Файл: admin.py Проект: t2y/trac
    def _sync(self, reponame, rev, clean):
        rm = RepositoryManager(self.env)
        if reponame == '*':
            if rev is not None:
                raise TracError(_('Cannot synchronize a single revision '
                                  'on multiple repositories'))
            repositories = rm.get_real_repositories()
        else:
            if is_default(reponame):
                reponame = ''
            repos = rm.get_repository(reponame)
            if repos is None:
                raise TracError(_("Repository '%(repo)s' not found",
                                  repo=reponame or '(default)'))
            if rev is not None:
                repos.sync_changeset(rev)
                printout(_('%(rev)s resynced on %(reponame)s.', rev=rev,
                           reponame=repos.reponame or '(default)'))
                return
            repositories = [repos]

        for repos in sorted(repositories, key=lambda r: r.reponame):
            printout(_('Resyncing repository history for %(reponame)s... ',
                       reponame=repos.reponame or '(default)'))
            repos.sync(self._sync_feedback, clean=clean)
            for cnt, in self.env.db_query(
                    "SELECT count(rev) FROM revision WHERE repos=%s",
                    (repos.id,)):
                printout(ngettext('%(num)s revision cached.',
                                  '%(num)s revisions cached.', num=cnt))
        printout(_('Done.'))
    def for_request(cls, env, req, create=False):
        """
        Return a **single** subscription for a HTTP request.
        """
        reponame = req.args.get('reponame')
        rm = RepositoryManager(env)
        repos = rm.get_repository(reponame)

        path = req.args.get('path') or ''
        rev = req.args.get('rev') or repos.youngest_rev

        dict_ = {
            'user': req.authname,
            'type': req.args.get('realm'),
            'path': '',
            'rev': '',
            'repos': '',
        }

        if dict_['type'] == 'attachment':
            dict_['path'] = path

        if dict_['type'] == 'changeset':
            dict_['rev'] = path[1:]
            dict_['repos'] = repos.reponame

        if dict_['type'] == 'browser':
            if len(path) == 0:
                dict_['path'] = '/'
            else:
                dict_['path'] = path[1:]
            dict_['rev'] = rev
            dict_['repos'] = repos.reponame

        return cls._from_dict(env, dict_, create=create)
Пример #12
0
    def from_comment(cls, env, comment, user=None, notify=True):
        """
        Creates a subscription from a Comment object.
        """
        sub = {
            'user': user or comment.author,
            'type': comment.type,
            'notify': notify,
        }

        # Munge attachments
        if comment.type == 'attachment':
            sub['path'] = comment.path.split(':')[1]
            sub['repos'] = ''
            sub['rev'] = ''

        # Munge changesets and browser
        if comment.type in ('changeset', 'browser'):
            rm = RepositoryManager(env)
            reponame, repos, path = rm.get_repository_by_path(comment.path)
            if comment.type == 'browser':
                sub['path'] = path
            else:
                sub['path'] = ''
            sub['repos'] = reponame or '(default)'
            try:
                _cs = repos.get_changeset(comment.revision)
            except NoSuchChangeset:
                # Invalid changeset
                return None
            else:
                sub['rev'] = _cs.rev

        return cls.from_dict(env, sub)
    def _do_seed(self):
        # Create a subscription for all existing attachments
        cursor = self.env.get_read_db().cursor()
        cursor.execute("SELECT DISTINCT type, id FROM attachment")
        rows = cursor.fetchall()
        for row in rows:
            for attachment in Attachment.select(self.env, row[0], row[1]):
                Subscription.from_attachment(self.env, attachment)

        # Create a subscription for all existing revisions
        rm = RepositoryManager(self.env)
        repos = rm.get_real_repositories()
        for repo in repos:
            _rev = repo.get_oldest_rev()
            while _rev:
                try:
                    _cs = repo.get_changeset(_rev)
                    Subscription.from_changeset(self.env, _cs)
                except NoSuchChangeset:
                    pass
                _rev = repo.next_rev(_rev)

        # Create a subscription for all existing comments
        comments = Comments(None, self.env).all()
        for comment in comments:
            Subscription.from_comment(self.env, comment)
Пример #14
0
 def _do_changeset_added(self, reponame, first_rev, *revs):
     if is_default(reponame):
         reponame = ''
     rm = RepositoryManager(self.env)
     errors = rm.notify('changeset_added', reponame, (first_rev, ) + revs)
     for error in errors:
         printout(error)
 def expand_macro(self, formatter, name, content, args=None):
     args = args or {}
     reponame = args.get('repository') or ''
     rev = args.get('revision')
     repos = RepositoryManager(self.env).get_repository(reponame)
     try:
         changeset = repos.get_changeset(rev)
         message = changeset.message
         rev = changeset.rev
         resource = repos.resource
     except Exception:
         message = content
         resource = Resource('repository', reponame)
     if formatter.context.resource.realm == 'ticket':
         ticket_re = CommitTicketUpdater.ticket_re
         if not any(int(tkt_id) == int(formatter.context.resource.id)
                    for tkt_id in ticket_re.findall(message)):
             return tag.p(_("(The changeset message doesn't reference this "
                            "ticket)"), class_='hint')
     if ChangesetModule(self.env).wiki_format_messages:
         return tag.div(format_to_html(self.env,
             formatter.context.child('changeset', rev, parent=resource),
             message, escape_newlines=True), class_='message')
     else:
         return tag.pre(message, class_='message')
Пример #16
0
    def _do_seed(self):
        # Create a subscription for all existing attachments
        for row in self.env.db_query("""
                SELECT DISTINCT type, id FROM attachment
                """):
            for attachment in Attachment.select(self.env, row[0], row[1]):
                Subscription.from_attachment(self.env, attachment)

        # Create a subscription for all existing revisions
        rm = RepositoryManager(self.env)
        repos = rm.get_real_repositories()
        for repo in repos:
            _rev = repo.get_oldest_rev()
            while _rev:
                try:
                    _cs = repo.get_changeset(_rev)
                    Subscription.from_changeset(self.env, _cs)
                except NoSuchChangeset:
                    pass
                _rev = repo.next_rev(_rev)

        # Create a subscription for all existing comments
        comments = Comments(None, self.env).all()
        for comment in comments:
            Subscription.from_comment(self.env, comment)
Пример #17
0
    def expand_macro(self, formatter, name, content, args={}):
        reponame = args.get('repository') or ''
        rev = args.get('revision')
        repos = RepositoryManager(self.env).get_repository(reponame)
        try:
            changeset = repos.get_changeset(rev)
            message = changeset.message

            # add review status to commit message (
            review = CodeReview(self.env, reponame, rev)
            status = review.encode(review.status)
            message += '\n\n{{{#!html \n'
            message += '<div class="codereviewstatus">'
            message += '  <div class="system-message %s">' % status.lower()
            message += '    <p>Code review status: '
            message += '      <span>%s</span>' % review.status
            message += '    </p>'
            message += '  </div>'
            message += '</div>'
            message += '\n}}}'

            rev = changeset.rev
            resource = repos.resource
        except Exception, e:
            message = content
            resource = Resource('repository', reponame)
Пример #18
0
    def for_request(cls, env, req, create=False):
        """
        Return a **single** subscription for a HTTP request.
        """
        rm = RepositoryManager(env)

        dict_ = {
            'user': req.authname,
            'type': req.args.get('realm'),
            'path': '',
            'rev': '',
            'repos': '',
        }
        path = req.args.get('path') or ''

        if dict_['type'] == 'attachment':
            dict_['path'] = path

        if dict_['type'] == 'changeset':
            parts = [p for p in path.split('/') if p]
            dict_['rev'] = parts[0]
            dict_['repos'] = parts[1]

        if dict_['type'] == 'browser':
            reponame, repos, path = rm.get_repository_by_path(path)
            dict_['path'] = '/' if len(path) == 0 else path
            dict_['rev'] = req.args.get('rev') or ''
            dict_['repos'] = reponame

        return cls.from_dict(env, dict_, create=create)
Пример #19
0
    def changeset_added(self, repos, changeset):
        newchange = changeset
        repo = RepositoryManager(self.env).repository_dir
        repdir = repo.split('.git')[0]
        changes = list(newchange.get_changes())
        print '....handling wikipages.......'
        for change in changes:
            directory = change[0].split('/')[0]
            filename = change[0].split('/')[1]
            pagename = filename.split('.txt')[0]
            extension = filename.split(pagename)[1]

            if (directory == 'wiki' and extension == '.txt'):
                path = repdir + change[0]

                if change[2] == 'edit' or change[2] == 'add':
                    self.add_wiki_file_to_trac(pagename, path)

                elif change[2] == 'delete':
                    self.delete_wiki_page_in_trac(pagename)
                    print (filename + ': wikipage removed.')

                else:
                    print 'Nothing todo.'
            else:
                print 'File was no textfile. Keep going.'
            print '....wikipage handling done......have a nice day :)!'
Пример #20
0
def _process_changeset_view(self, request):
    request.perm.require('CHANGESET_VIEW')

    new = request.args.get('new')
    new_path = request.args.get('new_path')
    old = request.args.get('old')
    repository_name = request.args.get('reponame')

    # -- support for the revision log ''View changes'' form,
    #    where we need to give the path and revision at the same time
    if old and '@' in old:
        old, old_path = old.split('@', 1)
    if new and '@' in new:
        new, new_path = new.split('@', 1)

    manager = RepositoryManager(self.env)

    if repository_name:
        repository = manager.get_repository(repository_name)
    else:
        repository_name, repository, new_path = manager.get_repository_by_path(new_path)

    repository_url = repository.params.get('url', '')

    if _valid_github_request(request) and re.match(r'^https?://(?:www\.)?github\.com/', repository_url):
        url = repository_url.rstrip('/') + '/'

        if old:
            url += 'compare/' + old + '...' + new
        else:
            url += 'commit/' + new

        request.redirect(url)
    else:
        return _old_process_changeset_view(self, request)
Пример #21
0
 def _sync(self, reponame, rev, clean):
     rm = RepositoryManager(self.env)
     if reponame == '*':
         if rev is not None:
             raise TracError(_('Cannot synchronize a single revision '
                               'on multiple repositories'))
         repositories = rm.get_real_repositories()
     else:
         if is_default(reponame):
             reponame = ''
         repos = rm.get_repository(reponame)
         if repos is None:
             raise TracError(_("Repository '%(repo)s' not found",
                               repo=reponame or '(default)'))
         if rev is not None:
             repos.sync_changeset(rev)
             printout(_('%(rev)s resynced on %(reponame)s.', rev=rev,
                        reponame=repos.reponame or '(default)'))
             return
         repositories = [repos]
     
     db = self.env.get_db_cnx()
     for repos in sorted(repositories, key=lambda r: r.reponame):
         printout(_('Resyncing repository history for %(reponame)s... ',
                    reponame=repos.reponame or '(default)'))
         repos.sync(self._sync_feedback, clean=clean)
         cursor = db.cursor()
         cursor.execute("SELECT count(rev) FROM revision WHERE repos=%s",
                        (repos.id,))
         for cnt, in cursor:
             printout(ngettext('%(num)s revision cached.',
                               '%(num)s revisions cached.', num=cnt))
     printout(_('Done.'))
Пример #22
0
 def expand_macro(self, formatter, name, content, args={}):
     reponame = args.get('repository') or ''
     rev = args.get('revision')
     repos = RepositoryManager(self.env).get_repository(reponame)
     try:
         changeset = repos.get_changeset(rev)
         message = changeset.message
         
         # add review status to commit message (
         review = CodeReview(self.env, reponame, rev)
         status = review.encode(review.status)
         message += '\n\n{{{#!html \n'
         message += '<div class="codereviewstatus">'
         message += '  <div class="system-message %s">' % status.lower()
         message += '    <p>Code review status: '
         message += '      <span>%s</span>' % review.status
         message += '    </p>'
         message += '  </div>'
         message += '</div>'
         message += '\n}}}'
         
         rev = changeset.rev
         resource = repos.resource
     except Exception, e:
         message = content
         resource = Resource('repository', reponame)
Пример #23
0
    def process_request(self, request):
        payload = request.args.get('payload')

        if not payload:
            raise Exception('Payload not found')

        payload = simplejson.loads(payload)

        repository_name = payload['repository']['name']
        repository = self.env.get_repository(repository_name)

        if not repository:
            raise Exception('Repository "%s" not found' % repository_name)

        # CachedRepository
        if repository.repos:
            repository.repos.git.repo.remote('update')
        # Normal repository
        else:
            repository.git.repo.remote('update')

        manager = RepositoryManager(self.env)

        revision_ids = [ commit['id'] for commit in payload['commits'] ]

        try:
            self.env.log.debug('Adding changesets: %s' % revision_ids)
            manager.notify('changeset_added', repository_name, revision_ids)
        except Exception as exception:
            self.env.log.error(exception)

        request.send_response(204)
        request.send_header('Content-Length', 0)
        request.write('')
        raise RequestDone
Пример #24
0
    def from_comment(cls, env, comment, user=None, notify=True):
        """
        Creates a subscription from a Comment object.
        """
        sub = {
            'user': user or comment.author,
            'type': comment.type,
            'notify': notify,
        }

        # Munge attachments
        if comment.type == 'attachment':
            sub['path'] = comment.path.split(':')[1]
            sub['repos'] = ''
            sub['rev'] = ''

        # Munge changesets and browser
        if comment.type in ('changeset', 'browser'):
            if comment.type == 'browser':
                sub['path'] = comment.path
            else:
                sub['path'] = ''
            repo = RepositoryManager(env).get_repository(None)
            try:
                sub['repos'] = repo.reponame
                try:
                    _cs = repo.get_changeset(comment.revision)
                    sub['rev'] = _cs.rev
                except NoSuchChangeset:
                    # Invalid changeset
                    return None
            finally:
                repo.close()

        return cls._from_dict(env, sub)
Пример #25
0
 def expand_macro(self, formatter, name, content, args=None):
     # pylint: disable=too-many-function-args
     args = args or {}
     reponame = args.get('repository') or ''
     rev = args.get('revision')
     # pylint: disable=no-member
     repos = RepositoryManager(self.env).get_repository(reponame)
     try:
         changeset = repos.get_changeset(rev)
         message = changeset.message
         rev = changeset.rev
         resource = repos.resource
     except Exception:  # pylint: disable=broad-except
         message = content
         resource = Resource('repository', reponame)
     if ChangesetModule(self.env).wiki_format_messages:
         return tag.div(format_to_html(self.env,
                                       formatter.context.child(
                                           'changeset',
                                           rev,
                                           parent=resource),
                                       message,
                                       escape_newlines=True),
                        class_='message')
     else:
         return tag.pre(message, class_='message')
    def for_request(cls, env, req, create=False):
        """
        Return a **single** subscription for a HTTP request.
        """
        rm = RepositoryManager(env)

        dict_ = {
            'user': req.authname,
            'type': req.args.get('realm'),
            'path': '',
            'rev': '',
            'repos': '',
        }
        path = req.args.get('path') or ''

        if dict_['type'] == 'attachment':
            dict_['path'] = path

        if dict_['type'] == 'changeset':
            parts = [p for p in path.split('/') if p]
            dict_['rev'] = parts[0]
            dict_['repos'] = parts[1]

        if dict_['type'] == 'browser':
            reponame, repos, path = rm.get_repository_by_path(path)
            dict_['path'] = '/' if len(path) == 0 else path
            dict_['rev'] = req.args.get('rev') or ''
            dict_['repos'] = reponame

        return cls.from_dict(env, dict_, create=create)
    def from_comment(cls, env, comment, user=None, notify=True):
        """
        Creates a subscription from a Comment object.
        """
        sub = {
            'user': user or comment.author,
            'type': comment.type,
            'notify': notify,
        }

        # Munge attachments
        if comment.type == 'attachment':
            sub['path'] = comment.path.split(':')[1]
            sub['repos'] = ''
            sub['rev'] = ''

        # Munge changesets and browser
        if comment.type in ('changeset', 'browser'):
            rm = RepositoryManager(env)
            reponame, repos, path = rm.get_repository_by_path(comment.path)
            if comment.type == 'browser':
                sub['path'] = path
            else:
                sub['path'] = ''
            sub['repos'] = reponame or '(default)'
            try:
                _cs = repos.get_changeset(comment.revision)
            except NoSuchChangeset:
                # Invalid changeset
                return None
            else:
                sub['rev'] = _cs.rev

        return cls.from_dict(env, sub)
Пример #28
0
 def _do_changeset_modified(self, reponame, first_rev, *revs):
     if is_default(reponame):
         reponame = ''
     rm = RepositoryManager(self.env)
     errors = rm.notify('changeset_modified', reponame, (first_rev,) + revs)
     for error in errors:
         printerr(error)
     return 2 if errors else 0
Пример #29
0
 def __init__(self):
     # Retrieve info for all repositories associated with this project
     self.authz_file = self.config.get('trac', 'authz_file')
     rm = RepositoryManager(self.env)
     all_repos = rm.get_all_repositories()
     for (reponame, info) in all_repos.iteritems():
         self.project_repos.append(reponame)
     self.env.log.debug("SvnAuthzAdminPlugin: project_repos: '%s'" % self.project_repos)
    def render_admin_panel(self, req, cat, page, path_info):
        req.perm.require('SVNVERIFY_REPORT')
        
        rm = RepositoryManager(self.env)
        all_repos = rm.get_all_repositories()
        db = self.env.get_read_db()
        cursor = db.cursor()
        
        if path_info:
            # detailed
            reponame = not is_default(path_info) and path_info or ''
            info = all_repos.get(reponame)
            if info is None:
                raise TracError(_("Repository '%(repo)s' not found",
                                  repo=path_info))

            cursor.execute("SELECT type, time, result, log "
                           "FROM svnverify_log WHERE repository_id = %s "
                           "ORDER BY time DESC LIMIT 1",
                           (info['id'],))
            row = cursor.fetchone()
            if row:
                info['check_type'] = row[0]
                info['time_checked'] = format_datetime(from_utimestamp(row[1]))
                info['pretty_status'] = int(row[2]) == 0 and "OK" or "Warning"
                info['status'] = row[2]
                info['log'] = row[3]
            info['prettydir'] = breakable_path(info['dir'])
            if info['name'] == '':
                info['name'] = "(default)"
            return 'svnverify.html', {"info": info}
        else:
            repositories = {}
            for reponame, info in all_repos.iteritems():
                if info.get('type',rm.repository_type) == "svn" or (rm.repository_type == 'svn' and info.get('type') == ''):
                    info['prettydir'] = breakable_path(info['dir'])
                    try:
                        r = RepositoryManager(self.env).get_repository(reponame)
                        info['rev'] = r.get_youngest_rev()
                        info['display_rev'] = r.display_rev(info['rev'])
                    except:
                        pass
                    cursor.execute("SELECT type, time, result "
                                   "FROM svnverify_log "
                                   "WHERE repository_id = %s "
                                   "ORDER BY time DESC LIMIT 1",
                                   (info['id'],))
                    row = cursor.fetchone()
                    if row:
                        info['check_type'] = row[0]
                        info['time_checked'] = format_datetime(from_utimestamp(row[1]))
                        info['pretty_status'] = int(row[2]) == 0 and "OK" or "Warning"
                        info['status'] = row[2]

                    repositories[reponame] = info

            add_stylesheet(req, 'svnverify/css/svnverify.css')
            return 'svnverifylist.html', {"repositories": repositories}
Пример #31
0
 def _do_list(self):
     rm = RepositoryManager(self.env)
     values = []
     for (reponame, info) in sorted(rm.get_all_repositories().iteritems()):
         alias = ""
         if "alias" in info:
             alias = info["alias"] or "(default)"
         values.append((reponame or "(default)", info.get("type", ""), alias, info.get("dir", "")))
     print_table(values, [_("Name"), _("Type"), _("Alias"), _("Directory")])
Пример #32
0
 def remove_repository(self, name):
     """Remove a repository."""
     try:
         dir = os.path.join(self.parentpath, name)
         shutil.rmtree(dir)
         rm = RepositoryManager(self.env)
         rm.reload_repositories()
     except OSError, why:
         raise TracError(str(why))
Пример #33
0
 def remove_repository(self, name):
     """Remove a repository."""
     try:
         dir = os.path.join(self.parentpath, name)
         shutil.rmtree(dir)
         rm = RepositoryManager(self.env)
         rm.reload_repositories()
     except OSError, why:
         raise TracError(str(why))
Пример #34
0
Файл: admin.py Проект: t2y/trac
 def _do_list(self):
     rm = RepositoryManager(self.env)
     values = []
     for (reponame, info) in sorted(rm.get_all_repositories().iteritems()):
         alias = ''
         if 'alias' in info:
             alias = info['alias'] or '(default)'
         values.append((reponame or '(default)', info.get('type', ''),
                        alias, info.get('dir', '')))
     print_table(values, [_('Name'), _('Type'), _('Alias'), _('Directory')])
Пример #35
0
 def _do_list(self):
     rm = RepositoryManager(self.env)
     values = []
     for (reponame, info) in sorted(rm.get_all_repositories().iteritems()):
         alias = ''
         if 'alias' in info:
             alias = info['alias'] or '(default)'
         values.append((reponame or '(default)', info.get('type', ''),
                        alias, info.get('dir', '')))
     print_table(values, [_('Name'), _('Type'), _('Alias'), _('Directory')])
Пример #36
0
    def wiki_page_deleted(self, page):
        repo = RepositoryManager(self.env).repository_dir
        repdir = repo.split('.git')[0]

        os.chdir(repdir + "wiki/")

        subprocess.call(["git", "rm", repdir + "wiki/" + page.name + ".txt"])
        subprocess.call(["git", "commit", "-m", page.name + ".txt removed."])

        os.chdir(self.env.path)
Пример #37
0
    def __init__(self, env, req, file):
        from trac.versioncontrol import RepositoryManager
        from trac.versioncontrol.web_ui import get_existing_node

        if hasattr(RepositoryManager, 'get_repository_by_path'): # Trac 0.12
            repo, file = RepositoryManager(env).get_repository_by_path(file)[1:3]
        else:
            repo = RepositoryManager(env).get_repository(req.authname)
        obj = get_existing_node(req, repo, file, None)

        TransformSource.__init__(self, "browser", "source", file, obj)
Пример #38
0
    def wiki_page_added(self, page):
        repo = RepositoryManager(self.env).repository_dir
        repdir = repo.split('.git')[0]

        subprocess.call(["trac-admin", "", "wiki export", page.name, repdir + "wiki/" + "tmp.txt"])
        subprocess.call(["mv", repdir + "wiki/" + "tmp.txt", repdir + "wiki/" + page.name + ".txt"])
        os.chdir(repdir + "wiki/")

        subprocess.call(["git", "add", repdir + "wiki/" + page.name + ".txt"])
        subprocess.call(["git", "commit", "-m", page.name + ".txt added."])

        os.chdir(self.env.path)
Пример #39
0
 def unlink_product(self, reponame):
     if not isinstance(self.env, ProductEnvironment):
         return
     rm = RepositoryManager(self.env.parent)
     repoid = rm.get_repository_id(reponame)
     links = self._get_repository_links(repoid)
     links.remove(self.env.product.prefix)
     with self.env.db_direct_transaction as db:
         if len(links) > 0:
             db("""UPDATE repository SET value=%s WHERE id=%s
                   AND name='product'""", (','.join(links), repoid))
         else:
             db("""DELETE FROM repository WHERE id=%s AND name='product'
                     AND value='%s'""" % (repoid, self.env.product.prefix))
Пример #40
0
    def openProject(self, req, projectname, revision, extensionlist):
        """ Returns project's connection string and repository file list matched to search criteria.
        """
        # Return values
        if str(projectname).strip() == '':
            e = exceptions.Exception
            raise e("Incorrect project name")

        if revision.strip() == '':
            revision = None
        if extensionlist.strip() == '':
            extensionlist = None

        # Find node for the requested path/rev
        repomgr = RepositoryManager(self.env)
        repository = repomgr.get_repository(None)
        projectname = conf.cleanupProjectName(projectname)
        parts = []

        project = Project.get(env_name=projectname)
        if project:
            parts.append(self.get_scm_repository_url(project.env_name))
        else:
            return []

        try:
            if revision:
                revision = repository.normalize_rev(revision)
            rev_or_latest = revision or repository.youngest_rev

            getfiles = []
            self._getfiles(req, getfiles, repository, '', rev_or_latest)

            if extensionlist:
                extensions = extensionlist.split(',')
                searchresult = []
                for file in getfiles:
                    extension = os.path.splitext(str(file))[1].strip('.')
                    if extension in extensions:
                        searchresult.append(file)
                addfiles = ",".join(searchresult)
            else:
                addfiles = ",".join(getfiles)

            if addfiles:
                # Append version control files
                parts.append('versioncontrolfiles|' + addfiles)
        except Exception:
            self.log.exception("ProjectsRPC.openProject failed")
        return parts
Пример #41
0
    def openProject(self, req, projectname, revision, extensionlist):
        """ Returns project's connection string and repository file list matched to search criteria.
        """
        # Return values
        if str(projectname).strip() == '':
            e = exceptions.Exception
            raise e("Incorrect project name")

        if revision.strip() == '':
            revision = None
        if extensionlist.strip() == '':
            extensionlist = None

        # Find node for the requested path/rev
        repomgr = RepositoryManager(self.env)
        repository = repomgr.get_repository(None)
        projectname = conf.cleanupProjectName(projectname)
        parts = []

        project = Project.get(env_name=projectname)
        if project:
            parts.append(self.get_scm_repository_url(project.env_name))
        else:
            return []

        try:
            if revision:
                revision = repository.normalize_rev(revision)
            rev_or_latest = revision or repository.youngest_rev

            getfiles = []
            self._getfiles(req, getfiles, repository, '', rev_or_latest)

            if extensionlist:
                extensions = extensionlist.split(',')
                searchresult = []
                for file in getfiles:
                    extension = os.path.splitext(str(file))[1].strip('.')
                    if extension in extensions:
                        searchresult.append(file)
                addfiles = ",".join(searchresult)
            else:
                addfiles = ",".join(getfiles)

            if addfiles:
                # Append version control files
                parts.append('versioncontrolfiles|' + addfiles)
        except Exception:
            self.log.exception("ProjectsRPC.openProject failed")
        return parts
Пример #42
0
 def unlink_product(self, reponame):
     if not isinstance(self.env, ProductEnvironment):
         return
     rm = RepositoryManager(self.env.parent)
     repoid = rm.get_repository_id(reponame)
     links = self._get_repository_links(repoid)
     links.remove(self.env.product.prefix)
     with self.env.db_direct_transaction as db:
         if len(links) > 0:
             db("""UPDATE repository SET value=%s WHERE id=%s
                   AND name='product'""", (','.join(links), repoid))
         else:
             db("""DELETE FROM repository WHERE id=%s AND name='product'
                     AND value='%s'""" % (repoid, self.env.product.prefix))
Пример #43
0
 def link_product(self, reponame):
     if not isinstance(self.env, ProductEnvironment):
         return
     rm = RepositoryManager(self.env.parent)
     repoid = rm.get_repository_id(reponame)
     links = self._get_repository_links(repoid)
     with self.env.db_direct_transaction as db:
         if links:
             links.append(self.env.product.prefix)
             db("""UPDATE repository SET value=%s WHERE id=%s
                   AND name='product'""", (','.join(links), repoid))
         else:
             db("""INSERT INTO repository (id, name, value)
                     VALUES(%s, 'product', '%s')""" %
                     (repoid, self.env.product.prefix))
Пример #44
0
 def link_product(self, reponame):
     if not isinstance(self.env, ProductEnvironment):
         return
     rm = RepositoryManager(self.env.parent)
     repoid = rm.get_repository_id(reponame)
     links = self._get_repository_links(repoid)
     with self.env.db_direct_transaction as db:
         if links:
             links.append(self.env.product.prefix)
             db("""UPDATE repository SET value=%s WHERE id=%s
                   AND name='product'""", (','.join(links), repoid))
         else:
             db("""INSERT INTO repository (id, name, value)
                     VALUES(%s, 'product', '%s')""" %
                     (repoid, self.env.product.prefix))
Пример #45
0
 def expand_macro(self, formatter, name, content, args=None):
     # pylint: disable=too-many-function-args
     args = args or {}
     reponame = args.get('repository') or ''
     rev = args.get('revision')
     # pylint: disable=no-member
     repos = RepositoryManager(self.env).get_repository(reponame)
     try:
         changeset = repos.get_changeset(rev)
         message = changeset.message
         rev = changeset.rev
         resource = repos.resource
     except Exception:  # pylint: disable=broad-except
         message = content
         resource = Resource('repository', reponame)
     config = self.ticket_replace_section
     fields = {}
     for key, value in config.options():
         idx = key.rfind('.')
         if idx >= 0:
             prefix, attribute = key[:idx], key[idx + 1:]
             field = fields.setdefault(prefix, {})
             field[attribute] = config.get(key)
         else:
             fields[key] = {'': value}
     for prefix, field in fields.iteritems():
         if not all(k in field for k in ['pattern', 'replace']):
             self.log.warn(
                 "Ignoring [%s] %s, missing .pattern or .replace" %
                 (self.ticket_replace_section_name, key))
             continue
         subst = {'repository': reponame, 'revision': rev}
         pattern = field['pattern'].replace('$(', '%(') % subst
         replace = field['replace'].replace('$(', '%(') % subst
         message = re.sub(pattern, replace, message)
     if ChangesetModule(self.env).wiki_format_messages:
         message = '\n'.join(
             map(lambda line: "> " + line, message.split('\n')))
         return tag.div(format_to_html(self.env,
                                       formatter.context.child(
                                           'changeset',
                                           rev,
                                           parent=resource),
                                       message,
                                       escape_newlines=True),
                        class_='message')
     else:
         return tag.pre(message, class_='message')
Пример #46
0
    def process_request(self, req):
        global page_version
        repos = RepositoryManager(self.env).repository_dir
        repdir = repos.split('.git')[0]
        dirList = os.listdir(repdir + 'wiki')
        dirList.sort()
        count_do = 0
        count_no = 0

        for sFile in dirList:
            if sFile.find('.txt') == -1:
                continue
            try:
                filename = os.path.splitext(sFile)[0]
                if filename not in page_version:
                    page_version[filename] = 0
                content = read_file(repdir + 'wiki/' + sFile)
                page = WikiPage(self.env, filename)
                page.text = content.decode('unicode-escape')
                if page_version[filename] != page.version:
                    print (filename + ': local page version does not match online version!')
                    print ('Local version: ' + str(page_version[filename]) + ' <-> online version: ' + str(page.version) + '. Overwrite? (y/n)')
                    user_input = raw_input()
                    if user_input == 'y':
                        page.save(author='me', comment='', remote_addr='127.0.0.1')
                        count_do = count_do + 1
                        print (filename + ' created/modified as wiki page from version ' + str(page_version[filename]) + ' to version ' + str(page.version))
                        page_version[filename] = page.version
                    else:
                        print 'Page not created/modified'
                        count_no = count_no + 1
                        continue
                else:
                    page.save(author='me', comment='', remote_addr='127.0.0.1')
                    count_do = count_do + 1
                    print (filename + ' created/modified as wiki page from version ' + str(page_version[filename]) + ' to version ' + str(page.version))
                    page_version[filename] = page.version
            except:
                count_no = count_no + 1
                print (filename + ' not modified or changed; remained untouched')
                continue

        cont = str(count_do) + ' wiki pages created/modified and ' + str(count_no) + ' untouched'
        req.send_response(200)
        req.send_header('Content-Type', 'text/plain')
        req.send_header('Content-Length', len(cont))
        req.end_headers()
        req.write(cont)
Пример #47
0
    def environment_created(self):
        """Index the repositories."""
        for repos in RepositoryManager(self.env).get_real_repositories():
            pretty_name = repos.reponame or '(default)'
            printout(_(" Indexing '%(name)s' repository", name=pretty_name))
            try:
                repos.sync(self._sync_feedback)
            except TracError:
                printerr(
                    _("""
 ---------------------------------------------------------------------
 Warning: couldn't index '%(pretty_name)s' repository.

 This can happen for a variety of reasons: wrong repository type,
 no appropriate third party library for this repository type,
 no repository at the specified repository path...

 You can nevertheless start using your Trac environment, but you'll
 need to check your `%(name)s.type` and `%(name)s.dir` option values
 in the [repositories] section of your trac.ini file.
""",
                      pretty_name=pretty_name,
                      name=repos.reponame or ''))
            else:
                # Erase to end of line.
                sys.stdout.write('\033[K')
                sys.stdout.flush()
Пример #48
0
 def _extend_info(self, reponame, info, editable):
     """Extend repository info for rendering."""
     info['name'] = reponame
     if info.get('dir') is not None:
         info['prettydir'] = breakable_path(info['dir']) or ''
     info['hidden'] = as_bool(info.get('hidden'))
     info['editable'] = editable
     if not info.get('alias'):
         try:
             repos = RepositoryManager(self.env).get_repository(reponame)
             youngest_rev = repos.get_youngest_rev()
             info['rev'] = youngest_rev
             info['display_rev'] = repos.display_rev(youngest_rev)
         except Exception:
             pass
     return info
Пример #49
0
 def _extend_info(self, reponame, info, editable):
     """Extend repository info for rendering."""
     info["name"] = reponame
     if info.get("dir") is not None:
         info["prettydir"] = breakable_path(info["dir"]) or ""
     info["hidden"] = as_bool(info.get("hidden"))
     info["editable"] = editable
     if not info.get("alias"):
         try:
             repos = RepositoryManager(self.env).get_repository(reponame)
             youngest_rev = repos.get_youngest_rev()
             info["rev"] = youngest_rev
             info["display_rev"] = repos.display_rev(youngest_rev)
         except Exception:
             pass
     return info
Пример #50
0
    def processCommitHook(self, req):
        self.env.log.debug("processCommitHook")
        status = self.closestatus
        if not status:
            status = 'closed'

        if self.autofetch:
            repodir = RepositoryManager(self.env).repository_dir
            if not os.path.isabs(repodir):
                repodir = os.path.join(self.env.path, repodir)
            # TODO: This was the previous code, the repo options is probably unecessary now.
			# repodir = "%s/%s" % (self.repo, reponame)
            self.env.log.debug("Autofetching: %s" % repodir)
            repo = Git(repodir)

            try:
              self.env.log.debug("Fetching repo %s" % self.repo)
              repo.execute(['git', 'fetch'])
              try:
                self.env.log.debug("Resyncing local repo")
                self.env.get_repository('').sync()
              except:
                self.env.log.error("git sync failed!")
            except:
              self.env.log.error("git fetch failed!")

        data = req.args.get('payload')
         
        if data:
            jsondata = simplejson.loads(data)
            reponame = jsondata['repository']['name']

            for i in jsondata['commits']:
                self.hook.process(i, status, self.enable_revmap,reponame)
Пример #51
0
 def _extend_info(self, reponame, info, editable):
     """Extend repository info for rendering."""
     info['name'] = reponame
     if info.get('dir') is not None:
         info['prettydir'] = breakable_path(info['dir']) or ''
     info['hidden'] = as_bool(info.get('hidden'))
     info['editable'] = editable
     if not info.get('alias'):
         try:
             repos = RepositoryManager(self.env).get_repository(reponame)
             youngest_rev = repos.get_youngest_rev()
             info['rev'] = youngest_rev
             info['display_rev'] = repos.display_rev(youngest_rev)
         except Exception:
             pass
     return info
Пример #52
0
    def source(self, req, args):
        arg = re.compile(":|@").split(args)

        if len(arg) < 2:
            raise TracError('[[Usage: BibAdd(source:file[@rev])')
        elif len(arg) == 2:
            revision = None
        else:
            revision = arg[2]

        file = arg[1]

        if version < 0.12:
            repos = self.env.get_repository()
            path = file
        else:
            (reponame, repos,
             path) = RepositoryManager(self.env).get_repository_by_path(file)

        # load the file from the repository
        bib = repos.get_node(path, revision)
        file = bib.get_content()
        text = file.read()

        return _extract(text)
Пример #53
0
 def get_repository(self, authname=None):
     """Return the version control repository configured for this
     environment.
     
     @param authname: user name for authorization
     """
     return RepositoryManager(self).get_repository(authname)
Пример #54
0
    def _update_tickets(self, req, review):
        """Updates the tickets referenced by the given review's changeset
        with a comment of field changes.  Field changes and command execution
        may occur if specified in trac.ini and the review's changeset is the
        last one of the ticket."""
        status = review.encode(review.status).lower()
        summary = review.summaries[-1]

        # build comment
        if summary['status']:
            comment = "Code review set to %(status)s" % summary
        else:
            comment = "Code review comment"
        summary['_ref'] = review.changeset
        if review.repo:
            summary['_ref'] += '/' + review.repo
        comment += " for [%(_ref)s]:\n\n%(summary)s" % summary

        # find and update tickets
        # TODO: handle when there's no explicitly named repo
        repo = RepositoryManager(self.env).get_repository(review.repo)
        changeset = repo.get_changeset(review.changeset)
        ticket_re = CommitTicketUpdater.ticket_re
        tickets = ticket_re.findall(changeset.message)

        invoked = False
        for ticket in tickets:
            tkt = Ticket(self.env, ticket)

            # determine ticket changes
            changes = {}
            if self._is_complete(ticket, tkt, review, failed_ok=True):
                changes = self._get_ticket_changes(tkt, status)

            # update ticket if there's a review summary or ticket changes
            if summary['summary'] or changes:
                for field, value in changes.items():
                    tkt[field] = value
                tkt.save_changes(author=summary['reviewer'], comment=comment)

            # check to invoke command
            if not invoked and self._is_complete(ticket, tkt, review):
                self._execute_command(status)
                invoked = True

        return tickets
Пример #55
0
 def shutdown(self, tid=None):
     """Close the environment."""
     RepositoryManager(self).shutdown(tid)
     DatabaseManager(self).shutdown(tid)
     if tid is None:
         self.log.removeHandler(self._log_handler)
         self._log_handler.flush()
         self._log_handler.close()
         del self._log_handler
Пример #56
0
 def add_repository(self, name):
     """Add a repository."""
     dir = os.path.join(self.parentpath, name)
     if not os.path.isabs(dir):
         raise TracError(_("The repository directory must be absolute"))
     trunk = os.path.join(dir, 'trunk')
     branches = os.path.join(dir, 'branches')
     tags = os.path.join(dir, 'tags')
     command = '"%(svnadmin)s" create "%(dir)s"; "%(svn)s" mkdir --parents -q -m "Created Folders" "file://%(trunk)s" "file://%(branches)s" "file://%(tags)s"' % {
         'svnadmin': self.admin,
         'dir': dir,
         'svn': self.client,
         'trunk': trunk,
         'branches': branches,
         'tags': tags
     }
     process = subprocess.Popen(command,
                                shell=True,
                                stdout=subprocess.PIPE,
                                stderr=subprocess.PIPE)
     (result, error) = process.communicate()
     if error is not None and error != "":
         if error.find('E165002') > -1:
             raise TracError(
                 _('The repository "%(name)s" already exists.', name=name))
         elif error.find('E000002') > -1 or error.find('E000013') > -1:
             raise TracError(
                 _(
                     "Can't create the repository '%(name)s.' "
                     "Make sure the parent directory '%(parentpath)s' exists "
                     "and the web server has write permissions for it.",
                     name=name,
                     parentpath=self.parentpath))
         else:
             raise TracError(error)
     if self.hookspath and os.path.exists(self.hookspath):
         hooksdir = os.path.join(dir, 'hooks/')
         files = os.listdir(self.hookspath)
         files = [self.hookspath + '/' + filename for filename in files]
         for file in files:
             shutil.copy2(file, hooksdir)
     rm = RepositoryManager(self.env)
     rm.reload_repositories()
Пример #57
0
 def _process_repository(self, name, kind, absurl):
     rm = RepositoryManager(self.env)
     repo, remote = self._find_repository(rm, name, kind, absurl)
     if repo is None:
         self.env.log.warn('BitbucketSync: Cannot find a %s repository named "%s"'
                           ' and origin "%s"' % (kind, name, absurl))
     elif kind == 'hg':
         self._process_hg_repository(rm, repo, remote)
     else: #elif kind == 'git':
         self._process_git_repository(rm, repo, remote)
Пример #58
0
 def shutdown(self, tid=None):
     """Close the environment."""
     RepositoryManager(self).shutdown(tid)
     # FIXME: Shared DB so IMO this should not happen ... at least not here
     #DatabaseManager(self).shutdown(tid)
     if tid is None:
         self.log.removeHandler(self._log_handler)
         self._log_handler.flush()
         self._log_handler.close()
         del self._log_handler
Пример #59
0
    def render_admin_panel(self, req, category, page, path_info):
        if not isinstance(self.env, ProductEnvironment):
            return super(ProductRepositoryAdminPanel,
                         self).render_admin_panel(req, category, page,
                                                  path_info)

        req.perm.require('VERSIONCONTROL_ADMIN')
        db_provider = self.env[DbRepositoryProvider]

        if req.method == 'POST' and db_provider:
            if req.args.get('remove'):
                repolist = req.args.get('sel')
                if repolist:
                    if isinstance(repolist, basestring):
                        repolist = [
                            repolist,
                        ]
                    for reponame in repolist:
                        db_provider.unlink_product(reponame)
            elif req.args.get('addlink') is not None and db_provider:
                reponame = req.args.get('repository')
                db_provider.link_product(reponame)
            req.redirect(req.href.admin(category, page))

        # Retrieve info for all product repositories
        rm_product = RepositoryManager(self.env)
        rm_product.reload_repositories()
        all_product_repos = rm_product.get_all_repositories()
        repositories = dict(
            (reponame, self._extend_info(reponame, info.copy(), True))
            for (reponame, info) in all_product_repos.iteritems())
        types = sorted([''] + rm_product.get_supported_types())

        # construct a list of all repositores not linked to this product
        rm = RepositoryManager(self.env.parent)
        all_repos = rm.get_all_repositories()
        unlinked_repositories = dict([
            (k, all_repos[k])
            for k in sorted(set(all_repos) - set(all_product_repos))
        ])

        data = {
            'types': types,
            'default_type': rm_product.repository_type,
            'repositories': repositories,
            'unlinked_repositories': unlinked_repositories
        }
        return 'repository_links.html', data