##// END OF EJS Templates
mercurial: show phases status in changelog....
marcink -
r1674:74692701 default
parent child Browse files
Show More
@@ -1,362 +1,373 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2
2
3 # Copyright (C) 2014-2017 RhodeCode GmbH
3 # Copyright (C) 2014-2017 RhodeCode GmbH
4 #
4 #
5 # This program is free software: you can redistribute it and/or modify
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU Affero General Public License, version 3
6 # it under the terms of the GNU Affero General Public License, version 3
7 # (only), as published by the Free Software Foundation.
7 # (only), as published by the Free Software Foundation.
8 #
8 #
9 # This program is distributed in the hope that it will be useful,
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU General Public License for more details.
12 # GNU General Public License for more details.
13 #
13 #
14 # You should have received a copy of the GNU Affero General Public License
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 #
16 #
17 # This program is dual-licensed. If you wish to learn more about the
17 # This program is dual-licensed. If you wish to learn more about the
18 # RhodeCode Enterprise Edition, including its added features, Support services,
18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20
20
21 """
21 """
22 HG commit module
22 HG commit module
23 """
23 """
24
24
25 import os
25 import os
26
26
27 from zope.cachedescriptors.property import Lazy as LazyProperty
27 from zope.cachedescriptors.property import Lazy as LazyProperty
28
28
29 from rhodecode.lib.datelib import utcdate_fromtimestamp
29 from rhodecode.lib.datelib import utcdate_fromtimestamp
30 from rhodecode.lib.utils import safe_str, safe_unicode
30 from rhodecode.lib.utils import safe_str, safe_unicode
31 from rhodecode.lib.vcs import path as vcspath
31 from rhodecode.lib.vcs import path as vcspath
32 from rhodecode.lib.vcs.backends import base
32 from rhodecode.lib.vcs.backends import base
33 from rhodecode.lib.vcs.backends.hg.diff import MercurialDiff
33 from rhodecode.lib.vcs.backends.hg.diff import MercurialDiff
34 from rhodecode.lib.vcs.exceptions import CommitError
34 from rhodecode.lib.vcs.exceptions import CommitError
35 from rhodecode.lib.vcs.nodes import (
35 from rhodecode.lib.vcs.nodes import (
36 AddedFileNodesGenerator, ChangedFileNodesGenerator, DirNode, FileNode,
36 AddedFileNodesGenerator, ChangedFileNodesGenerator, DirNode, FileNode,
37 NodeKind, RemovedFileNodesGenerator, RootNode, SubModuleNode,
37 NodeKind, RemovedFileNodesGenerator, RootNode, SubModuleNode,
38 LargeFileNode, LARGEFILE_PREFIX)
38 LargeFileNode, LARGEFILE_PREFIX)
39 from rhodecode.lib.vcs.utils.paths import get_dirs_for_path
39 from rhodecode.lib.vcs.utils.paths import get_dirs_for_path
40
40
41
41
42 class MercurialCommit(base.BaseCommit):
42 class MercurialCommit(base.BaseCommit):
43 """
43 """
44 Represents state of the repository at the single commit.
44 Represents state of the repository at the single commit.
45 """
45 """
46
46
47 _filter_pre_load = [
47 _filter_pre_load = [
48 # git specific property not supported here
48 # git specific property not supported here
49 "_commit",
49 "_commit",
50 ]
50 ]
51
51
52 def __init__(self, repository, raw_id, idx, pre_load=None):
52 def __init__(self, repository, raw_id, idx, pre_load=None):
53 raw_id = safe_str(raw_id)
53 raw_id = safe_str(raw_id)
54
54
55 self.repository = repository
55 self.repository = repository
56 self._remote = repository._remote
56 self._remote = repository._remote
57
57
58 self.raw_id = raw_id
58 self.raw_id = raw_id
59 self.idx = repository._sanitize_commit_idx(idx)
59 self.idx = repository._sanitize_commit_idx(idx)
60
60
61 self._set_bulk_properties(pre_load)
61 self._set_bulk_properties(pre_load)
62
62
63 # caches
63 # caches
64 self.nodes = {}
64 self.nodes = {}
65
65
66 def _set_bulk_properties(self, pre_load):
66 def _set_bulk_properties(self, pre_load):
67 if not pre_load:
67 if not pre_load:
68 return
68 return
69 pre_load = [entry for entry in pre_load
69 pre_load = [entry for entry in pre_load
70 if entry not in self._filter_pre_load]
70 if entry not in self._filter_pre_load]
71 if not pre_load:
71 if not pre_load:
72 return
72 return
73
73
74 result = self._remote.bulk_request(self.idx, pre_load)
74 result = self._remote.bulk_request(self.idx, pre_load)
75 for attr, value in result.items():
75 for attr, value in result.items():
76 if attr in ["author", "branch", "message"]:
76 if attr in ["author", "branch", "message"]:
77 value = safe_unicode(value)
77 value = safe_unicode(value)
78 elif attr == "affected_files":
78 elif attr == "affected_files":
79 value = map(safe_unicode, value)
79 value = map(safe_unicode, value)
80 elif attr == "date":
80 elif attr == "date":
81 value = utcdate_fromtimestamp(*value)
81 value = utcdate_fromtimestamp(*value)
82 elif attr in ["children", "parents"]:
82 elif attr in ["children", "parents"]:
83 value = self._make_commits(value)
83 value = self._make_commits(value)
84 self.__dict__[attr] = value
84 self.__dict__[attr] = value
85
85
86 @LazyProperty
86 @LazyProperty
87 def tags(self):
87 def tags(self):
88 tags = [name for name, commit_id in self.repository.tags.iteritems()
88 tags = [name for name, commit_id in self.repository.tags.iteritems()
89 if commit_id == self.raw_id]
89 if commit_id == self.raw_id]
90 return tags
90 return tags
91
91
92 @LazyProperty
92 @LazyProperty
93 def branch(self):
93 def branch(self):
94 return safe_unicode(self._remote.ctx_branch(self.idx))
94 return safe_unicode(self._remote.ctx_branch(self.idx))
95
95
96 @LazyProperty
96 @LazyProperty
97 def bookmarks(self):
97 def bookmarks(self):
98 bookmarks = [
98 bookmarks = [
99 name for name, commit_id in self.repository.bookmarks.iteritems()
99 name for name, commit_id in self.repository.bookmarks.iteritems()
100 if commit_id == self.raw_id]
100 if commit_id == self.raw_id]
101 return bookmarks
101 return bookmarks
102
102
103 @LazyProperty
103 @LazyProperty
104 def message(self):
104 def message(self):
105 return safe_unicode(self._remote.ctx_description(self.idx))
105 return safe_unicode(self._remote.ctx_description(self.idx))
106
106
107 @LazyProperty
107 @LazyProperty
108 def committer(self):
108 def committer(self):
109 return safe_unicode(self.author)
109 return safe_unicode(self.author)
110
110
111 @LazyProperty
111 @LazyProperty
112 def author(self):
112 def author(self):
113 return safe_unicode(self._remote.ctx_user(self.idx))
113 return safe_unicode(self._remote.ctx_user(self.idx))
114
114
115 @LazyProperty
115 @LazyProperty
116 def date(self):
116 def date(self):
117 return utcdate_fromtimestamp(*self._remote.ctx_date(self.idx))
117 return utcdate_fromtimestamp(*self._remote.ctx_date(self.idx))
118
118
119 @LazyProperty
119 @LazyProperty
120 def status(self):
120 def status(self):
121 """
121 """
122 Returns modified, added, removed, deleted files for current commit
122 Returns modified, added, removed, deleted files for current commit
123 """
123 """
124 return self._remote.ctx_status(self.idx)
124 return self._remote.ctx_status(self.idx)
125
125
126 @LazyProperty
126 @LazyProperty
127 def _file_paths(self):
127 def _file_paths(self):
128 return self._remote.ctx_list(self.idx)
128 return self._remote.ctx_list(self.idx)
129
129
130 @LazyProperty
130 @LazyProperty
131 def _dir_paths(self):
131 def _dir_paths(self):
132 p = list(set(get_dirs_for_path(*self._file_paths)))
132 p = list(set(get_dirs_for_path(*self._file_paths)))
133 p.insert(0, '')
133 p.insert(0, '')
134 return p
134 return p
135
135
136 @LazyProperty
136 @LazyProperty
137 def _paths(self):
137 def _paths(self):
138 return self._dir_paths + self._file_paths
138 return self._dir_paths + self._file_paths
139
139
140 @LazyProperty
140 @LazyProperty
141 def id(self):
141 def id(self):
142 if self.last:
142 if self.last:
143 return u'tip'
143 return u'tip'
144 return self.short_id
144 return self.short_id
145
145
146 @LazyProperty
146 @LazyProperty
147 def short_id(self):
147 def short_id(self):
148 return self.raw_id[:12]
148 return self.raw_id[:12]
149
149
150 def _make_commits(self, indexes):
150 def _make_commits(self, indexes):
151 return [self.repository.get_commit(commit_idx=idx)
151 return [self.repository.get_commit(commit_idx=idx)
152 for idx in indexes if idx >= 0]
152 for idx in indexes if idx >= 0]
153
153
154 @LazyProperty
154 @LazyProperty
155 def parents(self):
155 def parents(self):
156 """
156 """
157 Returns list of parent commits.
157 Returns list of parent commits.
158 """
158 """
159 parents = self._remote.ctx_parents(self.idx)
159 parents = self._remote.ctx_parents(self.idx)
160 return self._make_commits(parents)
160 return self._make_commits(parents)
161
161
162 @LazyProperty
162 @LazyProperty
163 def phase(self):
164 phase_id = self._remote.ctx_phase(self.idx)
165 phase_text = {
166 0: 'public',
167 1: 'draft',
168 2: 'secret',
169 }.get(phase_id) or ''
170
171 return safe_unicode(phase_text)
172
173 @LazyProperty
163 def children(self):
174 def children(self):
164 """
175 """
165 Returns list of child commits.
176 Returns list of child commits.
166 """
177 """
167 children = self._remote.ctx_children(self.idx)
178 children = self._remote.ctx_children(self.idx)
168 return self._make_commits(children)
179 return self._make_commits(children)
169
180
170 def diff(self, ignore_whitespace=True, context=3):
181 def diff(self, ignore_whitespace=True, context=3):
171 result = self._remote.ctx_diff(
182 result = self._remote.ctx_diff(
172 self.idx,
183 self.idx,
173 git=True, ignore_whitespace=ignore_whitespace, context=context)
184 git=True, ignore_whitespace=ignore_whitespace, context=context)
174 diff = ''.join(result)
185 diff = ''.join(result)
175 return MercurialDiff(diff)
186 return MercurialDiff(diff)
176
187
177 def _fix_path(self, path):
188 def _fix_path(self, path):
178 """
189 """
179 Mercurial keeps filenodes as str so we need to encode from unicode
190 Mercurial keeps filenodes as str so we need to encode from unicode
180 to str.
191 to str.
181 """
192 """
182 return safe_str(super(MercurialCommit, self)._fix_path(path))
193 return safe_str(super(MercurialCommit, self)._fix_path(path))
183
194
184 def _get_kind(self, path):
195 def _get_kind(self, path):
185 path = self._fix_path(path)
196 path = self._fix_path(path)
186 if path in self._file_paths:
197 if path in self._file_paths:
187 return NodeKind.FILE
198 return NodeKind.FILE
188 elif path in self._dir_paths:
199 elif path in self._dir_paths:
189 return NodeKind.DIR
200 return NodeKind.DIR
190 else:
201 else:
191 raise CommitError(
202 raise CommitError(
192 "Node does not exist at the given path '%s'" % (path, ))
203 "Node does not exist at the given path '%s'" % (path, ))
193
204
194 def _get_filectx(self, path):
205 def _get_filectx(self, path):
195 path = self._fix_path(path)
206 path = self._fix_path(path)
196 if self._get_kind(path) != NodeKind.FILE:
207 if self._get_kind(path) != NodeKind.FILE:
197 raise CommitError(
208 raise CommitError(
198 "File does not exist for idx %s at '%s'" % (self.raw_id, path))
209 "File does not exist for idx %s at '%s'" % (self.raw_id, path))
199 return path
210 return path
200
211
201 def get_file_mode(self, path):
212 def get_file_mode(self, path):
202 """
213 """
203 Returns stat mode of the file at the given ``path``.
214 Returns stat mode of the file at the given ``path``.
204 """
215 """
205 path = self._get_filectx(path)
216 path = self._get_filectx(path)
206 if 'x' in self._remote.fctx_flags(self.idx, path):
217 if 'x' in self._remote.fctx_flags(self.idx, path):
207 return base.FILEMODE_EXECUTABLE
218 return base.FILEMODE_EXECUTABLE
208 else:
219 else:
209 return base.FILEMODE_DEFAULT
220 return base.FILEMODE_DEFAULT
210
221
211 def is_link(self, path):
222 def is_link(self, path):
212 path = self._get_filectx(path)
223 path = self._get_filectx(path)
213 return 'l' in self._remote.fctx_flags(self.idx, path)
224 return 'l' in self._remote.fctx_flags(self.idx, path)
214
225
215 def get_file_content(self, path):
226 def get_file_content(self, path):
216 """
227 """
217 Returns content of the file at given ``path``.
228 Returns content of the file at given ``path``.
218 """
229 """
219 path = self._get_filectx(path)
230 path = self._get_filectx(path)
220 return self._remote.fctx_data(self.idx, path)
231 return self._remote.fctx_data(self.idx, path)
221
232
222 def get_file_size(self, path):
233 def get_file_size(self, path):
223 """
234 """
224 Returns size of the file at given ``path``.
235 Returns size of the file at given ``path``.
225 """
236 """
226 path = self._get_filectx(path)
237 path = self._get_filectx(path)
227 return self._remote.fctx_size(self.idx, path)
238 return self._remote.fctx_size(self.idx, path)
228
239
229 def get_file_history(self, path, limit=None, pre_load=None):
240 def get_file_history(self, path, limit=None, pre_load=None):
230 """
241 """
231 Returns history of file as reversed list of `MercurialCommit` objects
242 Returns history of file as reversed list of `MercurialCommit` objects
232 for which file at given ``path`` has been modified.
243 for which file at given ``path`` has been modified.
233 """
244 """
234 path = self._get_filectx(path)
245 path = self._get_filectx(path)
235 hist = self._remote.file_history(self.idx, path, limit)
246 hist = self._remote.file_history(self.idx, path, limit)
236 return [
247 return [
237 self.repository.get_commit(commit_id=commit_id, pre_load=pre_load)
248 self.repository.get_commit(commit_id=commit_id, pre_load=pre_load)
238 for commit_id in hist]
249 for commit_id in hist]
239
250
240 def get_file_annotate(self, path, pre_load=None):
251 def get_file_annotate(self, path, pre_load=None):
241 """
252 """
242 Returns a generator of four element tuples with
253 Returns a generator of four element tuples with
243 lineno, commit_id, commit lazy loader and line
254 lineno, commit_id, commit lazy loader and line
244 """
255 """
245 result = self._remote.fctx_annotate(self.idx, path)
256 result = self._remote.fctx_annotate(self.idx, path)
246
257
247 for ln_no, commit_id, content in result:
258 for ln_no, commit_id, content in result:
248 yield (
259 yield (
249 ln_no, commit_id,
260 ln_no, commit_id,
250 lambda: self.repository.get_commit(commit_id=commit_id,
261 lambda: self.repository.get_commit(commit_id=commit_id,
251 pre_load=pre_load),
262 pre_load=pre_load),
252 content)
263 content)
253
264
254 def get_nodes(self, path):
265 def get_nodes(self, path):
255 """
266 """
256 Returns combined ``DirNode`` and ``FileNode`` objects list representing
267 Returns combined ``DirNode`` and ``FileNode`` objects list representing
257 state of commit at the given ``path``. If node at the given ``path``
268 state of commit at the given ``path``. If node at the given ``path``
258 is not instance of ``DirNode``, CommitError would be raised.
269 is not instance of ``DirNode``, CommitError would be raised.
259 """
270 """
260
271
261 if self._get_kind(path) != NodeKind.DIR:
272 if self._get_kind(path) != NodeKind.DIR:
262 raise CommitError(
273 raise CommitError(
263 "Directory does not exist for idx %s at '%s'" %
274 "Directory does not exist for idx %s at '%s'" %
264 (self.idx, path))
275 (self.idx, path))
265 path = self._fix_path(path)
276 path = self._fix_path(path)
266
277
267 filenodes = [
278 filenodes = [
268 FileNode(f, commit=self) for f in self._file_paths
279 FileNode(f, commit=self) for f in self._file_paths
269 if os.path.dirname(f) == path]
280 if os.path.dirname(f) == path]
270 # TODO: johbo: Check if this can be done in a more obvious way
281 # TODO: johbo: Check if this can be done in a more obvious way
271 dirs = path == '' and '' or [
282 dirs = path == '' and '' or [
272 d for d in self._dir_paths
283 d for d in self._dir_paths
273 if d and vcspath.dirname(d) == path]
284 if d and vcspath.dirname(d) == path]
274 dirnodes = [
285 dirnodes = [
275 DirNode(d, commit=self) for d in dirs
286 DirNode(d, commit=self) for d in dirs
276 if os.path.dirname(d) == path]
287 if os.path.dirname(d) == path]
277
288
278 alias = self.repository.alias
289 alias = self.repository.alias
279 for k, vals in self._submodules.iteritems():
290 for k, vals in self._submodules.iteritems():
280 loc = vals[0]
291 loc = vals[0]
281 commit = vals[1]
292 commit = vals[1]
282 dirnodes.append(
293 dirnodes.append(
283 SubModuleNode(k, url=loc, commit=commit, alias=alias))
294 SubModuleNode(k, url=loc, commit=commit, alias=alias))
284 nodes = dirnodes + filenodes
295 nodes = dirnodes + filenodes
285 # cache nodes
296 # cache nodes
286 for node in nodes:
297 for node in nodes:
287 self.nodes[node.path] = node
298 self.nodes[node.path] = node
288 nodes.sort()
299 nodes.sort()
289
300
290 return nodes
301 return nodes
291
302
292 def get_node(self, path, pre_load=None):
303 def get_node(self, path, pre_load=None):
293 """
304 """
294 Returns `Node` object from the given `path`. If there is no node at
305 Returns `Node` object from the given `path`. If there is no node at
295 the given `path`, `NodeDoesNotExistError` would be raised.
306 the given `path`, `NodeDoesNotExistError` would be raised.
296 """
307 """
297 path = self._fix_path(path)
308 path = self._fix_path(path)
298
309
299 if path not in self.nodes:
310 if path not in self.nodes:
300 if path in self._file_paths:
311 if path in self._file_paths:
301 node = FileNode(path, commit=self, pre_load=pre_load)
312 node = FileNode(path, commit=self, pre_load=pre_load)
302 elif path in self._dir_paths:
313 elif path in self._dir_paths:
303 if path == '':
314 if path == '':
304 node = RootNode(commit=self)
315 node = RootNode(commit=self)
305 else:
316 else:
306 node = DirNode(path, commit=self)
317 node = DirNode(path, commit=self)
307 else:
318 else:
308 raise self.no_node_at_path(path)
319 raise self.no_node_at_path(path)
309
320
310 # cache node
321 # cache node
311 self.nodes[path] = node
322 self.nodes[path] = node
312 return self.nodes[path]
323 return self.nodes[path]
313
324
314 def get_largefile_node(self, path):
325 def get_largefile_node(self, path):
315
326
316 if self._remote.is_large_file(path):
327 if self._remote.is_large_file(path):
317 # content of that file regular FileNode is the hash of largefile
328 # content of that file regular FileNode is the hash of largefile
318 file_id = self.get_file_content(path).strip()
329 file_id = self.get_file_content(path).strip()
319
330
320 if self._remote.in_largefiles_store(file_id):
331 if self._remote.in_largefiles_store(file_id):
321 lf_path = self._remote.store_path(file_id)
332 lf_path = self._remote.store_path(file_id)
322 return LargeFileNode(lf_path, commit=self, org_path=path)
333 return LargeFileNode(lf_path, commit=self, org_path=path)
323 elif self._remote.in_user_cache(file_id):
334 elif self._remote.in_user_cache(file_id):
324 lf_path = self._remote.store_path(file_id)
335 lf_path = self._remote.store_path(file_id)
325 self._remote.link(file_id, path)
336 self._remote.link(file_id, path)
326 return LargeFileNode(lf_path, commit=self, org_path=path)
337 return LargeFileNode(lf_path, commit=self, org_path=path)
327
338
328 @LazyProperty
339 @LazyProperty
329 def _submodules(self):
340 def _submodules(self):
330 """
341 """
331 Returns a dictionary with submodule information from substate file
342 Returns a dictionary with submodule information from substate file
332 of hg repository.
343 of hg repository.
333 """
344 """
334 return self._remote.ctx_substate(self.idx)
345 return self._remote.ctx_substate(self.idx)
335
346
336 @LazyProperty
347 @LazyProperty
337 def affected_files(self):
348 def affected_files(self):
338 """
349 """
339 Gets a fast accessible file changes for given commit
350 Gets a fast accessible file changes for given commit
340 """
351 """
341 return self._remote.ctx_files(self.idx)
352 return self._remote.ctx_files(self.idx)
342
353
343 @property
354 @property
344 def added(self):
355 def added(self):
345 """
356 """
346 Returns list of added ``FileNode`` objects.
357 Returns list of added ``FileNode`` objects.
347 """
358 """
348 return AddedFileNodesGenerator([n for n in self.status[1]], self)
359 return AddedFileNodesGenerator([n for n in self.status[1]], self)
349
360
350 @property
361 @property
351 def changed(self):
362 def changed(self):
352 """
363 """
353 Returns list of modified ``FileNode`` objects.
364 Returns list of modified ``FileNode`` objects.
354 """
365 """
355 return ChangedFileNodesGenerator([n for n in self.status[0]], self)
366 return ChangedFileNodesGenerator([n for n in self.status[0]], self)
356
367
357 @property
368 @property
358 def removed(self):
369 def removed(self):
359 """
370 """
360 Returns list of removed ``FileNode`` objects.
371 Returns list of removed ``FileNode`` objects.
361 """
372 """
362 return RemovedFileNodesGenerator([n for n in self.status[2]], self)
373 return RemovedFileNodesGenerator([n for n in self.status[2]], self)
@@ -1,101 +1,109 b''
1 // tags.less
1 // tags.less
2 // For use in RhodeCode applications;
2 // For use in RhodeCode applications;
3 // see style guide documentation for guidelines.
3 // see style guide documentation for guidelines.
4
4
5 // TAGS
5 // TAGS
6 .tag,
6 .tag,
7 .tagtag {
7 .tagtag {
8 display: inline-block;
8 display: inline-block;
9 min-height: 0;
9 min-height: 0;
10 margin: 0 auto;
10 margin: 0 auto;
11 padding: .25em;
11 padding: .25em;
12 text-align: center;
12 text-align: center;
13 font-size: (-1 + @basefontsize); //fit in tables
13 font-size: (-1 + @basefontsize); //fit in tables
14 line-height: .9em;
14 line-height: .9em;
15 border: none;
15 border: none;
16 .border-radius(@border-radius);
16 .border-radius(@border-radius);
17 font-family: @text-regular;
17 font-family: @text-regular;
18 background-image: none;
18 background-image: none;
19 color: @grey4;
19 color: @grey4;
20 .border ( @border-thickness-tags, @grey4 );
20 .border ( @border-thickness-tags, @grey4 );
21 white-space: nowrap;
21 white-space: nowrap;
22 a {
22 a {
23 color: inherit;
23 color: inherit;
24 text-decoration: underline;
24 text-decoration: underline;
25
25
26 i,
26 i,
27 [class^="icon-"]:before,
27 [class^="icon-"]:before,
28 [class*=" icon-"]:before {
28 [class*=" icon-"]:before {
29 text-decoration: none;
29 text-decoration: none;
30 }
30 }
31 }
31 }
32 }
32 }
33
33
34 .tag0 { .border ( @border-thickness-tags, @grey4 ); color:@grey4; }
34 .tag0 { .border ( @border-thickness-tags, @grey4 ); color:@grey4; }
35 .tag1 { .border ( @border-thickness-tags, @color1 ); color:@color1; }
35 .tag1 { .border ( @border-thickness-tags, @color1 ); color:@color1; }
36 .tag2 { .border ( @border-thickness-tags, @color2 ); color:@color2; }
36 .tag2 { .border ( @border-thickness-tags, @color2 ); color:@color2; }
37 .tag3 { .border ( @border-thickness-tags, @color3 ); color:@color3; }
37 .tag3 { .border ( @border-thickness-tags, @color3 ); color:@color3; }
38 .tag4 { .border ( @border-thickness-tags, @color4 ); color:@color4; }
38 .tag4 { .border ( @border-thickness-tags, @color4 ); color:@color4; }
39 .tag5 { .border ( @border-thickness-tags, @color5 ); color:@color5; }
39 .tag5 { .border ( @border-thickness-tags, @color5 ); color:@color5; }
40 .tag6 { .border ( @border-thickness-tags, @color6 ); color:@color6; }
40 .tag6 { .border ( @border-thickness-tags, @color6 ); color:@color6; }
41 .tag7 { .border ( @border-thickness-tags, @color7 ); color:@color7; }
41 .tag7 { .border ( @border-thickness-tags, @color7 ); color:@color7; }
42 .tag8 { .border ( @border-thickness-tags, @color8 ); color:@color8; }
42 .tag8 { .border ( @border-thickness-tags, @color8 ); color:@color8; }
43
43
44 .metatag-list {
44 .metatag-list {
45 margin: 0;
45 margin: 0;
46 padding: 0;
46 padding: 0;
47
47
48 li {
48 li {
49 margin: 0 0 @padding;
49 margin: 0 0 @padding;
50 line-height: 1em;
50 line-height: 1em;
51 list-style-type: none;
51 list-style-type: none;
52
52
53 &:before { content: none; }
53 &:before { content: none; }
54 }
54 }
55 }
55 }
56
56
57 .branchtag, .booktag {
57 .branchtag, .booktag {
58 &:extend(.tag);
58 &:extend(.tag);
59
59
60
60
61 a {
61 a {
62 color:inherit;
62 color:inherit;
63 }
63 }
64 }
64 }
65
65
66 .metatag {
66 .metatag {
67 &:extend(.tag);
67 &:extend(.tag);
68 a {
68 a {
69 color:inherit;
69 color:inherit;
70 text-decoration: underline;
70 text-decoration: underline;
71 }
71 }
72 }
72 }
73
73
74 [tag="featured"] { &:extend(.tag1); }
74 [tag="featured"] { &:extend(.tag1); }
75 [tag="stale"] { &:extend(.tag2); }
75 [tag="stale"] { &:extend(.tag2); }
76 [tag="dead"] { &:extend(.tag3); }
76 [tag="dead"] { &:extend(.tag3); }
77 [tag="lang"] { &:extend(.tag4); }
77 [tag="lang"] { &:extend(.tag4); }
78 [tag="license"] { &:extend(.tag5); }
78 [tag="license"] { &:extend(.tag5); }
79 [tag="requires"] { &:extend(.tag6); }
79 [tag="requires"] { &:extend(.tag6); }
80 [tag="recommends"] { &:extend(.tag7); }
80 [tag="recommends"] { &:extend(.tag7); }
81 [tag="see"] { &:extend(.tag8); }
81 [tag="see"] { &:extend(.tag8); }
82
82
83 .perm_overriden {
83 .perm_overriden {
84 text-decoration: line-through;
84 text-decoration: line-through;
85 opacity: 0.6;
85 opacity: 0.6;
86 }
86 }
87
87
88 .perm_tag {
88 .perm_tag {
89 &:extend(.tag);
89 &:extend(.tag);
90
90
91 &.read {
91 &.read {
92 &:extend(.tag1);
92 &:extend(.tag1);
93 }
93 }
94
94
95 &.write {
95 &.write {
96 &:extend(.tag4);
96 &:extend(.tag4);
97 }
97 }
98 &.admin {
98 &.admin {
99 &:extend(.tag5);
99 &:extend(.tag5);
100 }
100 }
101 } No newline at end of file
101 }
102
103 .phase-draft {
104 color: @color3
105 }
106
107 .phase-secret {
108 color:@grey3
109 }
@@ -1,122 +1,127 b''
1 ## small box that displays changed/added/removed details fetched by AJAX
1 ## small box that displays changed/added/removed details fetched by AJAX
2 <%namespace name="base" file="/base/base.mako"/>
2 <%namespace name="base" file="/base/base.mako"/>
3
3
4
4
5 % if c.prev_page:
5 % if c.prev_page:
6 <tr>
6 <tr>
7 <td colspan="9" class="load-more-commits">
7 <td colspan="9" class="load-more-commits">
8 <a class="prev-commits" href="#loadPrevCommits" onclick="commitsController.loadPrev(this, ${c.prev_page}, '${c.branch_name}');return false">
8 <a class="prev-commits" href="#loadPrevCommits" onclick="commitsController.loadPrev(this, ${c.prev_page}, '${c.branch_name}');return false">
9 ${_('load previous')}
9 ${_('load previous')}
10 </a>
10 </a>
11 </td>
11 </td>
12 </tr>
12 </tr>
13 % endif
13 % endif
14
14
15 % for cnt,commit in enumerate(c.pagination):
15 % for cnt,commit in enumerate(c.pagination):
16 <tr id="sha_${commit.raw_id}" class="changelogRow container ${'tablerow%s' % (cnt%2)}">
16 <tr id="sha_${commit.raw_id}" class="changelogRow container ${'tablerow%s' % (cnt%2)}">
17
17
18 <td class="td-checkbox">
18 <td class="td-checkbox">
19 ${h.checkbox(commit.raw_id,class_="commit-range")}
19 ${h.checkbox(commit.raw_id,class_="commit-range")}
20 </td>
20 </td>
21 <td class="td-status">
21 <td class="td-status">
22
22
23 %if c.statuses.get(commit.raw_id):
23 %if c.statuses.get(commit.raw_id):
24 <div class="changeset-status-ico">
24 <div class="changeset-status-ico">
25 %if c.statuses.get(commit.raw_id)[2]:
25 %if c.statuses.get(commit.raw_id)[2]:
26 <a class="tooltip" title="${_('Commit status: %s\nClick to open associated pull request #%s') % (h.commit_status_lbl(c.statuses.get(commit.raw_id)[0]), c.statuses.get(commit.raw_id)[2])}" href="${h.url('pullrequest_show',repo_name=c.statuses.get(commit.raw_id)[3],pull_request_id=c.statuses.get(commit.raw_id)[2])}">
26 <a class="tooltip" title="${_('Commit status: %s\nClick to open associated pull request #%s') % (h.commit_status_lbl(c.statuses.get(commit.raw_id)[0]), c.statuses.get(commit.raw_id)[2])}" href="${h.url('pullrequest_show',repo_name=c.statuses.get(commit.raw_id)[3],pull_request_id=c.statuses.get(commit.raw_id)[2])}">
27 <div class="${'flag_status %s' % c.statuses.get(commit.raw_id)[0]}"></div>
27 <div class="${'flag_status %s' % c.statuses.get(commit.raw_id)[0]}"></div>
28 </a>
28 </a>
29 %else:
29 %else:
30 <a class="tooltip" title="${_('Commit status: %s') % h.commit_status_lbl(c.statuses.get(commit.raw_id)[0])}" href="${h.url('changeset_home',repo_name=c.repo_name,revision=commit.raw_id,anchor='comment-%s' % c.comments[commit.raw_id][0].comment_id)}">
30 <a class="tooltip" title="${_('Commit status: %s') % h.commit_status_lbl(c.statuses.get(commit.raw_id)[0])}" href="${h.url('changeset_home',repo_name=c.repo_name,revision=commit.raw_id,anchor='comment-%s' % c.comments[commit.raw_id][0].comment_id)}">
31 <div class="${'flag_status %s' % c.statuses.get(commit.raw_id)[0]}"></div>
31 <div class="${'flag_status %s' % c.statuses.get(commit.raw_id)[0]}"></div>
32 </a>
32 </a>
33 %endif
33 %endif
34 </div>
34 </div>
35 %else:
35 %else:
36 <div class="tooltip flag_status not_reviewed" title="${_('Commit status: Not Reviewed')}"></div>
36 <div class="tooltip flag_status not_reviewed" title="${_('Commit status: Not Reviewed')}"></div>
37 %endif
37 %endif
38 </td>
38 </td>
39 <td class="td-comments comments-col">
39 <td class="td-comments comments-col">
40 %if c.comments.get(commit.raw_id):
40 %if c.comments.get(commit.raw_id):
41 <a title="${_('Commit has comments')}" href="${h.url('changeset_home',repo_name=c.repo_name,revision=commit.raw_id,anchor='comment-%s' % c.comments[commit.raw_id][0].comment_id)}">
41 <a title="${_('Commit has comments')}" href="${h.url('changeset_home',repo_name=c.repo_name,revision=commit.raw_id,anchor='comment-%s' % c.comments[commit.raw_id][0].comment_id)}">
42 <i class="icon-comment"></i> ${len(c.comments[commit.raw_id])}
42 <i class="icon-comment"></i> ${len(c.comments[commit.raw_id])}
43 </a>
43 </a>
44 %endif
44 %endif
45 </td>
45 </td>
46 <td class="td-hash">
46 <td class="td-hash">
47 <code>
47 <code>
48 <a href="${h.url('changeset_home',repo_name=c.repo_name,revision=commit.raw_id)}">
48 <a href="${h.url('changeset_home',repo_name=c.repo_name,revision=commit.raw_id)}">
49 <span class="commit_hash">${h.show_id(commit)}</span>
49 <span class="commit_hash">${h.show_id(commit)}</span>
50 </a>
50 </a>
51 % if hasattr(commit, 'phase'):
52 % if commit.phase != 'public':
53 <span class="tag phase-${commit.phase} tooltip" title="${_('commit phase')}">${commit.phase}</span>
54 % endif
55 % endif
51 </code>
56 </code>
52 </td>
57 </td>
53 <td class="td-message expand_commit" data-commit-id="${commit.raw_id}" title="${_('Expand commit message')}" onclick="commitsController.expandCommit(this); return false">
58 <td class="td-message expand_commit" data-commit-id="${commit.raw_id}" title="${_('Expand commit message')}" onclick="commitsController.expandCommit(this); return false">
54 <div class="show_more_col">
59 <div class="show_more_col">
55 <i class="show_more"></i>&nbsp;
60 <i class="show_more"></i>&nbsp;
56 </div>
61 </div>
57 </td>
62 </td>
58 <td class="td-description mid">
63 <td class="td-description mid">
59 <div class="log-container truncate-wrap">
64 <div class="log-container truncate-wrap">
60 <div class="message truncate" id="c-${commit.raw_id}">${h.urlify_commit_message(commit.message, c.repo_name)}</div>
65 <div class="message truncate" id="c-${commit.raw_id}">${h.urlify_commit_message(commit.message, c.repo_name)}</div>
61 </div>
66 </div>
62 </td>
67 </td>
63
68
64 <td class="td-time">
69 <td class="td-time">
65 ${h.age_component(commit.date)}
70 ${h.age_component(commit.date)}
66 </td>
71 </td>
67 <td class="td-user">
72 <td class="td-user">
68 ${base.gravatar_with_user(commit.author)}
73 ${base.gravatar_with_user(commit.author)}
69 </td>
74 </td>
70
75
71 <td class="td-tags tags-col">
76 <td class="td-tags tags-col">
72 <div id="t-${commit.raw_id}">
77 <div id="t-${commit.raw_id}">
73
78
74 ## merge
79 ## merge
75 %if commit.merge:
80 %if commit.merge:
76 <span class="tag mergetag">
81 <span class="tag mergetag">
77 <i class="icon-merge"></i>${_('merge')}
82 <i class="icon-merge"></i>${_('merge')}
78 </span>
83 </span>
79 %endif
84 %endif
80
85
81 ## branch
86 ## branch
82 %if commit.branch:
87 %if commit.branch:
83 <span class="tag branchtag" title="${_('Branch %s') % commit.branch}">
88 <span class="tag branchtag" title="${_('Branch %s') % commit.branch}">
84 <a href="${h.url('changelog_home',repo_name=c.repo_name,branch=commit.branch)}"><i class="icon-code-fork"></i>${h.shorter(commit.branch)}</a>
89 <a href="${h.url('changelog_home',repo_name=c.repo_name,branch=commit.branch)}"><i class="icon-code-fork"></i>${h.shorter(commit.branch)}</a>
85 </span>
90 </span>
86 %endif
91 %endif
87
92
88 ## bookmarks
93 ## bookmarks
89 %if h.is_hg(c.rhodecode_repo):
94 %if h.is_hg(c.rhodecode_repo):
90 %for book in commit.bookmarks:
95 %for book in commit.bookmarks:
91 <span class="tag booktag" title="${_('Bookmark %s') % book}">
96 <span class="tag booktag" title="${_('Bookmark %s') % book}">
92 <a href="${h.url('files_home',repo_name=c.repo_name,revision=commit.raw_id)}"><i class="icon-bookmark"></i>${h.shorter(book)}</a>
97 <a href="${h.url('files_home',repo_name=c.repo_name,revision=commit.raw_id)}"><i class="icon-bookmark"></i>${h.shorter(book)}</a>
93 </span>
98 </span>
94 %endfor
99 %endfor
95 %endif
100 %endif
96
101
97 ## tags
102 ## tags
98 %for tag in commit.tags:
103 %for tag in commit.tags:
99 <span class="tag tagtag" title="${_('Tag %s') % tag}">
104 <span class="tag tagtag" title="${_('Tag %s') % tag}">
100 <a href="${h.url('files_home',repo_name=c.repo_name,revision=commit.raw_id)}"><i class="icon-tag"></i>${h.shorter(tag)}</a>
105 <a href="${h.url('files_home',repo_name=c.repo_name,revision=commit.raw_id)}"><i class="icon-tag"></i>${h.shorter(tag)}</a>
101 </span>
106 </span>
102 %endfor
107 %endfor
103
108
104 </div>
109 </div>
105 </td>
110 </td>
106 </tr>
111 </tr>
107 % endfor
112 % endfor
108
113
109 % if c.next_page:
114 % if c.next_page:
110 <tr>
115 <tr>
111 <td colspan="9" class="load-more-commits">
116 <td colspan="9" class="load-more-commits">
112 <a class="next-commits" href="#loadNextCommits" onclick="commitsController.loadNext(this, ${c.next_page}, '${c.branch_name}');return false">
117 <a class="next-commits" href="#loadNextCommits" onclick="commitsController.loadNext(this, ${c.next_page}, '${c.branch_name}');return false">
113 ${_('load next')}
118 ${_('load next')}
114 </a>
119 </a>
115 </td>
120 </td>
116 </tr>
121 </tr>
117 % endif
122 % endif
118 <tr class="chunk-graph-data" style="display:none"
123 <tr class="chunk-graph-data" style="display:none"
119 data-graph='${c.graph_data|n}'
124 data-graph='${c.graph_data|n}'
120 data-node='${c.prev_page}:${c.next_page}'
125 data-node='${c.prev_page}:${c.next_page}'
121 data-commits='${c.graph_commits|n}'>
126 data-commits='${c.graph_commits|n}'>
122 </tr> No newline at end of file
127 </tr>
General Comments 0
You need to be logged in to leave comments. Login now