Show More
@@ -32,6 +32,11 b' def includeme(config):' | |||||
32 | name='repo_summary_commits', |
|
32 | name='repo_summary_commits', | |
33 | pattern='/{repo_name:.*?[^/]}/summary-commits', repo_route=True) |
|
33 | pattern='/{repo_name:.*?[^/]}/summary-commits', repo_route=True) | |
34 |
|
34 | |||
|
35 | # repo commits | |||
|
36 | config.add_route( | |||
|
37 | name='repo_commit', | |||
|
38 | pattern='/{repo_name:.*?[^/]}/changeset/{commit_id}', repo_route=True) | |||
|
39 | ||||
35 | # refs data |
|
40 | # refs data | |
36 | config.add_route( |
|
41 | config.add_route( | |
37 | name='repo_refs_data', |
|
42 | name='repo_refs_data', |
@@ -52,6 +52,8 b' class PullRequestEvent(RepoEvent):' | |||||
52 | 'issues': issues, |
|
52 | 'issues': issues, | |
53 | 'pull_request_id': self.pullrequest.pull_request_id, |
|
53 | 'pull_request_id': self.pullrequest.pull_request_id, | |
54 | 'url': PullRequestModel().get_url(self.pullrequest), |
|
54 | 'url': PullRequestModel().get_url(self.pullrequest), | |
|
55 | 'permalink_url': PullRequestModel().get_url( | |||
|
56 | self.pullrequest, permalink=True), | |||
55 | 'status': self.pullrequest.calculated_review_status(), |
|
57 | 'status': self.pullrequest.calculated_review_status(), | |
56 | 'commits': commits, |
|
58 | 'commits': commits, | |
57 | } |
|
59 | } | |
@@ -131,7 +133,9 b' class PullRequestCommentEvent(PullReques' | |||||
131 | 'type': self.comment.comment_type, |
|
133 | 'type': self.comment.comment_type, | |
132 | 'file': self.comment.f_path, |
|
134 | 'file': self.comment.f_path, | |
133 | 'line': self.comment.line_no, |
|
135 | 'line': self.comment.line_no, | |
134 | 'url': CommentsModel().get_url(self.comment) |
|
136 | 'url': CommentsModel().get_url(self.comment), | |
|
137 | 'permalink_url': CommentsModel().get_url( | |||
|
138 | self.comment, permalink=True), | |||
135 | } |
|
139 | } | |
136 | }) |
|
140 | }) | |
137 | return data |
|
141 | return data |
@@ -35,9 +35,9 b' def _commits_as_dict(commit_ids, repos):' | |||||
35 | :param repos: list of repos to check |
|
35 | :param repos: list of repos to check | |
36 | """ |
|
36 | """ | |
37 | from rhodecode.lib.utils2 import extract_mentioned_users |
|
37 | from rhodecode.lib.utils2 import extract_mentioned_users | |
38 | from rhodecode.lib import helpers as h |
|
|||
39 | from rhodecode.lib.helpers import ( |
|
38 | from rhodecode.lib.helpers import ( | |
40 | urlify_commit_message, process_patterns, chop_at_smart) |
|
39 | urlify_commit_message, process_patterns, chop_at_smart) | |
|
40 | from rhodecode.model.repo import RepoModel | |||
41 |
|
41 | |||
42 | if not repos: |
|
42 | if not repos: | |
43 | raise Exception('no repo defined') |
|
43 | raise Exception('no repo defined') | |
@@ -68,11 +68,10 b' def _commits_as_dict(commit_ids, repos):' | |||||
68 | cs_data = cs.__json__() |
|
68 | cs_data = cs.__json__() | |
69 | cs_data['mentions'] = extract_mentioned_users(cs_data['message']) |
|
69 | cs_data['mentions'] = extract_mentioned_users(cs_data['message']) | |
70 | cs_data['reviewers'] = reviewers |
|
70 | cs_data['reviewers'] = reviewers | |
71 |
cs_data['url'] = |
|
71 | cs_data['url'] = RepoModel().get_commit_url( | |
72 |
|
|
72 | repo, cs_data['raw_id']) | |
73 | revision=cs_data['raw_id'], |
|
73 | cs_data['permalink_url'] = RepoModel().get_commit_url( | |
74 | qualified=True |
|
74 | repo, cs_data['raw_id'], permalink=True) | |
75 | ) |
|
|||
76 | urlified_message, issues_data = process_patterns( |
|
75 | urlified_message, issues_data = process_patterns( | |
77 | cs_data['message'], repo.repo_name) |
|
76 | cs_data['message'], repo.repo_name) | |
78 | cs_data['issues'] = issues_data |
|
77 | cs_data['issues'] = issues_data | |
@@ -130,6 +129,7 b' class RepoEvent(RhodecodeEvent):' | |||||
130 | 'repo_name': self.repo.repo_name, |
|
129 | 'repo_name': self.repo.repo_name, | |
131 | 'repo_type': self.repo.repo_type, |
|
130 | 'repo_type': self.repo.repo_type, | |
132 | 'url': RepoModel().get_url(self.repo), |
|
131 | 'url': RepoModel().get_url(self.repo), | |
|
132 | 'permalink_url': RepoModel().get_url(self.repo, permalink=True), | |||
133 | 'extra_fields': extra_fields |
|
133 | 'extra_fields': extra_fields | |
134 | } |
|
134 | } | |
135 | }) |
|
135 | }) | |
@@ -242,7 +242,10 b' class RepoPushEvent(RepoVCSEvent):' | |||||
242 |
|
242 | |||
243 | def as_dict(self): |
|
243 | def as_dict(self): | |
244 | data = super(RepoPushEvent, self).as_dict() |
|
244 | data = super(RepoPushEvent, self).as_dict() | |
245 | branch_url = repo_url = data['repo']['url'] |
|
245 | ||
|
246 | def branch_url(branch_name): | |||
|
247 | return '{}/changelog?branch={}'.format( | |||
|
248 | data['repo']['url'], branch_name) | |||
246 |
|
249 | |||
247 | commits = _commits_as_dict( |
|
250 | commits = _commits_as_dict( | |
248 | commit_ids=self.pushed_commit_ids, repos=[self.repo]) |
|
251 | commit_ids=self.pushed_commit_ids, repos=[self.repo]) | |
@@ -258,8 +261,7 b' class RepoPushEvent(RepoVCSEvent):' | |||||
258 | branches = [ |
|
261 | branches = [ | |
259 | { |
|
262 | { | |
260 | 'name': branch, |
|
263 | 'name': branch, | |
261 |
'url': |
|
264 | 'url': branch_url(branch) | |
262 | data['repo']['url'], branch) |
|
|||
263 | } |
|
265 | } | |
264 | for branch in branches |
|
266 | for branch in branches | |
265 | ] |
|
267 | ] |
@@ -29,14 +29,14 b' import collections' | |||||
29 | from datetime import datetime |
|
29 | from datetime import datetime | |
30 |
|
30 | |||
31 | from pylons.i18n.translation import _ |
|
31 | from pylons.i18n.translation import _ | |
32 | from pyramid.threadlocal import get_current_registry |
|
32 | from pyramid.threadlocal import get_current_registry, get_current_request | |
33 | from sqlalchemy.sql.expression import null |
|
33 | from sqlalchemy.sql.expression import null | |
34 | from sqlalchemy.sql.functions import coalesce |
|
34 | from sqlalchemy.sql.functions import coalesce | |
35 |
|
35 | |||
36 | from rhodecode.lib import helpers as h, diffs |
|
36 | from rhodecode.lib import helpers as h, diffs | |
37 | from rhodecode.lib.channelstream import channelstream_request |
|
37 | from rhodecode.lib.channelstream import channelstream_request | |
38 | from rhodecode.lib.utils import action_logger |
|
38 | from rhodecode.lib.utils import action_logger | |
39 | from rhodecode.lib.utils2 import extract_mentioned_users |
|
39 | from rhodecode.lib.utils2 import extract_mentioned_users, safe_str | |
40 | from rhodecode.model import BaseModel |
|
40 | from rhodecode.model import BaseModel | |
41 | from rhodecode.model.db import ( |
|
41 | from rhodecode.model.db import ( | |
42 | ChangesetComment, User, Notification, PullRequest, AttributeDict) |
|
42 | ChangesetComment, User, Notification, PullRequest, AttributeDict) | |
@@ -409,22 +409,40 b' class CommentsModel(BaseModel):' | |||||
409 | q = q.order_by(ChangesetComment.created_on) |
|
409 | q = q.order_by(ChangesetComment.created_on) | |
410 | return q.all() |
|
410 | return q.all() | |
411 |
|
411 | |||
412 | def get_url(self, comment): |
|
412 | def get_url(self, comment, request=None, permalink=False): | |
|
413 | if not request: | |||
|
414 | request = get_current_request() | |||
|
415 | ||||
413 | comment = self.__get_commit_comment(comment) |
|
416 | comment = self.__get_commit_comment(comment) | |
414 | if comment.pull_request: |
|
417 | if comment.pull_request: | |
415 | return h.url( |
|
418 | pull_request = comment.pull_request | |
|
419 | if permalink: | |||
|
420 | return request.route_url( | |||
|
421 | 'pull_requests_global', | |||
|
422 | pull_request_id=pull_request.pull_request_id, | |||
|
423 | _anchor='comment-%s' % comment.comment_id) | |||
|
424 | else: | |||
|
425 | return request.route_url( | |||
416 | 'pullrequest_show', |
|
426 | 'pullrequest_show', | |
417 |
repo_name= |
|
427 | repo_name=safe_str(pull_request.target_repo.repo_name), | |
418 |
pull_request_id= |
|
428 | pull_request_id=pull_request.pull_request_id, | |
419 |
anchor='comment-%s' % comment.comment_id |
|
429 | _anchor='comment-%s' % comment.comment_id) | |
420 | qualified=True,) |
|
430 | ||
421 | else: |
|
431 | else: | |
422 | return h.url( |
|
432 | repo = comment.repo | |
423 | 'changeset_home', |
|
433 | commit_id = comment.revision | |
424 | repo_name=comment.repo.repo_name, |
|
434 | ||
425 | revision=comment.revision, |
|
435 | if permalink: | |
426 | anchor='comment-%s' % comment.comment_id, |
|
436 | return request.route_url( | |
427 | qualified=True,) |
|
437 | 'repo_commit', repo_name=safe_str(repo.repo_id), | |
|
438 | commit_id=commit_id, | |||
|
439 | _anchor='comment-%s' % comment.comment_id) | |||
|
440 | ||||
|
441 | else: | |||
|
442 | return request.route_url( | |||
|
443 | 'repo_commit', repo_name=safe_str(repo.repo_name), | |||
|
444 | commit_id=commit_id, | |||
|
445 | _anchor='comment-%s' % comment.comment_id) | |||
428 |
|
446 | |||
429 | def get_comments(self, repo_id, revision=None, pull_request=None): |
|
447 | def get_comments(self, repo_id, revision=None, pull_request=None): | |
430 | """ |
|
448 | """ |
@@ -31,6 +31,7 b' import urllib' | |||||
31 |
|
31 | |||
32 | from pylons.i18n.translation import _ |
|
32 | from pylons.i18n.translation import _ | |
33 | from pylons.i18n.translation import lazy_ugettext |
|
33 | from pylons.i18n.translation import lazy_ugettext | |
|
34 | from pyramid.threadlocal import get_current_request | |||
34 | from sqlalchemy import or_ |
|
35 | from sqlalchemy import or_ | |
35 |
|
36 | |||
36 | from rhodecode.lib import helpers as h, hooks_utils, diffs |
|
37 | from rhodecode.lib import helpers as h, hooks_utils, diffs | |
@@ -961,11 +962,19 b' class PullRequestModel(BaseModel):' | |||||
961 | self.notify_reviewers(pull_request, ids_to_add) |
|
962 | self.notify_reviewers(pull_request, ids_to_add) | |
962 | return ids_to_add, ids_to_remove |
|
963 | return ids_to_add, ids_to_remove | |
963 |
|
964 | |||
964 | def get_url(self, pull_request): |
|
965 | def get_url(self, pull_request, request=None, permalink=False): | |
965 | return h.url('pullrequest_show', |
|
966 | if not request: | |
|
967 | request = get_current_request() | |||
|
968 | ||||
|
969 | if permalink: | |||
|
970 | return request.route_url( | |||
|
971 | 'pull_requests_global', | |||
|
972 | pull_request_id=pull_request.pull_request_id,) | |||
|
973 | else: | |||
|
974 | return request.route_url( | |||
|
975 | 'pullrequest_show', | |||
966 |
|
|
976 | repo_name=safe_str(pull_request.target_repo.repo_name), | |
967 |
|
|
977 | pull_request_id=pull_request.pull_request_id,) | |
968 | qualified=True) |
|
|||
969 |
|
978 | |||
970 | def get_shadow_clone_url(self, pull_request): |
|
979 | def get_shadow_clone_url(self, pull_request): | |
971 | """ |
|
980 | """ |
@@ -155,10 +155,30 b' class RepoModel(BaseModel):' | |||||
155 | repos = Repository.query().filter(Repository.group == root).all() |
|
155 | repos = Repository.query().filter(Repository.group == root).all() | |
156 | return repos |
|
156 | return repos | |
157 |
|
157 | |||
158 | def get_url(self, repo, request=None): |
|
158 | def get_url(self, repo, request=None, permalink=False): | |
159 | if not request: |
|
159 | if not request: | |
160 | request = get_current_request() |
|
160 | request = get_current_request() | |
161 | return request.route_url('repo_summary', repo_name=safe_str(repo.repo_name)) |
|
161 | ||
|
162 | if permalink: | |||
|
163 | return request.route_url( | |||
|
164 | 'repo_summary', repo_name=safe_str(repo.repo_id)) | |||
|
165 | else: | |||
|
166 | return request.route_url( | |||
|
167 | 'repo_summary', repo_name=safe_str(repo.repo_name)) | |||
|
168 | ||||
|
169 | def get_commit_url(self, repo, commit_id, request=None, permalink=False): | |||
|
170 | if not request: | |||
|
171 | request = get_current_request() | |||
|
172 | ||||
|
173 | if permalink: | |||
|
174 | return request.route_url( | |||
|
175 | 'repo_commit', repo_name=safe_str(repo.repo_id), | |||
|
176 | commit_id=commit_id) | |||
|
177 | ||||
|
178 | else: | |||
|
179 | return request.route_url( | |||
|
180 | 'repo_commit', repo_name=safe_str(repo.repo_name), | |||
|
181 | commit_id=commit_id) | |||
162 |
|
182 | |||
163 | @classmethod |
|
183 | @classmethod | |
164 | def update_repoinfo(cls, repositories=None): |
|
184 | def update_repoinfo(cls, repositories=None): |
@@ -50,6 +50,7 b' def test_pullrequest_events_serialized(E' | |||||
50 | assert data['repo']['repo_name'] == pr.target_repo.repo_name |
|
50 | assert data['repo']['repo_name'] == pr.target_repo.repo_name | |
51 | assert data['pullrequest']['pull_request_id'] == pr.pull_request_id |
|
51 | assert data['pullrequest']['pull_request_id'] == pr.pull_request_id | |
52 | assert data['pullrequest']['url'] |
|
52 | assert data['pullrequest']['url'] | |
|
53 | assert data['pullrequest']['permalink_url'] | |||
53 |
|
54 | |||
54 |
|
55 | |||
55 | @pytest.mark.backends("git", "hg") |
|
56 | @pytest.mark.backends("git", "hg") | |
@@ -71,6 +72,7 b' def test_pullrequest_comment_events_seri' | |||||
71 | assert data['repo']['repo_name'] == pr.target_repo.repo_name |
|
72 | assert data['repo']['repo_name'] == pr.target_repo.repo_name | |
72 | assert data['pullrequest']['pull_request_id'] == pr.pull_request_id |
|
73 | assert data['pullrequest']['pull_request_id'] == pr.pull_request_id | |
73 | assert data['pullrequest']['url'] |
|
74 | assert data['pullrequest']['url'] | |
|
75 | assert data['pullrequest']['permalink_url'] | |||
74 | assert data['comment']['text'] == comment.text |
|
76 | assert data['comment']['text'] == comment.text | |
75 |
|
77 | |||
76 |
|
78 |
@@ -62,6 +62,7 b' def test_repo_events_serialized(config_s' | |||||
62 | assert data['name'] == EventClass.name |
|
62 | assert data['name'] == EventClass.name | |
63 | assert data['repo']['repo_name'] == repo_stub.repo_name |
|
63 | assert data['repo']['repo_name'] == repo_stub.repo_name | |
64 | assert data['repo']['url'] |
|
64 | assert data['repo']['url'] | |
|
65 | assert data['repo']['permalink_url'] | |||
65 |
|
66 | |||
66 |
|
67 | |||
67 | @pytest.mark.parametrize('EventClass', [ |
|
68 | @pytest.mark.parametrize('EventClass', [ | |
@@ -73,6 +74,7 b' def test_vcs_repo_events_serialize(confi' | |||||
73 | assert data['name'] == EventClass.name |
|
74 | assert data['name'] == EventClass.name | |
74 | assert data['repo']['repo_name'] == repo_stub.repo_name |
|
75 | assert data['repo']['repo_name'] == repo_stub.repo_name | |
75 | assert data['repo']['url'] |
|
76 | assert data['repo']['url'] | |
|
77 | assert data['repo']['permalink_url'] | |||
76 |
|
78 | |||
77 |
|
79 | |||
78 | @pytest.mark.parametrize('EventClass', [RepoPushEvent]) |
|
80 | @pytest.mark.parametrize('EventClass', [RepoPushEvent]) | |
@@ -84,6 +86,7 b' def test_vcs_repo_push_event_serialize(c' | |||||
84 | assert data['name'] == EventClass.name |
|
86 | assert data['name'] == EventClass.name | |
85 | assert data['repo']['repo_name'] == repo_stub.repo_name |
|
87 | assert data['repo']['repo_name'] == repo_stub.repo_name | |
86 | assert data['repo']['url'] |
|
88 | assert data['repo']['url'] | |
|
89 | assert data['repo']['permalink_url'] | |||
87 |
|
90 | |||
88 |
|
91 | |||
89 | def test_create_delete_repo_fires_events(backend): |
|
92 | def test_create_delete_repo_fires_events(backend): |
@@ -964,11 +964,9 b' class TestPullrequestsController(object)' | |||||
964 | assert target.text.strip() == 'tag: target' |
|
964 | assert target.text.strip() == 'tag: target' | |
965 | assert target.getchildren() == [] |
|
965 | assert target.getchildren() == [] | |
966 |
|
966 | |||
967 |
|
||||
968 |
|
||||
969 | @pytest.mark.parametrize('mergeable', [True, False]) |
|
967 | @pytest.mark.parametrize('mergeable', [True, False]) | |
970 | def test_shadow_repository_link( |
|
968 | def test_shadow_repository_link( | |
971 | self, mergeable, pr_util, http_host_stub): |
|
969 | self, mergeable, pr_util, http_host_only_stub): | |
972 | """ |
|
970 | """ | |
973 | Check that the pull request summary page displays a link to the shadow |
|
971 | Check that the pull request summary page displays a link to the shadow | |
974 | repository if the pull request is mergeable. If it is not mergeable |
|
972 | repository if the pull request is mergeable. If it is not mergeable | |
@@ -979,7 +977,7 b' class TestPullrequestsController(object)' | |||||
979 | target_repo = pull_request.target_repo.scm_instance() |
|
977 | target_repo = pull_request.target_repo.scm_instance() | |
980 | pr_id = pull_request.pull_request_id |
|
978 | pr_id = pull_request.pull_request_id | |
981 | shadow_url = '{host}/{repo}/pull-request/{pr_id}/repository'.format( |
|
979 | shadow_url = '{host}/{repo}/pull-request/{pr_id}/repository'.format( | |
982 | host=http_host_stub, repo=target_repo.name, pr_id=pr_id) |
|
980 | host=http_host_only_stub, repo=target_repo.name, pr_id=pr_id) | |
983 |
|
981 | |||
984 | response = self.app.get(url( |
|
982 | response = self.app.get(url( | |
985 | controller='pullrequests', action='show', |
|
983 | controller='pullrequests', action='show', |
@@ -412,4 +412,12 b' def add_test_routes(config):' | |||||
412 | """ |
|
412 | """ | |
413 | config.add_route(name='home', pattern='/') |
|
413 | config.add_route(name='home', pattern='/') | |
414 | config.add_route(name='repo_summary', pattern='/{repo_name}') |
|
414 | config.add_route(name='repo_summary', pattern='/{repo_name}') | |
|
415 | config.add_route(name='repo_summary_explicit', pattern='/{repo_name}/summary') | |||
415 | config.add_route(name='repo_group_home', pattern='/{repo_group_name}') |
|
416 | config.add_route(name='repo_group_home', pattern='/{repo_group_name}') | |
|
417 | ||||
|
418 | config.add_route(name='pullrequest_show', | |||
|
419 | pattern='/{repo_name}/pull-request/{pull_request_id}') | |||
|
420 | config.add_route(name='pull_requests_global', | |||
|
421 | pattern='/pull-request/{pull_request_id}') | |||
|
422 | config.add_route(name='repo_commit', | |||
|
423 | pattern='/{repo_name}/changeset/{commit_id}') |
General Comments 0
You need to be logged in to leave comments.
Login now