Files @ aa3b55946089
Branch filter:

Location: kallithea/rhodecode/controllers/forks.py - annotation

"Bradley M. Kuhn"
Migrate to Mergely 3.3.4.

RhodeCode 2.2.5 distributed Mergely 3.3.4 with some of the changes that
Mergely 3.3.3 in RhodeCode 1.7.2 also had. That do however not seem to be
changes we want for Kallithea this way and we take the 3.3.4 files as they are.

I've also included the Mergely license file, as downloaded from:
http://www.mergely.com/license.php

That LICENSE file is kept in HTML just as it was downloaded from their
website. While it's a bit annoying to keep the license file in HTML, this is
the way it came from upstream so we'll leave it that way.

Since the Javascript code is used with other GPLv3 Javascript, we are using the
GPL option of Mergely's tri-license.

Finally, note that previously, this was incorrectly called "mergerly", so the
opportunity is taken here to correct the name. That required changes to
diff_2way.html.

As commands::

$ wget -N --output-document LICENSE-MERGELY.html http://www.mergely.com/license.php
$ hg add LICENSE-MERGELY.html
$ hg mv rhodecode/public/css/mergerly.css rhodecode/public/css/mergely.css
$ hg mv rhodecode/public/js/mergerly.js rhodecode/public/js/mergely.js
$ sed -i 's,mergerly\.,mergely,g' rhodecode/templates/files/diff_2way.html
$ ( cd /tmp; \
wget -N http://www.mergely.com/releases/mergely-3.3.4.zip; \
unzip mergely-3.3.4.zip )
$ sha256sum /tmp/mergely-3.3.4.zip
87415d30494bbe829c248881aa7cdc0303f7e70b458a5f687615564d4498cc82 mergely-3.3.4.zip
$ cp /tmp/mergely-3.3.4/lib/mergely.js rhodecode/public/js/mergely.js
$ cp /tmp/mergely-3.3.4/lib/mergely.css rhodecode/public/css/mergely.css
$ sed -i -e '/^ \* Version/a\ *\n * NOTE by bkuhn@sfconservancy.org for Kallithea:\n * Mergely license appears at http://www.mergely.com/license.php and in LICENSE-MERGELY.html' rhodecode/public/js/mergely.js rhodecode/public/css/mergely.css
7e75af301842
7e75af301842
7e75af301842
7e75af301842
7e75af301842
7e75af301842
7e75af301842
7e75af301842
7e75af301842
7e75af301842
7e75af301842
7e75af301842
7e75af301842
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
7e75af301842
e7eef7a1db6a
e7eef7a1db6a
e7eef7a1db6a
7e75af301842
e7eef7a1db6a
e7eef7a1db6a
e7eef7a1db6a
ffd45b185016
e7eef7a1db6a
e7eef7a1db6a
7e75af301842
7e75af301842
e7eef7a1db6a
ffd45b185016
7e75af301842
6c88624c719b
6c88624c719b
e7eef7a1db6a
e7eef7a1db6a
7e3d89d9d3a2
6b176c679896
ffd45b185016
7e75af301842
7e75af301842
7e75af301842
7e75af301842
7e75af301842
7e75af301842
7e75af301842
7e75af301842
7e75af301842
e7eef7a1db6a
7e3d89d9d3a2
a9565b8b429b
a9565b8b429b
e7eef7a1db6a
133209bf300c
133209bf300c
490e95264d7f
e7eef7a1db6a
e7eef7a1db6a
e7eef7a1db6a
e7eef7a1db6a
e7eef7a1db6a
e7eef7a1db6a
e7eef7a1db6a
e7eef7a1db6a
e7eef7a1db6a
e7eef7a1db6a
e7eef7a1db6a
e7eef7a1db6a
e7eef7a1db6a
144128efc6ab
e7eef7a1db6a
e7eef7a1db6a
a8f520540ab0
e7eef7a1db6a
e7eef7a1db6a
e7eef7a1db6a
e7eef7a1db6a
e7eef7a1db6a
1635a21485d6
e7eef7a1db6a
e7eef7a1db6a
e7eef7a1db6a
e7eef7a1db6a
1635a21485d6
e7eef7a1db6a
e7eef7a1db6a
e7eef7a1db6a
e7eef7a1db6a
e7eef7a1db6a
e7eef7a1db6a
e7eef7a1db6a
e7eef7a1db6a
48b176df890c
48b176df890c
48b176df890c
48b176df890c
bf96fd1920c1
bf96fd1920c1
48b176df890c
e7eef7a1db6a
e7eef7a1db6a
b950b884ab87
e7eef7a1db6a
e7eef7a1db6a
7e75af301842
9d743ca9cede
f9559677c953
162bf5c978f8
162bf5c978f8
162bf5c978f8
162bf5c978f8
162bf5c978f8
162bf5c978f8
162bf5c978f8
7e75af301842
7e75af301842
7e75af301842
7e75af301842
c6b811f11c94
7e75af301842
7e75af301842
7e75af301842
e7eef7a1db6a
b950b884ab87
e7eef7a1db6a
d2d35cf2b351
e7eef7a1db6a
e7eef7a1db6a
e7eef7a1db6a
e7eef7a1db6a
e7eef7a1db6a
144128efc6ab
e7eef7a1db6a
e7eef7a1db6a
e7eef7a1db6a
e7eef7a1db6a
e7eef7a1db6a
e7eef7a1db6a
e7eef7a1db6a
e7eef7a1db6a
e7eef7a1db6a
e7eef7a1db6a
e7eef7a1db6a
b950b884ab87
e7eef7a1db6a
d2d35cf2b351
e7eef7a1db6a
e7eef7a1db6a
e7eef7a1db6a
e7eef7a1db6a
e7eef7a1db6a
e7eef7a1db6a
133209bf300c
133209bf300c
e7eef7a1db6a
ffd45b185016
e7eef7a1db6a
e7eef7a1db6a
e7eef7a1db6a
6c88624c719b
6c88624c719b
6c88624c719b
6c88624c719b
e7eef7a1db6a
e7eef7a1db6a
ffd45b185016
ffd45b185016
ffd45b185016
ffd45b185016
e7eef7a1db6a
e7eef7a1db6a
e7eef7a1db6a
e7eef7a1db6a
e7eef7a1db6a
e7eef7a1db6a
e7eef7a1db6a
e7eef7a1db6a
e7eef7a1db6a
e7eef7a1db6a
e7eef7a1db6a
e7eef7a1db6a
e7eef7a1db6a
ffd45b185016
ffd45b185016
ffd45b185016
# -*- coding: utf-8 -*-
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
"""
rhodecode.controllers.forks
~~~~~~~~~~~~~~~~~~~~~~~~~~~

forks controller for rhodecode

:created_on: Apr 23, 2011
:author: marcink
:copyright: (c) 2013 RhodeCode GmbH.
:license: GPLv3, see LICENSE for more details.
"""

import logging
import formencode
import traceback
from formencode import htmlfill

from pylons import tmpl_context as c, request, url
from pylons.controllers.util import redirect
from pylons.i18n.translation import _
from webob.exc import HTTPNotFound, HTTPInternalServerError

import rhodecode.lib.helpers as h

from rhodecode.lib.helpers import Page
from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator, \
    NotAnonymous, HasRepoPermissionAny, HasPermissionAnyDecorator
from rhodecode.lib.base import BaseRepoController, render
from rhodecode.model.db import Repository, RepoGroup, UserFollowing, User,\
    RhodeCodeUi
from rhodecode.model.repo import RepoModel
from rhodecode.model.forms import RepoForkForm
from rhodecode.model.scm import ScmModel, RepoGroupList
from rhodecode.lib.utils2 import safe_int
from rhodecode.lib.utils import jsonify

log = logging.getLogger(__name__)


class ForksController(BaseRepoController):

    def __before__(self):
        super(ForksController, self).__before__()

    def __load_defaults(self):
        acl_groups = RepoGroupList(RepoGroup.query().all(),
                               perm_set=['group.write', 'group.admin'])
        c.repo_groups = RepoGroup.groups_choices(groups=acl_groups)
        c.repo_groups_choices = map(lambda k: unicode(k[0]), c.repo_groups)
        choices, c.landing_revs = ScmModel().get_repo_landing_revs()
        c.landing_revs_choices = choices
        c.can_update = RhodeCodeUi.get_by_key(RhodeCodeUi.HOOK_UPDATE).ui_active

    def __load_data(self, repo_name=None):
        """
        Load defaults settings for edit, and update

        :param repo_name:
        """
        self.__load_defaults()

        c.repo_info = db_repo = Repository.get_by_repo_name(repo_name)
        repo = db_repo.scm_instance

        if c.repo_info is None:
            h.not_mapped_error(repo_name)
            return redirect(url('repos'))

        c.default_user_id = User.get_default_user().user_id
        c.in_public_journal = UserFollowing.query()\
            .filter(UserFollowing.user_id == c.default_user_id)\
            .filter(UserFollowing.follows_repository == c.repo_info).scalar()

        if c.repo_info.stats:
            last_rev = c.repo_info.stats.stat_on_revision+1
        else:
            last_rev = 0
        c.stats_revision = last_rev

        c.repo_last_rev = repo.count() if repo.revisions else 0

        if last_rev == 0 or c.repo_last_rev == 0:
            c.stats_percentage = 0
        else:
            c.stats_percentage = '%.2f' % ((float((last_rev)) /
                                            c.repo_last_rev) * 100)

        defaults = RepoModel()._get_defaults(repo_name)
        # alter the description to indicate a fork
        defaults['description'] = ('fork of repository: %s \n%s'
                                   % (defaults['repo_name'],
                                      defaults['description']))
        # add suffix to fork
        defaults['repo_name'] = '%s-fork' % defaults['repo_name']

        return defaults

    @LoginRequired()
    @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
                                   'repository.admin')
    def forks(self, repo_name):
        p = safe_int(request.GET.get('page', 1), 1)
        repo_id = c.rhodecode_db_repo.repo_id
        d = []
        for r in Repository.get_repo_forks(repo_id):
            if not HasRepoPermissionAny(
                'repository.read', 'repository.write', 'repository.admin'
            )(r.repo_name, 'get forks check'):
                continue
            d.append(r)
        c.forks_pager = Page(d, page=p, items_per_page=20)

        c.forks_data = render('/forks/forks_data.html')

        if request.environ.get('HTTP_X_PARTIAL_XHR'):
            return c.forks_data

        return render('/forks/forks.html')

    @LoginRequired()
    @NotAnonymous()
    @HasPermissionAnyDecorator('hg.admin', 'hg.fork.repository')
    @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
                                   'repository.admin')
    def fork(self, repo_name):
        c.repo_info = Repository.get_by_repo_name(repo_name)
        if not c.repo_info:
            h.not_mapped_error(repo_name)
            return redirect(url('home'))

        defaults = self.__load_data(repo_name)

        return htmlfill.render(
            render('forks/fork.html'),
            defaults=defaults,
            encoding="UTF-8",
            force_defaults=False
        )

    @LoginRequired()
    @NotAnonymous()
    @HasPermissionAnyDecorator('hg.admin', 'hg.fork.repository')
    @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
                                   'repository.admin')
    def fork_create(self, repo_name):
        self.__load_defaults()
        c.repo_info = Repository.get_by_repo_name(repo_name)
        _form = RepoForkForm(old_data={'repo_type': c.repo_info.repo_type},
                             repo_groups=c.repo_groups_choices,
                             landing_revs=c.landing_revs_choices)()
        form_result = {}
        task_id = None
        try:
            form_result = _form.to_python(dict(request.POST))

            # an approximation that is better than nothing
            if not RhodeCodeUi.get_by_key(RhodeCodeUi.HOOK_UPDATE).ui_active:
                form_result['update_after_clone'] = False

            # create fork is done sometimes async on celery, db transaction
            # management is handled there.
            task = RepoModel().create_fork(form_result, self.rhodecode_user.user_id)
            from celery.result import BaseAsyncResult
            if isinstance(task, BaseAsyncResult):
                task_id = task.task_id
        except formencode.Invalid, errors:
            c.new_repo = errors.value['repo_name']
            return htmlfill.render(
                render('forks/fork.html'),
                defaults=errors.value,
                errors=errors.error_dict or {},
                prefix_error=False,
                encoding="UTF-8")
        except Exception:
            log.error(traceback.format_exc())
            h.flash(_('An error occurred during repository forking %s') %
                    repo_name, category='error')

        return redirect(h.url('repo_creating_home',
                              repo_name=form_result['repo_name_full'],
                              task_id=task_id))