Changeset - bf011c9f7f58
[Not reviewed]
kallithea/controllers/pullrequests.py
Show inline comments
 
@@ -309,97 +309,97 @@ class PullrequestsController(BaseRepoCon
 
            add_other_repo(org_repo.parent)
 
            c.default_other_repo = org_repo.parent.repo_name
 

	
 
        c.default_other_repo_info = other_repos_info[c.default_other_repo]
 
        c.other_repos_info = json.dumps(other_repos_info)
 

	
 
        return render('/pullrequests/pullrequest.html')
 

	
 
    @LoginRequired()
 
    @NotAnonymous()
 
    @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
 
                                   'repository.admin')
 
    def create(self, repo_name):
 
        repo = RepoModel()._get_repo(repo_name)
 
        try:
 
            _form = PullRequestForm(repo.repo_id)().to_python(request.POST)
 
        except formencode.Invalid, errors:
 
            log.error(traceback.format_exc())
 
            if errors.error_dict.get('revisions'):
 
                msg = 'Revisions: %s' % errors.error_dict['revisions']
 
            elif errors.error_dict.get('pullrequest_title'):
 
                msg = _('Pull request requires a title with min. 3 chars')
 
            else:
 
                msg = _('Error creating pull request: %s') % errors.msg
 

	
 
            h.flash(msg, 'error')
 
            return redirect(url('pullrequest_home', repo_name=repo_name)) ## would rather just go back to form ...
 

	
 
        org_repo = _form['org_repo']
 
        org_ref = _form['org_ref'] # will end with merge_rev but have symbolic name
 
        other_repo = _form['other_repo']
 
        other_ref = 'rev:ancestor:%s' % _form['ancestor_rev'] # could be calculated from other_ref ...
 
        revisions = [x for x in reversed(_form['revisions'])]
 
        reviewers = _form['review_members']
 

	
 
        title = _form['pullrequest_title']
 
        if not title:
 
            title = '%s#%s to %s' % (org_repo, org_ref.split(':', 2)[1], other_repo)
 
        description = _form['pullrequest_desc']
 
        try:
 
            pull_request = PullRequestModel().create(
 
                self.authuser.user_id, org_repo, org_ref, other_repo,
 
                other_ref, revisions, reviewers, title, description
 
            )
 
            Session().commit()
 
            h.flash(_('Successfully opened new pull request'),
 
                    category='success')
 
        except Exception:
 
            h.flash(_('Error occurred during sending pull request'),
 
            h.flash(_('Error occurred while creating pull request'),
 
                    category='error')
 
            log.error(traceback.format_exc())
 
            return redirect(url('pullrequest_home', repo_name=repo_name))
 

	
 
        return redirect(url('pullrequest_show', repo_name=other_repo,
 
                            pull_request_id=pull_request.pull_request_id))
 

	
 
    @LoginRequired()
 
    @NotAnonymous()
 
    @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
 
                                   'repository.admin')
 
    @jsonify
 
    def update(self, repo_name, pull_request_id):
 
        pull_request = PullRequest.get_or_404(pull_request_id)
 
        if pull_request.is_closed():
 
            raise HTTPForbidden()
 
        #only owner or admin can update it
 
        owner = pull_request.author.user_id == c.authuser.user_id
 
        repo_admin = h.HasRepoPermissionAny('repository.admin')(c.repo_name)
 
        if h.HasPermissionAny('hg.admin') or repo_admin or owner:
 
            reviewers_ids = map(int, filter(lambda v: v not in [None, ''],
 
                request.POST.get('reviewers_ids', '').split(',')))
 

	
 
            PullRequestModel().update_reviewers(pull_request_id, reviewers_ids)
 
            Session().commit()
 
            return True
 
        raise HTTPForbidden()
 

	
 
    @LoginRequired()
 
    @NotAnonymous()
 
    @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
 
                                   'repository.admin')
 
    @jsonify
 
    def delete(self, repo_name, pull_request_id):
 
        pull_request = PullRequest.get_or_404(pull_request_id)
 
        #only owner can delete it !
 
        if pull_request.author.user_id == c.authuser.user_id:
 
            PullRequestModel().delete(pull_request)
 
            Session().commit()
 
            h.flash(_('Successfully deleted pull request'),
 
                    category='success')
 
            return redirect(url('my_account_pullrequests'))
 
        raise HTTPForbidden()
 

	
 
    @LoginRequired()
 
    @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
 
                                   'repository.admin')
 
    def show(self, repo_name, pull_request_id):
kallithea/model/db.py
Show inline comments
 
@@ -1386,97 +1386,97 @@ class Repository(Base, BaseModel):
 
                grouped[rev] = [stat, status_lbl, pr_id, pr_repo]
 

	
 
        for stat in statuses.all():
 
            pr_id = pr_repo = None
 
            if stat.pull_request:
 
                pr_id = stat.pull_request.pull_request_id
 
                pr_repo = stat.pull_request.other_repo.repo_name
 
            grouped[stat.revision] = [str(stat.status), stat.status_lbl,
 
                                      pr_id, pr_repo]
 
        return grouped
 

	
 
    def _repo_size(self):
 
        from kallithea.lib import helpers as h
 
        log.debug('calculating repository size...')
 
        return h.format_byte_size(self.scm_instance.size)
 

	
 
    #==========================================================================
 
    # SCM CACHE INSTANCE
 
    #==========================================================================
 

	
 
    def set_invalidate(self):
 
        """
 
        Mark caches of this repo as invalid.
 
        """
 
        CacheInvalidation.set_invalidate(self.repo_name)
 

	
 
    def scm_instance_no_cache(self):
 
        return self.__get_instance()
 

	
 
    @property
 
    def scm_instance(self):
 
        import kallithea
 
        full_cache = str2bool(kallithea.CONFIG.get('vcs_full_cache'))
 
        if full_cache:
 
            return self.scm_instance_cached()
 
        return self.__get_instance()
 

	
 
    def scm_instance_cached(self, valid_cache_keys=None):
 
        @cache_region('long_term')
 
        def _c(repo_name):
 
            return self.__get_instance()
 
        rn = self.repo_name
 

	
 
        valid = CacheInvalidation.test_and_set_valid(rn, None, valid_cache_keys=valid_cache_keys)
 
        if not valid:
 
            log.debug('Cache for %s invalidated, getting new object' % (rn))
 
            region_invalidate(_c, None, rn)
 
        else:
 
            log.debug('Getting obj for %s from cache' % (rn))
 
            log.debug('Getting scm_instance of %s from cache' % (rn))
 
        return _c(rn)
 

	
 
    def __get_instance(self):
 
        repo_full_path = self.repo_full_path
 
        try:
 
            alias = get_scm(repo_full_path)[0]
 
            log.debug('Creating instance of %s repository from %s'
 
                      % (alias, repo_full_path))
 
            backend = get_backend(alias)
 
        except VCSError:
 
            log.error(traceback.format_exc())
 
            log.error('Perhaps this repository is in db and not in '
 
                      'filesystem run rescan repositories with '
 
                      '"destroy old data " option from admin panel')
 
            return
 

	
 
        if alias == 'hg':
 

	
 
            repo = backend(safe_str(repo_full_path), create=False,
 
                           baseui=self._ui)
 
            # skip hidden web repository
 
            if repo._get_hidden():
 
                return
 
        else:
 
            repo = backend(repo_full_path, create=False)
 

	
 
        return repo
 

	
 
    def __json__(self):
 
        return dict(landing_rev = self.landing_rev)
 

	
 
class RepoGroup(Base, BaseModel):
 
    __tablename__ = 'groups'
 
    __table_args__ = (
 
        UniqueConstraint('group_name', 'group_parent_id'),
 
        CheckConstraint('group_id != group_parent_id'),
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
 
    )
 
    __mapper_args__ = {'order_by': 'group_name'}
 

	
 
    SEP = ' » '
 

	
 
    group_id = Column("group_id", Integer(), nullable=False, unique=True, default=None, primary_key=True)
 
    group_name = Column("group_name", String(255, convert_unicode=False), nullable=False, unique=True, default=None)
 
    group_parent_id = Column("group_parent_id", Integer(), ForeignKey('groups.group_id'), nullable=True, unique=None, default=None)
 
    group_description = Column("group_description", String(10000, convert_unicode=False), nullable=True, unique=None, default=None)
 
    enable_locking = Column("enable_locking", Boolean(), nullable=False, unique=None, default=False)
 
@@ -2211,97 +2211,96 @@ class ChangesetStatus(Base, BaseModel):
 
    STATUS_UNDER_REVIEW = 'under_review'
 

	
 
    STATUSES = [
 
        (STATUS_NOT_REVIEWED, _("Not Reviewed")),  # (no icon) and default
 
        (STATUS_APPROVED, _("Approved")),
 
        (STATUS_REJECTED, _("Rejected")),
 
        (STATUS_UNDER_REVIEW, _("Under Review")),
 
    ]
 

	
 
    changeset_status_id = Column('changeset_status_id', Integer(), nullable=False, primary_key=True)
 
    repo_id = Column('repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
 
    user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
 
    revision = Column('revision', String(40), nullable=False)
 
    status = Column('status', String(128), nullable=False, default=DEFAULT)
 
    changeset_comment_id = Column('changeset_comment_id', Integer(), ForeignKey('changeset_comments.comment_id'))
 
    modified_at = Column('modified_at', DateTime(), nullable=False, default=datetime.datetime.now)
 
    version = Column('version', Integer(), nullable=False, default=0)
 
    pull_request_id = Column("pull_request_id", Integer(), ForeignKey('pull_requests.pull_request_id'), nullable=True)
 

	
 
    author = relationship('User', lazy='joined')
 
    repo = relationship('Repository')
 
    comment = relationship('ChangesetComment', lazy='joined')
 
    pull_request = relationship('PullRequest', lazy='joined')
 

	
 
    def __unicode__(self):
 
        return u"<%s('%s:%s')>" % (
 
            self.__class__.__name__,
 
            self.status, self.author
 
        )
 

	
 
    @classmethod
 
    def get_status_lbl(cls, value):
 
        return dict(cls.STATUSES).get(value)
 

	
 
    @property
 
    def status_lbl(self):
 
        return ChangesetStatus.get_status_lbl(self.status)
 

	
 

	
 
class PullRequest(Base, BaseModel):
 
    __tablename__ = 'pull_requests'
 
    __table_args__ = (
 
        {'extend_existing': True, 'mysql_engine': 'InnoDB',
 
         'mysql_charset': 'utf8', 'sqlite_autoincrement': True},
 
    )
 

	
 
    # values for .status
 
    STATUS_NEW = u'new'
 
    STATUS_OPEN = u'open'
 
    STATUS_CLOSED = u'closed'
 

	
 
    pull_request_id = Column('pull_request_id', Integer(), nullable=False, primary_key=True)
 
    title = Column('title', Unicode(256), nullable=True)
 
    description = Column('description', UnicodeText(10240), nullable=True)
 
    status = Column('status', Unicode(256), nullable=False, default=STATUS_NEW) # only for closedness, not approve/reject/etc
 
    created_on = Column('created_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
 
    updated_on = Column('updated_on', DateTime(timezone=False), nullable=False, default=datetime.datetime.now)
 
    user_id = Column("user_id", Integer(), ForeignKey('users.user_id'), nullable=False, unique=None)
 
    _revisions = Column('revisions', UnicodeText(20500))  # 500 revisions max
 
    org_repo_id = Column('org_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
 
    org_ref = Column('org_ref', Unicode(256), nullable=False)
 
    other_repo_id = Column('other_repo_id', Integer(), ForeignKey('repositories.repo_id'), nullable=False)
 
    other_ref = Column('other_ref', Unicode(256), nullable=False)
 

	
 
    @hybrid_property
 
    def revisions(self):
 
        return self._revisions.split(':')
 

	
 
    @revisions.setter
 
    def revisions(self, val):
 
        self._revisions = ':'.join(val)
 

	
 
    @property
 
    def org_ref_parts(self):
 
        return self.org_ref.split(':')
 

	
 
    @property
 
    def other_ref_parts(self):
 
        return self.other_ref.split(':')
 

	
 
    author = relationship('User', lazy='joined')
 
    reviewers = relationship('PullRequestReviewers',
 
                             cascade="all, delete, delete-orphan")
 
    org_repo = relationship('Repository', primaryjoin='PullRequest.org_repo_id==Repository.repo_id')
 
    other_repo = relationship('Repository', primaryjoin='PullRequest.other_repo_id==Repository.repo_id')
 
    statuses = relationship('ChangesetStatus')
 
    comments = relationship('ChangesetComment',
 
                             cascade="all, delete, delete-orphan")
 

	
 
    def is_closed(self):
 
        return self.status == self.STATUS_CLOSED
 

	
 
    @property
 
    def last_review_status(self):
 
        return self.statuses[-1].status if self.statuses else ''
 

	
 
    def __json__(self):
kallithea/model/notification.py
Show inline comments
 
@@ -105,97 +105,97 @@ class NotificationModel(BaseModel):
 
        notif = Notification.create(
 
            created_by=created_by_obj, subject=subject,
 
            body=body, recipients=recipients_objs, type_=type_
 
        )
 

	
 
        if not with_email:
 
            return notif
 

	
 
        #don't send email to person who created this comment
 
        rec_objs = set(recipients_objs).difference(set([created_by_obj]))
 

	
 
        # send email with notification to all other participants
 
        for rec in rec_objs:
 
            if not email_subject:
 
                email_subject = NotificationModel()\
 
                                    .make_description(notif, show_age=False)
 
            type_ = type_
 
            email_body = None  # we set body to none, we just send HTML emails
 
            ## this is passed into template
 
            kwargs = {'subject': subject, 'body': h.rst_w_mentions(body)}
 
            kwargs.update(email_kwargs)
 
            email_body_html = EmailNotificationModel()\
 
                                .get_email_tmpl(type_, **kwargs)
 

	
 
            run_task(tasks.send_email, rec.email, email_subject, email_body,
 
                     email_body_html)
 

	
 
        return notif
 

	
 
    def delete(self, user, notification):
 
        # we don't want to remove actual notification just the assignment
 
        try:
 
            notification = self.__get_notification(notification)
 
            user = self._get_user(user)
 
            if notification and user:
 
                obj = UserNotification.query()\
 
                        .filter(UserNotification.user == user)\
 
                        .filter(UserNotification.notification
 
                                == notification)\
 
                        .one()
 
                Session().delete(obj)
 
                return True
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            raise
 

	
 
    def get_for_user(self, user, filter_=None):
 
        """
 
        Get mentions for given user, filter them if filter dict is given
 
        Get notifications for given user, filter them if filter dict is given
 

	
 
        :param user:
 
        :param filter:
 
        """
 
        user = self._get_user(user)
 

	
 
        q = UserNotification.query()\
 
            .filter(UserNotification.user == user)\
 
            .join((Notification, UserNotification.notification_id ==
 
                                 Notification.notification_id))
 

	
 
        if filter_:
 
            q = q.filter(Notification.type_.in_(filter_))
 

	
 
        return q.all()
 

	
 
    def mark_read(self, user, notification):
 
        try:
 
            notification = self.__get_notification(notification)
 
            user = self._get_user(user)
 
            if notification and user:
 
                obj = UserNotification.query()\
 
                        .filter(UserNotification.user == user)\
 
                        .filter(UserNotification.notification
 
                                == notification)\
 
                        .one()
 
                obj.read = True
 
                Session().add(obj)
 
                return True
 
        except Exception:
 
            log.error(traceback.format_exc())
 
            raise
 

	
 
    def mark_all_read_for_user(self, user, filter_=None):
 
        user = self._get_user(user)
 
        q = UserNotification.query()\
 
            .filter(UserNotification.user == user)\
 
            .filter(UserNotification.read == False)\
 
            .join((Notification, UserNotification.notification_id ==
 
                                 Notification.notification_id))
 
        if filter_:
 
            q = q.filter(Notification.type_.in_(filter_))
 

	
 
        # this is a little inefficient but sqlalchemy doesn't support
 
        # update on joined tables :(
 
        for obj in q.all():
 
            obj.read = True
 
            Session().add(obj)
kallithea/public/js/base.js
Show inline comments
 
@@ -1662,97 +1662,97 @@ var revisionSort = function(a, b, desc, 
 
    var b_ = parseInt(b.getData('last_rev_raw') || 0);
 

	
 
    return YAHOO.util.Sort.compare(a_, b_, desc);
 
};
 

	
 
var ageSort = function(a, b, desc, field) {
 
    // data is like: <span class="tooltip" date="2014-06-04 18:18:55.325474" title="Wed, 04 Jun 2014 18:18:55">1 day and 23 hours ago</span>
 
    var a_ = $(a.getData(field)).attr('date');
 
    var b_ = $(b.getData(field)).attr('date');
 

	
 
    return YAHOO.util.Sort.compare(a_, b_, desc);
 
};
 

	
 
var lastLoginSort = function(a, b, desc, field) {
 
    var a_ = parseFloat(a.getData('last_login_raw') || 0);
 
    var b_ = parseFloat(b.getData('last_login_raw') || 0);
 

	
 
    return YAHOO.util.Sort.compare(a_, b_, desc);
 
};
 

	
 
var nameSort = function(a, b, desc, field) {
 
    var a_ = a.getData('raw_name') || 0;
 
    var b_ = b.getData('raw_name') || 0;
 

	
 
    return YAHOO.util.Sort.compare(a_, b_, desc);
 
};
 

	
 
var dateSort = function(a, b, desc, field) {
 
    var a_ = parseFloat(a.getData('raw_date') || 0);
 
    var b_ = parseFloat(b.getData('raw_date') || 0);
 

	
 
    return YAHOO.util.Sort.compare(a_, b_, desc);
 
};
 

	
 
var addPermAction = function(_html, users_list, groups_list){
 
    var $last_node = $('.last_new_member').last(); // empty tr between last and add
 
    var next_id = $('.new_members').length;
 
    $last_node.before($('<tr class="new_members">').append(_html.format(next_id)));
 
    _MembersAutoComplete("perm_new_member_name_"+next_id,
 
            "perm_container_"+next_id, users_list, groups_list);
 
}
 

	
 
function ajaxActionRevokePermission(url, obj_id, obj_type, field_id, extra_data) {
 
    var callback = {
 
        success: function (o) {
 
            $('#' + field_id).remove();
 
        },
 
        failure: function (o) {
 
            alert(_TM['Failed to remoke permission'] + ": " + o.status);
 
            alert(_TM['Failed to revoke permission'] + ": " + o.status);
 
        },
 
    };
 
    query_params = {
 
        '_method': 'delete'
 
    }
 
    // put extra data into POST
 
    if (extra_data !== undefined && (typeof extra_data === 'object')){
 
        for(k in extra_data){
 
            query_params[k] = extra_data[k];
 
        }
 
    }
 

	
 
    if (obj_type=='user'){
 
        query_params['user_id'] = obj_id;
 
        query_params['obj_type'] = 'user';
 
    }
 
    else if (obj_type=='user_group'){
 
        query_params['user_group_id'] = obj_id;
 
        query_params['obj_type'] = 'user_group';
 
    }
 

	
 
    var request = YAHOO.util.Connect.asyncRequest('POST', url, callback,
 
            _toQueryString(query_params));
 
};
 

	
 
/* Multi selectors */
 

	
 
var MultiSelectWidget = function(selected_id, available_id, form_id){
 
    var $availableselect = $('#' + available_id);
 
    var $selectedselect = $('#' + selected_id);
 

	
 
    //fill available only with those not in selected
 
    var $selectedoptions = $selectedselect.children('option');
 
    $availableselect.children('option').filter(function(i, e){
 
            for(var j = 0, node; node = $selectedoptions[j]; j++){
 
                if(node.value == e.value){
 
                    return true;
 
                }
 
            }
 
            return false;
 
        }).remove();
 

	
 
    $('#add_element').click(function(e){
 
            $selectedselect.append($availableselect.children('option:selected'));
 
        });
 
    $('#remove_element').click(function(e){
 
            $availableselect.append($selectedselect.children('option:selected'));
 
        });
kallithea/templates/base/root.html
Show inline comments
 
@@ -8,107 +8,107 @@
 
        <meta name="robots" content="index, nofollow"/>
 
        <link rel="icon" href="${h.url('/images/favicon.ico')}" type="image/png" />
 

	
 
        ## CSS ###
 
        <%def name="css()">
 
            <link rel="stylesheet" type="text/css" href="${h.url('/js/select2/select2.css', ver=c.kallithea_version)}"/>
 
            <link rel="stylesheet" type="text/css" href="${h.url('/css/pygments.css', ver=c.kallithea_version)}"/>
 
            <link rel="stylesheet" type="text/css" href="${h.url('/css/style.css', ver=c.kallithea_version)}" media="screen"/>
 
            <link rel="stylesheet" type="text/css" href="${h.url('/css/contextbar.css', ver=c.kallithea_version)}" media="screen"/>
 
            ## EXTRA FOR CSS
 
            ${self.css_extra()}
 
        </%def>
 

	
 
        <%def name="css_extra()"></%def>
 

	
 
        ${self.css()}
 

	
 
        %if c.ga_code:
 
        <!-- Analytics -->
 
        <script type="text/javascript">
 
            var _gaq = _gaq || [];
 
            _gaq.push(['_setAccount', '${c.ga_code}']);
 
            _gaq.push(['_trackPageview']);
 

	
 
            (function() {
 
                var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
 
                ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
 
                var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
 
                })();
 
        </script>
 
        %endif
 

	
 
        ## JAVASCRIPT ##
 
        <%def name="js()">
 
            <script type="text/javascript">
 
            //JS translations map
 
            var TRANSLATION_MAP = {
 
                'Add another comment':'${_("Add another comment")}',
 
                'Stop following this repository':"${_('Stop following this repository')}",
 
                'Start following this repository':"${_('Start following this repository')}",
 
                'Group':"${_('Group')}",
 
                'members':"${_('members')}",
 
                'Loading ...':"${_('Loading ...')}",
 
                'loading ...':"${_('loading ...')}",
 
                'Search truncated': "${_('Search truncated')}",
 
                'No matching files': "${_('No matching files')}",
 
                'Open new pull request': "${_('Open new pull request')}",
 
                'Open new pull request for selected changesets':  "${_('Open new pull request for selected changesets')}",
 
                'Show selected changesets __S -> __E': "${_('Show selected changesets __S -> __E')}",
 
                'Show selected changesets __S &rarr; __E': "${h.literal(_('Show selected changesets __S &rarr; __E'))}",
 
                'Show selected changeset __S': "${_('Show selected changeset __S')}",
 
                'Selection link': "${_('Selection link')}",
 
                'Collapse diff': "${_('Collapse diff')}",
 
                'Expand diff': "${_('Expand diff')}",
 
                'Failed to revoke permission': "${_('Failed to revoke permission')}",
 
                'Confirm to revoke permission for {0}: {1} ?': "${_('confirm to revoke permission for {0}: {1} ?')}",
 
                'enabled': "${_('enabled')}",
 
                'disabled': "${_('disabled')}",
 
                'Select changeset': "${_('Select changeset')}",
 
                'specify changeset': "${_('specify changeset')}",
 
                'Specify changeset': "${_('Specify changeset')}",
 
                'MSG_SORTASC': "${_('Click to sort ascending')}",
 
                'MSG_SORTDESC': "${_('Click to sort descending')}",
 
                'MSG_EMPTY': "${_('No records found.')}",
 
                'MSG_ERROR': "${_('Data error.')}",
 
                'MSG_LOADING': "${_('Loading...')}",
 

	
 

	
 
            };
 
            var _TM = TRANSLATION_MAP;
 

	
 
            var TOGGLE_FOLLOW_URL  = "${h.url('toggle_following')}";
 

	
 
            var REPO_NAME = "";
 
            %if hasattr(c, 'repo_name'):
 
                var REPO_NAME = "${c.repo_name}";
 
            %endif
 
            </script>
 
            <script type="text/javascript" src="${h.url('/js/yui.2.9.js', ver=c.kallithea_version)}"></script>
 
            <script type="text/javascript" src="${h.url('/js/jquery-1.10.2.min.js', ver=c.kallithea_version)}"></script>
 
            <script type="text/javascript" src="${h.url('/js/bootstrap.js', ver=c.kallithea_version)}"></script>
 
            <script type="text/javascript" src="${h.url('/js/select2/select2.js', ver=c.kallithea_version)}"></script>
 
            <script type="text/javascript" src="${h.url('/js/mousetrap.js', ver=c.kallithea_version)}"></script>
 
            <!--[if lt IE 9]>
 
               <script language="javascript" type="text/javascript" src="${h.url('/js/excanvas.min.js')}"></script>
 
            <![endif]-->
 
            <script type="text/javascript" src="${h.url('/js/yui.flot.js', ver=c.kallithea_version)}"></script>
 
            <script type="text/javascript" src="${h.url('/js/native.history.js', ver=c.kallithea_version)}"></script>
 
            <script type="text/javascript" src="${h.url('/js/pyroutes_map.js', ver=c.kallithea_version)}"></script>
 
            <script type="text/javascript" src="${h.url('/js/base.js', ver=c.kallithea_version)}"></script>
 
           ## EXTRA FOR JS
 
           ${self.js_extra()}
 
            <script type="text/javascript">
 
            (function(window,undefined){
 
                // Prepare
 
                var History = window.History; // Note: We are using a capital H instead of a lower h
 
                if ( !History.enabled ) {
 
                     // History.js is disabled for this browser.
 
                     // This is because we can optionally choose to support HTML4 browsers or not.
 
                    return false;
 
                }
 
            })(window);
 

	
 
            YUE.onDOMReady(function(){
 
              tooltip_activate();
 
              show_more_event();
 
              show_changeset_tooltip();
 
              // routes registration
 
              pyroutes.register('home', "${h.url('home')}", []);
kallithea/templates/changelog/changelog.html
Show inline comments
 
## -*- coding: utf-8 -*-
 

	
 
<%inherit file="/base/base.html"/>
 

	
 
<%def name="title()">
 
    ${_('%s Changelog') % c.repo_name}
 
    %if c.changelog_for_path:
 
      /${c.changelog_for_path}
 
    %endif
 
    %if c.site_name:
 
        &middot; ${c.site_name}
 
    %endif
 
</%def>
 

	
 
<%def name="breadcrumbs_links()">
 
    <% size = c.size if c.size <= c.total_cs else c.total_cs %>
 
    ${_('Changelog')}
 
    %if c.changelog_for_path:
 
     - /${c.changelog_for_path}
 
    %endif
 
    - ${ungettext('showing %d out of %d revision', 'showing %d out of %d revisions', size) % (size, c.total_cs)}
 
</%def>
 

	
 
<%def name="page_nav()">
 
    ${self.menu('repositories')}
 
</%def>
 

	
 
<%def name="main()">
 
${self.repo_context_bar('changelog')}
 
<div class="box">
 
    <!-- box / title -->
 
    <div class="title">
 
        ${self.breadcrumbs()}
 
    </div>
 
    <div class="table">
 
        % if c.pagination:
 
            <div id="graph">
 
                <div style="overflow:auto; display:${'none' if c.changelog_for_path else ''}">
 
                    <div class="container_header">
 
                       <div style="float:right; margin: 0px 0px 0px 4px">${h.select('branch_filter',c.branch_name,c.branch_filters)}</div>
 
                       <div class="info_box" style="text-align: right; float: right">
 
                            <a href="#" class="btn btn-mini" id="rev_range_container" style="display:none"></a>
 
                            <a href="#" class="btn btn-mini" id="rev_range_clear" style="display:none">${_('Clear selection')}</a>
 

	
 
                            %if c.db_repo.fork:
 
                                <a id="compare_fork"
 
                                   title="${_('Compare fork with %s' % c.db_repo.fork.repo_name)}"
 
                                   href="${h.url('compare_url',repo_name=c.db_repo.fork.repo_name,org_ref_type=c.db_repo.landing_rev[0],org_ref=c.db_repo.landing_rev[1],other_repo=c.repo_name,other_ref_type='branch' if request.GET.get('branch') else c.db_repo.landing_rev[0],other_ref=request.GET.get('branch') or c.db_repo.landing_rev[1], merge=1)}"
 
                                   class="btn btn-mini"><i class="icon-loop"></i> ${_('Compare fork with Parent(%s)' % c.db_repo.fork.repo_name)}</a>
 
                                   class="btn btn-mini"><i class="icon-loop"></i> ${_('Compare fork with parent repo (%s)' % c.db_repo.fork.repo_name)}</a>
 
                            %endif
 
                            <a id="open_new_pr" href="${h.url('pullrequest_home',repo_name=c.repo_name)}" class="btn btn-mini">${_('Open new pull request')}</a>
 
                       </div>
 

	
 
                       ${h.form(h.url.current(),method='get')}
 
                       <div style="float:left">
 
                           ${h.submit('set',_('Show'),class_="btn btn-mini")}
 
                           ${h.text('size',size=1,value=c.size)}
 
                           ${_('revisions')}
 
                       </div>
 
                       ${h.end_form()}
 
                    </div>
 
                </div>
 
                <div id="graph_nodes">
 
                    <canvas id="graph_canvas"></canvas>
 
                </div>
 
                <div id="graph_content" style="${'margin: 0px' if c.changelog_for_path else ''}">
 

	
 
                <table id="changesets">
 
                <tbody>
 
                %for cnt,cs in enumerate(c.pagination):
 
                    <tr id="chg_${cnt+1}" class="container ${'tablerow%s' % (cnt%2)}">
 
                        <td class="checkbox">
 
                            %if c.changelog_for_path:
 
                                ${h.checkbox(cs.raw_id,class_="changeset_range", disabled="disabled")}
 
                            %else:
 
                                ${h.checkbox(cs.raw_id,class_="changeset_range")}
 
                            %endif
 
                        <td class="status">
 
                          %if c.statuses.get(cs.raw_id):
 
                            <div class="changeset-status-ico">
 
                            %if c.statuses.get(cs.raw_id)[2]:
 
                              <a class="tooltip" title="${_('Changeset status: %s\nClick to open associated pull request #%s') % (h.changeset_status_lbl(c.statuses.get(cs.raw_id)[0]), c.statuses.get(cs.raw_id)[2])}" href="${h.url('pullrequest_show',repo_name=c.statuses.get(cs.raw_id)[3],pull_request_id=c.statuses.get(cs.raw_id)[2])}">
 
                                <img src="${h.url('/images/icons/flag_status_%s.png' % c.statuses.get(cs.raw_id)[0])}" />
 
                              </a>
 
                            %else:
 
                              <a class="tooltip" title="${_('Changeset status: %s') % h.changeset_status_lbl(c.statuses.get(cs.raw_id)[0])}" href="${h.url('changeset_home',repo_name=c.repo_name,revision=cs.raw_id,anchor='comment-%s' % c.comments[cs.raw_id][0].comment_id)}">
 
                                  <img src="${h.url('/images/icons/flag_status_%s.png' % c.statuses.get(cs.raw_id)[0])}" />
 
                              </a>
 
                            %endif
 
                            </div>
 
                          %endif
 
                        </td>
 
                        <td class="author">
 
                            <img alt="gravatar" src="${h.gravatar_url(h.email_or_none(cs.author),16)}"/>
 
                            <span title="${cs.author}" class="user">${h.shorter(h.person(cs.author),22)}</span>
 
                        </td>
 
                        <td class="hash" style="width:${len(h.show_id(cs))*6.5}px">
 
@@ -143,97 +143,97 @@ ${self.repo_context_bar('changelog')}
 
                %endfor
 
                </tbody>
 
                </table>
 

	
 
                <div class="pagination-wh pagination-left">
 
                    ${c.pagination.pager('$link_previous ~2~ $link_next')}
 
                </div>
 
            </div>
 
        </div>
 

	
 
        <script type="text/javascript" src="${h.url('/js/graph.js')}"></script>
 
        <script type="text/javascript">
 
            YAHOO.util.Event.onDOMReady(function(){
 

	
 
                //Monitor range checkboxes and build a link to changesets
 
                //ranges
 
                var checkboxes = YUD.getElementsByClassName('changeset_range');
 
                // register our routes needed for this view
 
                pyroutes.register('changeset_home', "${h.url('changeset_home', repo_name='%(repo_name)s', revision='%(revision)s')}", ['repo_name', 'revision']);
 

	
 
                var checkbox_checker = function(e){
 
                    var checked_checkboxes = [];
 
                    for (pos in checkboxes){
 
                        if(checkboxes[pos].checked){
 
                            checked_checkboxes.push(checkboxes[pos]);
 
                        }
 
                    }
 
                    if(YUD.get('open_new_pr')){
 
                        if(checked_checkboxes.length>1){
 
                            YUD.setStyle('open_new_pr','display','none');
 
                        } else {
 
                            YUD.setStyle('open_new_pr','display','');
 
                            if(checked_checkboxes.length>0){
 
                                YUD.get('open_new_pr').innerHTML = _TM['Open new pull request for selected changesets'];
 
                            }else{
 
                                YUD.get('open_new_pr').innerHTML = _TM['Open new pull request'];
 
                            }
 
                        }
 
                    }
 

	
 
                    if(checked_checkboxes.length>0){
 
                        var rev_end = checked_checkboxes[0].name;
 
                        var rev_start = checked_checkboxes[checked_checkboxes.length-1].name;
 
                        var url = pyroutes.url('changeset_home', {'repo_name': '${c.repo_name}',
 
                                                                  'revision': rev_start+'...'+rev_end});
 

	
 
                        var link = (rev_start == rev_end)
 
                            ? _TM['Show selected changeset __S']
 
                            : _TM['Show selected changesets __S -> __E'];
 
                            : _TM['Show selected changesets __S &rarr; __E'];
 

	
 
                        link = link.replace('__S',rev_start.substr(0,6));
 
                        link = link.replace('__E',rev_end.substr(0,6));
 
                        YUD.get('rev_range_container').href = url;
 
                        YUD.get('rev_range_container').innerHTML = link;
 
                        YUD.setStyle('rev_range_container','display','');
 
                        YUD.setStyle('rev_range_clear','display','');
 

	
 
                        YUD.get('open_new_pr').href = pyroutes.url('pullrequest_home',
 
                                                                   {'repo_name': '${c.repo_name}',
 
                                                                    'rev_start': rev_start,
 
                                                                    'rev_end': rev_end})
 

	
 
                        YUD.setStyle('compare_fork','display','none');
 
                    }else{
 
                        YUD.setStyle('rev_range_container','display','none');
 
                        YUD.setStyle('rev_range_clear','display','none');
 
                        %if c.branch_name:
 
                            YUD.get('open_new_pr').href = pyroutes.url('pullrequest_home',
 
                                                                       {'repo_name': '${c.repo_name}',
 
                                                                        'branch':'${c.branch_name}'});
 
                        %else:
 
                            YUD.get('open_new_pr').href = pyroutes.url('pullrequest_home',
 
                                                                       {'repo_name': '${c.repo_name}'});
 
                        %endif
 
                        YUD.setStyle('compare_fork','display','');
 
                    }
 
                };
 
                YUE.onDOMReady(checkbox_checker);
 
                YUE.on(checkboxes,'click', checkbox_checker);
 

	
 
                YUE.on('rev_range_clear','click',function(e){
 
                    for (var i=0; i<checkboxes.length; i++){
 
                        var cb = checkboxes[i];
 
                        cb.checked = false;
 
                    }
 
                    checkbox_checker();
 
                    YUE.preventDefault(e);
 
                });
 

	
 
                var msgs = YUQ('.message');
 
                // get first element height
 
                var el = YUQ('#graph_content .container')[0];
 
                var row_h = el.clientHeight;
 
                for(var i=0;i<msgs.length;i++){
 
                    var m = msgs[i];
 

	
 
                    var h = m.clientHeight;
kallithea/templates/changeset/changeset_file_comment.html
Show inline comments
 
@@ -20,97 +20,97 @@
 
         %if co.pull_request:
 
            <a href="${h.url('pullrequest_show',repo_name=co.pull_request.other_repo.repo_name,pull_request_id=co.pull_request.pull_request_id)}">
 
            %if co.status_change:
 
              ${_('Vote on pull request #%s') % co.pull_request.pull_request_id}:
 
            %else:
 
              ${_('Comment on pull request #%s') % co.pull_request.pull_request_id}
 
            %endif
 
            </a>
 
         %else:
 
            %if co.status_change:
 
              ${_('Status change on changeset')}:
 
            %else:
 
              ${_('Comment on changeset')}
 
            %endif
 
         %endif
 
        </span>
 
       </div>
 

	
 
        %if co.status_change:
 
           <div  style="float:left" class="changeset-status-container">
 
             <div style="float:left;padding:10px 2px 0px 2px"></div>
 
             <div title="${_('Changeset status')}" class="changeset-status-lbl"> ${co.status_change[0].status_lbl}</div>
 
             <div class="changeset-status-ico"><img src="${h.url(str('/images/icons/flag_status_%s.png' % co.status_change[0].status))}" /></div>
 
           </div>
 
        %endif
 

	
 
      <a class="permalink" href="#comment-${co.comment_id}">&para;</a>
 
      %if h.HasPermissionAny('hg.admin')() or h.HasRepoPermissionAny('repository.admin')(c.repo_name) or co.author.user_id == c.authuser.user_id:
 
          <div onClick="deleteComment(${co.comment_id})" class="buttons delete-comment btn btn-mini">${_('Delete')}</div>
 
      %endif
 
      </div>
 
      <div class="text">
 
          ${h.rst_w_mentions(co.text)|n}
 
      </div>
 
    </div>
 
  </div>
 
</%def>
 

	
 

	
 
<%def name="comment_inline_form()">
 
<div id='comment-inline-form-template' style="display:none">
 
  <div class="comment-inline-form ac">
 
  %if c.authuser.username != 'default':
 
      ${h.form('#', class_='inline-form')}
 
      <div id="edit-container_{1}" class="clearfix">
 
          <div class="comment-help">${_('Commenting on line {1}.')}
 
          ${(_('Comments parsed using %s syntax with %s support.') % (
 
                 ('<a href="%s">RST</a>' % h.url('rst_help')),
 
                   ('<span style="color:#577632" class="tooltip" title="%s">@mention</span>' % _('Use @username inside this text to send notification to this Kallithea user'))
 
                   ('<span style="color:#577632" class="tooltip" title="%s">@mention</span>' % _('Use @username inside this text to notify another user'))
 
               )
 
            )|n
 
           }
 
          <div id="preview-btn_{1}" class="preview-btn btn btn-mini">${_('Preview')}</div>
 
          </div>
 
            <div class="mentions-container" id="mentions_container_{1}"></div>
 
            <textarea id="text_{1}" name="text" class="comment-block-ta yui-ac-input"></textarea>
 
      </div>
 
      <div id="preview-container_{1}" class="clearfix" style="display:none">
 
         <div class="comment-help">
 
              ${_('Comment preview')}
 
            <div id="edit-btn_{1}" class="edit-btn btn btn-mini">${_('Edit')}</div>
 
          </div>
 
          <div id="preview-box_{1}" class="preview-box"></div>
 
      </div>
 
      <div class="comment-button">
 
      <div class="submitting-overlay">${_('Submitting ...')}</div>
 
      <input type="hidden" name="f_path" value="{0}">
 
      <input type="hidden" name="line" value="{1}">
 
      ${h.submit('save', _('Comment'), class_='btn btn-small save-inline-form')}
 
      ${h.reset('hide-inline-form', _('Cancel'), class_='btn btn-small hide-inline-form')}
 
      </div>
 
      ${h.end_form()}
 
  %else:
 
      ${h.form('')}
 
      <div class="clearfix">
 
          <div class="comment-help">
 
            ${_('You need to be logged in to comment.')} <a href="${h.url('login_home',came_from=h.url.current())}">${_('Login now')}</a>
 
          </div>
 
      </div>
 
      <div class="comment-button">
 
      ${h.reset('hide-inline-form', _('Hide'), class_='btn btn-small hide-inline-form')}
 
      </div>
 
      ${h.end_form()}
 
  %endif
 
  </div>
 
</div>
 
</%def>
 

	
 

	
 
## generates inlines taken from c.comments var
 
<%def name="inlines()">
 
    <div class="comments-number">${ungettext("%d comment", "%d comments", len(c.comments)) % len(c.comments)} ${ungettext("(%d inline)", "(%d inline)", c.inline_cnt) % c.inline_cnt}</div>
 
    %for path, lines in c.inline_comments:
 
        % for line,comments in lines.iteritems():
 
            <div style="display:none" class="inline-comment-placeholder" path="${path}" target_id="${h.safeid(h.safe_unicode(path))}">
 
            %for co in comments:
 
                ${comment_block(co)}
kallithea/templates/compare/compare_diff.html
Show inline comments
 
@@ -70,120 +70,120 @@ ${self.repo_context_bar('changelog')}
 
                        <div class="changes">${h.fancy_file_stats(stat)}</div>
 
                      </div>
 
                  %endfor
 
                </div>
 
                % if c.limited_diff:
 
                  <h5>${_('Changeset was too big and was cut off...')} <a href="${h.url.current(fulldiff=1, **request.GET.mixed())}">${_('Show full diff')}</a></h5>
 
                % endif
 
         </div>
 

	
 
        ## diff block
 
        <%namespace name="diff_block" file="/changeset/diff_block.html"/>
 
        %for fid, change, f, stat in c.files:
 
          ${diff_block.diff_block_simple([c.changes[fid]])}
 
        %endfor
 
        % if c.limited_diff:
 
          <h4>${_('Changeset was too big and was cut off...')} <a href="${h.url.current(fulldiff=1, **request.GET.mixed())}">${_('Show full diff')}</a></h4>
 
        % endif
 
    %endif
 
    </div>
 

	
 
</div>
 
    <script type="text/javascript">
 

	
 
   $(document).ready(function(){
 
    var cache = {}
 
    $("#compare_org").select2({
 
        placeholder: "${'%s@%s' % (c.org_repo.repo_name, c.org_ref)}",
 
        formatSelection: function(obj){
 
            return '{0}@{1}'.format("${c.org_repo.repo_name}", obj.text)
 
        },
 
        dropdownAutoWidth: true,
 
        query: function(query){
 
          var key = 'cache';
 
          var cached = cache[key] ;
 
          if(cached) {
 
            var data = {results: []};
 
            //filter results
 
            $.each(cached.results, function(){
 
                var section = this.text;
 
                var children = [];
 
                $.each(this.children, function(){
 
                    if(query.term.length == 0 || this.text.toUpperCase().indexOf(query.term.toUpperCase()) >= 0 ){
 
                        children.push({'id': this.id, 'text': this.text})
 
                    }
 
                })
 
                data.results.push({'text': section, 'children': children})
 
            });
 
            //push the typed in changeset
 
            data.results.push({'text':_TM['specify changeset'],
 
            data.results.push({'text':_TM['Specify changeset'],
 
                               'children': [{'id': query.term, 'text': query.term, 'type': 'rev'}]})
 
            query.callback(data);
 
          }else{
 
              $.ajax({
 
                url: pyroutes.url('repo_refs_data', {'repo_name': '${c.org_repo.repo_name}'}),
 
                data: {},
 
                dataType: 'json',
 
                type: 'GET',
 
                success: function(data) {
 
                  cache[key] = data;
 
                  query.callback({results: data.results});
 
                  query.callback(data);
 
                }
 
              })
 
          }
 
        },
 
    });
 
    $("#compare_other").select2({
 
        placeholder: "${'%s@%s' % (c.other_repo.repo_name, c.other_ref)}",
 
        dropdownAutoWidth: true,
 
        formatSelection: function(obj){
 
            return '{0}@{1}'.format("${c.other_repo.repo_name}", obj.text)
 
        },
 
        query: function(query){
 
          var key = 'cache2';
 
          var cached = cache[key] ;
 
          if(cached) {
 
            var data = {results: []};
 
            //filter results
 
            $.each(cached.results, function(){
 
                var section = this.text;
 
                var children = [];
 
                $.each(this.children, function(){
 
                    if(query.term.length == 0 || this.text.toUpperCase().indexOf(query.term.toUpperCase()) >= 0 ){
 
                        children.push({'id': this.id, 'text': this.text})
 
                    }
 
                })
 
                data.results.push({'text': section, 'children': children})
 
            });
 
            //push the typed in changeset
 
            data.results.push({'text':_TM['specify changeset'],
 
            data.results.push({'text':_TM['Specify changeset'],
 
                               'children': [{'id': query.term, 'text': query.term, 'type': 'rev'}]})
 
            query.callback(data);
 
          }else{
 
              $.ajax({
 
                url: pyroutes.url('repo_refs_data', {'repo_name': '${c.other_repo.repo_name}'}),
 
                data: {},
 
                dataType: 'json',
 
                type: 'GET',
 
                success: function(data) {
 
                  cache[key] = data;
 
                  query.callback({results: data.results});
 
                }
 
              })
 
          }
 
        },
 
    });
 

	
 
    $('#compare_revs').on('click', function(e){
 
        var org = $('#compare_org').select2('data');
 
        var other = $('#compare_other').select2('data');
 

	
 
        var compare_url = "${h.url('compare_url',repo_name=c.repo_name,org_ref_type='__other_ref_type__',org_ref='__org__',other_ref_type='__org_ref_type__',other_ref='__other__', other_repo=c.other_repo.repo_name)}";
 
        var u = compare_url.replace('__other_ref_type__',org.type)
 
                           .replace('__org__',org.text)
 
                           .replace('__org_ref_type__',other.type)
 
                           .replace('__other__',other.text);
 
        window.location=u;
 
    })
 
   });
 
    </script>
 
</%def>
kallithea/templates/pullrequests/pullrequest.html
Show inline comments
 
@@ -34,97 +34,97 @@ ${self.repo_context_bar('showpullrequest
 
                    ${h.text('pullrequest_title', class_="large")}
 
                </div>
 
             </div>
 

	
 
            <div class="field">
 
                <div class="label label-textarea">
 
                    <label for="pullrequest_desc">${_('Description')}:</label>
 
                </div>
 
                <div class="textarea text-area editor">
 
                    ${h.textarea('pullrequest_desc',size=30, style="height:100px")}
 
                    <span class="help-block">${_('Write a short description on this pull request')}</span>
 
                </div>
 
            </div>
 

	
 
            <div class="field">
 
                <div class="label label-textarea">
 
                    <label for="pullrequest_desc">${_('Changeset flow')}:</label>
 
                </div>
 
                <div class="input">
 
                    ##ORG
 
                    <div>
 
                        <div>
 
                            <div style="padding:5px 3px 3px 3px;">
 
                            <b>${_('Origin repository')}:</b> ${c.db_repo.description}
 
                            </div>
 
                            <span style="font-size: 20px">
 
                            ${h.select('org_repo','',c.org_repos,class_='refs')}:${h.select('org_ref',c.default_org_ref,c.org_refs,class_='refs')}
 
                            </span>
 
                        </div>
 
                    </div>
 

	
 
                    ##OTHER, most Probably the PARENT OF THIS FORK
 
                    <div style="border-top: 1px solid #EEE; margin: 5px 0px 0px 0px">
 
                        <div>
 
                            ## filled with JS
 
                            <div id="other_repo_desc" style="padding:5px 3px 3px 3px;">
 
                            </div>
 
                            <span style="font-size: 20px">
 
                            ${h.select('other_repo',c.default_other_repo,c.other_repos,class_='refs')}:${c.default_other_repo_info['revs']}
 
                            </span>
 
                        </div>
 
                    </div>
 
                    <div style="clear:both"></div>
 
                </div>
 
            </div>
 

	
 
            <div class="field">
 
                <div class="buttons">
 
                    ${h.submit('save',_('Send Pull Request'),class_="btn")}
 
                    ${h.submit('save',_('Create Pull Request'),class_="btn")}
 
                    ${h.reset('reset',_('Reset'),class_="btn")}
 
               </div>
 
            </div>
 

	
 
        </div>
 

	
 
        ## Reviewers
 
        <div style="float:left; border-left:1px dashed #eee">
 
            <div class="pr-details-title">${_('Pull request reviewers')}</div>
 
            <div id="reviewers" style="padding:0px 0px 0px 15px">
 
              ## members goes here !
 
              <div>
 
                <ul id="review_members" class="group_members">
 
                %for member in [c.default_other_repo_info['user']]:
 
                  <li id="reviewer_${member['user_id']}">
 
                    <div class="reviewers_member">
 
                      <div class="gravatar"><img alt="gravatar" src="${member['gravatar_link']}"/> </div>
 
                      <div style="float:left">${member['firstname']} ${member['lastname']} (${_('owner')})</div>
 
                      <input type="hidden" value="${member['user_id']}" name="review_members" />
 
                      <span class="action_button" style="padding: 3px" onclick="removeReviewMember(${member['user_id']})">
 
                          <i class="icon-remove-sign"  style="color: #FF4444;"></i>
 
                      </span>
 
                    </div>
 
                  </li>
 
                %endfor
 
                </ul>
 
              </div>
 

	
 
              <div class='ac'>
 
                <div class="reviewer_ac">
 
                   ${h.text('user', class_='yui-ac-input')}
 
                   <span class="help-block">${_('Add reviewer to this pull request.')}</span>
 
                   <div id="reviewers_container"></div>
 
                </div>
 
              </div>
 
            </div>
 
        </div>
 

	
 
        <div style="clear:both;padding: 0 0 30px 0;"></div>
 

	
 
        <h4>${_('Changesets')}</h4>
 
        <div style="float:left;padding:0px 30px 30px 30px">
 
           ## overview pulled by ajax
 
           <div style="float:left" id="pull_request_overview"></div>
 
           <div style="float:left;clear:both;padding:10px 10px 10px 0px;display:none">
 
                <a id="pull_request_overview_url" href="#">${_('Detailed compare view')}</a>
 
           </div>
 
        </div>
setup.py
Show inline comments
 
#!/usr/bin/env python2
 
# -*- coding: utf-8 -*-
 
import os
 
import sys
 
import platform
 

	
 
if sys.version_info < (2, 5):
 
    raise Exception('Kallithea requires python 2.5 or later')
 

	
 

	
 
here = os.path.abspath(os.path.dirname(__file__))
 

	
 

	
 
def _get_meta_var(name, data, callback_handler=None):
 
    import re
 
    matches = re.compile(r'(?:%s)\s*=\s*(.*)' % name).search(data)
 
    if matches:
 
        if not callable(callback_handler):
 
            callback_handler = lambda v: v
 

	
 
        return callback_handler(eval(matches.groups()[0]))
 

	
 
_meta = open(os.path.join(here, 'kallithea', '__init__.py'), 'rb')
 
_metadata = _meta.read()
 
_meta.close()
 

	
 
callback = lambda V: ('.'.join(map(str, V[:3])) + '.'.join(V[3:]))
 
__version__ = _get_meta_var('VERSION', _metadata, callback)
 
__license__ = _get_meta_var('__license__', _metadata)
 
__author__ = _get_meta_var('__author__', _metadata)
 
__url__ = _get_meta_var('__url__', _metadata)
 
# defines current platform
 
__platform__ = platform.system()
 

	
 
is_windows = __platform__ in ['Windows']
 

	
 
requirements = [
 
    "waitress==0.8.8",
 
    "webob==1.0.8",
 
    "webtest==1.4.3",
 
    "Pylons==1.0.0",
 
    "Beaker==1.6.4",
 
    "WebHelpers==1.3",
 
    "formencode==1.2.4",
 
    "SQLAlchemy==0.7.10",
 
    "Mako==0.9.0",
 
    "pygments>=1.5",
 
    "whoosh>=2.4.0,<2.5",
 
    "celery>=2.2.5,<2.3",
0 comments (0 inline, 0 general)