diff --git a/rhodecode/__init__.py b/rhodecode/__init__.py --- a/rhodecode/__init__.py +++ b/rhodecode/__init__.py @@ -48,7 +48,7 @@ PYRAMID_SETTINGS = {} EXTENSIONS = {} __version__ = ('.'.join((str(each) for each in VERSION[:3]))) -__dbversion__ = 106 # defines current db version for migrations +__dbversion__ = 107 # defines current db version for migrations __platform__ = platform.system() __license__ = 'AGPLv3, and Commercial License' __author__ = 'RhodeCode GmbH' diff --git a/rhodecode/api/views/pull_request_api.py b/rhodecode/api/views/pull_request_api.py --- a/rhodecode/api/views/pull_request_api.py +++ b/rhodecode/api/views/pull_request_api.py @@ -686,28 +686,9 @@ def create_pull_request( full_source_ref = resolve_ref_or_error(source_ref, source_db_repo) full_target_ref = resolve_ref_or_error(target_ref, target_db_repo) - source_scm = source_db_repo.scm_instance() - target_scm = target_db_repo.scm_instance() - source_commit = get_commit_or_error(full_source_ref, source_db_repo) target_commit = get_commit_or_error(full_target_ref, target_db_repo) - ancestor = source_scm.get_common_ancestor( - source_commit.raw_id, target_commit.raw_id, target_scm) - if not ancestor: - raise JSONRPCError('no common ancestor found') - - # recalculate target ref based on ancestor - target_ref_type, target_ref_name, __ = full_target_ref.split(':') - full_target_ref = ':'.join((target_ref_type, target_ref_name, ancestor)) - - commit_ranges = target_scm.compare( - target_commit.raw_id, source_commit.raw_id, source_scm, - merge=True, pre_load=[]) - - if not commit_ranges: - raise JSONRPCError('no commits found') - reviewer_objects = Optional.extract(reviewers) or [] # serialize and validate passed in given reviewers @@ -727,16 +708,16 @@ def create_pull_request( PullRequestModel().get_reviewer_functions() # recalculate reviewers logic, to make sure we can validate this - reviewer_rules = get_default_reviewers_data( + default_reviewers_data = get_default_reviewers_data( owner, source_db_repo, source_commit, target_db_repo, target_commit) # now MERGE our given with the calculated - reviewer_objects = reviewer_rules['reviewers'] + reviewer_objects + reviewer_objects = default_reviewers_data['reviewers'] + reviewer_objects try: reviewers = validate_default_reviewers( - reviewer_objects, reviewer_rules) + reviewer_objects, default_reviewers_data) except ValueError as e: raise JSONRPCError('Reviewers Validation: {}'.format(e)) @@ -748,6 +729,24 @@ def create_pull_request( source_ref=title_source_ref, target=target_repo ) + + diff_info = default_reviewers_data['diff_info'] + common_ancestor_id = diff_info['ancestor'] + commits = diff_info['commits'] + + if not common_ancestor_id: + raise JSONRPCError('no common ancestor found') + + if not commits: + raise JSONRPCError('no commits found') + + # NOTE(marcink): reversed is consistent with how we open it in the WEB interface + revisions = [commit.raw_id for commit in reversed(commits)] + + # recalculate target ref based on ancestor + target_ref_type, target_ref_name, __ = full_target_ref.split(':') + full_target_ref = ':'.join((target_ref_type, target_ref_name, common_ancestor_id)) + # fetch renderer, if set fallback to plain in case of PR rc_config = SettingsModel().get_all_settings() default_system_renderer = rc_config.get('rhodecode_markup_renderer', 'plain') @@ -760,12 +759,13 @@ def create_pull_request( source_ref=full_source_ref, target_repo=target_repo, target_ref=full_target_ref, - revisions=[commit.raw_id for commit in reversed(commit_ranges)], + common_ancestor_id=common_ancestor_id, + revisions=revisions, reviewers=reviewers, title=title, description=description, description_renderer=description_renderer, - reviewer_data=reviewer_rules, + reviewer_data=default_reviewers_data, auth_user=apiuser ) diff --git a/rhodecode/apps/repository/tests/test_repo_compare.py b/rhodecode/apps/repository/tests/test_repo_compare.py --- a/rhodecode/apps/repository/tests/test_repo_compare.py +++ b/rhodecode/apps/repository/tests/test_repo_compare.py @@ -484,7 +484,7 @@ class TestCompareView(object): # outgoing commits between those commits compare_page = ComparePage(response) - compare_page.contains_commits(commits=[commit1], ancestors=[commit0]) + compare_page.contains_commits(commits=[commit1]) def test_errors_when_comparing_unknown_source_repo(self, backend): repo = backend.repo @@ -641,6 +641,7 @@ class ComparePage(AssertResponse): self.contains_one_link( 'r%s:%s' % (commit.idx, commit.short_id), self._commit_url(commit)) + if ancestors: response.mustcontain('Ancestor') for ancestor in ancestors: diff --git a/rhodecode/apps/repository/utils.py b/rhodecode/apps/repository/utils.py --- a/rhodecode/apps/repository/utils.py +++ b/rhodecode/apps/repository/utils.py @@ -20,6 +20,9 @@ from rhodecode.lib import helpers as h from rhodecode.lib.utils2 import safe_int +from rhodecode.model.pull_request import get_diff_info + +REVIEWER_API_VERSION = 'V3' def reviewer_as_json(user, reasons=None, mandatory=False, rules=None, user_group=None): @@ -47,15 +50,20 @@ def reviewer_as_json(user, reasons=None, def get_default_reviewers_data( current_user, source_repo, source_commit, target_repo, target_commit): + """ + Return json for default reviewers of a repository + """ - """ Return json for default reviewers of a repository """ + diff_info = get_diff_info( + source_repo, source_commit.raw_id, target_repo, target_commit.raw_id) reasons = ['Default reviewer', 'Repository owner'] json_reviewers = [reviewer_as_json( user=target_repo.user, reasons=reasons, mandatory=False, rules=None)] return { - 'api_ver': 'v1', # define version for later possible schema upgrade + 'api_ver': REVIEWER_API_VERSION, # define version for later possible schema upgrade + 'diff_info': diff_info, 'reviewers': json_reviewers, 'rules': {}, 'rules_data': {}, diff --git a/rhodecode/apps/repository/views/repo_pull_requests.py b/rhodecode/apps/repository/views/repo_pull_requests.py --- a/rhodecode/apps/repository/views/repo_pull_requests.py +++ b/rhodecode/apps/repository/views/repo_pull_requests.py @@ -40,12 +40,12 @@ from rhodecode.lib.auth import ( NotAnonymous, CSRFRequired) from rhodecode.lib.utils2 import str2bool, safe_str, safe_unicode from rhodecode.lib.vcs.backends.base import EmptyCommit, UpdateFailureReason -from rhodecode.lib.vcs.exceptions import (CommitDoesNotExistError, - RepositoryRequirementError, EmptyRepositoryError) +from rhodecode.lib.vcs.exceptions import ( + CommitDoesNotExistError, RepositoryRequirementError, EmptyRepositoryError) from rhodecode.model.changeset_status import ChangesetStatusModel from rhodecode.model.comment import CommentsModel -from rhodecode.model.db import (func, or_, PullRequest, PullRequestVersion, - ChangesetComment, ChangesetStatus, Repository) +from rhodecode.model.db import ( + func, or_, PullRequest, ChangesetComment, ChangesetStatus, Repository) from rhodecode.model.forms import PullRequestForm from rhodecode.model.meta import Session from rhodecode.model.pull_request import PullRequestModel, MergeCheck @@ -210,10 +210,12 @@ class RepoPullRequestsView(RepoAppView, return caching_enabled def _get_diffset(self, source_repo_name, source_repo, + ancestor_commit, source_ref_id, target_ref_id, target_commit, source_commit, diff_limit, file_limit, fulldiff, hide_whitespace_changes, diff_context): + target_ref_id = ancestor_commit.raw_id vcs_diff = PullRequestModel().get_diff( source_repo, source_ref_id, target_ref_id, hide_whitespace_changes, diff_context) @@ -278,6 +280,7 @@ class RepoPullRequestsView(RepoAppView, _new_state = { 'created': PullRequest.STATE_CREATED, }.get(self.request.GET.get('force_state')) + if c.is_super_admin and _new_state: with pull_request.set_state(PullRequest.STATE_UPDATING, final_state=_new_state): h.flash( @@ -557,7 +560,8 @@ class RepoPullRequestsView(RepoAppView, source_scm, target_commit, target_ref_id, - target_scm, maybe_unreachable=maybe_unreachable) + target_scm, + maybe_unreachable=maybe_unreachable) # register our commit range for comm in commit_cache.values(): @@ -591,11 +595,10 @@ class RepoPullRequestsView(RepoAppView, has_proper_diff_cache = cached_diff and cached_diff.get('commits') if not force_recache and has_proper_diff_cache: c.diffset = cached_diff['diff'] - (ancestor_commit, commit_cache, missing_requirements, - source_commit, target_commit) = cached_diff['commits'] else: c.diffset = self._get_diffset( c.source_repo.repo_name, commits_source_repo, + c.ancestor_commit, source_ref_id, target_ref_id, target_commit, source_commit, diff_limit, file_limit, c.fulldiff, @@ -675,8 +678,10 @@ class RepoPullRequestsView(RepoAppView, # calculate the diff for commits between versions c.commit_changes = [] - mark = lambda cs, fw: list( - h.itertools.izip_longest([], cs, fillvalue=fw)) + + def mark(cs, fw): + return list(h.itertools.izip_longest([], cs, fillvalue=fw)) + for c_type, raw_id in mark(commit_changes.added, 'a') \ + mark(commit_changes.removed, 'r') \ + mark(commit_changes.common, 'c'): @@ -739,13 +744,14 @@ class RepoPullRequestsView(RepoAppView, except RepositoryRequirementError: log.warning('Failed to get all required data from repo', exc_info=True) missing_requirements = True - ancestor_commit = None + + pr_ancestor_id = pull_request_at_ver.common_ancestor_id + try: - ancestor_id = source_scm.get_common_ancestor( - source_commit.raw_id, target_commit.raw_id, target_scm) - ancestor_commit = source_scm.get_commit(ancestor_id) + ancestor_commit = source_scm.get_commit(pr_ancestor_id) except Exception: ancestor_commit = None + return ancestor_commit, commit_cache, missing_requirements, source_commit, target_commit def assure_not_empty_repo(self): @@ -949,6 +955,7 @@ class RepoPullRequestsView(RepoAppView, target_repo = _form['target_repo'] target_ref = _form['target_ref'] commit_ids = _form['revisions'][::-1] + common_ancestor_id = _form['common_ancestor'] # find the ancestor for this pr source_db_repo = Repository.get_by_repo_name(_form['source_repo']) @@ -1035,6 +1042,7 @@ class RepoPullRequestsView(RepoAppView, target_repo=target_repo, target_ref=target_ref, revisions=commit_ids, + common_ancestor_id=common_ancestor_id, reviewers=reviewers, title=pullrequest_title, description=description, diff --git a/rhodecode/apps/repository/views/repo_review_rules.py b/rhodecode/apps/repository/views/repo_review_rules.py --- a/rhodecode/apps/repository/views/repo_review_rules.py +++ b/rhodecode/apps/repository/views/repo_review_rules.py @@ -54,8 +54,20 @@ class RepoReviewRulesView(RepoAppView): renderer='json_ext') def repo_default_reviewers_data(self): self.load_default_context() - target_repo_name = self.request.GET.get('target_repo', self.db_repo.repo_name) + + request = self.request + source_repo = self.db_repo + source_repo_name = source_repo.repo_name + target_repo_name = request.GET.get('target_repo', source_repo_name) target_repo = Repository.get_by_repo_name(target_repo_name) + + source_ref = request.GET['source_ref'] + target_ref = request.GET['target_ref'] + source_commit = source_repo.get_commit(source_ref) + target_commit = target_repo.get_commit(target_ref) + + current_user = request.user.get_instance() review_data = get_default_reviewers_data( - self.db_repo.user, None, None, target_repo, None) + current_user, source_repo, source_commit, target_repo, target_commit) + return review_data diff --git a/rhodecode/lib/dbmigrate/versions/107_version_4_19_0.py b/rhodecode/lib/dbmigrate/versions/107_version_4_19_0.py new file mode 100644 --- /dev/null +++ b/rhodecode/lib/dbmigrate/versions/107_version_4_19_0.py @@ -0,0 +1,47 @@ +# -*- coding: utf-8 -*- + +import logging +from sqlalchemy import * + +from alembic.migration import MigrationContext +from alembic.operations import Operations +from sqlalchemy import BigInteger + +from rhodecode.lib.dbmigrate.versions import _reset_base +from rhodecode.model import init_model_encryption + + +log = logging.getLogger(__name__) + + +def upgrade(migrate_engine): + """ + Upgrade operations go here. + Don't create your own engine; bind migrate_engine to your metadata + """ + _reset_base(migrate_engine) + from rhodecode.lib.dbmigrate.schema import db_4_19_0_0 as db + + init_model_encryption(db) + + context = MigrationContext.configure(migrate_engine.connect()) + op = Operations(context) + + pull_requests = db.PullRequest.__table__ + with op.batch_alter_table(pull_requests.name) as batch_op: + new_column = Column('common_ancestor_id', Unicode(255), nullable=True) + batch_op.add_column(new_column) + + pull_request_version = db.PullRequestVersion.__table__ + with op.batch_alter_table(pull_request_version.name) as batch_op: + new_column = Column('common_ancestor_id', Unicode(255), nullable=True) + batch_op.add_column(new_column) + + +def downgrade(migrate_engine): + meta = MetaData() + meta.bind = migrate_engine + + +def fixups(models, _SESSION): + pass diff --git a/rhodecode/lib/vcs/backends/git/repository.py b/rhodecode/lib/vcs/backends/git/repository.py --- a/rhodecode/lib/vcs/backends/git/repository.py +++ b/rhodecode/lib/vcs/backends/git/repository.py @@ -580,6 +580,9 @@ class GitRepository(BaseRepository): return len(self.commit_ids) def get_common_ancestor(self, commit_id1, commit_id2, repo2): + log.debug('Calculating common ancestor between %sc1:%s and %sc2:%s', + self, commit_id1, repo2, commit_id2) + if commit_id1 == commit_id2: return commit_id1 @@ -600,6 +603,8 @@ class GitRepository(BaseRepository): ['merge-base', commit_id1, commit_id2]) ancestor_id = re.findall(r'[0-9a-fA-F]{40}', output)[0] + log.debug('Found common ancestor with sha: %s', ancestor_id) + return ancestor_id def compare(self, commit_id1, commit_id2, repo2, merge, pre_load=None): diff --git a/rhodecode/lib/vcs/backends/hg/repository.py b/rhodecode/lib/vcs/backends/hg/repository.py --- a/rhodecode/lib/vcs/backends/hg/repository.py +++ b/rhodecode/lib/vcs/backends/hg/repository.py @@ -297,13 +297,20 @@ class MercurialRepository(BaseRepository return update_cache def get_common_ancestor(self, commit_id1, commit_id2, repo2): + log.debug('Calculating common ancestor between %sc1:%s and %sc2:%s', + self, commit_id1, repo2, commit_id2) + if commit_id1 == commit_id2: return commit_id1 ancestors = self._remote.revs_from_revspec( "ancestor(id(%s), id(%s))", commit_id1, commit_id2, other_path=repo2.path) - return repo2[ancestors[0]].raw_id if ancestors else None + + ancestor_id = repo2[ancestors[0]].raw_id if ancestors else None + + log.debug('Found common ancestor with sha: %s', ancestor_id) + return ancestor_id def compare(self, commit_id1, commit_id2, repo2, merge, pre_load=None): if commit_id1 == commit_id2: diff --git a/rhodecode/model/db.py b/rhodecode/model/db.py --- a/rhodecode/model/db.py +++ b/rhodecode/model/db.py @@ -3989,6 +3989,8 @@ class _PullRequestBase(BaseModel): _revisions = Column( 'revisions', UnicodeText().with_variant(UnicodeText(20500), 'mysql')) + common_ancestor_id = Column('common_ancestor_id', Unicode(255), nullable=True) + @declared_attr def source_repo_id(cls): # TODO: dan: rename column to source_repo_id @@ -4302,7 +4304,7 @@ class PullRequest(Base, _PullRequestBase attrs.source_ref_parts = pull_request_obj.source_ref_parts attrs.target_ref_parts = pull_request_obj.target_ref_parts attrs.revisions = pull_request_obj.revisions - + attrs.common_ancestor_id = pull_request_obj.common_ancestor_id attrs.shadow_merge_ref = org_pull_request_obj.shadow_merge_ref attrs.reviewer_data = org_pull_request_obj.reviewer_data attrs.reviewer_data_json = org_pull_request_obj.reviewer_data_json diff --git a/rhodecode/model/pull_request.py b/rhodecode/model/pull_request.py --- a/rhodecode/model/pull_request.py +++ b/rhodecode/model/pull_request.py @@ -35,6 +35,7 @@ import collections from pyramid import compat from pyramid.threadlocal import get_current_request +from rhodecode.lib.vcs.nodes import FileNode from rhodecode.translation import lazy_ugettext from rhodecode.lib import helpers as h, hooks_utils, diffs from rhodecode.lib import audit_logger @@ -82,6 +83,126 @@ class UpdateResponse(object): self.target_changed = target_changed +def get_diff_info( + source_repo, source_ref, target_repo, target_ref, get_authors=False, + get_commit_authors=True): + """ + Calculates detailed diff information for usage in preview of creation of a pull-request. + This is also used for default reviewers logic + """ + + source_scm = source_repo.scm_instance() + target_scm = target_repo.scm_instance() + + ancestor_id = target_scm.get_common_ancestor(target_ref, source_ref, source_scm) + if not ancestor_id: + raise ValueError( + 'cannot calculate diff info without a common ancestor. ' + 'Make sure both repositories are related, and have a common forking commit.') + + # case here is that want a simple diff without incoming commits, + # previewing what will be merged based only on commits in the source. + log.debug('Using ancestor %s as source_ref instead of %s', + ancestor_id, source_ref) + + # source of changes now is the common ancestor + source_commit = source_scm.get_commit(commit_id=ancestor_id) + # target commit becomes the source ref as it is the last commit + # for diff generation this logic gives proper diff + target_commit = source_scm.get_commit(commit_id=source_ref) + + vcs_diff = \ + source_scm.get_diff(commit1=source_commit, commit2=target_commit, + ignore_whitespace=False, context=3) + + diff_processor = diffs.DiffProcessor( + vcs_diff, format='newdiff', diff_limit=None, + file_limit=None, show_full_diff=True) + + _parsed = diff_processor.prepare() + + all_files = [] + all_files_changes = [] + changed_lines = {} + stats = [0, 0] + for f in _parsed: + all_files.append(f['filename']) + all_files_changes.append({ + 'filename': f['filename'], + 'stats': f['stats'] + }) + stats[0] += f['stats']['added'] + stats[1] += f['stats']['deleted'] + + changed_lines[f['filename']] = [] + if len(f['chunks']) < 2: + continue + # first line is "context" information + for chunks in f['chunks'][1:]: + for chunk in chunks['lines']: + if chunk['action'] not in ('del', 'mod'): + continue + changed_lines[f['filename']].append(chunk['old_lineno']) + + commit_authors = [] + user_counts = {} + email_counts = {} + author_counts = {} + _commit_cache = {} + + commits = [] + if get_commit_authors: + commits = target_scm.compare( + target_ref, source_ref, source_scm, merge=True, + pre_load=["author"]) + + for commit in commits: + user = User.get_from_cs_author(commit.author) + if user and user not in commit_authors: + commit_authors.append(user) + + # lines + if get_authors: + target_commit = source_repo.get_commit(ancestor_id) + + for fname, lines in changed_lines.items(): + try: + node = target_commit.get_node(fname) + except Exception: + continue + + if not isinstance(node, FileNode): + continue + + for annotation in node.annotate: + line_no, commit_id, get_commit_func, line_text = annotation + if line_no in lines: + if commit_id not in _commit_cache: + _commit_cache[commit_id] = get_commit_func() + commit = _commit_cache[commit_id] + author = commit.author + email = commit.author_email + user = User.get_from_cs_author(author) + if user: + user_counts[user] = user_counts.get(user, 0) + 1 + author_counts[author] = author_counts.get(author, 0) + 1 + email_counts[email] = email_counts.get(email, 0) + 1 + + return { + 'commits': commits, + 'files': all_files_changes, + 'stats': stats, + 'ancestor': ancestor_id, + # original authors of modified files + 'original_authors': { + 'users': user_counts, + 'authors': author_counts, + 'emails': email_counts, + }, + 'commit_authors': commit_authors + } + + class PullRequestModel(BaseModel): cls = PullRequest @@ -453,6 +574,7 @@ class PullRequestModel(BaseModel): def create(self, created_by, source_repo, source_ref, target_repo, target_ref, revisions, reviewers, title, description=None, + common_ancestor_id=None, description_renderer=None, reviewer_data=None, translator=None, auth_user=None): translator = translator or get_current_request().translate @@ -474,6 +596,8 @@ class PullRequestModel(BaseModel): pull_request.author = created_by_user pull_request.reviewer_data = reviewer_data pull_request.pull_request_state = pull_request.STATE_CREATING + pull_request.common_ancestor_id = common_ancestor_id + Session().add(pull_request) Session().flush() @@ -805,8 +929,17 @@ class PullRequestModel(BaseModel): target_commit.raw_id, source_commit.raw_id, source_repo, merge=True, pre_load=pre_load) - ancestor_commit_id = source_repo.get_common_ancestor( - source_commit.raw_id, target_commit.raw_id, target_repo) + target_ref = target_commit.raw_id + source_ref = source_commit.raw_id + ancestor_commit_id = target_repo.get_common_ancestor( + target_ref, source_ref, source_repo) + + if not ancestor_commit_id: + raise ValueError( + 'cannot calculate diff info without a common ancestor. ' + 'Make sure both repositories are related, and have a common forking commit.') + + pull_request.common_ancestor_id = ancestor_commit_id pull_request.source_ref = '%s:%s:%s' % ( source_ref_type, source_ref_name, source_commit.raw_id) @@ -913,6 +1046,7 @@ class PullRequestModel(BaseModel): version.reviewer_data = pull_request.reviewer_data version.revisions = pull_request.revisions + version.common_ancestor_id = pull_request.common_ancestor_id version.pull_request = pull_request Session().add(version) Session().flush() diff --git a/rhodecode/public/css/main.less b/rhodecode/public/css/main.less --- a/rhodecode/public/css/main.less +++ b/rhodecode/public/css/main.less @@ -467,9 +467,9 @@ ul.auth_plugins { #pr_open_message { border: @border-thickness solid #fff; border-radius: @border-radius; - padding: @padding-large-vertical @padding-large-vertical @padding-large-vertical 0; text-align: left; overflow: hidden; + white-space: pre-line; } .pr-details-title { @@ -1796,7 +1796,7 @@ table.integrations { } div.ancestor { - line-height: 33px; + } .cs_icon_td input[type="checkbox"] { diff --git a/rhodecode/public/css/select2.less b/rhodecode/public/css/select2.less --- a/rhodecode/public/css/select2.less +++ b/rhodecode/public/css/select2.less @@ -205,7 +205,9 @@ select.select2{height:28px;visibility:hi font-family: @text-regular; color: @grey2; cursor: pointer; + white-space: nowrap; } + &.select2-result-with-children { .select2-result-label { @@ -220,6 +222,7 @@ select.select2{height:28px;visibility:hi font-family: @text-regular; color: @grey2; cursor: pointer; + white-space: nowrap; } } } diff --git a/rhodecode/public/js/src/i18n_utils.js b/rhodecode/public/js/src/i18n_utils.js --- a/rhodecode/public/js/src/i18n_utils.js +++ b/rhodecode/public/js/src/i18n_utils.js @@ -22,7 +22,7 @@ var _gettext = function (s) { if (_TM.hasOwnProperty(s)) { return _TM[s]; } - i18nLog.error( + i18nLog.warning( 'String `' + s + '` was requested but cannot be ' + 'found in translation table'); return s @@ -34,3 +34,5 @@ var _ngettext = function (singular, plur } return _gettext(plural) }; + + diff --git a/rhodecode/public/js/src/rhodecode/pullrequests.js b/rhodecode/public/js/src/rhodecode/pullrequests.js --- a/rhodecode/public/js/src/rhodecode/pullrequests.js +++ b/rhodecode/public/js/src/rhodecode/pullrequests.js @@ -75,12 +75,12 @@ var getTitleAndDescription = function(so var desc = ''; $.each($(elements).get().reverse().slice(0, limit), function(idx, value) { - var rawMessage = $(value).find('td.td-description .message').data('messageRaw').toString(); + var rawMessage = value['message']; desc += '- ' + rawMessage.split('\n')[0].replace(/\n+$/, "") + '\n'; }); // only 1 commit, use commit message as title if (elements.length === 1) { - var rawMessage = $(elements[0]).find('td.td-description .message').data('messageRaw').toString(); + var rawMessage = elements[0]['message']; title = rawMessage.split('\n')[0]; } else { @@ -92,7 +92,6 @@ var getTitleAndDescription = function(so }; - ReviewersController = function () { var self = this; this.$reviewRulesContainer = $('#review_rules'); @@ -100,28 +99,35 @@ ReviewersController = function () { this.forbidReviewUsers = undefined; this.$reviewMembers = $('#review_members'); this.currentRequest = null; + this.diffData = null; + //dummy handler, we might register our own later + this.diffDataHandler = function(data){}; - this.defaultForbidReviewUsers = function() { + this.defaultForbidReviewUsers = function () { return [ - {'username': 'default', - 'user_id': templateContext.default_user.user_id} + { + 'username': 'default', + 'user_id': templateContext.default_user.user_id + } ]; }; - this.hideReviewRules = function() { + this.hideReviewRules = function () { self.$reviewRulesContainer.hide(); }; - this.showReviewRules = function() { + this.showReviewRules = function () { self.$reviewRulesContainer.show(); }; - this.addRule = function(ruleText) { + this.addRule = function (ruleText) { self.showReviewRules(); return '