Ejemplo n.º 1
0
class RepoRootController(BaseController):
    _discuss = AppDiscussionController()
    commit_browser_widget=SCMCommitBrowserWidget()

    def _check_security(self):
        security.require(security.has_access(c.app, 'read'))

    @with_trailing_slash
    @expose()
    def index(self, offset=0, branch=None, **kw):
        if branch is None:
            branch=c.app.default_branch_name
        redirect(url(quote('%s%s/' % (
                        branch, c.app.END_OF_REF_ESCAPE))))

    @expose()
    def refresh(self):
        allura.tasks.repo_tasks.refresh.post()
        if request.referer:
            flash('Repository is being refreshed')
            redirect(request.referer)
        else:
            return '%r refresh queued.\n' % c.app.repo

    @with_trailing_slash
    @expose('jinja:allura:templates/repo/fork.html')
    def fork(self, project_id=None, mount_point=None, mount_label=None):
        # this shows the form and handles the submission
        security.require_authenticated()
        if not c.app.forkable: raise exc.HTTPNotFound
        from_repo = c.app.repo
        ThreadLocalORMSession.flush_all()
        ThreadLocalORMSession.close_all()
        from_project = c.project
        to_project = M.Project.query.get(_id=ObjectId(project_id))
        mount_label = mount_label or '%s - %s' % (c.project.name, c.app.config.options.mount_label)
        mount_point = (mount_point or from_project.shortname)
        if request.method != 'POST' or not mount_point:
            return dict(from_repo=from_repo,
                        user_project=c.user.private_project(),
                        mount_point=mount_point,
                        mount_label=mount_label)
        else:
            with h.push_config(c, project=to_project):
                if not to_project.database_configured:
                    to_project.configure_project(is_user_project=True)
                security.require(security.has_access(to_project, 'admin'))
                try:
                    to_project.install_app(
                        ep_name=from_repo.tool_name,
                        mount_point=mount_point,
                        mount_label=mount_label,
                        cloned_from_project_id=from_project._id,
                        cloned_from_repo_id=from_repo._id)
                    redirect(to_project.url()+mount_point+'/')
                except exc.HTTPRedirection:
                    raise
                except Exception, ex:
                    flash(str(ex), 'error')
                    redirect(request.referer)
Ejemplo n.º 2
0
 def __init__(self):
     self._discuss = AppDiscussionController()
Ejemplo n.º 3
0
 def __init__(self):
     setattr(self, 'feed.atom', self.feed)
     setattr(self, 'feed.rss', self.feed)
     c.create_page_lightbox = W.create_page_lightbox
     self._discuss = AppDiscussionController()
Ejemplo n.º 4
0
 def __init__(self):
     c.create_page_lightbox = W.create_page_lightbox
     self._discuss = AppDiscussionController()
Ejemplo n.º 5
0
class RepoRootController(BaseController, FeedController):
    _discuss = AppDiscussionController()
    commit_browser_widget = SCMCommitBrowserWidget()

    def get_feed(self, project, app, user):
        query = dict(project_id=project._id, app_config_id=app.config._id)
        pname, repo = (project.shortname, app.config.options.mount_label)
        title = '%s %s changes' % (pname, repo)
        description = 'Recent changes to %s repository in %s project' % (
            repo, pname)
        return FeedArgs(query, title, app.url, description=description)

    def _check_security(self):
        require_access(c.app, 'read')

    @expose('jinja:allura:templates/markdown_syntax_dialog.html')
    def markdown_syntax_dialog(self):
        """Static page explaining markdown."""
        return dict()

    @with_trailing_slash
    @expose()
    def index(self, offset=0, branch=None, **kw):
        if branch is None:
            branch = c.app.default_branch_name
        redirect(c.app.repo.url_for_commit(branch, url_type='ref'))

    @with_trailing_slash
    @expose('jinja:allura:templates/repo/forks.html')
    def forks(self, **kw):

        links = []
        if c.app.repo.forks:
            for f in c.app.repo.forks:
                repo_path_parts = f.url().strip('/').split('/')
                links.append(dict(
                    repo_url=f.url(),
                    repo='%s / %s' % (repo_path_parts[1],
                                      repo_path_parts[-1]),
                ))
        return dict(links=links)

    @expose()
    def refresh(self, **kw):
        allura.tasks.repo_tasks.refresh.post()
        if request.referer:
            flash('Repository is being refreshed')
            redirect(request.referer)
        else:
            return '%r refresh queued.\n' % c.app.repo

    @with_trailing_slash
    @expose('jinja:allura:templates/repo/fork.html')
    def fork(self, project_id=None, mount_point=None, mount_label=None, **kw):
        # this shows the form and handles the submission
        require_authenticated()
        if not c.app.forkable:
            raise exc.HTTPNotFound
        from_repo = c.app.repo
        ThreadLocalORMSession.flush_all()
        ThreadLocalORMSession.close_all()
        from_project = c.project
        to_project = M.Project.query.get(_id=ObjectId(project_id))
        mount_label = mount_label or '%s - %s' % (c.project.name,
                                                  c.app.config.options.mount_label)
        mount_point = (mount_point or from_project.shortname)
        if request.method != 'POST' or not mount_point:
            return dict(from_repo=from_repo,
                        user_project=c.user.private_project(),
                        mount_point=mount_point,
                        mount_label=mount_label)
        else:
            with h.push_config(c, project=to_project):
                if not to_project.database_configured:
                    to_project.configure_project(is_user_project=True)
                require_access(to_project, 'admin')
                try:
                    to_project.install_app(
                        ep_name=from_repo.tool_name,
                        mount_point=mount_point,
                        mount_label=mount_label,
                        cloned_from_project_id=from_project._id,
                        cloned_from_repo_id=from_repo._id)
                    redirect(to_project.url() + mount_point + '/')
                except exc.HTTPRedirection:
                    raise
                except Exception, ex:
                    flash(str(ex), 'error')
                    redirect(request.referer)
Ejemplo n.º 6
0
 def __init__(self):
     setattr(self, 'feed.atom', self.feed)
     setattr(self, 'feed.rss', self.feed)
     self._discuss = AppDiscussionController()
Ejemplo n.º 7
0
class RepoRootController(BaseController, FeedController):
    _discuss = AppDiscussionController()
    commit_browser_widget = SCMCommitBrowserWidget()

    def get_feed(self, project, app, user):
        query = dict(project_id=project._id, app_config_id=app.config._id)
        pname, repo = (project.shortname, app.config.options.mount_label)
        title = '%s %s changes' % (pname, repo)
        description = 'Recent changes to %s repository in %s project' % (repo,
                                                                         pname)
        return FeedArgs(query, title, app.url, description=description)

    def _check_security(self):
        require_access(c.app, 'read')

    @expose('jinja:allura:templates/markdown_syntax_dialog.html')
    def markdown_syntax_dialog(self, **kw):
        """Static page explaining markdown."""
        return dict()

    @with_trailing_slash
    @expose()
    def index(self, offset=0, branch=None, **kw):
        if branch is None:
            branch = c.app.default_branch_name
        redirect(c.app.repo.url_for_commit(branch, url_type='ref'))

    @with_trailing_slash
    @expose('jinja:allura:templates/repo/forks.html')
    def forks(self, **kw):

        links = []
        if c.app.repo.forks:
            for f in c.app.repo.forks:
                repo_path_parts = f.url().strip('/').split('/')
                links.append(
                    dict(
                        repo_url=f.url(),
                        repo='%s / %s' %
                        (repo_path_parts[1], repo_path_parts[-1]),
                    ))
        return dict(links=links)

    @expose()
    def refresh(self, **kw):
        allura.tasks.repo_tasks.refresh.post()
        if request.referer:
            flash('Repository is being refreshed')
            redirect(six.ensure_text(request.referer or '/'))
        else:
            return '%r refresh queued.\n' % c.app.repo

    @with_trailing_slash
    @expose('jinja:allura:templates/repo/fork.html')
    def fork(self, project_id=None, mount_point=None, mount_label=None, **kw):
        # this shows the form and handles the submission
        require_authenticated()
        if not c.app.forkable:
            raise exc.HTTPNotFound
        from_repo = c.app.repo
        ThreadLocalORMSession.flush_all()
        ThreadLocalORMSession.close_all()
        from_project = c.project
        to_project = M.Project.query.get(_id=ObjectId(project_id))
        mount_label = mount_label or '%s - %s' % (
            c.project.name, c.app.config.options.mount_label)
        mount_point = (mount_point or from_project.shortname)
        if request.method != 'POST' or not mount_point:
            return dict(from_repo=from_repo,
                        user_project=c.user.private_project(),
                        mount_point=mount_point,
                        mount_label=mount_label)
        else:
            with h.push_config(c, project=to_project):
                if not to_project.database_configured:
                    to_project.configure_project(is_user_project=True)
                require_access(to_project, 'admin')
                try:
                    to_project.install_app(
                        ep_name=from_repo.tool_name,
                        mount_point=mount_point,
                        mount_label=mount_label,
                        cloned_from_project_id=from_project._id,
                        cloned_from_repo_id=from_repo._id)
                    redirect(to_project.url() + mount_point + '/')
                except exc.HTTPRedirection:
                    raise
                except Exception as ex:
                    flash(str(ex), 'error')
                    redirect(six.ensure_text(request.referer or '/'))

    @property
    def mr_widget(self):
        source_branches = [
            b.name for b in c.app.repo.get_branches() +
            c.app.repo.get_tags(for_merge_request=True)
        ]
        with c.app.repo.push_upstream_context():
            target_branches = [b.name for b in c.app.repo.get_branches()]
            subscribed_to_upstream = M.Mailbox.subscribed()
        return SCMMergeRequestWidget(
            source_branches=source_branches,
            target_branches=target_branches,
            show_subscribe_checkbox=not subscribed_to_upstream,
        )

    @without_trailing_slash
    @expose('jinja:allura:templates/repo/request_merge.html')
    def request_merge(self, branch=None, **kw):
        require_access(c.app.repo, 'admin')
        c.form = self.mr_widget
        if branch in c.form.source_branches:
            source_branch = branch
        else:
            source_branch = c.app.default_branch_name
        with c.app.repo.push_upstream_context():
            target_branch = c.app.default_branch_name
        return {
            'source_branch': source_branch,
            'target_branch': target_branch,
        }

    @memorable_forget()
    @expose('jinja:allura:templates/repo/request_merge.html'
            )  # needed when we "return self.request_merge(...)"
    @require_post()
    def do_request_merge(self, **kw):
        try:
            kw = self.mr_widget.to_python(kw)
        except formencode.Invalid:
            # trigger error_handler directly
            return self.request_merge(**kw)
        downstream = dict(project_id=c.project._id,
                          mount_point=c.app.config.options.mount_point,
                          commit_id=c.app.repo.commit(kw['source_branch'])._id)
        with c.app.repo.push_upstream_context():
            mr = M.MergeRequest.upsert(downstream=downstream,
                                       target_branch=kw['target_branch'],
                                       source_branch=kw['source_branch'],
                                       summary=kw['summary'],
                                       description=kw['description'])
            if kw.get('subscribe'):
                mr.subscribe(user=c.user)
            M.Notification.post(
                mr,
                'merge_request',
                subject=mr.email_subject,
                message_id=mr.message_id(),
            )
            t = M.Thread.new(
                discussion_id=c.app.config.discussion_id,
                ref_id=mr.index_id(),
            )
            session(t).flush()
            allura.tasks.notification_tasks.send_usermentions_notification.post(
                mr.index_id(), kw['description'])
            g.director.create_activity(c.user,
                                       'created',
                                       mr,
                                       related_nodes=[c.project],
                                       tags=['merge-request'])
            redirect(mr.url())

    @without_trailing_slash
    @expose('jinja:allura:templates/repo/commit_browser.html')
    def commit_browser(self, **kw):
        if not c.app.repo or c.app.repo.status != 'ready':
            return dict(status='not_ready')
        # if c.app.repo.count() > 2000:
        #     return dict(status='too_many_commits')
        if c.app.repo.is_empty():
            return dict(status='no_commits')
        c.commit_browser_widget = self.commit_browser_widget
        return dict(status='ready')

    @without_trailing_slash
    @expose('json:')
    def commit_browser_data(self, start=None, limit=None, **kw):
        log.debug('Start commit_browser_data')
        if limit is None:
            limit = int(tg.config.get('scm.view.commit_browser.limit', 500))

        if start:
            head_ids = start.split(',')
        else:
            # master, and any other branches
            head_ids = [head.object_id for head in c.app.repo.get_heads()]
        log.debug('Got %s heads', len(head_ids))

        # recent commits from any head
        heads_log = list(
            c.app.repo.log(head_ids, id_only=True, limit=int(limit)))
        log.debug('Did log lookup')
        commit_ids = [c.app.repo.rev_to_commit_id(r) for r in heads_log]

        # any we didn't get to will be attempted in next page of commits
        next_page_commits = list(set(head_ids) - set(commit_ids))
        # and remove any heads that didn't come through from further processing
        head_ids = set(head_ids).intersection(set(commit_ids))

        log.info('Grab %d commit objects by ID', len(commit_ids))
        commits_by_id = {
            c_obj._id: c_obj
            for c_obj in M.repository.CommitDoc.m.find(
                dict(_id={'$in': commit_ids}))
        }

        log.info('... build graph')
        parents = {}
        children = defaultdict(list)
        dates = {}
        for row, (oid, ci) in enumerate(six.iteritems(commits_by_id)):
            parents[oid] = list(ci.parent_ids)
            dates[oid] = ci.committed.date
            for p_oid in ci.parent_ids:
                children[p_oid].append(oid)
        result = []
        row = 0
        for oid in topo_sort(children, parents, dates, head_ids):
            if oid not in commits_by_id:
                next_page_commits.append(oid)
                continue
            ci = commits_by_id[oid]
            url = c.app.repo.url_for_commit(Object(_id=oid))
            msg_split = ci.message.splitlines()
            if msg_split:
                msg = h.hide_private_info(msg_split[0])
            else:
                msg = "No commit message."
            result.append(
                dict(oid=oid,
                     short_id=c.app.repo.shorthand_for_commit(oid),
                     row=row,
                     parents=ci.parent_ids,
                     message=msg,
                     url=url))
            row += 1

        built_tree = OrderedDict(
            (ci_json['oid'], ci_json) for ci_json in result)
        log.info('...done')
        return dict(
            built_tree=built_tree,
            next_commit=','.join(next_page_commits),
        )

    @expose('json:')
    def status(self, **kw):
        return dict(status=c.app.repo.status)