##// END OF EJS Templates
rev_start for compare should use parents only if there are present
marcink -
r3386:934f1fd5 beta
parent child Browse files
Show More
@@ -1,191 +1,192
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.controllers.compare
4 4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 5
6 6 compare controller for pylons showing differences between two
7 7 repos, branches, bookmarks or tips
8 8
9 9 :created_on: May 6, 2012
10 10 :author: marcink
11 11 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
12 12 :license: GPLv3, see COPYING for more details.
13 13 """
14 14 # This program is free software: you can redistribute it and/or modify
15 15 # it under the terms of the GNU General Public License as published by
16 16 # the Free Software Foundation, either version 3 of the License, or
17 17 # (at your option) any later version.
18 18 #
19 19 # This program is distributed in the hope that it will be useful,
20 20 # but WITHOUT ANY WARRANTY; without even the implied warranty of
21 21 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 22 # GNU General Public License for more details.
23 23 #
24 24 # You should have received a copy of the GNU General Public License
25 25 # along with this program. If not, see <http://www.gnu.org/licenses/>.
26 26 import logging
27 27 import traceback
28 28
29 29 from webob.exc import HTTPNotFound
30 30 from pylons import request, response, session, tmpl_context as c, url
31 31 from pylons.controllers.util import abort, redirect
32 32 from pylons.i18n.translation import _
33 33
34 34 from rhodecode.lib.vcs.exceptions import EmptyRepositoryError, RepositoryError
35 35 from rhodecode.lib import helpers as h
36 36 from rhodecode.lib.base import BaseRepoController, render
37 37 from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator
38 38 from rhodecode.lib import diffs
39 39
40 40 from rhodecode.model.db import Repository
41 41 from rhodecode.model.pull_request import PullRequestModel
42 42 from webob.exc import HTTPBadRequest
43 43 from rhodecode.lib.diffs import LimitedDiffContainer
44 from rhodecode.lib.vcs.backends.base import EmptyChangeset
44 45
45 46 log = logging.getLogger(__name__)
46 47
47 48
48 49 class CompareController(BaseRepoController):
49 50
50 51 @LoginRequired()
51 52 @HasRepoPermissionAnyDecorator('repository.read', 'repository.write',
52 53 'repository.admin')
53 54 def __before__(self):
54 55 super(CompareController, self).__before__()
55 56
56 57 def __get_cs_or_redirect(self, rev, repo, redirect_after=True,
57 58 partial=False):
58 59 """
59 60 Safe way to get changeset if error occur it redirects to changeset with
60 61 proper message. If partial is set then don't do redirect raise Exception
61 62 instead
62 63
63 64 :param rev: revision to fetch
64 65 :param repo: repo instance
65 66 """
66 67
67 68 try:
68 69 type_, rev = rev
69 70 return repo.scm_instance.get_changeset(rev)
70 71 except EmptyRepositoryError, e:
71 72 if not redirect_after:
72 73 return None
73 74 h.flash(h.literal(_('There are no changesets yet')),
74 75 category='warning')
75 76 redirect(url('summary_home', repo_name=repo.repo_name))
76 77
77 78 except RepositoryError, e:
78 79 log.error(traceback.format_exc())
79 80 h.flash(str(e), category='warning')
80 81 if not partial:
81 82 redirect(h.url('summary_home', repo_name=repo.repo_name))
82 83 raise HTTPBadRequest()
83 84
84 85 def index(self, org_ref_type, org_ref, other_ref_type, other_ref):
85 86
86 87 org_repo = c.rhodecode_db_repo.repo_name
87 88 org_ref = (org_ref_type, org_ref)
88 89 other_ref = (other_ref_type, other_ref)
89 90 other_repo = request.GET.get('other_repo', org_repo)
90 91 c.fulldiff = fulldiff = request.GET.get('fulldiff')
91 92 rev_start = request.GET.get('rev_start')
92 93 rev_end = request.GET.get('rev_end')
93 94
94 95 c.swap_url = h.url('compare_url', as_form=request.GET.get('as_form'),
95 96 repo_name=other_repo,
96 97 org_ref_type=other_ref[0], org_ref=other_ref[1],
97 98 other_repo=org_repo,
98 99 other_ref_type=org_ref[0], other_ref=org_ref[1])
99 100
100 101 partial = request.environ.get('HTTP_X_PARTIAL_XHR')
101 102
102 103 org_repo = Repository.get_by_repo_name(org_repo)
103 104 other_repo = Repository.get_by_repo_name(other_repo)
104 105
105 106 self.__get_cs_or_redirect(rev=org_ref, repo=org_repo, partial=partial)
106 107 self.__get_cs_or_redirect(rev=other_ref, repo=other_repo, partial=partial)
107 108
108 109 if org_repo is None:
109 110 log.error('Could not find org repo %s' % org_repo)
110 111 raise HTTPNotFound
111 112 if other_repo is None:
112 113 log.error('Could not find other repo %s' % other_repo)
113 114 raise HTTPNotFound
114 115
115 116 if org_repo != other_repo and h.is_git(org_repo):
116 117 log.error('compare of two remote repos not available for GIT REPOS')
117 118 raise HTTPNotFound
118 119
119 120 if org_repo.scm_instance.alias != other_repo.scm_instance.alias:
120 121 log.error('compare of two different kind of remote repos not available')
121 122 raise HTTPNotFound
122 123
123 124 c.org_repo = org_repo
124 125 c.other_repo = other_repo
125 126 c.org_ref = org_ref[1]
126 127 c.other_ref = other_ref[1]
127 128 c.org_ref_type = org_ref[0]
128 129 c.other_ref_type = other_ref[0]
129 130
130 131 if rev_start and rev_end:
131 132 # swap revs with cherry picked ones, save them for display
132 133 #org_ref = ('rev', rev_start)
133 134 #other_ref = ('rev', rev_end)
134 135 c.org_ref = rev_start[:12]
135 136 c.other_ref = rev_end[:12]
136 137 # get parent of
137 138 # rev start to include it in the diff
138 139 _cs = other_repo.scm_instance.get_changeset(rev_start)
139 rev_start = _cs.parents[0].raw_id
140 rev_start = _cs.parents[0].raw_id if _cs.parents else EmptyChangeset()
140 141 org_ref = ('rev', rev_start)
141 142 other_ref = ('rev', rev_end)
142 143 #if we cherry pick it's not remote, make the other_repo org_repo
143 144 org_repo = other_repo
144 145
145 146 c.cs_ranges, ancestor = PullRequestModel().get_compare_data(
146 147 org_repo, org_ref, other_repo, other_ref)
147 148
148 149 c.statuses = c.rhodecode_db_repo.statuses([x.raw_id for x in
149 150 c.cs_ranges])
150 151 # defines that we need hidden inputs with changesets
151 152 c.as_form = request.GET.get('as_form', False)
152 153 if partial:
153 154 return render('compare/compare_cs.html')
154 155
155 156 if ancestor and org_repo != other_repo:
156 157 # case we want a simple diff without incoming changesets,
157 158 # previewing what will be merged.
158 159 # Make the diff on the forked repo, with
159 160 # revision that is common ancestor
160 161 log.debug('Using ancestor %s as org_ref instead of %s'
161 162 % (ancestor, org_ref))
162 163 org_ref = ('rev', ancestor)
163 164 org_repo = other_repo
164 165
165 166 diff_limit = self.cut_off_limit if not fulldiff else None
166 167
167 168 _diff = diffs.differ(org_repo, org_ref, other_repo, other_ref)
168 169
169 170 diff_processor = diffs.DiffProcessor(_diff or '', format='gitdiff',
170 171 diff_limit=diff_limit)
171 172 _parsed = diff_processor.prepare()
172 173
173 174 c.limited_diff = False
174 175 if isinstance(_parsed, LimitedDiffContainer):
175 176 c.limited_diff = True
176 177
177 178 c.files = []
178 179 c.changes = {}
179 180 c.lines_added = 0
180 181 c.lines_deleted = 0
181 182 for f in _parsed:
182 183 st = f['stats']
183 184 if st[0] != 'b':
184 185 c.lines_added += st[0]
185 186 c.lines_deleted += st[1]
186 187 fid = h.FID('', f['filename'])
187 188 c.files.append([fid, f['operation'], f['filename'], f['stats']])
188 189 diff = diff_processor.as_html(enable_comments=False, parsed_lines=[f])
189 190 c.changes[fid] = [f['operation'], f['filename'], diff]
190 191
191 192 return render('compare/compare_diff.html')
General Comments 0
You need to be logged in to leave comments. Login now