Show More
The requested changes are too big and content was truncated. Show full diff
This diff has been collapsed as it changes many lines, (570 lines changed) Show them Hide them | |||
@@ -0,0 +1,570 b'' | |||
|
1 | diff --git a/img/baseline-10px.png b/img/baseline-10px.png | |
|
2 | new file mode 100644 | |
|
3 | index 0000000000000000000000000000000000000000..16095dcbf5c9ea41caeb1e3e41d647d425222ed1 | |
|
4 | GIT binary patch | |
|
5 | literal 152 | |
|
6 | zcmeAS@N?(olHy`uVBq!ia0vp^j6j^i!3HGVb)pi0lw^r(L`iUdT1k0gQ7VIDN`6wR | |
|
7 | zf@f}GdTLN=VoGJ<$y6JlA}dc9$B>F!Nx%O8w`Ue+77%bXFxq5j_~-xsZV_1~1zCBH | |
|
8 | y)y@U((_~Lrb!=|_@`K?vV_&A58+!u-Gs6x+MGjBnI|qTLFnGH9xvX<aXaWHBd@WW0 | |
|
9 | ||
|
10 | literal 0 | |
|
11 | HcmV?d00001 | |
|
12 | ||
|
13 | diff --git a/img/baseline-20px.png b/img/baseline-20px.png | |
|
14 | deleted file mode 100644 | |
|
15 | index 6894c4c8289e8600b595caf70d481324e640b8bd..0000000000000000000000000000000000000000 | |
|
16 | GIT binary patch | |
|
17 | literal 0 | |
|
18 | HcmV?d00001 | |
|
19 | ||
|
20 | literal 127 | |
|
21 | zcmeAS@N?(olHy`uVBq!ia0vp^j6j^i!3HGVb)pi0lw^r(L`iUdT1k0gQ7VIDN`6wR | |
|
22 | zf@f}GdTLN=VoGJ<$y6JlB1KOZ$B>F!Nk9Jow`XSN<z!=HoHesY!R@WWAwG@Mj0y)B | |
|
23 | YKKcpQXiYX%0xD+kboFyt=akR{0IF0Y6aWAK | |
|
24 | ||
|
25 | diff --git a/index.html b/index.html | |
|
26 | index 9aa2355b0d5f3dd324c8191637703c944ca14fca..654d5cc338e5cb27b41e09739363b025242d8acf 100644 | |
|
27 | --- a/index.html | |
|
28 | +++ b/index.html | |
|
29 | @@ -2,7 +2,7 @@ | |
|
30 | <html lang="en"> | |
|
31 | <head> | |
|
32 | <meta charset="utf-8"> | |
|
33 | - <title>Baseline</title> | |
|
34 | + <title>Twitter Baseline</title> | |
|
35 | ||
|
36 | <!-- // Less.js at the ready! --> | |
|
37 | <link rel="stylesheet/less" type="text/css" media="all" href="less/baseline.less" /> | |
|
38 | @@ -11,6 +11,7 @@ | |
|
39 | <!-- // jQuery! --> | |
|
40 | <script type="text/javascript" src="http://code.jquery.com/jquery-1.5.2.min.js"></script> | |
|
41 | <script type="text/javascript" src="http://tablesorter.com/jquery.tablesorter.min.js"></script> | |
|
42 | + <script type="text/javascript" src="js/jquery/hashgrid.js"></script> | |
|
43 | <script type="text/javascript"> | |
|
44 | $(document).ready(function(){ | |
|
45 | // Active state in top nav | |
|
46 | @@ -36,7 +37,7 @@ | |
|
47 | <!-- | |
|
48 | <style> | |
|
49 | body { | |
|
50 | - background: url(img/baseline-20px.png) repeat 0 0, url(img/grid-940px.png) repeat-y top center; | |
|
51 | + background: url(img/baseline-10px.png) repeat 0 0, url(img/grid-940px.png) repeat-y top center; | |
|
52 | background-color: #fff; | |
|
53 | } | |
|
54 | </style> | |
|
55 | diff --git a/js/global.js b/js/global.js | |
|
56 | deleted file mode 100644 | |
|
57 | index a934a3360ef6bdf340a036e6f3475daa7a54103c..0000000000000000000000000000000000000000 | |
|
58 | --- a/js/global.js | |
|
59 | +++ /dev/null | |
|
60 | @@ -1,75 +0,0 @@ | |
|
61 | -$(document).ready(function(){ | |
|
62 | - // Get Heights | |
|
63 | - windowHeight = $(window).height(); | |
|
64 | - documentHeight = $(document).height(); | |
|
65 | - sidebarHeight = windowHeight - 40; | |
|
66 | - containerHeight = windowHeight - 40; | |
|
67 | - | |
|
68 | - // Get Widths | |
|
69 | - windowWidth = $(window).width(); | |
|
70 | - containerWidth = windowWidth - 200; | |
|
71 | - | |
|
72 | - if (windowHeight < containerHeight) { | |
|
73 | - | |
|
74 | - // Set Dimensions for default state (before resize) | |
|
75 | - $('div#sidebar').css({ | |
|
76 | - height: sidebarHeight | |
|
77 | - }); | |
|
78 | - $('div#container').css({ | |
|
79 | - width: containerWidth, | |
|
80 | - height: containerHeight | |
|
81 | - }); | |
|
82 | - | |
|
83 | - } else { | |
|
84 | - | |
|
85 | - // During resize, set widths | |
|
86 | - $(window).resize(function() { | |
|
87 | - console.log('Window Height: ' + $(window).height() + ', Sidebar Height:' + ($(window).height() - 40)); | |
|
88 | - | |
|
89 | - // Get Heights | |
|
90 | - windowHeight = $(window).height(); | |
|
91 | - sidebarHeight = windowHeight - 40; | |
|
92 | - containerHeight = windowHeight - 40; | |
|
93 | - | |
|
94 | - // Get Widths | |
|
95 | - windowWidth = $(window).width(); | |
|
96 | - containerWidth = windowWidth - 200; | |
|
97 | - | |
|
98 | - // Set Dimensions for default state (before resize) | |
|
99 | - $('div#sidebar').css({ | |
|
100 | - height: sidebarHeight | |
|
101 | - }); | |
|
102 | - $('div#container').css({ | |
|
103 | - width: containerWidth, | |
|
104 | - height: containerHeight | |
|
105 | - }); | |
|
106 | - }); | |
|
107 | - // console.log('omgz window is less than container so... fuck.'); | |
|
108 | - $('div#sidebar').css({ | |
|
109 | - height: documentHeight - 40 | |
|
110 | - }); | |
|
111 | - | |
|
112 | - } | |
|
113 | - | |
|
114 | - | |
|
115 | - | |
|
116 | -/* | |
|
117 | - // Toggle Calendars | |
|
118 | - $('div#sidebar ul li a').click(function() { | |
|
119 | - if ($(this).is('#toggleMonthView')) { | |
|
120 | - console.log('toggle month'); | |
|
121 | - $(this).addClass('active'); | |
|
122 | - $('#toggleListView').removeClass('active'); | |
|
123 | - $('table#monthView').show(); | |
|
124 | - $('table#listView').hide(); | |
|
125 | - } else { | |
|
126 | - console.log('toggle list'); | |
|
127 | - $(this).addClass('active'); | |
|
128 | - $('#toggleMonthView').removeClass('active'); | |
|
129 | - $('table#listView').show(); | |
|
130 | - $('table#monthView').hide(); | |
|
131 | - } | |
|
132 | - return false; | |
|
133 | - }); | |
|
134 | -*/ | |
|
135 | -}); | |
|
136 | diff --git a/js/jquery/hashgrid.js b/js/jquery/hashgrid.js | |
|
137 | new file mode 100755 | |
|
138 | index 0000000000000000000000000000000000000000..db7af7989499dd359737a880828f8d1b08571f81 | |
|
139 | --- /dev/null | |
|
140 | +++ b/js/jquery/hashgrid.js | |
|
141 | @@ -0,0 +1,340 @@ | |
|
142 | +/** | |
|
143 | + * hashgrid (jQuery version) | |
|
144 | + * http://github.com/dotjay/hashgrid | |
|
145 | + * Version 5, 3 Nov 2010 | |
|
146 | + * Written by Jon Gibbins, dotjay.co.uk, accessibility.co.uk | |
|
147 | + * Contibutors: | |
|
148 | + * Sean Coates, seancoates.com | |
|
149 | + * Phil Dokas, jetless.org | |
|
150 | + * | |
|
151 | + * // Using a basic #grid setup | |
|
152 | + * var grid = new hashgrid(); | |
|
153 | + * | |
|
154 | + * // Using #grid with a custom id (e.g. #mygrid) | |
|
155 | + * var grid = new hashgrid("mygrid"); | |
|
156 | + * | |
|
157 | + * // Using #grid with additional options | |
|
158 | + * var grid = new hashgrid({ | |
|
159 | + * id: 'mygrid', // id for the grid container | |
|
160 | + * modifierKey: 'alt', // optional 'ctrl', 'alt' or 'shift' | |
|
161 | + * showGridKey: 's', // key to show the grid | |
|
162 | + * holdGridKey: 'enter', // key to hold the grid in place | |
|
163 | + * foregroundKey: 'f', // key to toggle foreground/background | |
|
164 | + * jumpGridsKey: 'd', // key to cycle through the grid classes | |
|
165 | + * numberOfGrids: 2, // number of grid classes used | |
|
166 | + * classPrefix: 'class', // prefix for the grid classes | |
|
167 | + * cookiePrefix: 'mygrid' // prefix for the cookie name | |
|
168 | + * }); | |
|
169 | + */ | |
|
170 | +if (typeof jQuery == "undefined") { | |
|
171 | + alert("Hashgrid: jQuery not loaded. Make sure it's linked to your pages."); | |
|
172 | +} | |
|
173 | + | |
|
174 | + | |
|
175 | +/** | |
|
176 | + * hashgrid overlay | |
|
177 | + */ | |
|
178 | +var hashgrid = function(set) { | |
|
179 | + | |
|
180 | + var options = { | |
|
181 | + id: 'grid', // id for the grid container | |
|
182 | + modifierKey: null, // optional 'ctrl', 'alt' or 'shift' | |
|
183 | + showGridKey: 'g', // key to show the grid | |
|
184 | + holdGridKey: 'h', // key to hold the grid in place | |
|
185 | + foregroundKey: 'f', // key to toggle foreground/background | |
|
186 | + jumpGridsKey: 'j', // key to cycle through the grid classes | |
|
187 | + numberOfGrids: 1, // number of grid classes used | |
|
188 | + classPrefix: 'grid-', // prefix for the grid classes | |
|
189 | + cookiePrefix: 'hashgrid'// prefix for the cookie name | |
|
190 | + }; | |
|
191 | + var overlayOn = false, | |
|
192 | + sticky = false, | |
|
193 | + overlayZState = 'B', | |
|
194 | + overlayZBackground = -1, | |
|
195 | + overlayZForeground = 9999, | |
|
196 | + classNumber = 1; | |
|
197 | + | |
|
198 | + // Apply options | |
|
199 | + if (typeof set == 'object') { | |
|
200 | + var k; | |
|
201 | + for (k in set) options[k] = set[k]; | |
|
202 | + } | |
|
203 | + else if (typeof set == 'string') { | |
|
204 | + options.id = set; | |
|
205 | + } | |
|
206 | + | |
|
207 | + // Remove any conflicting overlay | |
|
208 | + if ($('#' + options.id).length > 0) { | |
|
209 | + $('#' + options.id).remove(); | |
|
210 | + } | |
|
211 | + | |
|
212 | + // Create overlay, hidden before adding to DOM | |
|
213 | + var overlayEl = $('<div></div>'); | |
|
214 | + overlayEl | |
|
215 | + .attr('id', options.id) | |
|
216 | + .css({ | |
|
217 | + display: 'none', | |
|
218 | + 'pointer-events': 'none' | |
|
219 | + }); | |
|
220 | + $("body").prepend(overlayEl); | |
|
221 | + var overlay = $('#' + options.id); | |
|
222 | + | |
|
223 | + // Unless a custom z-index is set, ensure the overlay will be behind everything | |
|
224 | + if (overlay.css('z-index') == 'auto') overlay.css('z-index', overlayZBackground); | |
|
225 | + | |
|
226 | + // Override the default overlay height with the actual page height | |
|
227 | + var pageHeight = parseFloat($(document).height()); | |
|
228 | + overlay.height(pageHeight); | |
|
229 | + | |
|
230 | + // Add the first grid line so that we can measure it | |
|
231 | + overlay.append('<div id="' + options.id + '-horiz" class="horiz first-line">'); | |
|
232 | + | |
|
233 | + // Position off-screen and display to calculate height | |
|
234 | + var top = overlay.css("top"); | |
|
235 | + overlay.css({ | |
|
236 | + top: "-999px", | |
|
237 | + display: "block" | |
|
238 | + }); | |
|
239 | + | |
|
240 | + // Calculate the number of grid lines needed | |
|
241 | + var line = $('#' + options.id + '-horiz'), | |
|
242 | + lineHeight = line.outerHeight(); | |
|
243 | + | |
|
244 | + // Hide and reset top | |
|
245 | + overlay.css({ | |
|
246 | + display: "none", | |
|
247 | + top: top | |
|
248 | + }); | |
|
249 | + | |
|
250 | + // Break on zero line height | |
|
251 | + if (lineHeight <= 0) return true; | |
|
252 | + | |
|
253 | + // Add the remaining grid lines | |
|
254 | + var i, numGridLines = Math.floor(pageHeight / lineHeight); | |
|
255 | + for (i = numGridLines - 1; i >= 1; i--) { | |
|
256 | + overlay.append('<div class="horiz"></div>'); | |
|
257 | + } | |
|
258 | + | |
|
259 | + // vertical grid | |
|
260 | + overlay.append($('<div class="vert-container"></div>')); | |
|
261 | + var overlayVert = overlay.children('.vert-container'); | |
|
262 | + var gridWidth = overlay.width(); | |
|
263 | + overlayVert.css({width: gridWidth, position: 'absolute', top: 0}); | |
|
264 | + overlayVert.append('<div class="vert first-line"> </div>'); | |
|
265 | + | |
|
266 | + // 30 is an arbitrarily large number... | |
|
267 | + // can't calculate the margin width properly | |
|
268 | + for (i = 0; i < 30; i++) { | |
|
269 | + overlayVert.append('<div class="vert"> </div>'); | |
|
270 | + } | |
|
271 | + | |
|
272 | + overlayVert.children() | |
|
273 | + .height(pageHeight) | |
|
274 | + .css({display: 'inline-block'}); | |
|
275 | + | |
|
276 | + // Check for saved state | |
|
277 | + var overlayCookie = readCookie(options.cookiePrefix + options.id); | |
|
278 | + if (typeof overlayCookie == 'string') { | |
|
279 | + var state = overlayCookie.split(','); | |
|
280 | + state[2] = Number(state[2]); | |
|
281 | + if ((typeof state[2] == 'number') && !isNaN(state[2])) { | |
|
282 | + classNumber = state[2].toFixed(0); | |
|
283 | + overlay.addClass(options.classPrefix + classNumber); | |
|
284 | + } | |
|
285 | + if (state[1] == 'F') { | |
|
286 | + overlayZState = 'F'; | |
|
287 | + overlay.css('z-index', overlayZForeground); | |
|
288 | + } | |
|
289 | + if (state[0] == '1') { | |
|
290 | + overlayOn = true; | |
|
291 | + sticky = true; | |
|
292 | + showOverlay(); | |
|
293 | + } | |
|
294 | + } | |
|
295 | + else { | |
|
296 | + overlay.addClass(options.classPrefix + classNumber); | |
|
297 | + } | |
|
298 | + | |
|
299 | + // Keyboard controls | |
|
300 | + $(document).bind('keydown', keydownHandler); | |
|
301 | + $(document).bind('keyup', keyupHandler); | |
|
302 | + | |
|
303 | + /** | |
|
304 | + * Helpers | |
|
305 | + */ | |
|
306 | + | |
|
307 | + function getModifier(e) { | |
|
308 | + if (options.modifierKey == null) return true; // Bypass by default | |
|
309 | + var m = true; | |
|
310 | + switch(options.modifierKey) { | |
|
311 | + case 'ctrl': | |
|
312 | + m = (e.ctrlKey ? e.ctrlKey : false); | |
|
313 | + break; | |
|
314 | + | |
|
315 | + case 'alt': | |
|
316 | + m = (e.altKey ? e.altKey : false); | |
|
317 | + break; | |
|
318 | + | |
|
319 | + case 'shift': | |
|
320 | + m = (e.shiftKey ? e.shiftKey : false); | |
|
321 | + break; | |
|
322 | + } | |
|
323 | + return m; | |
|
324 | + } | |
|
325 | + | |
|
326 | + function getKey(e) { | |
|
327 | + var k = false, c = (e.keyCode ? e.keyCode : e.which); | |
|
328 | + // Handle keywords | |
|
329 | + if (c == 13) k = 'enter'; | |
|
330 | + // Handle letters | |
|
331 | + else k = String.fromCharCode(c).toLowerCase(); | |
|
332 | + return k; | |
|
333 | + } | |
|
334 | + | |
|
335 | + function saveState() { | |
|
336 | + createCookie(options.cookiePrefix + options.id, (sticky ? '1' : '0') + ',' + overlayZState + ',' + classNumber, 1); | |
|
337 | + } | |
|
338 | + | |
|
339 | + function showOverlay() { | |
|
340 | + overlay.show(); | |
|
341 | + overlayVert.css({width: overlay.width()}); | |
|
342 | + // hide any vertical blocks that aren't at the top of the viewport | |
|
343 | + overlayVert.children('.vert').each(function () { | |
|
344 | + $(this).css('display','inline-block'); | |
|
345 | + if ($(this).offset().top > 0) { | |
|
346 | + $(this).hide(); | |
|
347 | + } | |
|
348 | + }); | |
|
349 | + } | |
|
350 | + | |
|
351 | + /** | |
|
352 | + * Event handlers | |
|
353 | + */ | |
|
354 | + | |
|
355 | + function keydownHandler(e) { | |
|
356 | + var source = e.target.tagName.toLowerCase(); | |
|
357 | + if ((source == 'input') || (source == 'textarea') || (source == 'select')) return true; | |
|
358 | + var m = getModifier(e); | |
|
359 | + if (!m) return true; | |
|
360 | + var k = getKey(e); | |
|
361 | + if (!k) return true; | |
|
362 | + switch(k) { | |
|
363 | + case options.showGridKey: | |
|
364 | + if (!overlayOn) { | |
|
365 | + showOverlay(); | |
|
366 | + overlayOn = true; | |
|
367 | + } | |
|
368 | + else if (sticky) { | |
|
369 | + overlay.hide(); | |
|
370 | + overlayOn = false; | |
|
371 | + sticky = false; | |
|
372 | + saveState(); | |
|
373 | + } | |
|
374 | + break; | |
|
375 | + case options.holdGridKey: | |
|
376 | + if (overlayOn && !sticky) { | |
|
377 | + // Turn sticky overlay on | |
|
378 | + sticky = true; | |
|
379 | + saveState(); | |
|
380 | + } | |
|
381 | + break; | |
|
382 | + case options.foregroundKey: | |
|
383 | + if (overlayOn) { | |
|
384 | + // Toggle sticky overlay z-index | |
|
385 | + if (overlay.css('z-index') == overlayZForeground) { | |
|
386 | + overlay.css('z-index', overlayZBackground); | |
|
387 | + overlayZState = 'B'; | |
|
388 | + } | |
|
389 | + else { | |
|
390 | + overlay.css('z-index', overlayZForeground); | |
|
391 | + overlayZState = 'F'; | |
|
392 | + } | |
|
393 | + saveState(); | |
|
394 | + } | |
|
395 | + break; | |
|
396 | + case options.jumpGridsKey: | |
|
397 | + if (overlayOn && (options.numberOfGrids > 1)) { | |
|
398 | + // Cycle through the available grids | |
|
399 | + overlay.removeClass(options.classPrefix + classNumber); | |
|
400 | + classNumber++; | |
|
401 | + if (classNumber > options.numberOfGrids) classNumber = 1; | |
|
402 | + overlay.addClass(options.classPrefix + classNumber); | |
|
403 | + showOverlay(); | |
|
404 | + if (/webkit/.test( navigator.userAgent.toLowerCase() )) { | |
|
405 | + forceRepaint(); | |
|
406 | + } | |
|
407 | + saveState(); | |
|
408 | + } | |
|
409 | + break; | |
|
410 | + } | |
|
411 | + } | |
|
412 | + | |
|
413 | + function keyupHandler(e) { | |
|
414 | + var m = getModifier(e); | |
|
415 | + if (!m) return true; | |
|
416 | + var k = getKey(e); | |
|
417 | + if (!k) return true; | |
|
418 | + if ((k == options.showGridKey) && !sticky) { | |
|
419 | + overlay.hide(); | |
|
420 | + overlayOn = false; | |
|
421 | + } | |
|
422 | + } | |
|
423 | + | |
|
424 | + /** | |
|
425 | + * Cookie functions | |
|
426 | + * | |
|
427 | + * By Peter-Paul Koch: | |
|
428 | + * http://www.quirksmode.org/js/cookies.html | |
|
429 | + */ | |
|
430 | + function createCookie(name,value,days) { | |
|
431 | + if (days) { | |
|
432 | + var date = new Date(); | |
|
433 | + date.setTime(date.getTime()+(days*24*60*60*1000)); | |
|
434 | + var expires = "; expires="+date.toGMTString(); | |
|
435 | + } | |
|
436 | + else var expires = ""; | |
|
437 | + document.cookie = name+"="+value+expires+"; path=/"; | |
|
438 | + } | |
|
439 | + | |
|
440 | + function readCookie(name) { | |
|
441 | + var nameEQ = name + "="; | |
|
442 | + var ca = document.cookie.split(';'); | |
|
443 | + for(var i=0;i < ca.length;i++) { | |
|
444 | + var c = ca[i]; | |
|
445 | + while (c.charAt(0)==' ') c = c.substring(1,c.length); | |
|
446 | + if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length); | |
|
447 | + } | |
|
448 | + return null; | |
|
449 | + } | |
|
450 | + | |
|
451 | + function eraseCookie(name) { | |
|
452 | + createCookie(name,"",-1); | |
|
453 | + } | |
|
454 | + | |
|
455 | + /** | |
|
456 | + * Forces a repaint (because WebKit has issues) | |
|
457 | + * http://www.sitepoint.com/forums/showthread.php?p=4538763 | |
|
458 | + * http://www.phpied.com/the-new-game-show-will-it-reflow/ | |
|
459 | + */ | |
|
460 | + function forceRepaint() { | |
|
461 | + var ss = document.styleSheets[0]; | |
|
462 | + try { | |
|
463 | + ss.addRule('.xxxxxx', 'position: relative'); | |
|
464 | + ss.removeRule(ss.rules.length - 1); | |
|
465 | + } catch(e){} | |
|
466 | + } | |
|
467 | + | |
|
468 | +} | |
|
469 | + | |
|
470 | + | |
|
471 | +/** | |
|
472 | + * You can call hashgrid from your own code, but it's loaded here as | |
|
473 | + * an example for your convenience. | |
|
474 | + */ | |
|
475 | +$(document).ready(function() { | |
|
476 | + | |
|
477 | + var grid = new hashgrid({ | |
|
478 | + numberOfGrids: 2 | |
|
479 | + }); | |
|
480 | + | |
|
481 | +}); | |
|
482 | diff --git a/less/docs.less b/less/docs.less | |
|
483 | index 165ddb142019d6ec45aae1fa3fdbb3cbcea3bfdb..30b561118c290925a213d987691dfcbeafeb8f44 100644 | |
|
484 | --- a/less/docs.less | |
|
485 | +++ b/less/docs.less | |
|
486 | @@ -1,3 +1,10 @@ | |
|
487 | +body { | |
|
488 | + #gradient > .vertical-three-colors(#eee, #fff, 0.15, #fff); | |
|
489 | + background-attachment: fixed; | |
|
490 | + background-position: 0 40px; | |
|
491 | + position: relative; | |
|
492 | +} | |
|
493 | + | |
|
494 | // Give us some love | |
|
495 | header, | |
|
496 | section, | |
|
497 | @@ -77,3 +84,30 @@ aside { | |
|
498 | section { | |
|
499 | margin-bottom: 40px; | |
|
500 | } | |
|
501 | + | |
|
502 | +// Hashgrid grid | |
|
503 | +/** | |
|
504 | + * Grid | |
|
505 | + */ | |
|
506 | +#grid { | |
|
507 | + width: 980px; | |
|
508 | + position: absolute; | |
|
509 | + top: 0; | |
|
510 | + left: 50%; | |
|
511 | + margin-left: -490px; | |
|
512 | +} | |
|
513 | +#grid div.vert { | |
|
514 | + width: 39px; | |
|
515 | + border: solid darkturquoise; | |
|
516 | + border-width: 0 1px; | |
|
517 | + margin-right: 19px; | |
|
518 | +} | |
|
519 | +#grid div.vert.first-line { | |
|
520 | + margin-left: 19px; | |
|
521 | +} | |
|
522 | +#grid div.horiz { | |
|
523 | + height: 19px; | |
|
524 | + border-bottom: 1px dotted rgba(255,0,0,.25); | |
|
525 | + margin: 0; | |
|
526 | + padding: 0; | |
|
527 | +} | |
|
528 | diff --git a/less/scaffolding.less b/less/scaffolding.less | |
|
529 | index 2191d98b3f3f805b62eb3b60f1cb4f0be5bf1aa8..88bcf714a9f075cd7ba60033022f21ff95efc776 100644 | |
|
530 | --- a/less/scaffolding.less | |
|
531 | +++ b/less/scaffolding.less | |
|
532 | @@ -7,7 +7,7 @@ | |
|
533 | -------------------------------------------------- */ | |
|
534 | ||
|
535 | div.row { | |
|
536 | - .clearfix; | |
|
537 | + .clearfix(); | |
|
538 | div.span1 { .columns(1); } | |
|
539 | div.span2 { .columns(2); } | |
|
540 | div.span3 { .columns(3); } | |
|
541 | @@ -34,8 +34,6 @@ html, body { | |
|
542 | background-color: #fff; | |
|
543 | } | |
|
544 | body { | |
|
545 | - #gradient > .vertical-three-colors(#eee, #fff, 0.25, #fff); | |
|
546 | - background-attachment: fixed; | |
|
547 | margin: 0; | |
|
548 | .sans-serif(normal,14px,20px); | |
|
549 | color: @gray; | |
|
550 | diff --git a/readme.markdown b/readme.markdown | |
|
551 | index 36b357b31afdee5fffbeddeba3144ffbd98d9778..41966346963824f2ce5497b8275c3a15c2044ac9 100644 | |
|
552 | --- a/readme.markdown | |
|
553 | +++ b/readme.markdown | |
|
554 | @@ -1,13 +1,4 @@ | |
|
555 | TODOS | |
|
556 | ||
|
557 | -* Write "Using Twitter BP" section | |
|
558 | -** Two ways to use: LESS.js or compiled | |
|
559 | -** Not meant to be 100% bulletproof, but is 90% bulletproof (stats?) | |
|
560 | -** Advanced framework for fast prototyping, internal app development, bootstraping new websites | |
|
561 | -** Can be easily modified to provide more legacy support | |
|
562 | - | |
|
563 | -* Add grid examples back in | |
|
564 | * Cross browser checks? Show this anywhere? | |
|
565 | -* Add layouts section back in | |
|
566 | - | |
|
567 | -* Point JS libraries to public library links instead of within the repo | |
|
568 | \ No newline at end of file | |
|
569 | +* Add layouts section back in | |
|
570 | \ No newline at end of file |
This diff has been collapsed as it changes many lines, (1094 lines changed) Show them Hide them | |||
@@ -0,0 +1,1094 b'' | |||
|
1 | diff --git a/US Warszawa.jpg b/US Warszawa.jpg | |
|
2 | index 5a4b530a9322aad2b13d39a423a6a93146a09a29..b3b889566812a77f52376379e96d32d3db117150 | |
|
3 | GIT binary patch | |
|
4 | literal 85172 | |
|
5 | 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 | |
|
1093 | T!viJ;E(+{1YEXtu4BY<*Qm7~* | |
|
1094 |
@@ -0,0 +1,4 b'' | |||
|
1 | diff --git a/work-horus.xls b/file.xls | |
|
2 | similarity index 100% | |
|
3 | rename from work-horus.xls | |
|
4 | rename to file.xls |
|
1 | NO CONTENT: new file 100644 | |
The requested commit or file is too big and content was truncated. Show full diff |
|
1 | NO CONTENT: new file 100644 | |
The requested commit or file is too big and content was truncated. Show full diff |
|
1 | NO CONTENT: new file 100644 | |
The requested commit or file is too big and content was truncated. Show full diff |
|
1 | NO CONTENT: new file 100644 | |
The requested commit or file is too big and content was truncated. Show full diff |
|
1 | NO CONTENT: new file 100644 | |
The requested commit or file is too big and content was truncated. Show full diff |
|
1 | NO CONTENT: new file 100644 | |
The requested commit or file is too big and content was truncated. Show full diff |
|
1 | NO CONTENT: new file 100644 | |
The requested commit or file is too big and content was truncated. Show full diff |
|
1 | NO CONTENT: new file 100644 | |
The requested commit or file is too big and content was truncated. Show full diff |
@@ -1,457 +1,381 b'' | |||
|
1 | 1 | # -*- coding: utf-8 -*- |
|
2 | 2 | """ |
|
3 | 3 | rhodecode.controllers.changeset |
|
4 | 4 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|
5 | 5 | |
|
6 | 6 | changeset controller for pylons showoing changes beetween |
|
7 | 7 | revisions |
|
8 | 8 | |
|
9 | 9 | :created_on: Apr 25, 2010 |
|
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 | from collections import defaultdict |
|
29 | 29 | from webob.exc import HTTPForbidden, HTTPBadRequest |
|
30 | 30 | |
|
31 | 31 | from pylons import tmpl_context as c, url, request, response |
|
32 | 32 | from pylons.i18n.translation import _ |
|
33 | 33 | from pylons.controllers.util import redirect |
|
34 | 34 | from pylons.decorators import jsonify |
|
35 | 35 | |
|
36 | 36 | from rhodecode.lib.vcs.exceptions import RepositoryError, ChangesetError, \ |
|
37 | 37 | ChangesetDoesNotExistError |
|
38 | 38 | from rhodecode.lib.vcs.nodes import FileNode |
|
39 | 39 | |
|
40 | 40 | import rhodecode.lib.helpers as h |
|
41 | 41 | from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator |
|
42 | 42 | from rhodecode.lib.base import BaseRepoController, render |
|
43 | 43 | from rhodecode.lib.utils import action_logger |
|
44 | 44 | from rhodecode.lib.compat import OrderedDict |
|
45 | 45 | from rhodecode.lib import diffs |
|
46 | 46 | from rhodecode.model.db import ChangesetComment, ChangesetStatus |
|
47 | 47 | from rhodecode.model.comment import ChangesetCommentsModel |
|
48 | 48 | from rhodecode.model.changeset_status import ChangesetStatusModel |
|
49 | 49 | from rhodecode.model.meta import Session |
|
50 |
from rhodecode.lib.diffs import |
|
|
50 | from rhodecode.lib.diffs import LimitedDiffContainer | |
|
51 | 51 | from rhodecode.model.repo import RepoModel |
|
52 | 52 | from rhodecode.lib.exceptions import StatusChangeOnClosedPullRequestError |
|
53 | 53 | from rhodecode.lib.vcs.backends.base import EmptyChangeset |
|
54 | 54 | |
|
55 | 55 | log = logging.getLogger(__name__) |
|
56 | 56 | |
|
57 | 57 | |
|
58 | 58 | def _update_with_GET(params, GET): |
|
59 | 59 | for k in ['diff1', 'diff2', 'diff']: |
|
60 | 60 | params[k] += GET.getall(k) |
|
61 | 61 | |
|
62 | 62 | |
|
63 | 63 | def anchor_url(revision, path, GET): |
|
64 | 64 | fid = h.FID(revision, path) |
|
65 | 65 | return h.url.current(anchor=fid, **dict(GET)) |
|
66 | 66 | |
|
67 | 67 | |
|
68 | 68 | def get_ignore_ws(fid, GET): |
|
69 | 69 | ig_ws_global = GET.get('ignorews') |
|
70 | 70 | ig_ws = filter(lambda k: k.startswith('WS'), GET.getall(fid)) |
|
71 | 71 | if ig_ws: |
|
72 | 72 | try: |
|
73 | 73 | return int(ig_ws[0].split(':')[-1]) |
|
74 | 74 | except: |
|
75 | 75 | pass |
|
76 | 76 | return ig_ws_global |
|
77 | 77 | |
|
78 | 78 | |
|
79 | 79 | def _ignorews_url(GET, fileid=None): |
|
80 | 80 | fileid = str(fileid) if fileid else None |
|
81 | 81 | params = defaultdict(list) |
|
82 | 82 | _update_with_GET(params, GET) |
|
83 | 83 | lbl = _('show white space') |
|
84 | 84 | ig_ws = get_ignore_ws(fileid, GET) |
|
85 | 85 | ln_ctx = get_line_ctx(fileid, GET) |
|
86 | 86 | # global option |
|
87 | 87 | if fileid is None: |
|
88 | 88 | if ig_ws is None: |
|
89 | 89 | params['ignorews'] += [1] |
|
90 | 90 | lbl = _('ignore white space') |
|
91 | 91 | ctx_key = 'context' |
|
92 | 92 | ctx_val = ln_ctx |
|
93 | 93 | # per file options |
|
94 | 94 | else: |
|
95 | 95 | if ig_ws is None: |
|
96 | 96 | params[fileid] += ['WS:1'] |
|
97 | 97 | lbl = _('ignore white space') |
|
98 | 98 | |
|
99 | 99 | ctx_key = fileid |
|
100 | 100 | ctx_val = 'C:%s' % ln_ctx |
|
101 | 101 | # if we have passed in ln_ctx pass it along to our params |
|
102 | 102 | if ln_ctx: |
|
103 | 103 | params[ctx_key] += [ctx_val] |
|
104 | 104 | |
|
105 | 105 | params['anchor'] = fileid |
|
106 | 106 | img = h.image(h.url('/images/icons/text_strikethrough.png'), lbl, class_='icon') |
|
107 | 107 | return h.link_to(img, h.url.current(**params), title=lbl, class_='tooltip') |
|
108 | 108 | |
|
109 | 109 | |
|
110 | 110 | def get_line_ctx(fid, GET): |
|
111 | 111 | ln_ctx_global = GET.get('context') |
|
112 | if fid: | |
|
112 | 113 | ln_ctx = filter(lambda k: k.startswith('C'), GET.getall(fid)) |
|
114 | else: | |
|
115 | _ln_ctx = filter(lambda k: k.startswith('C'), GET) | |
|
116 | ln_ctx = GET.get(_ln_ctx[0]) if _ln_ctx else ln_ctx_global | |
|
117 | if ln_ctx: | |
|
118 | ln_ctx = [ln_ctx] | |
|
113 | 119 | |
|
114 | 120 | if ln_ctx: |
|
115 | 121 | retval = ln_ctx[0].split(':')[-1] |
|
116 | 122 | else: |
|
117 | 123 | retval = ln_ctx_global |
|
118 | 124 | |
|
119 | 125 | try: |
|
120 | 126 | return int(retval) |
|
121 | 127 | except: |
|
122 | return | |
|
128 | return 3 | |
|
123 | 129 | |
|
124 | 130 | |
|
125 | 131 | def _context_url(GET, fileid=None): |
|
126 | 132 | """ |
|
127 | 133 | Generates url for context lines |
|
128 | 134 | |
|
129 | 135 | :param fileid: |
|
130 | 136 | """ |
|
131 | 137 | |
|
132 | 138 | fileid = str(fileid) if fileid else None |
|
133 | 139 | ig_ws = get_ignore_ws(fileid, GET) |
|
134 | 140 | ln_ctx = (get_line_ctx(fileid, GET) or 3) * 2 |
|
135 | 141 | |
|
136 | 142 | params = defaultdict(list) |
|
137 | 143 | _update_with_GET(params, GET) |
|
138 | 144 | |
|
139 | 145 | # global option |
|
140 | 146 | if fileid is None: |
|
141 | 147 | if ln_ctx > 0: |
|
142 | 148 | params['context'] += [ln_ctx] |
|
143 | 149 | |
|
144 | 150 | if ig_ws: |
|
145 | 151 | ig_ws_key = 'ignorews' |
|
146 | 152 | ig_ws_val = 1 |
|
147 | 153 | |
|
148 | 154 | # per file option |
|
149 | 155 | else: |
|
150 | 156 | params[fileid] += ['C:%s' % ln_ctx] |
|
151 | 157 | ig_ws_key = fileid |
|
152 | 158 | ig_ws_val = 'WS:%s' % 1 |
|
153 | 159 | |
|
154 | 160 | if ig_ws: |
|
155 | 161 | params[ig_ws_key] += [ig_ws_val] |
|
156 | 162 | |
|
157 | 163 | lbl = _('%s line context') % ln_ctx |
|
158 | 164 | |
|
159 | 165 | params['anchor'] = fileid |
|
160 | 166 | img = h.image(h.url('/images/icons/table_add.png'), lbl, class_='icon') |
|
161 | 167 | return h.link_to(img, h.url.current(**params), title=lbl, class_='tooltip') |
|
162 | 168 | |
|
163 | 169 | |
|
164 | 170 | class ChangesetController(BaseRepoController): |
|
165 | 171 | |
|
166 | 172 | @LoginRequired() |
|
167 | 173 | @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', |
|
168 | 174 | 'repository.admin') |
|
169 | 175 | def __before__(self): |
|
170 | 176 | super(ChangesetController, self).__before__() |
|
171 | 177 | c.affected_files_cut_off = 60 |
|
172 | 178 | repo_model = RepoModel() |
|
173 | 179 | c.users_array = repo_model.get_users_js() |
|
174 | 180 | c.users_groups_array = repo_model.get_users_groups_js() |
|
175 | 181 | |
|
176 | 182 | def index(self, revision): |
|
177 | ||
|
183 | method = request.GET.get('diff', 'show') | |
|
178 | 184 | c.anchor_url = anchor_url |
|
179 | 185 | c.ignorews_url = _ignorews_url |
|
180 | 186 | c.context_url = _context_url |
|
181 | 187 | limit_off = request.GET.get('fulldiff') |
|
182 | 188 | #get ranges of revisions if preset |
|
183 | 189 | rev_range = revision.split('...')[:2] |
|
184 | 190 | enable_comments = True |
|
185 | 191 | try: |
|
186 | 192 | if len(rev_range) == 2: |
|
187 | 193 | enable_comments = False |
|
188 | 194 | rev_start = rev_range[0] |
|
189 | 195 | rev_end = rev_range[1] |
|
190 | 196 | rev_ranges = c.rhodecode_repo.get_changesets(start=rev_start, |
|
191 | 197 | end=rev_end) |
|
192 | 198 | else: |
|
193 | 199 | rev_ranges = [c.rhodecode_repo.get_changeset(revision)] |
|
194 | 200 | |
|
195 | 201 | c.cs_ranges = list(rev_ranges) |
|
196 | 202 | if not c.cs_ranges: |
|
197 | 203 | raise RepositoryError('Changeset range returned empty result') |
|
198 | 204 | |
|
199 | 205 | except (RepositoryError, ChangesetDoesNotExistError, Exception), e: |
|
200 | 206 | log.error(traceback.format_exc()) |
|
201 | 207 | h.flash(str(e), category='warning') |
|
202 | 208 | return redirect(url('home')) |
|
203 | 209 | |
|
204 | 210 | c.changes = OrderedDict() |
|
205 | 211 | |
|
206 | 212 | c.lines_added = 0 # count of lines added |
|
207 | 213 | c.lines_deleted = 0 # count of lines removes |
|
208 | 214 | |
|
209 | cumulative_diff = 0 | |
|
210 | c.cut_off = False # defines if cut off limit is reached | |
|
211 | 215 | c.changeset_statuses = ChangesetStatus.STATUSES |
|
212 | 216 | c.comments = [] |
|
213 | 217 | c.statuses = [] |
|
214 | 218 | c.inline_comments = [] |
|
215 | 219 | c.inline_cnt = 0 |
|
220 | ||
|
216 | 221 | # Iterate over ranges (default changeset view is always one changeset) |
|
217 | 222 | for changeset in c.cs_ranges: |
|
218 | ||
|
223 | inlines = [] | |
|
224 | if method == 'show': | |
|
219 | 225 | c.statuses.extend([ChangesetStatusModel()\ |
|
220 | 226 | .get_status(c.rhodecode_db_repo.repo_id, |
|
221 | 227 | changeset.raw_id)]) |
|
222 | 228 | |
|
223 | 229 | c.comments.extend(ChangesetCommentsModel()\ |
|
224 | 230 | .get_comments(c.rhodecode_db_repo.repo_id, |
|
225 | 231 | revision=changeset.raw_id)) |
|
226 | 232 | inlines = ChangesetCommentsModel()\ |
|
227 | 233 | .get_inline_comments(c.rhodecode_db_repo.repo_id, |
|
228 | 234 | revision=changeset.raw_id) |
|
229 | 235 | c.inline_comments.extend(inlines) |
|
236 | ||
|
230 | 237 | c.changes[changeset.raw_id] = [] |
|
231 | try: | |
|
232 |
|
|
|
233 | except IndexError: | |
|
234 | changeset_parent = None | |
|
238 | ||
|
239 | cs2 = changeset.raw_id | |
|
240 | cs1 = changeset.parents[0].raw_id if changeset.parents else EmptyChangeset() | |
|
241 | context_lcl = get_line_ctx('', request.GET) | |
|
242 | ign_whitespace_lcl = ign_whitespace_lcl = get_ignore_ws('', request.GET) | |
|
235 | 243 | |
|
236 | #================================================================== | |
|
237 | # ADDED FILES | |
|
238 | #================================================================== | |
|
239 | for node in changeset.added: | |
|
240 | fid = h.FID(revision, node.path) | |
|
241 | line_context_lcl = get_line_ctx(fid, request.GET) | |
|
242 | ign_whitespace_lcl = get_ignore_ws(fid, request.GET) | |
|
243 | lim = self.cut_off_limit | |
|
244 | if cumulative_diff > self.cut_off_limit: | |
|
245 | lim = -1 if limit_off is None else None | |
|
246 | size, cs1, cs2, diff, st = wrapped_diff( | |
|
247 | filenode_old=None, | |
|
248 | filenode_new=node, | |
|
249 | cut_off_limit=lim, | |
|
250 | ignore_whitespace=ign_whitespace_lcl, | |
|
251 | line_context=line_context_lcl, | |
|
252 | enable_comments=enable_comments | |
|
253 | ) | |
|
254 | cumulative_diff += size | |
|
244 | _diff = c.rhodecode_repo.get_diff(cs1, cs2, | |
|
245 | ignore_whitespace=ign_whitespace_lcl, context=context_lcl) | |
|
246 | diff_limit = self.cut_off_limit if not limit_off else None | |
|
247 | diff_processor = diffs.DiffProcessor(_diff, | |
|
248 | vcs=c.rhodecode_repo.alias, | |
|
249 | format='gitdiff', | |
|
250 | diff_limit=diff_limit) | |
|
251 | cs_changes = OrderedDict() | |
|
252 | if method == 'show': | |
|
253 | _parsed = diff_processor.prepare() | |
|
254 | c.limited_diff = False | |
|
255 | if isinstance(_parsed, LimitedDiffContainer): | |
|
256 | c.limited_diff = True | |
|
257 | for f in _parsed: | |
|
258 | st = f['stats'] | |
|
259 | if st[0] != 'b': | |
|
255 | 260 | c.lines_added += st[0] |
|
256 | 261 | c.lines_deleted += st[1] |
|
257 |
|
|
|
258 | ('added', node, diff, cs1, cs2, st) | |
|
259 | ) | |
|
260 | ||
|
261 | #================================================================== | |
|
262 | # CHANGED FILES | |
|
263 | #================================================================== | |
|
264 | for node in changeset.changed: | |
|
265 | try: | |
|
266 | filenode_old = changeset_parent.get_node(node.path) | |
|
267 | except ChangesetError: | |
|
268 | log.warning('Unable to fetch parent node for diff') | |
|
269 | filenode_old = FileNode(node.path, '', EmptyChangeset()) | |
|
270 | ||
|
271 | fid = h.FID(revision, node.path) | |
|
272 | line_context_lcl = get_line_ctx(fid, request.GET) | |
|
273 | ign_whitespace_lcl = get_ignore_ws(fid, request.GET) | |
|
274 | lim = self.cut_off_limit | |
|
275 | if cumulative_diff > self.cut_off_limit: | |
|
276 | lim = -1 if limit_off is None else None | |
|
277 | size, cs1, cs2, diff, st = wrapped_diff( | |
|
278 | filenode_old=filenode_old, | |
|
279 | filenode_new=node, | |
|
280 | cut_off_limit=lim, | |
|
281 | ignore_whitespace=ign_whitespace_lcl, | |
|
282 | line_context=line_context_lcl, | |
|
283 | enable_comments=enable_comments | |
|
284 | ) | |
|
285 | cumulative_diff += size | |
|
286 | c.lines_added += st[0] | |
|
287 | c.lines_deleted += st[1] | |
|
288 | c.changes[changeset.raw_id].append( | |
|
289 | ('changed', node, diff, cs1, cs2, st) | |
|
290 | ) | |
|
291 | #================================================================== | |
|
292 | # REMOVED FILES | |
|
293 | #================================================================== | |
|
294 | for node in changeset.removed: | |
|
295 | c.changes[changeset.raw_id].append( | |
|
296 | ('removed', node, None, None, None, (0, 0)) | |
|
297 | ) | |
|
262 | fid = h.FID(changeset.raw_id, f['filename']) | |
|
263 | diff = diff_processor.as_html(enable_comments=enable_comments, | |
|
264 | parsed_lines=[f]) | |
|
265 | cs_changes[fid] = [cs1, cs2, f['operation'], f['filename'], | |
|
266 | diff, st] | |
|
267 | else: | |
|
268 | # downloads/raw we only need RAW diff nothing else | |
|
269 | diff = diff_processor.as_raw() | |
|
270 | cs_changes[''] = [None, None, None, None, diff, None] | |
|
271 | c.changes[changeset.raw_id] = cs_changes | |
|
298 | 272 | |
|
299 | 273 | # count inline comments |
|
300 | 274 | for __, lines in c.inline_comments: |
|
301 | 275 | for comments in lines.values(): |
|
302 | 276 | c.inline_cnt += len(comments) |
|
303 | 277 | |
|
304 | 278 | if len(c.cs_ranges) == 1: |
|
305 | 279 | c.changeset = c.cs_ranges[0] |
|
306 | c.changes = c.changes[c.changeset.raw_id] | |
|
307 | ||
|
280 | c.parent_tmpl = ''.join(['# Parent %s\n' % x.raw_id | |
|
281 | for x in c.changeset.parents]) | |
|
282 | if method == 'download': | |
|
283 | response.content_type = 'text/plain' | |
|
284 | response.content_disposition = 'attachment; filename=%s.patch' \ | |
|
285 | % revision | |
|
286 | return render('changeset/raw_changeset.html') | |
|
287 | elif method == 'raw': | |
|
288 | response.content_type = 'text/plain' | |
|
289 | return render('changeset/raw_changeset.html') | |
|
290 | elif method == 'show': | |
|
291 | if len(c.cs_ranges) == 1: | |
|
308 | 292 | return render('changeset/changeset.html') |
|
309 | 293 | else: |
|
310 | 294 | return render('changeset/changeset_range.html') |
|
311 | 295 | |
|
312 | 296 | def raw_changeset(self, revision): |
|
313 | ||
|
314 | method = request.GET.get('diff', 'show') | |
|
315 | ignore_whitespace = request.GET.get('ignorews') == '1' | |
|
316 | line_context = request.GET.get('context', 3) | |
|
317 | try: | |
|
318 | c.scm_type = c.rhodecode_repo.alias | |
|
319 | c.changeset = c.rhodecode_repo.get_changeset(revision) | |
|
320 | except RepositoryError: | |
|
321 | log.error(traceback.format_exc()) | |
|
322 | return redirect(url('home')) | |
|
323 | else: | |
|
324 | try: | |
|
325 | c.changeset_parent = c.changeset.parents[0] | |
|
326 | except IndexError: | |
|
327 | c.changeset_parent = None | |
|
328 | c.changes = [] | |
|
329 | ||
|
330 | for node in c.changeset.added: | |
|
331 | filenode_old = FileNode(node.path, '') | |
|
332 | if filenode_old.is_binary or node.is_binary: | |
|
333 | diff = _('binary file') + '\n' | |
|
334 | else: | |
|
335 | f_gitdiff = diffs.get_gitdiff(filenode_old, node, | |
|
336 | ignore_whitespace=ignore_whitespace, | |
|
337 | context=line_context) | |
|
338 | diff = diffs.DiffProcessor(f_gitdiff, | |
|
339 | format='gitdiff').raw_diff() | |
|
340 | ||
|
341 | cs1 = None | |
|
342 | cs2 = node.changeset.raw_id | |
|
343 | c.changes.append(('added', node, diff, cs1, cs2)) | |
|
344 | ||
|
345 | for node in c.changeset.changed: | |
|
346 | filenode_old = c.changeset_parent.get_node(node.path) | |
|
347 | if filenode_old.is_binary or node.is_binary: | |
|
348 | diff = _('binary file') | |
|
349 | else: | |
|
350 | f_gitdiff = diffs.get_gitdiff(filenode_old, node, | |
|
351 | ignore_whitespace=ignore_whitespace, | |
|
352 | context=line_context) | |
|
353 | diff = diffs.DiffProcessor(f_gitdiff, | |
|
354 | format='gitdiff').raw_diff() | |
|
355 | ||
|
356 | cs1 = filenode_old.changeset.raw_id | |
|
357 | cs2 = node.changeset.raw_id | |
|
358 | c.changes.append(('changed', node, diff, cs1, cs2)) | |
|
359 | ||
|
360 | response.content_type = 'text/plain' | |
|
361 | ||
|
362 | if method == 'download': | |
|
363 | response.content_disposition = 'attachment; filename=%s.patch' \ | |
|
364 | % revision | |
|
365 | ||
|
366 | c.parent_tmpl = ''.join(['# Parent %s\n' % x.raw_id | |
|
367 | for x in c.changeset.parents]) | |
|
368 | ||
|
369 | c.diffs = '' | |
|
370 | for x in c.changes: | |
|
371 | c.diffs += x[2] | |
|
372 | ||
|
373 | return render('changeset/raw_changeset.html') | |
|
297 | return self.index(revision) | |
|
374 | 298 | |
|
375 | 299 | @jsonify |
|
376 | 300 | def comment(self, repo_name, revision): |
|
377 | 301 | status = request.POST.get('changeset_status') |
|
378 | 302 | change_status = request.POST.get('change_changeset_status') |
|
379 | 303 | text = request.POST.get('text') |
|
380 | 304 | if status and change_status: |
|
381 | 305 | text = text or (_('Status change -> %s') |
|
382 | 306 | % ChangesetStatus.get_status_lbl(status)) |
|
383 | 307 | |
|
384 | 308 | comm = ChangesetCommentsModel().create( |
|
385 | 309 | text=text, |
|
386 | 310 | repo=c.rhodecode_db_repo.repo_id, |
|
387 | 311 | user=c.rhodecode_user.user_id, |
|
388 | 312 | revision=revision, |
|
389 | 313 | f_path=request.POST.get('f_path'), |
|
390 | 314 | line_no=request.POST.get('line'), |
|
391 | 315 | status_change=(ChangesetStatus.get_status_lbl(status) |
|
392 | 316 | if status and change_status else None) |
|
393 | 317 | ) |
|
394 | 318 | |
|
395 | 319 | # get status if set ! |
|
396 | 320 | if status and change_status: |
|
397 | 321 | # if latest status was from pull request and it's closed |
|
398 | 322 | # disallow changing status ! |
|
399 | 323 | # dont_allow_on_closed_pull_request = True ! |
|
400 | 324 | |
|
401 | 325 | try: |
|
402 | 326 | ChangesetStatusModel().set_status( |
|
403 | 327 | c.rhodecode_db_repo.repo_id, |
|
404 | 328 | status, |
|
405 | 329 | c.rhodecode_user.user_id, |
|
406 | 330 | comm, |
|
407 | 331 | revision=revision, |
|
408 | 332 | dont_allow_on_closed_pull_request=True |
|
409 | 333 | ) |
|
410 | 334 | except StatusChangeOnClosedPullRequestError: |
|
411 | 335 | log.error(traceback.format_exc()) |
|
412 | 336 | msg = _('Changing status on a changeset associated with' |
|
413 | 337 | 'a closed pull request is not allowed') |
|
414 | 338 | h.flash(msg, category='warning') |
|
415 | 339 | return redirect(h.url('changeset_home', repo_name=repo_name, |
|
416 | 340 | revision=revision)) |
|
417 | 341 | action_logger(self.rhodecode_user, |
|
418 | 342 | 'user_commented_revision:%s' % revision, |
|
419 | 343 | c.rhodecode_db_repo, self.ip_addr, self.sa) |
|
420 | 344 | |
|
421 | 345 | Session().commit() |
|
422 | 346 | |
|
423 | 347 | if not request.environ.get('HTTP_X_PARTIAL_XHR'): |
|
424 | 348 | return redirect(h.url('changeset_home', repo_name=repo_name, |
|
425 | 349 | revision=revision)) |
|
426 | 350 | |
|
427 | 351 | data = { |
|
428 | 352 | 'target_id': h.safeid(h.safe_unicode(request.POST.get('f_path'))), |
|
429 | 353 | } |
|
430 | 354 | if comm: |
|
431 | 355 | c.co = comm |
|
432 | 356 | data.update(comm.get_dict()) |
|
433 | 357 | data.update({'rendered_text': |
|
434 | 358 | render('changeset/changeset_comment_block.html')}) |
|
435 | 359 | |
|
436 | 360 | return data |
|
437 | 361 | |
|
438 | 362 | @jsonify |
|
439 | 363 | def delete_comment(self, repo_name, comment_id): |
|
440 | 364 | co = ChangesetComment.get(comment_id) |
|
441 | 365 | owner = lambda: co.author.user_id == c.rhodecode_user.user_id |
|
442 | 366 | if h.HasPermissionAny('hg.admin', 'repository.admin')() or owner: |
|
443 | 367 | ChangesetCommentsModel().delete(comment=co) |
|
444 | 368 | Session().commit() |
|
445 | 369 | return True |
|
446 | 370 | else: |
|
447 | 371 | raise HTTPForbidden() |
|
448 | 372 | |
|
449 | 373 | @jsonify |
|
450 | 374 | def changeset_info(self, repo_name, revision): |
|
451 | 375 | if request.is_xhr: |
|
452 | 376 | try: |
|
453 | 377 | return c.rhodecode_repo.get_changeset(revision) |
|
454 | 378 | except ChangesetDoesNotExistError, e: |
|
455 | 379 | return EmptyChangeset(message=str(e)) |
|
456 | 380 | else: |
|
457 | 381 | raise HTTPBadRequest() |
@@ -1,148 +1,148 b'' | |||
|
1 | 1 | # -*- coding: utf-8 -*- |
|
2 | 2 | """ |
|
3 | 3 | rhodecode.controllers.compare |
|
4 | 4 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|
5 | 5 | |
|
6 | 6 | compare controller for pylons showoing 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.utils2 import str2bool |
|
44 | 44 | |
|
45 | 45 | log = logging.getLogger(__name__) |
|
46 | 46 | |
|
47 | 47 | |
|
48 | 48 | class CompareController(BaseRepoController): |
|
49 | 49 | |
|
50 | 50 | @LoginRequired() |
|
51 | 51 | @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', |
|
52 | 52 | 'repository.admin') |
|
53 | 53 | def __before__(self): |
|
54 | 54 | super(CompareController, self).__before__() |
|
55 | 55 | |
|
56 | 56 | def __get_cs_or_redirect(self, rev, repo, redirect_after=True, |
|
57 | 57 | partial=False): |
|
58 | 58 | """ |
|
59 | 59 | Safe way to get changeset if error occur it redirects to changeset with |
|
60 | 60 | proper message. If partial is set then don't do redirect raise Exception |
|
61 | 61 | instead |
|
62 | 62 | |
|
63 | 63 | :param rev: revision to fetch |
|
64 | 64 | :param repo: repo instance |
|
65 | 65 | """ |
|
66 | 66 | |
|
67 | 67 | try: |
|
68 | 68 | type_, rev = rev |
|
69 | 69 | return repo.scm_instance.get_changeset(rev) |
|
70 | 70 | except EmptyRepositoryError, e: |
|
71 | 71 | if not redirect_after: |
|
72 | 72 | return None |
|
73 | 73 | h.flash(h.literal(_('There are no changesets yet')), |
|
74 | 74 | category='warning') |
|
75 | 75 | redirect(url('summary_home', repo_name=repo.repo_name)) |
|
76 | 76 | |
|
77 | 77 | except RepositoryError, e: |
|
78 | 78 | log.error(traceback.format_exc()) |
|
79 | 79 | h.flash(str(e), category='warning') |
|
80 | 80 | if not partial: |
|
81 | 81 | redirect(h.url('summary_home', repo_name=repo.repo_name)) |
|
82 | 82 | raise HTTPBadRequest() |
|
83 | 83 | |
|
84 | 84 | def index(self, org_ref_type, org_ref, other_ref_type, other_ref): |
|
85 | 85 | |
|
86 | 86 | org_repo = c.rhodecode_db_repo.repo_name |
|
87 | 87 | org_ref = (org_ref_type, org_ref) |
|
88 | 88 | other_ref = (other_ref_type, other_ref) |
|
89 | 89 | other_repo = request.GET.get('repo', org_repo) |
|
90 | 90 | bundle_compare = str2bool(request.GET.get('bundle', True)) |
|
91 | 91 | |
|
92 | 92 | c.swap_url = h.url('compare_url', repo_name=other_repo, |
|
93 | 93 | org_ref_type=other_ref[0], org_ref=other_ref[1], |
|
94 | 94 | other_ref_type=org_ref[0], other_ref=org_ref[1], |
|
95 | 95 | repo=org_repo, as_form=request.GET.get('as_form'), |
|
96 | 96 | bundle=bundle_compare) |
|
97 | 97 | |
|
98 | 98 | c.org_repo = org_repo = Repository.get_by_repo_name(org_repo) |
|
99 | 99 | c.other_repo = other_repo = Repository.get_by_repo_name(other_repo) |
|
100 | 100 | |
|
101 | 101 | if c.org_repo is None or c.other_repo is None: |
|
102 | 102 | log.error('Could not found repo %s or %s' % (org_repo, other_repo)) |
|
103 | 103 | raise HTTPNotFound |
|
104 | 104 | |
|
105 | 105 | if c.org_repo.scm_instance.alias != 'hg': |
|
106 | 106 | log.error('Review not available for GIT REPOS') |
|
107 | 107 | raise HTTPNotFound |
|
108 | 108 | partial = request.environ.get('HTTP_X_PARTIAL_XHR') |
|
109 | 109 | self.__get_cs_or_redirect(rev=org_ref, repo=org_repo, partial=partial) |
|
110 | 110 | self.__get_cs_or_redirect(rev=other_ref, repo=other_repo, partial=partial) |
|
111 | 111 | |
|
112 | 112 | c.cs_ranges, discovery_data = PullRequestModel().get_compare_data( |
|
113 | 113 | org_repo, org_ref, other_repo, other_ref |
|
114 | 114 | ) |
|
115 | 115 | |
|
116 | 116 | c.statuses = c.rhodecode_db_repo.statuses([x.raw_id for x in |
|
117 | 117 | c.cs_ranges]) |
|
118 | 118 | c.target_repo = c.repo_name |
|
119 | 119 | # defines that we need hidden inputs with changesets |
|
120 | 120 | c.as_form = request.GET.get('as_form', False) |
|
121 | 121 | if partial: |
|
122 | 122 | return render('compare/compare_cs.html') |
|
123 | 123 | |
|
124 | 124 | if not bundle_compare and c.cs_ranges: |
|
125 | 125 | # case we want a simple diff without incoming changesets, just |
|
126 | 126 | # for review purposes. Make the diff on the forked repo, with |
|
127 | 127 | # revision that is common ancestor |
|
128 | 128 | other_ref = ('rev', c.cs_ranges[-1].parents[0].raw_id) |
|
129 | 129 | other_repo = org_repo |
|
130 | 130 | |
|
131 | 131 | c.org_ref = org_ref[1] |
|
132 | 132 | c.other_ref = other_ref[1] |
|
133 | 133 | |
|
134 | 134 | _diff = diffs.differ(other_repo, other_ref, org_repo, org_ref, |
|
135 | 135 | discovery_data, bundle_compare=bundle_compare) |
|
136 | 136 | diff_processor = diffs.DiffProcessor(_diff, format='gitdiff') |
|
137 | 137 | _parsed = diff_processor.prepare() |
|
138 | 138 | |
|
139 | 139 | c.files = [] |
|
140 | 140 | c.changes = {} |
|
141 | 141 | |
|
142 | 142 | for f in _parsed: |
|
143 | 143 | fid = h.FID('', f['filename']) |
|
144 | 144 | c.files.append([fid, f['operation'], f['filename'], f['stats']]) |
|
145 |
diff = diff_processor.as_html(enable_comments=False, d |
|
|
145 | diff = diff_processor.as_html(enable_comments=False, parsed_lines=[f]) | |
|
146 | 146 | c.changes[fid] = [f['operation'], f['filename'], diff] |
|
147 | 147 | |
|
148 | 148 | return render('compare/compare_diff.html') |
@@ -1,556 +1,574 b'' | |||
|
1 | 1 | # -*- coding: utf-8 -*- |
|
2 | 2 | """ |
|
3 | 3 | rhodecode.controllers.files |
|
4 | 4 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|
5 | 5 | |
|
6 | 6 | Files controller for RhodeCode |
|
7 | 7 | |
|
8 | 8 | :created_on: Apr 21, 2010 |
|
9 | 9 | :author: marcink |
|
10 | 10 | :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com> |
|
11 | 11 | :license: GPLv3, see COPYING for more details. |
|
12 | 12 | """ |
|
13 | 13 | # This program is free software: you can redistribute it and/or modify |
|
14 | 14 | # it under the terms of the GNU General Public License as published by |
|
15 | 15 | # the Free Software Foundation, either version 3 of the License, or |
|
16 | 16 | # (at your option) any later version. |
|
17 | 17 | # |
|
18 | 18 | # This program is distributed in the hope that it will be useful, |
|
19 | 19 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
20 | 20 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
21 | 21 | # GNU General Public License for more details. |
|
22 | 22 | # |
|
23 | 23 | # You should have received a copy of the GNU General Public License |
|
24 | 24 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
25 | 25 | from __future__ import with_statement |
|
26 | 26 | import os |
|
27 | 27 | import logging |
|
28 | 28 | import traceback |
|
29 | 29 | import tempfile |
|
30 | 30 | |
|
31 | 31 | from pylons import request, response, tmpl_context as c, url |
|
32 | 32 | from pylons.i18n.translation import _ |
|
33 | 33 | from pylons.controllers.util import redirect |
|
34 | 34 | from pylons.decorators import jsonify |
|
35 | 35 | |
|
36 | 36 | from rhodecode.lib import diffs |
|
37 | 37 | from rhodecode.lib import helpers as h |
|
38 | 38 | |
|
39 | 39 | from rhodecode.lib.compat import OrderedDict |
|
40 | 40 | from rhodecode.lib.utils2 import convert_line_endings, detect_mode, safe_str,\ |
|
41 | 41 | str2bool |
|
42 | 42 | from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator |
|
43 | 43 | from rhodecode.lib.base import BaseRepoController, render |
|
44 | 44 | from rhodecode.lib.vcs.backends.base import EmptyChangeset |
|
45 | 45 | from rhodecode.lib.vcs.conf import settings |
|
46 | 46 | from rhodecode.lib.vcs.exceptions import RepositoryError, \ |
|
47 | 47 | ChangesetDoesNotExistError, EmptyRepositoryError, \ |
|
48 | 48 | ImproperArchiveTypeError, VCSError, NodeAlreadyExistsError,\ |
|
49 | 49 | NodeDoesNotExistError, ChangesetError |
|
50 | 50 | from rhodecode.lib.vcs.nodes import FileNode |
|
51 | 51 | |
|
52 | 52 | from rhodecode.model.repo import RepoModel |
|
53 | 53 | from rhodecode.model.scm import ScmModel |
|
54 | 54 | from rhodecode.model.db import Repository |
|
55 | 55 | |
|
56 | 56 | from rhodecode.controllers.changeset import anchor_url, _ignorews_url,\ |
|
57 | 57 | _context_url, get_line_ctx, get_ignore_ws |
|
58 | 58 | |
|
59 | 59 | |
|
60 | 60 | log = logging.getLogger(__name__) |
|
61 | 61 | |
|
62 | 62 | |
|
63 | 63 | class FilesController(BaseRepoController): |
|
64 | 64 | |
|
65 | 65 | def __before__(self): |
|
66 | 66 | super(FilesController, self).__before__() |
|
67 | 67 | c.cut_off_limit = self.cut_off_limit |
|
68 | 68 | |
|
69 | 69 | def __get_cs_or_redirect(self, rev, repo_name, redirect_after=True): |
|
70 | 70 | """ |
|
71 | 71 | Safe way to get changeset if error occur it redirects to tip with |
|
72 | 72 | proper message |
|
73 | 73 | |
|
74 | 74 | :param rev: revision to fetch |
|
75 | 75 | :param repo_name: repo name to redirect after |
|
76 | 76 | """ |
|
77 | 77 | |
|
78 | 78 | try: |
|
79 | 79 | return c.rhodecode_repo.get_changeset(rev) |
|
80 | 80 | except EmptyRepositoryError, e: |
|
81 | 81 | if not redirect_after: |
|
82 | 82 | return None |
|
83 | 83 | url_ = url('files_add_home', |
|
84 | 84 | repo_name=c.repo_name, |
|
85 | 85 | revision=0, f_path='') |
|
86 | 86 | add_new = '<a href="%s">[%s]</a>' % (url_, _('click here to add new file')) |
|
87 | 87 | h.flash(h.literal(_('There are no files yet %s') % add_new), |
|
88 | 88 | category='warning') |
|
89 | 89 | redirect(h.url('summary_home', repo_name=repo_name)) |
|
90 | 90 | |
|
91 | 91 | except RepositoryError, e: |
|
92 | 92 | h.flash(str(e), category='warning') |
|
93 | 93 | redirect(h.url('files_home', repo_name=repo_name, revision='tip')) |
|
94 | 94 | |
|
95 | 95 | def __get_filenode_or_redirect(self, repo_name, cs, path): |
|
96 | 96 | """ |
|
97 | 97 | Returns file_node, if error occurs or given path is directory, |
|
98 | 98 | it'll redirect to top level path |
|
99 | 99 | |
|
100 | 100 | :param repo_name: repo_name |
|
101 | 101 | :param cs: given changeset |
|
102 | 102 | :param path: path to lookup |
|
103 | 103 | """ |
|
104 | 104 | |
|
105 | 105 | try: |
|
106 | 106 | file_node = cs.get_node(path) |
|
107 | 107 | if file_node.is_dir(): |
|
108 | 108 | raise RepositoryError('given path is a directory') |
|
109 | 109 | except RepositoryError, e: |
|
110 | 110 | h.flash(str(e), category='warning') |
|
111 | 111 | redirect(h.url('files_home', repo_name=repo_name, |
|
112 | 112 | revision=cs.raw_id)) |
|
113 | 113 | |
|
114 | 114 | return file_node |
|
115 | 115 | |
|
116 | 116 | @LoginRequired() |
|
117 | 117 | @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', |
|
118 | 118 | 'repository.admin') |
|
119 | 119 | def index(self, repo_name, revision, f_path, annotate=False): |
|
120 | 120 | # redirect to given revision from form if given |
|
121 | 121 | post_revision = request.POST.get('at_rev', None) |
|
122 | 122 | if post_revision: |
|
123 | 123 | cs = self.__get_cs_or_redirect(post_revision, repo_name) |
|
124 | 124 | redirect(url('files_home', repo_name=c.repo_name, |
|
125 | 125 | revision=cs.raw_id, f_path=f_path)) |
|
126 | 126 | |
|
127 | 127 | c.changeset = self.__get_cs_or_redirect(revision, repo_name) |
|
128 | 128 | c.branch = request.GET.get('branch', None) |
|
129 | 129 | c.f_path = f_path |
|
130 | 130 | c.annotate = annotate |
|
131 | 131 | cur_rev = c.changeset.revision |
|
132 | 132 | |
|
133 | 133 | # prev link |
|
134 | 134 | try: |
|
135 | 135 | prev_rev = c.rhodecode_repo.get_changeset(cur_rev).prev(c.branch) |
|
136 | 136 | c.url_prev = url('files_home', repo_name=c.repo_name, |
|
137 | 137 | revision=prev_rev.raw_id, f_path=f_path) |
|
138 | 138 | if c.branch: |
|
139 | 139 | c.url_prev += '?branch=%s' % c.branch |
|
140 | 140 | except (ChangesetDoesNotExistError, VCSError): |
|
141 | 141 | c.url_prev = '#' |
|
142 | 142 | |
|
143 | 143 | # next link |
|
144 | 144 | try: |
|
145 | 145 | next_rev = c.rhodecode_repo.get_changeset(cur_rev).next(c.branch) |
|
146 | 146 | c.url_next = url('files_home', repo_name=c.repo_name, |
|
147 | 147 | revision=next_rev.raw_id, f_path=f_path) |
|
148 | 148 | if c.branch: |
|
149 | 149 | c.url_next += '?branch=%s' % c.branch |
|
150 | 150 | except (ChangesetDoesNotExistError, VCSError): |
|
151 | 151 | c.url_next = '#' |
|
152 | 152 | |
|
153 | 153 | # files or dirs |
|
154 | 154 | try: |
|
155 | 155 | c.file = c.changeset.get_node(f_path) |
|
156 | 156 | |
|
157 | 157 | if c.file.is_file(): |
|
158 | 158 | c.file_history, _hist = self._get_node_history(c.changeset, f_path) |
|
159 | 159 | c.file_changeset = c.changeset |
|
160 | 160 | if _hist: |
|
161 | 161 | c.file_changeset = (c.changeset |
|
162 | 162 | if c.changeset.revision < _hist[0].revision |
|
163 | 163 | else _hist[0]) |
|
164 | 164 | c.authors = [] |
|
165 | 165 | for a in set([x.author for x in _hist]): |
|
166 | 166 | c.authors.append((h.email(a), h.person(a))) |
|
167 | 167 | else: |
|
168 | 168 | c.authors = c.file_history = [] |
|
169 | 169 | except RepositoryError, e: |
|
170 | 170 | h.flash(str(e), category='warning') |
|
171 | 171 | redirect(h.url('files_home', repo_name=repo_name, |
|
172 | 172 | revision='tip')) |
|
173 | 173 | |
|
174 | 174 | if request.environ.get('HTTP_X_PARTIAL_XHR'): |
|
175 | 175 | return render('files/files_ypjax.html') |
|
176 | 176 | |
|
177 | 177 | return render('files/files.html') |
|
178 | 178 | |
|
179 | 179 | @LoginRequired() |
|
180 | 180 | @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', |
|
181 | 181 | 'repository.admin') |
|
182 | 182 | def rawfile(self, repo_name, revision, f_path): |
|
183 | 183 | cs = self.__get_cs_or_redirect(revision, repo_name) |
|
184 | 184 | file_node = self.__get_filenode_or_redirect(repo_name, cs, f_path) |
|
185 | 185 | |
|
186 | 186 | response.content_disposition = 'attachment; filename=%s' % \ |
|
187 | 187 | safe_str(f_path.split(Repository.url_sep())[-1]) |
|
188 | 188 | |
|
189 | 189 | response.content_type = file_node.mimetype |
|
190 | 190 | return file_node.content |
|
191 | 191 | |
|
192 | 192 | @LoginRequired() |
|
193 | 193 | @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', |
|
194 | 194 | 'repository.admin') |
|
195 | 195 | def raw(self, repo_name, revision, f_path): |
|
196 | 196 | cs = self.__get_cs_or_redirect(revision, repo_name) |
|
197 | 197 | file_node = self.__get_filenode_or_redirect(repo_name, cs, f_path) |
|
198 | 198 | |
|
199 | 199 | raw_mimetype_mapping = { |
|
200 | 200 | # map original mimetype to a mimetype used for "show as raw" |
|
201 | 201 | # you can also provide a content-disposition to override the |
|
202 | 202 | # default "attachment" disposition. |
|
203 | 203 | # orig_type: (new_type, new_dispo) |
|
204 | 204 | |
|
205 | 205 | # show images inline: |
|
206 | 206 | 'image/x-icon': ('image/x-icon', 'inline'), |
|
207 | 207 | 'image/png': ('image/png', 'inline'), |
|
208 | 208 | 'image/gif': ('image/gif', 'inline'), |
|
209 | 209 | 'image/jpeg': ('image/jpeg', 'inline'), |
|
210 | 210 | 'image/svg+xml': ('image/svg+xml', 'inline'), |
|
211 | 211 | } |
|
212 | 212 | |
|
213 | 213 | mimetype = file_node.mimetype |
|
214 | 214 | try: |
|
215 | 215 | mimetype, dispo = raw_mimetype_mapping[mimetype] |
|
216 | 216 | except KeyError: |
|
217 | 217 | # we don't know anything special about this, handle it safely |
|
218 | 218 | if file_node.is_binary: |
|
219 | 219 | # do same as download raw for binary files |
|
220 | 220 | mimetype, dispo = 'application/octet-stream', 'attachment' |
|
221 | 221 | else: |
|
222 | 222 | # do not just use the original mimetype, but force text/plain, |
|
223 | 223 | # otherwise it would serve text/html and that might be unsafe. |
|
224 | 224 | # Note: underlying vcs library fakes text/plain mimetype if the |
|
225 | 225 | # mimetype can not be determined and it thinks it is not |
|
226 | 226 | # binary.This might lead to erroneous text display in some |
|
227 | 227 | # cases, but helps in other cases, like with text files |
|
228 | 228 | # without extension. |
|
229 | 229 | mimetype, dispo = 'text/plain', 'inline' |
|
230 | 230 | |
|
231 | 231 | if dispo == 'attachment': |
|
232 | 232 | dispo = 'attachment; filename=%s' % \ |
|
233 | 233 | safe_str(f_path.split(os.sep)[-1]) |
|
234 | 234 | |
|
235 | 235 | response.content_disposition = dispo |
|
236 | 236 | response.content_type = mimetype |
|
237 | 237 | return file_node.content |
|
238 | 238 | |
|
239 | 239 | @LoginRequired() |
|
240 | 240 | @HasRepoPermissionAnyDecorator('repository.write', 'repository.admin') |
|
241 | 241 | def edit(self, repo_name, revision, f_path): |
|
242 | 242 | repo = Repository.get_by_repo_name(repo_name) |
|
243 | 243 | if repo.enable_locking and repo.locked[0]: |
|
244 | 244 | h.flash(_('This repository is has been locked by %s on %s') |
|
245 | 245 | % (h.person_by_id(repo.locked[0]), |
|
246 | 246 | h.fmt_date(h.time_to_datetime(repo.locked[1]))), |
|
247 | 247 | 'warning') |
|
248 | 248 | return redirect(h.url('files_home', |
|
249 | 249 | repo_name=repo_name, revision='tip')) |
|
250 | 250 | |
|
251 | 251 | r_post = request.POST |
|
252 | 252 | |
|
253 | 253 | c.cs = self.__get_cs_or_redirect(revision, repo_name) |
|
254 | 254 | c.file = self.__get_filenode_or_redirect(repo_name, c.cs, f_path) |
|
255 | 255 | |
|
256 | 256 | if c.file.is_binary: |
|
257 | 257 | return redirect(url('files_home', repo_name=c.repo_name, |
|
258 | 258 | revision=c.cs.raw_id, f_path=f_path)) |
|
259 | 259 | |
|
260 | 260 | c.f_path = f_path |
|
261 | 261 | |
|
262 | 262 | if r_post: |
|
263 | 263 | |
|
264 | 264 | old_content = c.file.content |
|
265 | 265 | sl = old_content.splitlines(1) |
|
266 | 266 | first_line = sl[0] if sl else '' |
|
267 | 267 | # modes: 0 - Unix, 1 - Mac, 2 - DOS |
|
268 | 268 | mode = detect_mode(first_line, 0) |
|
269 | 269 | content = convert_line_endings(r_post.get('content'), mode) |
|
270 | 270 | |
|
271 | 271 | message = r_post.get('message') or (_('Edited %s via RhodeCode') |
|
272 | 272 | % (f_path)) |
|
273 | 273 | author = self.rhodecode_user.full_contact |
|
274 | 274 | |
|
275 | 275 | if content == old_content: |
|
276 | 276 | h.flash(_('No changes'), |
|
277 | 277 | category='warning') |
|
278 | 278 | return redirect(url('changeset_home', repo_name=c.repo_name, |
|
279 | 279 | revision='tip')) |
|
280 | 280 | |
|
281 | 281 | try: |
|
282 | 282 | self.scm_model.commit_change(repo=c.rhodecode_repo, |
|
283 | 283 | repo_name=repo_name, cs=c.cs, |
|
284 | 284 | user=self.rhodecode_user, |
|
285 | 285 | author=author, message=message, |
|
286 | 286 | content=content, f_path=f_path) |
|
287 | 287 | h.flash(_('Successfully committed to %s') % f_path, |
|
288 | 288 | category='success') |
|
289 | 289 | |
|
290 | 290 | except Exception: |
|
291 | 291 | log.error(traceback.format_exc()) |
|
292 | 292 | h.flash(_('Error occurred during commit'), category='error') |
|
293 | 293 | return redirect(url('changeset_home', |
|
294 | 294 | repo_name=c.repo_name, revision='tip')) |
|
295 | 295 | |
|
296 | 296 | return render('files/files_edit.html') |
|
297 | 297 | |
|
298 | 298 | @LoginRequired() |
|
299 | 299 | @HasRepoPermissionAnyDecorator('repository.write', 'repository.admin') |
|
300 | 300 | def add(self, repo_name, revision, f_path): |
|
301 | 301 | |
|
302 | 302 | repo = Repository.get_by_repo_name(repo_name) |
|
303 | 303 | if repo.enable_locking and repo.locked[0]: |
|
304 | 304 | h.flash(_('This repository is has been locked by %s on %s') |
|
305 | 305 | % (h.person_by_id(repo.locked[0]), |
|
306 | 306 | h.fmt_date(h.time_to_datetime(repo.locked[1]))), |
|
307 | 307 | 'warning') |
|
308 | 308 | return redirect(h.url('files_home', |
|
309 | 309 | repo_name=repo_name, revision='tip')) |
|
310 | 310 | |
|
311 | 311 | r_post = request.POST |
|
312 | 312 | c.cs = self.__get_cs_or_redirect(revision, repo_name, |
|
313 | 313 | redirect_after=False) |
|
314 | 314 | if c.cs is None: |
|
315 | 315 | c.cs = EmptyChangeset(alias=c.rhodecode_repo.alias) |
|
316 | 316 | |
|
317 | 317 | c.f_path = f_path |
|
318 | 318 | |
|
319 | 319 | if r_post: |
|
320 | 320 | unix_mode = 0 |
|
321 | 321 | content = convert_line_endings(r_post.get('content'), unix_mode) |
|
322 | 322 | |
|
323 | 323 | message = r_post.get('message') or (_('Added %s via RhodeCode') |
|
324 | 324 | % (f_path)) |
|
325 | 325 | location = r_post.get('location') |
|
326 | 326 | filename = r_post.get('filename') |
|
327 | 327 | file_obj = r_post.get('upload_file', None) |
|
328 | 328 | |
|
329 | 329 | if file_obj is not None and hasattr(file_obj, 'filename'): |
|
330 | 330 | filename = file_obj.filename |
|
331 | 331 | content = file_obj.file |
|
332 | 332 | |
|
333 | 333 | node_path = os.path.join(location, filename) |
|
334 | 334 | author = self.rhodecode_user.full_contact |
|
335 | 335 | |
|
336 | 336 | if not content: |
|
337 | 337 | h.flash(_('No content'), category='warning') |
|
338 | 338 | return redirect(url('changeset_home', repo_name=c.repo_name, |
|
339 | 339 | revision='tip')) |
|
340 | 340 | if not filename: |
|
341 | 341 | h.flash(_('No filename'), category='warning') |
|
342 | 342 | return redirect(url('changeset_home', repo_name=c.repo_name, |
|
343 | 343 | revision='tip')) |
|
344 | 344 | |
|
345 | 345 | try: |
|
346 | 346 | self.scm_model.create_node(repo=c.rhodecode_repo, |
|
347 | 347 | repo_name=repo_name, cs=c.cs, |
|
348 | 348 | user=self.rhodecode_user, |
|
349 | 349 | author=author, message=message, |
|
350 | 350 | content=content, f_path=node_path) |
|
351 | 351 | h.flash(_('Successfully committed to %s') % node_path, |
|
352 | 352 | category='success') |
|
353 | 353 | except NodeAlreadyExistsError, e: |
|
354 | 354 | h.flash(_(e), category='error') |
|
355 | 355 | except Exception: |
|
356 | 356 | log.error(traceback.format_exc()) |
|
357 | 357 | h.flash(_('Error occurred during commit'), category='error') |
|
358 | 358 | return redirect(url('changeset_home', |
|
359 | 359 | repo_name=c.repo_name, revision='tip')) |
|
360 | 360 | |
|
361 | 361 | return render('files/files_add.html') |
|
362 | 362 | |
|
363 | 363 | @LoginRequired() |
|
364 | 364 | @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', |
|
365 | 365 | 'repository.admin') |
|
366 | 366 | def archivefile(self, repo_name, fname): |
|
367 | 367 | |
|
368 | 368 | fileformat = None |
|
369 | 369 | revision = None |
|
370 | 370 | ext = None |
|
371 | 371 | subrepos = request.GET.get('subrepos') == 'true' |
|
372 | 372 | |
|
373 | 373 | for a_type, ext_data in settings.ARCHIVE_SPECS.items(): |
|
374 | 374 | archive_spec = fname.split(ext_data[1]) |
|
375 | 375 | if len(archive_spec) == 2 and archive_spec[1] == '': |
|
376 | 376 | fileformat = a_type or ext_data[1] |
|
377 | 377 | revision = archive_spec[0] |
|
378 | 378 | ext = ext_data[1] |
|
379 | 379 | |
|
380 | 380 | try: |
|
381 | 381 | dbrepo = RepoModel().get_by_repo_name(repo_name) |
|
382 | 382 | if dbrepo.enable_downloads is False: |
|
383 | 383 | return _('downloads disabled') |
|
384 | 384 | |
|
385 | 385 | if c.rhodecode_repo.alias == 'hg': |
|
386 | 386 | # patch and reset hooks section of UI config to not run any |
|
387 | 387 | # hooks on fetching archives with subrepos |
|
388 | 388 | for k, v in c.rhodecode_repo._repo.ui.configitems('hooks'): |
|
389 | 389 | c.rhodecode_repo._repo.ui.setconfig('hooks', k, None) |
|
390 | 390 | |
|
391 | 391 | cs = c.rhodecode_repo.get_changeset(revision) |
|
392 | 392 | content_type = settings.ARCHIVE_SPECS[fileformat][0] |
|
393 | 393 | except ChangesetDoesNotExistError: |
|
394 | 394 | return _('Unknown revision %s') % revision |
|
395 | 395 | except EmptyRepositoryError: |
|
396 | 396 | return _('Empty repository') |
|
397 | 397 | except (ImproperArchiveTypeError, KeyError): |
|
398 | 398 | return _('Unknown archive type') |
|
399 | 399 | |
|
400 | 400 | fd, archive = tempfile.mkstemp() |
|
401 | 401 | t = open(archive, 'wb') |
|
402 | 402 | cs.fill_archive(stream=t, kind=fileformat, subrepos=subrepos) |
|
403 | 403 | t.close() |
|
404 | 404 | |
|
405 | 405 | def get_chunked_archive(archive): |
|
406 | 406 | stream = open(archive, 'rb') |
|
407 | 407 | while True: |
|
408 | 408 | data = stream.read(16 * 1024) |
|
409 | 409 | if not data: |
|
410 | 410 | stream.close() |
|
411 | 411 | os.close(fd) |
|
412 | 412 | os.remove(archive) |
|
413 | 413 | break |
|
414 | 414 | yield data |
|
415 | 415 | |
|
416 | 416 | response.content_disposition = str('attachment; filename=%s-%s%s' \ |
|
417 | 417 | % (repo_name, revision[:12], ext)) |
|
418 | 418 | response.content_type = str(content_type) |
|
419 | 419 | return get_chunked_archive(archive) |
|
420 | 420 | |
|
421 | 421 | @LoginRequired() |
|
422 | 422 | @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', |
|
423 | 423 | 'repository.admin') |
|
424 | 424 | def diff(self, repo_name, f_path): |
|
425 | 425 | ignore_whitespace = request.GET.get('ignorews') == '1' |
|
426 | 426 | line_context = request.GET.get('context', 3) |
|
427 | 427 | diff1 = request.GET.get('diff1', '') |
|
428 | 428 | diff2 = request.GET.get('diff2', '') |
|
429 | 429 | c.action = request.GET.get('diff') |
|
430 | 430 | c.no_changes = diff1 == diff2 |
|
431 | 431 | c.f_path = f_path |
|
432 | 432 | c.big_diff = False |
|
433 | 433 | c.anchor_url = anchor_url |
|
434 | 434 | c.ignorews_url = _ignorews_url |
|
435 | 435 | c.context_url = _context_url |
|
436 | 436 | c.changes = OrderedDict() |
|
437 | 437 | c.changes[diff2] = [] |
|
438 | 438 | |
|
439 | 439 | #special case if we want a show rev only, it's impl here |
|
440 | 440 | #to reduce JS and callbacks |
|
441 | ||
|
441 | 442 | if request.GET.get('show_rev'): |
|
442 | 443 | if str2bool(request.GET.get('annotate', 'False')): |
|
443 | 444 | _url = url('files_annotate_home', repo_name=c.repo_name, |
|
444 | 445 | revision=diff1, f_path=c.f_path) |
|
445 | 446 | else: |
|
446 | 447 | _url = url('files_home', repo_name=c.repo_name, |
|
447 | 448 | revision=diff1, f_path=c.f_path) |
|
448 | 449 | |
|
449 | 450 | return redirect(_url) |
|
450 | 451 | try: |
|
451 | 452 | if diff1 not in ['', None, 'None', '0' * 12, '0' * 40]: |
|
452 | 453 | c.changeset_1 = c.rhodecode_repo.get_changeset(diff1) |
|
454 | try: | |
|
453 | 455 | node1 = c.changeset_1.get_node(f_path) |
|
456 | except NodeDoesNotExistError: | |
|
457 | c.changeset_1 = EmptyChangeset(cs=diff1, | |
|
458 | revision=c.changeset_1.revision, | |
|
459 | repo=c.rhodecode_repo) | |
|
460 | node1 = FileNode(f_path, '', changeset=c.changeset_1) | |
|
454 | 461 | else: |
|
455 | 462 | c.changeset_1 = EmptyChangeset(repo=c.rhodecode_repo) |
|
456 |
node1 = FileNode( |
|
|
463 | node1 = FileNode(f_path, '', changeset=c.changeset_1) | |
|
457 | 464 | |
|
458 | 465 | if diff2 not in ['', None, 'None', '0' * 12, '0' * 40]: |
|
459 | 466 | c.changeset_2 = c.rhodecode_repo.get_changeset(diff2) |
|
467 | try: | |
|
460 | 468 | node2 = c.changeset_2.get_node(f_path) |
|
469 | except NodeDoesNotExistError: | |
|
470 | c.changeset_2 = EmptyChangeset(cs=diff2, | |
|
471 | revision=c.changeset_2.revision, | |
|
472 | repo=c.rhodecode_repo) | |
|
473 | node2 = FileNode(f_path, '', changeset=c.changeset_2) | |
|
461 | 474 | else: |
|
462 | 475 | c.changeset_2 = EmptyChangeset(repo=c.rhodecode_repo) |
|
463 |
node2 = FileNode( |
|
|
476 | node2 = FileNode(f_path, '', changeset=c.changeset_2) | |
|
464 | 477 | except RepositoryError: |
|
478 | log.error(traceback.format_exc()) | |
|
465 | 479 | return redirect(url('files_home', repo_name=c.repo_name, |
|
466 | 480 | f_path=f_path)) |
|
467 | 481 | |
|
468 | 482 | if c.action == 'download': |
|
469 | 483 | _diff = diffs.get_gitdiff(node1, node2, |
|
470 | 484 | ignore_whitespace=ignore_whitespace, |
|
471 | 485 | context=line_context) |
|
472 | 486 | diff = diffs.DiffProcessor(_diff, format='gitdiff') |
|
473 | 487 | |
|
474 | 488 | diff_name = '%s_vs_%s.diff' % (diff1, diff2) |
|
475 | 489 | response.content_type = 'text/plain' |
|
476 | 490 | response.content_disposition = ( |
|
477 | 491 | 'attachment; filename=%s' % diff_name |
|
478 | 492 | ) |
|
479 |
return diff.raw |
|
|
493 | return diff.as_raw() | |
|
480 | 494 | |
|
481 | 495 | elif c.action == 'raw': |
|
482 | 496 | _diff = diffs.get_gitdiff(node1, node2, |
|
483 | 497 | ignore_whitespace=ignore_whitespace, |
|
484 | 498 | context=line_context) |
|
485 | 499 | diff = diffs.DiffProcessor(_diff, format='gitdiff') |
|
486 | 500 | response.content_type = 'text/plain' |
|
487 |
return diff.raw |
|
|
501 | return diff.as_raw() | |
|
488 | 502 | |
|
489 | 503 | else: |
|
490 | 504 | fid = h.FID(diff2, node2.path) |
|
491 | 505 | line_context_lcl = get_line_ctx(fid, request.GET) |
|
492 | 506 | ign_whitespace_lcl = get_ignore_ws(fid, request.GET) |
|
493 | 507 | |
|
494 | 508 | lim = request.GET.get('fulldiff') or self.cut_off_limit |
|
495 | 509 | _, cs1, cs2, diff, st = diffs.wrapped_diff(filenode_old=node1, |
|
496 | 510 | filenode_new=node2, |
|
497 | 511 | cut_off_limit=lim, |
|
498 | 512 | ignore_whitespace=ign_whitespace_lcl, |
|
499 | 513 | line_context=line_context_lcl, |
|
500 | 514 | enable_comments=False) |
|
501 | ||
|
502 | c.changes = [('', node2, diff, cs1, cs2, st,)] | |
|
515 | op = '' | |
|
516 | filename = node1.path | |
|
517 | cs_changes = { | |
|
518 | 'fid': [cs1, cs2, op, filename, diff, st] | |
|
519 | } | |
|
520 | c.changes = cs_changes | |
|
503 | 521 | |
|
504 | 522 | return render('files/file_diff.html') |
|
505 | 523 | |
|
506 | 524 | def _get_node_history(self, cs, f_path, changesets=None): |
|
507 | 525 | """ |
|
508 | 526 | get changesets history for given node |
|
509 | 527 | |
|
510 | 528 | :param cs: changeset to calculate history |
|
511 | 529 | :param f_path: path for node to calculate history for |
|
512 | 530 | :param changesets: if passed don't calculate history and take |
|
513 | 531 | changesets defined in this list |
|
514 | 532 | """ |
|
515 | 533 | # calculate history based on tip |
|
516 | 534 | tip_cs = c.rhodecode_repo.get_changeset() |
|
517 | 535 | if changesets is None: |
|
518 | 536 | try: |
|
519 | 537 | changesets = tip_cs.get_file_history(f_path) |
|
520 | 538 | except (NodeDoesNotExistError, ChangesetError): |
|
521 | 539 | #this node is not present at tip ! |
|
522 | 540 | changesets = cs.get_file_history(f_path) |
|
523 | 541 | |
|
524 | 542 | hist_l = [] |
|
525 | 543 | |
|
526 | 544 | changesets_group = ([], _("Changesets")) |
|
527 | 545 | branches_group = ([], _("Branches")) |
|
528 | 546 | tags_group = ([], _("Tags")) |
|
529 | 547 | _hg = cs.repository.alias == 'hg' |
|
530 | 548 | for chs in changesets: |
|
531 | 549 | _branch = '(%s)' % chs.branch if _hg else '' |
|
532 | 550 | n_desc = 'r%s:%s %s' % (chs.revision, chs.short_id, _branch) |
|
533 | 551 | changesets_group[0].append((chs.raw_id, n_desc,)) |
|
534 | 552 | |
|
535 | 553 | hist_l.append(changesets_group) |
|
536 | 554 | |
|
537 | 555 | for name, chs in c.rhodecode_repo.branches.items(): |
|
538 | 556 | branches_group[0].append((chs, name),) |
|
539 | 557 | hist_l.append(branches_group) |
|
540 | 558 | |
|
541 | 559 | for name, chs in c.rhodecode_repo.tags.items(): |
|
542 | 560 | tags_group[0].append((chs, name),) |
|
543 | 561 | hist_l.append(tags_group) |
|
544 | 562 | |
|
545 | 563 | return hist_l, changesets |
|
546 | 564 | |
|
547 | 565 | @LoginRequired() |
|
548 | 566 | @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', |
|
549 | 567 | 'repository.admin') |
|
550 | 568 | @jsonify |
|
551 | 569 | def nodelist(self, repo_name, revision, f_path): |
|
552 | 570 | if request.environ.get('HTTP_X_PARTIAL_XHR'): |
|
553 | 571 | cs = self.__get_cs_or_redirect(revision, repo_name) |
|
554 | 572 | _d, _f = ScmModel().get_nodes(repo_name, cs.raw_id, f_path, |
|
555 | 573 | flat=False) |
|
556 | 574 | return {'nodes': _d + _f} |
@@ -1,446 +1,446 b'' | |||
|
1 | 1 | # -*- coding: utf-8 -*- |
|
2 | 2 | """ |
|
3 | 3 | rhodecode.controllers.pullrequests |
|
4 | 4 | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
|
5 | 5 | |
|
6 | 6 | pull requests controller for rhodecode for initializing pull requests |
|
7 | 7 | |
|
8 | 8 | :created_on: May 7, 2012 |
|
9 | 9 | :author: marcink |
|
10 | 10 | :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com> |
|
11 | 11 | :license: GPLv3, see COPYING for more details. |
|
12 | 12 | """ |
|
13 | 13 | # This program is free software: you can redistribute it and/or modify |
|
14 | 14 | # it under the terms of the GNU General Public License as published by |
|
15 | 15 | # the Free Software Foundation, either version 3 of the License, or |
|
16 | 16 | # (at your option) any later version. |
|
17 | 17 | # |
|
18 | 18 | # This program is distributed in the hope that it will be useful, |
|
19 | 19 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
20 | 20 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
21 | 21 | # GNU General Public License for more details. |
|
22 | 22 | # |
|
23 | 23 | # You should have received a copy of the GNU General Public License |
|
24 | 24 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
25 | 25 | import logging |
|
26 | 26 | import traceback |
|
27 | 27 | import formencode |
|
28 | 28 | |
|
29 | 29 | from webob.exc import HTTPNotFound, HTTPForbidden |
|
30 | 30 | from collections import defaultdict |
|
31 | 31 | from itertools import groupby |
|
32 | 32 | |
|
33 | 33 | from pylons import request, response, session, tmpl_context as c, url |
|
34 | 34 | from pylons.controllers.util import abort, redirect |
|
35 | 35 | from pylons.i18n.translation import _ |
|
36 | 36 | from pylons.decorators import jsonify |
|
37 | 37 | |
|
38 | 38 | from rhodecode.lib.compat import json |
|
39 | 39 | from rhodecode.lib.base import BaseRepoController, render |
|
40 | 40 | from rhodecode.lib.auth import LoginRequired, HasRepoPermissionAnyDecorator,\ |
|
41 | 41 | NotAnonymous |
|
42 | 42 | from rhodecode.lib import helpers as h |
|
43 | 43 | from rhodecode.lib import diffs |
|
44 | 44 | from rhodecode.lib.utils import action_logger |
|
45 | 45 | from rhodecode.model.db import User, PullRequest, ChangesetStatus,\ |
|
46 | 46 | ChangesetComment |
|
47 | 47 | from rhodecode.model.pull_request import PullRequestModel |
|
48 | 48 | from rhodecode.model.meta import Session |
|
49 | 49 | from rhodecode.model.repo import RepoModel |
|
50 | 50 | from rhodecode.model.comment import ChangesetCommentsModel |
|
51 | 51 | from rhodecode.model.changeset_status import ChangesetStatusModel |
|
52 | 52 | from rhodecode.model.forms import PullRequestForm |
|
53 | 53 | from rhodecode.lib.vcs.exceptions import EmptyRepositoryError |
|
54 | 54 | |
|
55 | 55 | log = logging.getLogger(__name__) |
|
56 | 56 | |
|
57 | 57 | |
|
58 | 58 | class PullrequestsController(BaseRepoController): |
|
59 | 59 | |
|
60 | 60 | @LoginRequired() |
|
61 | 61 | @HasRepoPermissionAnyDecorator('repository.read', 'repository.write', |
|
62 | 62 | 'repository.admin') |
|
63 | 63 | def __before__(self): |
|
64 | 64 | super(PullrequestsController, self).__before__() |
|
65 | 65 | repo_model = RepoModel() |
|
66 | 66 | c.users_array = repo_model.get_users_js() |
|
67 | 67 | c.users_groups_array = repo_model.get_users_groups_js() |
|
68 | 68 | |
|
69 | 69 | def _get_repo_refs(self, repo): |
|
70 | 70 | hist_l = [] |
|
71 | 71 | |
|
72 | 72 | branches_group = ([('branch:%s:%s' % (k, v), k) for |
|
73 | 73 | k, v in repo.branches.iteritems()], _("Branches")) |
|
74 | 74 | bookmarks_group = ([('book:%s:%s' % (k, v), k) for |
|
75 | 75 | k, v in repo.bookmarks.iteritems()], _("Bookmarks")) |
|
76 | 76 | tags_group = ([('tag:%s:%s' % (k, v), k) for |
|
77 | 77 | k, v in repo.tags.iteritems()], _("Tags")) |
|
78 | 78 | |
|
79 | 79 | hist_l.append(bookmarks_group) |
|
80 | 80 | hist_l.append(branches_group) |
|
81 | 81 | hist_l.append(tags_group) |
|
82 | 82 | |
|
83 | 83 | return hist_l |
|
84 | 84 | |
|
85 | 85 | def _get_default_rev(self, repo): |
|
86 | 86 | """ |
|
87 | 87 | Get's default revision to do compare on pull request |
|
88 | 88 | |
|
89 | 89 | :param repo: |
|
90 | 90 | """ |
|
91 | 91 | repo = repo.scm_instance |
|
92 | 92 | if 'default' in repo.branches: |
|
93 | 93 | return 'default' |
|
94 | 94 | else: |
|
95 | 95 | #if repo doesn't have default branch return first found |
|
96 | 96 | return repo.branches.keys()[0] |
|
97 | 97 | |
|
98 | 98 | def show_all(self, repo_name): |
|
99 | 99 | c.pull_requests = PullRequestModel().get_all(repo_name) |
|
100 | 100 | c.repo_name = repo_name |
|
101 | 101 | return render('/pullrequests/pullrequest_show_all.html') |
|
102 | 102 | |
|
103 | 103 | @NotAnonymous() |
|
104 | 104 | def index(self): |
|
105 | 105 | org_repo = c.rhodecode_db_repo |
|
106 | 106 | |
|
107 | 107 | if org_repo.scm_instance.alias != 'hg': |
|
108 | 108 | log.error('Review not available for GIT REPOS') |
|
109 | 109 | raise HTTPNotFound |
|
110 | 110 | |
|
111 | 111 | try: |
|
112 | 112 | org_repo.scm_instance.get_changeset() |
|
113 | 113 | except EmptyRepositoryError, e: |
|
114 | 114 | h.flash(h.literal(_('There are no changesets yet')), |
|
115 | 115 | category='warning') |
|
116 | 116 | redirect(url('summary_home', repo_name=org_repo.repo_name)) |
|
117 | 117 | |
|
118 | 118 | other_repos_info = {} |
|
119 | 119 | |
|
120 | 120 | c.org_refs = self._get_repo_refs(c.rhodecode_repo) |
|
121 | 121 | c.org_repos = [] |
|
122 | 122 | c.other_repos = [] |
|
123 | 123 | c.org_repos.append((org_repo.repo_name, '%s/%s' % ( |
|
124 | 124 | org_repo.user.username, c.repo_name)) |
|
125 | 125 | ) |
|
126 | 126 | |
|
127 | 127 | # add org repo to other so we can open pull request agains itself |
|
128 | 128 | c.other_repos.extend(c.org_repos) |
|
129 | 129 | |
|
130 | 130 | c.default_pull_request = org_repo.repo_name # repo name pre-selected |
|
131 | 131 | c.default_pull_request_rev = self._get_default_rev(org_repo) # revision pre-selected |
|
132 | 132 | c.default_revs = self._get_repo_refs(org_repo.scm_instance) |
|
133 | 133 | #add orginal repo |
|
134 | 134 | other_repos_info[org_repo.repo_name] = { |
|
135 | 135 | 'gravatar': h.gravatar_url(org_repo.user.email, 24), |
|
136 | 136 | 'description': org_repo.description, |
|
137 | 137 | 'revs': h.select('other_ref', '', c.default_revs, class_='refs') |
|
138 | 138 | } |
|
139 | 139 | |
|
140 | 140 | #gather forks and add to this list |
|
141 | 141 | for fork in org_repo.forks: |
|
142 | 142 | c.other_repos.append((fork.repo_name, '%s/%s' % ( |
|
143 | 143 | fork.user.username, fork.repo_name)) |
|
144 | 144 | ) |
|
145 | 145 | other_repos_info[fork.repo_name] = { |
|
146 | 146 | 'gravatar': h.gravatar_url(fork.user.email, 24), |
|
147 | 147 | 'description': fork.description, |
|
148 | 148 | 'revs': h.select('other_ref', '', |
|
149 | 149 | self._get_repo_refs(fork.scm_instance), |
|
150 | 150 | class_='refs') |
|
151 | 151 | } |
|
152 | 152 | #add parents of this fork also, but only if it's not empty |
|
153 | 153 | if org_repo.parent and org_repo.parent.scm_instance.revisions: |
|
154 | 154 | c.default_pull_request = org_repo.parent.repo_name |
|
155 | 155 | c.default_pull_request_rev = self._get_default_rev(org_repo.parent) |
|
156 | 156 | c.default_revs = self._get_repo_refs(org_repo.parent.scm_instance) |
|
157 | 157 | c.other_repos.append((org_repo.parent.repo_name, '%s/%s' % ( |
|
158 | 158 | org_repo.parent.user.username, |
|
159 | 159 | org_repo.parent.repo_name)) |
|
160 | 160 | ) |
|
161 | 161 | other_repos_info[org_repo.parent.repo_name] = { |
|
162 | 162 | 'gravatar': h.gravatar_url(org_repo.parent.user.email, 24), |
|
163 | 163 | 'description': org_repo.parent.description, |
|
164 | 164 | 'revs': h.select('other_ref', '', |
|
165 | 165 | self._get_repo_refs(org_repo.parent.scm_instance), |
|
166 | 166 | class_='refs') |
|
167 | 167 | } |
|
168 | 168 | |
|
169 | 169 | c.other_repos_info = json.dumps(other_repos_info) |
|
170 | 170 | c.review_members = [org_repo.user] |
|
171 | 171 | return render('/pullrequests/pullrequest.html') |
|
172 | 172 | |
|
173 | 173 | @NotAnonymous() |
|
174 | 174 | def create(self, repo_name): |
|
175 | 175 | repo = RepoModel()._get_repo(repo_name) |
|
176 | 176 | try: |
|
177 | 177 | _form = PullRequestForm(repo.repo_id)().to_python(request.POST) |
|
178 | 178 | except formencode.Invalid, errors: |
|
179 | 179 | log.error(traceback.format_exc()) |
|
180 | 180 | if errors.error_dict.get('revisions'): |
|
181 | 181 | msg = 'Revisions: %s' % errors.error_dict['revisions'] |
|
182 | 182 | elif errors.error_dict.get('pullrequest_title'): |
|
183 | 183 | msg = _('Pull request requires a title with min. 3 chars') |
|
184 | 184 | else: |
|
185 | 185 | msg = _('error during creation of pull request') |
|
186 | 186 | |
|
187 | 187 | h.flash(msg, 'error') |
|
188 | 188 | return redirect(url('pullrequest_home', repo_name=repo_name)) |
|
189 | 189 | |
|
190 | 190 | org_repo = _form['org_repo'] |
|
191 | 191 | org_ref = _form['org_ref'] |
|
192 | 192 | other_repo = _form['other_repo'] |
|
193 | 193 | other_ref = _form['other_ref'] |
|
194 | 194 | revisions = _form['revisions'] |
|
195 | 195 | reviewers = _form['review_members'] |
|
196 | 196 | |
|
197 | 197 | title = _form['pullrequest_title'] |
|
198 | 198 | description = _form['pullrequest_desc'] |
|
199 | 199 | |
|
200 | 200 | try: |
|
201 | 201 | pull_request = PullRequestModel().create( |
|
202 | 202 | self.rhodecode_user.user_id, org_repo, org_ref, other_repo, |
|
203 | 203 | other_ref, revisions, reviewers, title, description |
|
204 | 204 | ) |
|
205 | 205 | Session().commit() |
|
206 | 206 | h.flash(_('Successfully opened new pull request'), |
|
207 | 207 | category='success') |
|
208 | 208 | except Exception: |
|
209 | 209 | h.flash(_('Error occurred during sending pull request'), |
|
210 | 210 | category='error') |
|
211 | 211 | log.error(traceback.format_exc()) |
|
212 | 212 | return redirect(url('pullrequest_home', repo_name=repo_name)) |
|
213 | 213 | |
|
214 | 214 | return redirect(url('pullrequest_show', repo_name=other_repo, |
|
215 | 215 | pull_request_id=pull_request.pull_request_id)) |
|
216 | 216 | |
|
217 | 217 | @NotAnonymous() |
|
218 | 218 | @jsonify |
|
219 | 219 | def update(self, repo_name, pull_request_id): |
|
220 | 220 | pull_request = PullRequest.get_or_404(pull_request_id) |
|
221 | 221 | if pull_request.is_closed(): |
|
222 | 222 | raise HTTPForbidden() |
|
223 | 223 | #only owner or admin can update it |
|
224 | 224 | owner = pull_request.author.user_id == c.rhodecode_user.user_id |
|
225 | 225 | if h.HasPermissionAny('hg.admin', 'repository.admin')() or owner: |
|
226 | 226 | reviewers_ids = map(int, filter(lambda v: v not in [None, ''], |
|
227 | 227 | request.POST.get('reviewers_ids', '').split(','))) |
|
228 | 228 | |
|
229 | 229 | PullRequestModel().update_reviewers(pull_request_id, reviewers_ids) |
|
230 | 230 | Session.commit() |
|
231 | 231 | return True |
|
232 | 232 | raise HTTPForbidden() |
|
233 | 233 | |
|
234 | 234 | @NotAnonymous() |
|
235 | 235 | @jsonify |
|
236 | 236 | def delete(self, repo_name, pull_request_id): |
|
237 | 237 | pull_request = PullRequest.get_or_404(pull_request_id) |
|
238 | 238 | #only owner can delete it ! |
|
239 | 239 | if pull_request.author.user_id == c.rhodecode_user.user_id: |
|
240 | 240 | PullRequestModel().delete(pull_request) |
|
241 | 241 | Session().commit() |
|
242 | 242 | h.flash(_('Successfully deleted pull request'), |
|
243 | 243 | category='success') |
|
244 | 244 | return redirect(url('admin_settings_my_account')) |
|
245 | 245 | raise HTTPForbidden() |
|
246 | 246 | |
|
247 | 247 | def _load_compare_data(self, pull_request, enable_comments=True): |
|
248 | 248 | """ |
|
249 | 249 | Load context data needed for generating compare diff |
|
250 | 250 | |
|
251 | 251 | :param pull_request: |
|
252 | 252 | :type pull_request: |
|
253 | 253 | """ |
|
254 | 254 | |
|
255 | 255 | org_repo = pull_request.org_repo |
|
256 | 256 | (org_ref_type, |
|
257 | 257 | org_ref_name, |
|
258 | 258 | org_ref_rev) = pull_request.org_ref.split(':') |
|
259 | 259 | |
|
260 | 260 | other_repo = pull_request.other_repo |
|
261 | 261 | (other_ref_type, |
|
262 | 262 | other_ref_name, |
|
263 | 263 | other_ref_rev) = pull_request.other_ref.split(':') |
|
264 | 264 | |
|
265 | 265 | # despite opening revisions for bookmarks/branches/tags, we always |
|
266 | 266 | # convert this to rev to prevent changes after book or branch change |
|
267 | 267 | org_ref = ('rev', org_ref_rev) |
|
268 | 268 | other_ref = ('rev', other_ref_rev) |
|
269 | 269 | |
|
270 | 270 | c.org_repo = org_repo |
|
271 | 271 | c.other_repo = other_repo |
|
272 | 272 | |
|
273 | 273 | c.cs_ranges, discovery_data = PullRequestModel().get_compare_data( |
|
274 | 274 | org_repo, org_ref, other_repo, other_ref |
|
275 | 275 | ) |
|
276 | 276 | if c.cs_ranges: |
|
277 | 277 | # case we want a simple diff without incoming changesets, just |
|
278 | 278 | # for review purposes. Make the diff on the forked repo, with |
|
279 | 279 | # revision that is common ancestor |
|
280 | 280 | other_ref = ('rev', c.cs_ranges[-1].parents[0].raw_id) |
|
281 | 281 | other_repo = org_repo |
|
282 | 282 | |
|
283 | 283 | c.statuses = org_repo.statuses([x.raw_id for x in c.cs_ranges]) |
|
284 | 284 | # defines that we need hidden inputs with changesets |
|
285 | 285 | c.as_form = request.GET.get('as_form', False) |
|
286 | 286 | |
|
287 | 287 | c.org_ref = org_ref[1] |
|
288 | 288 | c.other_ref = other_ref[1] |
|
289 | 289 | # diff needs to have swapped org with other to generate proper diff |
|
290 | 290 | _diff = diffs.differ(other_repo, other_ref, org_repo, org_ref, |
|
291 | 291 | discovery_data) |
|
292 | 292 | diff_processor = diffs.DiffProcessor(_diff, format='gitdiff') |
|
293 | 293 | _parsed = diff_processor.prepare() |
|
294 | 294 | |
|
295 | 295 | c.files = [] |
|
296 | 296 | c.changes = {} |
|
297 | 297 | |
|
298 | 298 | for f in _parsed: |
|
299 | 299 | fid = h.FID('', f['filename']) |
|
300 | 300 | c.files.append([fid, f['operation'], f['filename'], f['stats']]) |
|
301 | 301 | diff = diff_processor.as_html(enable_comments=enable_comments, |
|
302 |
d |
|
|
302 | parsed_lines=[f]) | |
|
303 | 303 | c.changes[fid] = [f['operation'], f['filename'], diff] |
|
304 | 304 | |
|
305 | 305 | def show(self, repo_name, pull_request_id): |
|
306 | 306 | repo_model = RepoModel() |
|
307 | 307 | c.users_array = repo_model.get_users_js() |
|
308 | 308 | c.users_groups_array = repo_model.get_users_groups_js() |
|
309 | 309 | c.pull_request = PullRequest.get_or_404(pull_request_id) |
|
310 | 310 | c.target_repo = c.pull_request.org_repo.repo_name |
|
311 | 311 | |
|
312 | 312 | cc_model = ChangesetCommentsModel() |
|
313 | 313 | cs_model = ChangesetStatusModel() |
|
314 | 314 | _cs_statuses = cs_model.get_statuses(c.pull_request.org_repo, |
|
315 | 315 | pull_request=c.pull_request, |
|
316 | 316 | with_revisions=True) |
|
317 | 317 | |
|
318 | 318 | cs_statuses = defaultdict(list) |
|
319 | 319 | for st in _cs_statuses: |
|
320 | 320 | cs_statuses[st.author.username] += [st] |
|
321 | 321 | |
|
322 | 322 | c.pull_request_reviewers = [] |
|
323 | 323 | c.pull_request_pending_reviewers = [] |
|
324 | 324 | for o in c.pull_request.reviewers: |
|
325 | 325 | st = cs_statuses.get(o.user.username, None) |
|
326 | 326 | if st: |
|
327 | 327 | sorter = lambda k: k.version |
|
328 | 328 | st = [(x, list(y)[0]) |
|
329 | 329 | for x, y in (groupby(sorted(st, key=sorter), sorter))] |
|
330 | 330 | else: |
|
331 | 331 | c.pull_request_pending_reviewers.append(o.user) |
|
332 | 332 | c.pull_request_reviewers.append([o.user, st]) |
|
333 | 333 | |
|
334 | 334 | # pull_requests repo_name we opened it against |
|
335 | 335 | # ie. other_repo must match |
|
336 | 336 | if repo_name != c.pull_request.other_repo.repo_name: |
|
337 | 337 | raise HTTPNotFound |
|
338 | 338 | |
|
339 | 339 | # load compare data into template context |
|
340 | 340 | enable_comments = not c.pull_request.is_closed() |
|
341 | 341 | self._load_compare_data(c.pull_request, enable_comments=enable_comments) |
|
342 | 342 | |
|
343 | 343 | # inline comments |
|
344 | 344 | c.inline_cnt = 0 |
|
345 | 345 | c.inline_comments = cc_model.get_inline_comments( |
|
346 | 346 | c.rhodecode_db_repo.repo_id, |
|
347 | 347 | pull_request=pull_request_id) |
|
348 | 348 | # count inline comments |
|
349 | 349 | for __, lines in c.inline_comments: |
|
350 | 350 | for comments in lines.values(): |
|
351 | 351 | c.inline_cnt += len(comments) |
|
352 | 352 | # comments |
|
353 | 353 | c.comments = cc_model.get_comments(c.rhodecode_db_repo.repo_id, |
|
354 | 354 | pull_request=pull_request_id) |
|
355 | 355 | |
|
356 | 356 | try: |
|
357 | 357 | cur_status = c.statuses[c.pull_request.revisions[0]][0] |
|
358 | 358 | except: |
|
359 | 359 | log.error(traceback.format_exc()) |
|
360 | 360 | cur_status = 'undefined' |
|
361 | 361 | if c.pull_request.is_closed() and 0: |
|
362 | 362 | c.current_changeset_status = cur_status |
|
363 | 363 | else: |
|
364 | 364 | # changeset(pull-request) status calulation based on reviewers |
|
365 | 365 | c.current_changeset_status = cs_model.calculate_status( |
|
366 | 366 | c.pull_request_reviewers, |
|
367 | 367 | ) |
|
368 | 368 | c.changeset_statuses = ChangesetStatus.STATUSES |
|
369 | 369 | |
|
370 | 370 | return render('/pullrequests/pullrequest_show.html') |
|
371 | 371 | |
|
372 | 372 | @NotAnonymous() |
|
373 | 373 | @jsonify |
|
374 | 374 | def comment(self, repo_name, pull_request_id): |
|
375 | 375 | pull_request = PullRequest.get_or_404(pull_request_id) |
|
376 | 376 | if pull_request.is_closed(): |
|
377 | 377 | raise HTTPForbidden() |
|
378 | 378 | |
|
379 | 379 | status = request.POST.get('changeset_status') |
|
380 | 380 | change_status = request.POST.get('change_changeset_status') |
|
381 | 381 | text = request.POST.get('text') |
|
382 | 382 | if status and change_status: |
|
383 | 383 | text = text or (_('Status change -> %s') |
|
384 | 384 | % ChangesetStatus.get_status_lbl(status)) |
|
385 | 385 | comm = ChangesetCommentsModel().create( |
|
386 | 386 | text=text, |
|
387 | 387 | repo=c.rhodecode_db_repo.repo_id, |
|
388 | 388 | user=c.rhodecode_user.user_id, |
|
389 | 389 | pull_request=pull_request_id, |
|
390 | 390 | f_path=request.POST.get('f_path'), |
|
391 | 391 | line_no=request.POST.get('line'), |
|
392 | 392 | status_change=(ChangesetStatus.get_status_lbl(status) |
|
393 | 393 | if status and change_status else None) |
|
394 | 394 | ) |
|
395 | 395 | |
|
396 | 396 | # get status if set ! |
|
397 | 397 | if status and change_status: |
|
398 | 398 | ChangesetStatusModel().set_status( |
|
399 | 399 | c.rhodecode_db_repo.repo_id, |
|
400 | 400 | status, |
|
401 | 401 | c.rhodecode_user.user_id, |
|
402 | 402 | comm, |
|
403 | 403 | pull_request=pull_request_id |
|
404 | 404 | ) |
|
405 | 405 | action_logger(self.rhodecode_user, |
|
406 | 406 | 'user_commented_pull_request:%s' % pull_request_id, |
|
407 | 407 | c.rhodecode_db_repo, self.ip_addr, self.sa) |
|
408 | 408 | |
|
409 | 409 | if request.POST.get('save_close'): |
|
410 | 410 | PullRequestModel().close_pull_request(pull_request_id) |
|
411 | 411 | action_logger(self.rhodecode_user, |
|
412 | 412 | 'user_closed_pull_request:%s' % pull_request_id, |
|
413 | 413 | c.rhodecode_db_repo, self.ip_addr, self.sa) |
|
414 | 414 | |
|
415 | 415 | Session().commit() |
|
416 | 416 | |
|
417 | 417 | if not request.environ.get('HTTP_X_PARTIAL_XHR'): |
|
418 | 418 | return redirect(h.url('pullrequest_show', repo_name=repo_name, |
|
419 | 419 | pull_request_id=pull_request_id)) |
|
420 | 420 | |
|
421 | 421 | data = { |
|
422 | 422 | 'target_id': h.safeid(h.safe_unicode(request.POST.get('f_path'))), |
|
423 | 423 | } |
|
424 | 424 | if comm: |
|
425 | 425 | c.co = comm |
|
426 | 426 | data.update(comm.get_dict()) |
|
427 | 427 | data.update({'rendered_text': |
|
428 | 428 | render('changeset/changeset_comment_block.html')}) |
|
429 | 429 | |
|
430 | 430 | return data |
|
431 | 431 | |
|
432 | 432 | @NotAnonymous() |
|
433 | 433 | @jsonify |
|
434 | 434 | def delete_comment(self, repo_name, comment_id): |
|
435 | 435 | co = ChangesetComment.get(comment_id) |
|
436 | 436 | if co.pull_request.is_closed(): |
|
437 | 437 | #don't allow deleting comments on closed pull request |
|
438 | 438 | raise HTTPForbidden() |
|
439 | 439 | |
|
440 | 440 | owner = lambda: co.author.user_id == c.rhodecode_user.user_id |
|
441 | 441 | if h.HasPermissionAny('hg.admin', 'repository.admin')() or owner: |
|
442 | 442 | ChangesetCommentsModel().delete(comment=co) |
|
443 | 443 | Session().commit() |
|
444 | 444 | return True |
|
445 | 445 | else: |
|
446 | 446 | raise HTTPForbidden() |
@@ -1,647 +1,766 b'' | |||
|
1 | 1 | # -*- coding: utf-8 -*- |
|
2 | 2 | """ |
|
3 | 3 | rhodecode.lib.diffs |
|
4 | 4 | ~~~~~~~~~~~~~~~~~~~ |
|
5 | 5 | |
|
6 | 6 | Set of diffing helpers, previously part of vcs |
|
7 | 7 | |
|
8 | 8 | |
|
9 | 9 | :created_on: Dec 4, 2011 |
|
10 | 10 | :author: marcink |
|
11 | 11 | :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com> |
|
12 | 12 | :original copyright: 2007-2008 by Armin Ronacher |
|
13 | 13 | :license: GPLv3, see COPYING for more details. |
|
14 | 14 | """ |
|
15 | 15 | # This program is free software: you can redistribute it and/or modify |
|
16 | 16 | # it under the terms of the GNU General Public License as published by |
|
17 | 17 | # the Free Software Foundation, either version 3 of the License, or |
|
18 | 18 | # (at your option) any later version. |
|
19 | 19 | # |
|
20 | 20 | # This program is distributed in the hope that it will be useful, |
|
21 | 21 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
22 | 22 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
23 | 23 | # GNU General Public License for more details. |
|
24 | 24 | # |
|
25 | 25 | # You should have received a copy of the GNU General Public License |
|
26 | 26 | # along with this program. If not, see <http://www.gnu.org/licenses/>. |
|
27 | 27 | |
|
28 | 28 | import re |
|
29 | 29 | import difflib |
|
30 | 30 | import logging |
|
31 | import traceback | |
|
31 | 32 | |
|
32 | 33 | from itertools import tee, imap |
|
33 | 34 | |
|
34 | 35 | from mercurial import patch |
|
35 | 36 | from mercurial.mdiff import diffopts |
|
36 | 37 | from mercurial.bundlerepo import bundlerepository |
|
37 | 38 | |
|
38 | 39 | from pylons.i18n.translation import _ |
|
39 | 40 | |
|
40 | 41 | from rhodecode.lib.compat import BytesIO |
|
41 | 42 | from rhodecode.lib.vcs.utils.hgcompat import localrepo |
|
42 | 43 | from rhodecode.lib.vcs.exceptions import VCSError |
|
43 | 44 | from rhodecode.lib.vcs.nodes import FileNode, SubModuleNode |
|
44 | 45 | from rhodecode.lib.vcs.backends.base import EmptyChangeset |
|
45 | 46 | from rhodecode.lib.helpers import escape |
|
46 | 47 | from rhodecode.lib.utils import make_ui |
|
47 | 48 | from rhodecode.lib.utils2 import safe_unicode |
|
48 | 49 | |
|
49 | 50 | log = logging.getLogger(__name__) |
|
50 | 51 | |
|
51 | 52 | |
|
52 | 53 | def wrap_to_table(str_): |
|
53 | 54 | return '''<table class="code-difftable"> |
|
54 | 55 | <tr class="line no-comment"> |
|
55 | 56 | <td class="lineno new"></td> |
|
56 | 57 | <td class="code no-comment"><pre>%s</pre></td> |
|
57 | 58 | </tr> |
|
58 | 59 | </table>''' % str_ |
|
59 | 60 | |
|
60 | 61 | |
|
61 | 62 | def wrapped_diff(filenode_old, filenode_new, cut_off_limit=None, |
|
62 | 63 | ignore_whitespace=True, line_context=3, |
|
63 | 64 | enable_comments=False): |
|
64 | 65 | """ |
|
65 | 66 | returns a wrapped diff into a table, checks for cut_off_limit and presents |
|
66 | 67 | proper message |
|
67 | 68 | """ |
|
68 | 69 | |
|
69 | 70 | if filenode_old is None: |
|
70 | 71 | filenode_old = FileNode(filenode_new.path, '', EmptyChangeset()) |
|
71 | 72 | |
|
72 | 73 | if filenode_old.is_binary or filenode_new.is_binary: |
|
73 | 74 | diff = wrap_to_table(_('binary file')) |
|
74 | 75 | stats = (0, 0) |
|
75 | 76 | size = 0 |
|
76 | 77 | |
|
77 | 78 | elif cut_off_limit != -1 and (cut_off_limit is None or |
|
78 | 79 | (filenode_old.size < cut_off_limit and filenode_new.size < cut_off_limit)): |
|
79 | 80 | |
|
80 | 81 | f_gitdiff = get_gitdiff(filenode_old, filenode_new, |
|
81 | 82 | ignore_whitespace=ignore_whitespace, |
|
82 | 83 | context=line_context) |
|
83 | 84 | diff_processor = DiffProcessor(f_gitdiff, format='gitdiff') |
|
84 | 85 | |
|
85 | 86 | diff = diff_processor.as_html(enable_comments=enable_comments) |
|
86 | 87 | stats = diff_processor.stat() |
|
87 | 88 | size = len(diff or '') |
|
88 | 89 | else: |
|
89 | 90 | diff = wrap_to_table(_('Changeset was too big and was cut off, use ' |
|
90 | 91 | 'diff menu to display this diff')) |
|
91 | 92 | stats = (0, 0) |
|
92 | 93 | size = 0 |
|
93 | 94 | if not diff: |
|
94 | 95 | submodules = filter(lambda o: isinstance(o, SubModuleNode), |
|
95 | 96 | [filenode_new, filenode_old]) |
|
96 | 97 | if submodules: |
|
97 | 98 | diff = wrap_to_table(escape('Submodule %r' % submodules[0])) |
|
98 | 99 | else: |
|
99 | 100 | diff = wrap_to_table(_('No changes detected')) |
|
100 | 101 | |
|
101 | 102 | cs1 = filenode_old.changeset.raw_id |
|
102 | 103 | cs2 = filenode_new.changeset.raw_id |
|
103 | 104 | |
|
104 | 105 | return size, cs1, cs2, diff, stats |
|
105 | 106 | |
|
106 | 107 | |
|
107 | 108 | def get_gitdiff(filenode_old, filenode_new, ignore_whitespace=True, context=3): |
|
108 | 109 | """ |
|
109 | 110 | Returns git style diff between given ``filenode_old`` and ``filenode_new``. |
|
110 | 111 | |
|
111 | 112 | :param ignore_whitespace: ignore whitespaces in diff |
|
112 | 113 | """ |
|
113 | 114 | # make sure we pass in default context |
|
114 | 115 | context = context or 3 |
|
115 | 116 | submodules = filter(lambda o: isinstance(o, SubModuleNode), |
|
116 | 117 | [filenode_new, filenode_old]) |
|
117 | 118 | if submodules: |
|
118 | 119 | return '' |
|
119 | 120 | |
|
120 | 121 | for filenode in (filenode_old, filenode_new): |
|
121 | 122 | if not isinstance(filenode, FileNode): |
|
122 | 123 | raise VCSError("Given object should be FileNode object, not %s" |
|
123 | 124 | % filenode.__class__) |
|
124 | 125 | |
|
125 | 126 | repo = filenode_new.changeset.repository |
|
126 | 127 | old_raw_id = getattr(filenode_old.changeset, 'raw_id', repo.EMPTY_CHANGESET) |
|
127 | 128 | new_raw_id = getattr(filenode_new.changeset, 'raw_id', repo.EMPTY_CHANGESET) |
|
128 | 129 | |
|
129 | 130 | vcs_gitdiff = repo.get_diff(old_raw_id, new_raw_id, filenode_new.path, |
|
130 | 131 |
|
|
131 | 132 | return vcs_gitdiff |
|
132 | 133 | |
|
134 | NEW_FILENODE = 1 | |
|
135 | DEL_FILENODE = 2 | |
|
136 | MOD_FILENODE = 3 | |
|
137 | RENAMED_FILENODE = 4 | |
|
138 | CHMOD_FILENODE = 5 | |
|
139 | ||
|
140 | ||
|
141 | class DiffLimitExceeded(Exception): | |
|
142 | pass | |
|
143 | ||
|
144 | ||
|
145 | class LimitedDiffContainer(object): | |
|
146 | ||
|
147 | def __init__(self, diff_limit, cur_diff_size, diff): | |
|
148 | self.diff = diff | |
|
149 | self.diff_limit = diff_limit | |
|
150 | self.cur_diff_size = cur_diff_size | |
|
151 | ||
|
152 | def __iter__(self): | |
|
153 | for l in self.diff: | |
|
154 | yield l | |
|
155 | ||
|
133 | 156 | |
|
134 | 157 | class DiffProcessor(object): |
|
135 | 158 | """ |
|
136 | Give it a unified diff and it returns a list of the files that were | |
|
159 | Give it a unified or git diff and it returns a list of the files that were | |
|
137 | 160 | mentioned in the diff together with a dict of meta information that |
|
138 | 161 | can be used to render it in a HTML template. |
|
139 | 162 | """ |
|
140 | 163 | _chunk_re = re.compile(r'@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@(.*)') |
|
141 | 164 | _newline_marker = '\\ No newline at end of file\n' |
|
165 | _git_header_re = re.compile(r""" | |
|
166 | #^diff[ ]--git | |
|
167 | [ ]a/(?P<a_path>.+?)[ ]b/(?P<b_path>.+?)\n | |
|
168 | (?:^similarity[ ]index[ ](?P<similarity_index>\d+)%\n | |
|
169 | ^rename[ ]from[ ](?P<rename_from>\S+)\n | |
|
170 | ^rename[ ]to[ ](?P<rename_to>\S+)(?:\n|$))? | |
|
171 | (?:^old[ ]mode[ ](?P<old_mode>\d+)\n | |
|
172 | ^new[ ]mode[ ](?P<new_mode>\d+)(?:\n|$))? | |
|
173 | (?:^new[ ]file[ ]mode[ ](?P<new_file_mode>.+)(?:\n|$))? | |
|
174 | (?:^deleted[ ]file[ ]mode[ ](?P<deleted_file_mode>.+)(?:\n|$))? | |
|
175 | (?:^index[ ](?P<a_blob_id>[0-9A-Fa-f]+) | |
|
176 | \.\.(?P<b_blob_id>[0-9A-Fa-f]+)[ ]?(?P<b_mode>.+)?(?:\n|$))? | |
|
177 | (?:^---[ ](a/(?P<a_file>.+)|/dev/null)(?:\n|$))? | |
|
178 | (?:^\+\+\+[ ](b/(?P<b_file>.+)|/dev/null)(?:\n|$))? | |
|
179 | """, re.VERBOSE | re.MULTILINE) | |
|
180 | _hg_header_re = re.compile(r""" | |
|
181 | #^diff[ ]--git | |
|
182 | [ ]a/(?P<a_path>.+?)[ ]b/(?P<b_path>.+?)\n | |
|
183 | (?:^similarity[ ]index[ ](?P<similarity_index>\d+)%(?:\n|$))? | |
|
184 | (?:^rename[ ]from[ ](?P<rename_from>\S+)\n | |
|
185 | ^rename[ ]to[ ](?P<rename_to>\S+)(?:\n|$))? | |
|
186 | (?:^old[ ]mode[ ](?P<old_mode>\d+)\n | |
|
187 | ^new[ ]mode[ ](?P<new_mode>\d+)(?:\n|$))? | |
|
188 | (?:^new[ ]file[ ]mode[ ](?P<new_file_mode>.+)(?:\n|$))? | |
|
189 | (?:^deleted[ ]file[ ]mode[ ](?P<deleted_file_mode>.+)(?:\n|$))? | |
|
190 | (?:^index[ ](?P<a_blob_id>[0-9A-Fa-f]+) | |
|
191 | \.\.(?P<b_blob_id>[0-9A-Fa-f]+)[ ]?(?P<b_mode>.+)?(?:\n|$))? | |
|
192 | (?:^---[ ](a/(?P<a_file>.+)|/dev/null)(?:\n|$))? | |
|
193 | (?:^\+\+\+[ ](b/(?P<b_file>.+)|/dev/null)(?:\n|$))? | |
|
194 | """, re.VERBOSE | re.MULTILINE) | |
|
142 | 195 | |
|
143 |
def __init__(self, diff, |
|
|
144 | """ | |
|
145 | :param diff: a text in diff format or generator | |
|
146 | :param format: format of diff passed, `udiff` or `gitdiff` | |
|
196 | def __init__(self, diff, vcs='hg', format='gitdiff', diff_limit=None): | |
|
147 | 197 |
|
|
148 | if isinstance(diff, basestring): | |
|
149 | diff = [diff] | |
|
198 | :param diff: a text in diff format | |
|
199 | :param vcs: type of version controll hg or git | |
|
200 | :param format: format of diff passed, `udiff` or `gitdiff` | |
|
201 | :param diff_limit: define the size of diff that is considered "big" | |
|
202 | based on that parameter cut off will be triggered, set to None | |
|
203 | to show full diff | |
|
204 | """ | |
|
205 | if not isinstance(diff, basestring): | |
|
206 | raise Exception('Diff must be a basestring got %s instead' % type(diff)) | |
|
150 | 207 | |
|
151 |
self._ |
|
|
152 |
self. |
|
|
208 | self._diff = diff | |
|
209 | self._format = format | |
|
153 | 210 | self.adds = 0 |
|
154 | 211 | self.removes = 0 |
|
155 | ||
|
156 | if isinstance(self.__udiff, basestring): | |
|
157 | self.lines = iter(self.__udiff.splitlines(1)) | |
|
212 | # calculate diff size | |
|
213 | self.diff_size = len(diff) | |
|
214 | self.diff_limit = diff_limit | |
|
215 | self.cur_diff_size = 0 | |
|
216 | self.parsed = False | |
|
217 | self.parsed_diff = [] | |
|
218 | self.vcs = vcs | |
|
158 | 219 | |
|
159 |
|
|
|
160 | udiff_copy = self.copy_iterator() | |
|
161 | self.lines = imap(self.escaper, self._parse_gitdiff(udiff_copy)) | |
|
162 | else: | |
|
163 | udiff_copy = self.copy_iterator() | |
|
164 | self.lines = imap(self.escaper, udiff_copy) | |
|
165 | ||
|
166 | # Select a differ. | |
|
167 | if differ == 'difflib': | |
|
220 | if format == 'gitdiff': | |
|
168 | 221 | self.differ = self._highlight_line_difflib |
|
222 | self._parser = self._parse_gitdiff | |
|
169 | 223 | else: |
|
170 | 224 | self.differ = self._highlight_line_udiff |
|
225 | self._parser = self._parse_udiff | |
|
171 | 226 | |
|
172 |
def |
|
|
173 | return string.replace('&', '&')\ | |
|
174 | .replace('<', '<')\ | |
|
175 | .replace('>', '>') | |
|
176 | ||
|
177 | def copy_iterator(self): | |
|
227 | def _copy_iterator(self): | |
|
178 | 228 | """ |
|
179 | 229 | make a fresh copy of generator, we should not iterate thru |
|
180 | 230 | an original as it's needed for repeating operations on |
|
181 | 231 | this instance of DiffProcessor |
|
182 | 232 | """ |
|
183 | 233 | self.__udiff, iterator_copy = tee(self.__udiff) |
|
184 | 234 | return iterator_copy |
|
185 | 235 | |
|
186 |
def _e |
|
|
236 | def _escaper(self, string): | |
|
187 | 237 | """ |
|
188 | Extract the operation (A/M/D), filename and revision hint from a line. | |
|
238 | Escaper for diff escapes special chars and checks the diff limit | |
|
239 | ||
|
240 | :param string: | |
|
241 | :type string: | |
|
189 | 242 | """ |
|
190 | 243 | |
|
191 | try: | |
|
192 | if line1.startswith('--- ') and line2.startswith('+++ '): | |
|
193 | l1 = line1[4:].split(None, 1) | |
|
194 | old_filename = (l1[0].replace('a/', '', 1) | |
|
195 | if len(l1) >= 1 else None) | |
|
196 | old_rev = l1[1] if len(l1) == 2 else 'old' | |
|
244 | self.cur_diff_size += len(string) | |
|
197 | 245 | |
|
198 | l2 = line2[4:].split(None, 1) | |
|
199 | new_filename = (l2[0].replace('b/', '', 1) | |
|
200 | if len(l1) >= 1 else None) | |
|
201 | new_rev = l2[1] if len(l2) == 2 else 'new' | |
|
246 | # escaper get's iterated on each .next() call and it checks if each | |
|
247 | # parsed line doesn't exceed the diff limit | |
|
248 | if self.diff_limit is not None and self.cur_diff_size > self.diff_limit: | |
|
249 | raise DiffLimitExceeded('Diff Limit Exceeded') | |
|
202 | 250 | |
|
203 | filename = (old_filename | |
|
204 | if old_filename != '/dev/null' else new_filename) | |
|
205 | ||
|
206 | operation = 'D' if new_filename == '/dev/null' else None | |
|
207 | if not operation: | |
|
208 | operation = 'M' if old_filename != '/dev/null' else 'A' | |
|
251 | return safe_unicode(string).replace('&', '&')\ | |
|
252 | .replace('<', '<')\ | |
|
253 | .replace('>', '>') | |
|
209 | 254 | |
|
210 | return operation, filename, new_rev, old_rev | |
|
211 | except (ValueError, IndexError): | |
|
212 | pass | |
|
255 | def _line_counter(self, l): | |
|
256 | """ | |
|
257 | Checks each line and bumps total adds/removes for this diff | |
|
213 | 258 |
|
|
214 | return None, None, None, None | |
|
215 | ||
|
216 | def _parse_gitdiff(self, diffiterator): | |
|
217 | def line_decoder(l): | |
|
259 | :param l: | |
|
260 | """ | |
|
218 | 261 |
|
|
219 | 262 |
|
|
220 | 263 |
|
|
221 | 264 |
|
|
222 |
|
|
|
223 | ||
|
224 | output = list(diffiterator) | |
|
225 | size = len(output) | |
|
226 | ||
|
227 | if size == 2: | |
|
228 | l = [] | |
|
229 | l.extend([output[0]]) | |
|
230 | l.extend(output[1].splitlines(1)) | |
|
231 | return map(line_decoder, l) | |
|
232 | elif size == 1: | |
|
233 | return map(line_decoder, output[0].splitlines(1)) | |
|
234 | elif size == 0: | |
|
235 | return [] | |
|
236 | ||
|
237 | raise Exception('wrong size of diff %s' % size) | |
|
265 | return l | |
|
238 | 266 | |
|
239 | 267 | def _highlight_line_difflib(self, line, next_): |
|
240 | 268 | """ |
|
241 | 269 | Highlight inline changes in both lines. |
|
242 | 270 | """ |
|
243 | 271 | |
|
244 | 272 | if line['action'] == 'del': |
|
245 | 273 | old, new = line, next_ |
|
246 | 274 | else: |
|
247 | 275 | old, new = next_, line |
|
248 | 276 | |
|
249 | 277 | oldwords = re.split(r'(\W)', old['line']) |
|
250 | 278 | newwords = re.split(r'(\W)', new['line']) |
|
251 | 279 | |
|
252 | 280 | sequence = difflib.SequenceMatcher(None, oldwords, newwords) |
|
253 | 281 | |
|
254 | 282 | oldfragments, newfragments = [], [] |
|
255 | 283 | for tag, i1, i2, j1, j2 in sequence.get_opcodes(): |
|
256 | 284 | oldfrag = ''.join(oldwords[i1:i2]) |
|
257 | 285 | newfrag = ''.join(newwords[j1:j2]) |
|
258 | 286 | if tag != 'equal': |
|
259 | 287 | if oldfrag: |
|
260 | 288 | oldfrag = '<del>%s</del>' % oldfrag |
|
261 | 289 | if newfrag: |
|
262 | 290 | newfrag = '<ins>%s</ins>' % newfrag |
|
263 | 291 | oldfragments.append(oldfrag) |
|
264 | 292 | newfragments.append(newfrag) |
|
265 | 293 | |
|
266 | 294 | old['line'] = "".join(oldfragments) |
|
267 | 295 | new['line'] = "".join(newfragments) |
|
268 | 296 | |
|
269 | 297 | def _highlight_line_udiff(self, line, next_): |
|
270 | 298 | """ |
|
271 | 299 | Highlight inline changes in both lines. |
|
272 | 300 | """ |
|
273 | 301 | start = 0 |
|
274 | 302 | limit = min(len(line['line']), len(next_['line'])) |
|
275 | 303 | while start < limit and line['line'][start] == next_['line'][start]: |
|
276 | 304 | start += 1 |
|
277 | 305 | end = -1 |
|
278 | 306 | limit -= start |
|
279 | 307 | while -end <= limit and line['line'][end] == next_['line'][end]: |
|
280 | 308 | end -= 1 |
|
281 | 309 | end += 1 |
|
282 | 310 | if start or end: |
|
283 | 311 | def do(l): |
|
284 | 312 | last = end + len(l['line']) |
|
285 | 313 | if l['action'] == 'add': |
|
286 | 314 | tag = 'ins' |
|
287 | 315 | else: |
|
288 | 316 | tag = 'del' |
|
289 | 317 | l['line'] = '%s<%s>%s</%s>%s' % ( |
|
290 | 318 | l['line'][:start], |
|
291 | 319 | tag, |
|
292 | 320 | l['line'][start:last], |
|
293 | 321 | tag, |
|
294 | 322 | l['line'][last:] |
|
295 | 323 | ) |
|
296 | 324 | do(line) |
|
297 | 325 | do(next_) |
|
298 | 326 | |
|
327 | def _get_header(self, diff_chunk): | |
|
328 | """ | |
|
329 | parses the diff header, and returns parts, and leftover diff | |
|
330 | parts consists of 14 elements:: | |
|
331 | ||
|
332 | a_path, b_path, similarity_index, rename_from, rename_to, | |
|
333 | old_mode, new_mode, new_file_mode, deleted_file_mode, | |
|
334 | a_blob_id, b_blob_id, b_mode, a_file, b_file | |
|
335 | ||
|
336 | :param diff_chunk: | |
|
337 | :type diff_chunk: | |
|
338 | """ | |
|
339 | ||
|
340 | if self.vcs == 'git': | |
|
341 | match = self._git_header_re.match(diff_chunk) | |
|
342 | diff = diff_chunk[match.end():] | |
|
343 | return match.groupdict(), imap(self._escaper, diff.splitlines(1)) | |
|
344 | elif self.vcs == 'hg': | |
|
345 | match = self._hg_header_re.match(diff_chunk) | |
|
346 | diff = diff_chunk[match.end():] | |
|
347 | return match.groupdict(), imap(self._escaper, diff.splitlines(1)) | |
|
348 | else: | |
|
349 | raise Exception('VCS type %s is not supported' % self.vcs) | |
|
350 | ||
|
351 | def _parse_gitdiff(self, inline_diff=True): | |
|
352 | _files = [] | |
|
353 | diff_container = lambda arg: arg | |
|
354 | ||
|
355 | ##split the diff in chunks of separate --git a/file b/file chunks | |
|
356 | for raw_diff in ('\n' + self._diff).split('\ndiff --git')[1:]: | |
|
357 | binary = False | |
|
358 | binary_msg = 'unknown binary' | |
|
359 | head, diff = self._get_header(raw_diff) | |
|
360 | ||
|
361 | if not head['a_file'] and head['b_file']: | |
|
362 | op = 'A' | |
|
363 | elif head['a_file'] and head['b_file']: | |
|
364 | op = 'M' | |
|
365 | elif head['a_file'] and not head['b_file']: | |
|
366 | op = 'D' | |
|
367 | else: | |
|
368 | #probably we're dealing with a binary file 1 | |
|
369 | binary = True | |
|
370 | if head['deleted_file_mode']: | |
|
371 | op = 'D' | |
|
372 | stats = ['b', DEL_FILENODE] | |
|
373 | binary_msg = 'deleted binary file' | |
|
374 | elif head['new_file_mode']: | |
|
375 | op = 'A' | |
|
376 | stats = ['b', NEW_FILENODE] | |
|
377 | binary_msg = 'new binary file %s' % head['new_file_mode'] | |
|
378 | else: | |
|
379 | if head['new_mode'] and head['old_mode']: | |
|
380 | stats = ['b', CHMOD_FILENODE] | |
|
381 | op = 'M' | |
|
382 | binary_msg = ('modified binary file chmod %s => %s' | |
|
383 | % (head['old_mode'], head['new_mode'])) | |
|
384 | elif (head['rename_from'] and head['rename_to'] | |
|
385 | and head['rename_from'] != head['rename_to']): | |
|
386 | stats = ['b', RENAMED_FILENODE] | |
|
387 | op = 'M' | |
|
388 | binary_msg = ('file renamed from %s to %s' | |
|
389 | % (head['rename_from'], head['rename_to'])) | |
|
390 | else: | |
|
391 | stats = ['b', MOD_FILENODE] | |
|
392 | op = 'M' | |
|
393 | binary_msg = 'modified binary file' | |
|
394 | ||
|
395 | if not binary: | |
|
396 | try: | |
|
397 | chunks, stats = self._parse_lines(diff) | |
|
398 | except DiffLimitExceeded: | |
|
399 | diff_container = lambda _diff: LimitedDiffContainer( | |
|
400 | self.diff_limit, | |
|
401 | self.cur_diff_size, | |
|
402 | _diff) | |
|
403 | break | |
|
404 | else: | |
|
405 | chunks = [] | |
|
406 | chunks.append([{ | |
|
407 | 'old_lineno': '', | |
|
408 | 'new_lineno': '', | |
|
409 | 'action': 'binary', | |
|
410 | 'line': binary_msg, | |
|
411 | }]) | |
|
412 | ||
|
413 | _files.append({ | |
|
414 | 'filename': head['b_path'], | |
|
415 | 'old_revision': head['a_blob_id'], | |
|
416 | 'new_revision': head['b_blob_id'], | |
|
417 | 'chunks': chunks, | |
|
418 | 'operation': op, | |
|
419 | 'stats': stats, | |
|
420 | }) | |
|
421 | ||
|
422 | sorter = lambda info: {'A': 0, 'M': 1, 'D': 2}.get(info['operation']) | |
|
423 | ||
|
424 | if inline_diff is False: | |
|
425 | return diff_container(sorted(_files, key=sorter)) | |
|
426 | ||
|
427 | # highlight inline changes | |
|
428 | for diff_data in _files: | |
|
429 | for chunk in diff_data['chunks']: | |
|
430 | lineiter = iter(chunk) | |
|
431 | try: | |
|
432 | while 1: | |
|
433 | line = lineiter.next() | |
|
434 | if line['action'] not in ['unmod', 'context']: | |
|
435 | nextline = lineiter.next() | |
|
436 | if nextline['action'] in ['unmod', 'context'] or \ | |
|
437 | nextline['action'] == line['action']: | |
|
438 | continue | |
|
439 | self.differ(line, nextline) | |
|
440 | except StopIteration: | |
|
441 | pass | |
|
442 | ||
|
443 | return diff_container(sorted(_files, key=sorter)) | |
|
444 | ||
|
299 | 445 | def _parse_udiff(self, inline_diff=True): |
|
446 | raise NotImplementedError() | |
|
447 | ||
|
448 | def _parse_lines(self, diff): | |
|
300 | 449 | """ |
|
301 | 450 | Parse the diff an return data for the template. |
|
302 | 451 | """ |
|
303 | lineiter = self.lines | |
|
304 | 452 | |
|
305 | files = [] | |
|
453 | lineiter = iter(diff) | |
|
454 | stats = [0, 0] | |
|
455 | ||
|
306 | 456 | try: |
|
307 | line = lineiter.next() | |
|
308 | while 1: | |
|
309 | # continue until we found the old file | |
|
310 | if not line.startswith('--- '): | |
|
311 | line = lineiter.next() | |
|
312 | continue | |
|
313 | ||
|
314 | 457 |
|
|
315 | stats = [0, 0] | |
|
316 | operation, filename, old_rev, new_rev = \ | |
|
317 | self._extract_rev(line, lineiter.next()) | |
|
318 | files.append({ | |
|
319 | 'filename': filename, | |
|
320 | 'old_revision': old_rev, | |
|
321 | 'new_revision': new_rev, | |
|
322 | 'chunks': chunks, | |
|
323 | 'operation': operation, | |
|
324 | 'stats': stats, | |
|
325 | }) | |
|
326 | ||
|
327 | 458 |
|
|
328 | 459 | |
|
329 | 460 |
|
|
461 | lines = [] | |
|
462 | chunks.append(lines) | |
|
463 | ||
|
330 | 464 |
|
|
465 | ||
|
331 | 466 |
|
|
332 | 467 |
|
|
333 | 468 | |
|
334 | lines = [] | |
|
335 | chunks.append(lines) | |
|
336 | ||
|
337 | old_line, old_end, new_line, new_end = \ | |
|
338 | [int(x or 1) for x in match.groups()[:-1]] | |
|
469 | gr = match.groups() | |
|
470 | (old_line, old_end, | |
|
471 | new_line, new_end) = [int(x or 1) for x in gr[:-1]] | |
|
339 | 472 |
|
|
340 | 473 |
|
|
341 | gr = match.groups() | |
|
474 | ||
|
342 | 475 |
|
|
343 | 476 |
|
|
344 | 477 |
|
|
345 | 478 | |
|
346 | 479 |
|
|
347 | 480 |
|
|
348 | 481 |
|
|
349 | 482 |
|
|
350 | 483 |
|
|
351 | 484 |
|
|
352 | 485 |
|
|
353 | 486 |
|
|
354 | 487 |
|
|
355 | 488 | |
|
356 | 489 |
|
|
357 | 490 | |
|
358 | 491 |
|
|
359 | 492 |
|
|
360 | 493 |
|
|
361 | 494 |
|
|
362 | 495 |
|
|
363 | 496 |
|
|
364 | 497 |
|
|
365 | 498 |
|
|
366 | 499 |
|
|
367 | 500 | |
|
368 | 501 |
|
|
369 | 502 | |
|
370 | 503 |
|
|
371 | 504 |
|
|
372 | 505 |
|
|
373 | 506 |
|
|
374 | 507 |
|
|
375 | 508 |
|
|
376 | 509 |
|
|
377 | 510 |
|
|
378 | 511 |
|
|
379 | 512 |
|
|
380 | 513 |
|
|
381 | 514 |
|
|
382 | 515 |
|
|
383 | 516 |
|
|
384 | 517 | |
|
385 | 518 |
|
|
386 | 519 |
|
|
387 | 520 |
|
|
388 | 521 |
|
|
389 | 522 |
|
|
390 | 523 |
|
|
391 | 524 |
|
|
392 | 525 |
|
|
393 | 526 |
|
|
394 | 527 | |
|
395 | 528 |
|
|
529 | ||
|
396 | 530 |
|
|
397 | 531 |
|
|
398 | 532 |
|
|
399 | 533 |
|
|
400 | 534 |
|
|
401 | 535 |
|
|
402 | 536 |
|
|
403 | 537 |
|
|
404 | 538 |
|
|
405 | 539 | |
|
406 | 540 | except StopIteration: |
|
407 | 541 | pass |
|
408 | ||
|
409 | sorter = lambda info: {'A': 0, 'M': 1, 'D': 2}.get(info['operation']) | |
|
410 | if inline_diff is False: | |
|
411 | return sorted(files, key=sorter) | |
|
412 | ||
|
413 | # highlight inline changes | |
|
414 | for diff_data in files: | |
|
415 | for chunk in diff_data['chunks']: | |
|
416 | lineiter = iter(chunk) | |
|
417 | try: | |
|
418 | while 1: | |
|
419 | line = lineiter.next() | |
|
420 | if line['action'] not in ['unmod', 'context']: | |
|
421 | nextline = lineiter.next() | |
|
422 | if nextline['action'] in ['unmod', 'context'] or \ | |
|
423 | nextline['action'] == line['action']: | |
|
424 | continue | |
|
425 | self.differ(line, nextline) | |
|
426 | except StopIteration: | |
|
427 | pass | |
|
428 | ||
|
429 | return sorted(files, key=sorter) | |
|
430 | ||
|
431 | def prepare(self, inline_diff=True): | |
|
432 | """ | |
|
433 | Prepare the passed udiff for HTML rendering. It'l return a list | |
|
434 | of dicts | |
|
435 | """ | |
|
436 | return self._parse_udiff(inline_diff=inline_diff) | |
|
542 | return chunks, stats | |
|
437 | 543 | |
|
438 | 544 | def _safe_id(self, idstring): |
|
439 | 545 | """Make a string safe for including in an id attribute. |
|
440 | 546 | |
|
441 | 547 | The HTML spec says that id attributes 'must begin with |
|
442 | 548 | a letter ([A-Za-z]) and may be followed by any number |
|
443 | 549 | of letters, digits ([0-9]), hyphens ("-"), underscores |
|
444 | 550 | ("_"), colons (":"), and periods (".")'. These regexps |
|
445 | 551 | are slightly over-zealous, in that they remove colons |
|
446 | 552 | and periods unnecessarily. |
|
447 | 553 | |
|
448 | 554 | Whitespace is transformed into underscores, and then |
|
449 | 555 | anything which is not a hyphen or a character that |
|
450 | 556 | matches \w (alphanumerics and underscore) is removed. |
|
451 | 557 | |
|
452 | 558 | """ |
|
453 | 559 | # Transform all whitespace to underscore |
|
454 | 560 | idstring = re.sub(r'\s', "_", '%s' % idstring) |
|
455 | 561 | # Remove everything that is not a hyphen or a member of \w |
|
456 | 562 | idstring = re.sub(r'(?!-)\W', "", idstring).lower() |
|
457 | 563 | return idstring |
|
458 | 564 | |
|
459 | def raw_diff(self): | |
|
565 | def prepare(self, inline_diff=True): | |
|
566 | """ | |
|
567 | Prepare the passed udiff for HTML rendering. It'l return a list | |
|
568 | of dicts with diff information | |
|
569 | """ | |
|
570 | parsed = self._parser(inline_diff=inline_diff) | |
|
571 | self.parsed = True | |
|
572 | self.parsed_diff = parsed | |
|
573 | return parsed | |
|
574 | ||
|
575 | def as_raw(self, diff_lines=None): | |
|
460 | 576 | """ |
|
461 | 577 | Returns raw string as udiff |
|
462 | 578 | """ |
|
463 | udiff_copy = self.copy_iterator() | |
|
464 | if self.__format == 'gitdiff': | |
|
465 | udiff_copy = self._parse_gitdiff(udiff_copy) | |
|
466 | return u''.join(udiff_copy) | |
|
579 | return u''.join(imap(self._line_counter, self._diff.splitlines(1))) | |
|
467 | 580 | |
|
468 | 581 | def as_html(self, table_class='code-difftable', line_class='line', |
|
469 | 582 | new_lineno_class='lineno old', old_lineno_class='lineno new', |
|
470 |
code_class='code', enable_comments=False, d |
|
|
583 | code_class='code', enable_comments=False, parsed_lines=None): | |
|
471 | 584 | """ |
|
472 | 585 | Return given diff as html table with customized css classes |
|
473 | 586 | """ |
|
474 | 587 | def _link_to_if(condition, label, url): |
|
475 | 588 | """ |
|
476 | 589 | Generates a link if condition is meet or just the label if not. |
|
477 | 590 | """ |
|
478 | 591 | |
|
479 | 592 | if condition: |
|
480 | 593 | return '''<a href="%(url)s">%(label)s</a>''' % { |
|
481 | 594 | 'url': url, |
|
482 | 595 | 'label': label |
|
483 | 596 | } |
|
484 | 597 | else: |
|
485 | 598 | return label |
|
486 | if diff_lines is None: | |
|
487 |
|
|
|
599 | if not self.parsed: | |
|
600 | self.prepare() | |
|
601 | ||
|
602 | diff_lines = self.parsed_diff | |
|
603 | if parsed_lines: | |
|
604 | diff_lines = parsed_lines | |
|
605 | ||
|
488 | 606 | _html_empty = True |
|
489 | 607 | _html = [] |
|
490 | 608 | _html.append('''<table class="%(table_class)s">\n''' % { |
|
491 | 609 | 'table_class': table_class |
|
492 | 610 | }) |
|
611 | ||
|
493 | 612 | for diff in diff_lines: |
|
494 | 613 | for line in diff['chunks']: |
|
495 | 614 | _html_empty = False |
|
496 | 615 | for change in line: |
|
497 | 616 | _html.append('''<tr class="%(lc)s %(action)s">\n''' % { |
|
498 | 617 | 'lc': line_class, |
|
499 | 618 | 'action': change['action'] |
|
500 | 619 | }) |
|
501 | 620 | anchor_old_id = '' |
|
502 | 621 | anchor_new_id = '' |
|
503 | 622 | anchor_old = "%(filename)s_o%(oldline_no)s" % { |
|
504 | 623 | 'filename': self._safe_id(diff['filename']), |
|
505 | 624 | 'oldline_no': change['old_lineno'] |
|
506 | 625 | } |
|
507 | 626 | anchor_new = "%(filename)s_n%(oldline_no)s" % { |
|
508 | 627 | 'filename': self._safe_id(diff['filename']), |
|
509 | 628 | 'oldline_no': change['new_lineno'] |
|
510 | 629 | } |
|
511 | 630 | cond_old = (change['old_lineno'] != '...' and |
|
512 | 631 | change['old_lineno']) |
|
513 | 632 | cond_new = (change['new_lineno'] != '...' and |
|
514 | 633 | change['new_lineno']) |
|
515 | 634 | if cond_old: |
|
516 | 635 | anchor_old_id = 'id="%s"' % anchor_old |
|
517 | 636 | if cond_new: |
|
518 | 637 | anchor_new_id = 'id="%s"' % anchor_new |
|
519 | 638 | ########################################################### |
|
520 | 639 | # OLD LINE NUMBER |
|
521 | 640 | ########################################################### |
|
522 | 641 | _html.append('''\t<td %(a_id)s class="%(olc)s">''' % { |
|
523 | 642 | 'a_id': anchor_old_id, |
|
524 | 643 | 'olc': old_lineno_class |
|
525 | 644 | }) |
|
526 | 645 | |
|
527 | 646 | _html.append('''%(link)s''' % { |
|
528 | 647 | 'link': _link_to_if(True, change['old_lineno'], |
|
529 | 648 | '#%s' % anchor_old) |
|
530 | 649 | }) |
|
531 | 650 | _html.append('''</td>\n''') |
|
532 | 651 | ########################################################### |
|
533 | 652 | # NEW LINE NUMBER |
|
534 | 653 | ########################################################### |
|
535 | 654 | |
|
536 | 655 | _html.append('''\t<td %(a_id)s class="%(nlc)s">''' % { |
|
537 | 656 | 'a_id': anchor_new_id, |
|
538 | 657 | 'nlc': new_lineno_class |
|
539 | 658 | }) |
|
540 | 659 | |
|
541 | 660 | _html.append('''%(link)s''' % { |
|
542 | 661 | 'link': _link_to_if(True, change['new_lineno'], |
|
543 | 662 | '#%s' % anchor_new) |
|
544 | 663 | }) |
|
545 | 664 | _html.append('''</td>\n''') |
|
546 | 665 | ########################################################### |
|
547 | 666 | # CODE |
|
548 | 667 | ########################################################### |
|
549 | 668 | comments = '' if enable_comments else 'no-comment' |
|
550 | 669 | _html.append('''\t<td class="%(cc)s %(inc)s">''' % { |
|
551 | 670 | 'cc': code_class, |
|
552 | 671 | 'inc': comments |
|
553 | 672 | }) |
|
554 | 673 | _html.append('''\n\t\t<pre>%(code)s</pre>\n''' % { |
|
555 | 674 | 'code': change['line'] |
|
556 | 675 | }) |
|
557 | 676 | |
|
558 | 677 | _html.append('''\t</td>''') |
|
559 | 678 | _html.append('''\n</tr>\n''') |
|
560 | 679 | _html.append('''</table>''') |
|
561 | 680 | if _html_empty: |
|
562 | 681 | return None |
|
563 | 682 | return ''.join(_html) |
|
564 | 683 | |
|
565 | 684 | def stat(self): |
|
566 | 685 | """ |
|
567 | 686 | Returns tuple of added, and removed lines for this instance |
|
568 | 687 | """ |
|
569 | 688 | return self.adds, self.removes |
|
570 | 689 | |
|
571 | 690 | |
|
572 | 691 | class InMemoryBundleRepo(bundlerepository): |
|
573 | 692 | def __init__(self, ui, path, bundlestream): |
|
574 | 693 | self._tempparent = None |
|
575 | 694 | localrepo.localrepository.__init__(self, ui, path) |
|
576 | 695 | self.ui.setconfig('phases', 'publish', False) |
|
577 | 696 | |
|
578 | 697 | self.bundle = bundlestream |
|
579 | 698 | |
|
580 | 699 | # dict with the mapping 'filename' -> position in the bundle |
|
581 | 700 | self.bundlefilespos = {} |
|
582 | 701 | |
|
583 | 702 | |
|
584 | 703 | def differ(org_repo, org_ref, other_repo, other_ref, discovery_data=None, |
|
585 | bundle_compare=False): | |
|
704 | bundle_compare=False, context=3, ignore_whitespace=False): | |
|
586 | 705 | """ |
|
587 |
General differ between branches, bookmarks |
|
|
706 | General differ between branches, bookmarks, revisions of two remote related | |
|
588 | 707 | repositories |
|
589 | 708 | |
|
590 | 709 | :param org_repo: |
|
591 | 710 | :type org_repo: |
|
592 | 711 | :param org_ref: |
|
593 | 712 | :type org_ref: |
|
594 | 713 | :param other_repo: |
|
595 | 714 | :type other_repo: |
|
596 | 715 | :param other_ref: |
|
597 | 716 | :type other_ref: |
|
598 | 717 | """ |
|
599 | 718 | |
|
600 | 719 | bundlerepo = None |
|
601 |
ignore_whitespace = |
|
|
602 |
context = |
|
|
720 | ignore_whitespace = ignore_whitespace | |
|
721 | context = context | |
|
603 | 722 | org_repo = org_repo.scm_instance._repo |
|
604 | 723 | other_repo = other_repo.scm_instance._repo |
|
605 | 724 | opts = diffopts(git=True, ignorews=ignore_whitespace, context=context) |
|
606 | 725 | org_ref = org_ref[1] |
|
607 | 726 | other_ref = other_ref[1] |
|
608 | 727 | |
|
609 | 728 | if org_repo != other_repo and bundle_compare: |
|
610 | 729 | |
|
611 | 730 | common, incoming, rheads = discovery_data |
|
612 | 731 | other_repo_peer = localrepo.locallegacypeer(other_repo.local()) |
|
613 | 732 | # create a bundle (uncompressed if other repo is not local) |
|
614 | 733 | if other_repo_peer.capable('getbundle') and incoming: |
|
615 | 734 | # disable repo hooks here since it's just bundle ! |
|
616 | 735 | # patch and reset hooks section of UI config to not run any |
|
617 | 736 | # hooks on fetching archives with subrepos |
|
618 | 737 | for k, _ in other_repo.ui.configitems('hooks'): |
|
619 | 738 | other_repo.ui.setconfig('hooks', k, None) |
|
620 | 739 | |
|
621 | 740 | unbundle = other_repo.getbundle('incoming', common=common, |
|
622 | 741 | heads=None) |
|
623 | 742 | |
|
624 | 743 | buf = BytesIO() |
|
625 | 744 | while True: |
|
626 | 745 | chunk = unbundle._stream.read(1024 * 4) |
|
627 | 746 | if not chunk: |
|
628 | 747 | break |
|
629 | 748 | buf.write(chunk) |
|
630 | 749 | |
|
631 | 750 | buf.seek(0) |
|
632 | 751 | # replace chunked _stream with data that can do tell() and seek() |
|
633 | 752 | unbundle._stream = buf |
|
634 | 753 | |
|
635 | 754 | ui = make_ui('db') |
|
636 | 755 | bundlerepo = InMemoryBundleRepo(ui, path=org_repo.root, |
|
637 | 756 | bundlestream=unbundle) |
|
638 | 757 | |
|
639 | 758 | return ''.join(patch.diff(bundlerepo or org_repo, |
|
640 | 759 | node1=org_repo[org_ref].node(), |
|
641 | 760 | node2=other_repo[other_ref].node(), |
|
642 | 761 | opts=opts)) |
|
643 | 762 | else: |
|
644 | 763 | log.debug('running diff between %s@%s and %s@%s' |
|
645 | 764 | % (org_repo, org_ref, other_repo, other_ref)) |
|
646 | 765 | return ''.join(patch.diff(org_repo, node1=org_ref, node2=other_ref, |
|
647 | 766 | opts=opts)) |
@@ -1,1104 +1,1111 b'' | |||
|
1 | 1 | """Helper functions |
|
2 | 2 | |
|
3 | 3 | Consists of functions to typically be used within templates, but also |
|
4 | 4 | available to Controllers. This module is available to both as 'h'. |
|
5 | 5 | """ |
|
6 | 6 | import random |
|
7 | 7 | import hashlib |
|
8 | 8 | import StringIO |
|
9 | 9 | import urllib |
|
10 | 10 | import math |
|
11 | 11 | import logging |
|
12 | 12 | import re |
|
13 | 13 | import urlparse |
|
14 | 14 | |
|
15 | 15 | from datetime import datetime |
|
16 | 16 | from pygments.formatters.html import HtmlFormatter |
|
17 | 17 | from pygments import highlight as code_highlight |
|
18 | 18 | from pylons import url, request, config |
|
19 | 19 | from pylons.i18n.translation import _, ungettext |
|
20 | 20 | from hashlib import md5 |
|
21 | 21 | |
|
22 | 22 | from webhelpers.html import literal, HTML, escape |
|
23 | 23 | from webhelpers.html.tools import * |
|
24 | 24 | from webhelpers.html.builder import make_tag |
|
25 | 25 | from webhelpers.html.tags import auto_discovery_link, checkbox, css_classes, \ |
|
26 | 26 | end_form, file, form, hidden, image, javascript_link, link_to, \ |
|
27 | 27 | link_to_if, link_to_unless, ol, required_legend, select, stylesheet_link, \ |
|
28 | 28 | submit, text, password, textarea, title, ul, xml_declaration, radio |
|
29 | 29 | from webhelpers.html.tools import auto_link, button_to, highlight, \ |
|
30 | 30 | js_obfuscate, mail_to, strip_links, strip_tags, tag_re |
|
31 | 31 | from webhelpers.number import format_byte_size, format_bit_size |
|
32 | 32 | from webhelpers.pylonslib import Flash as _Flash |
|
33 | 33 | from webhelpers.pylonslib.secure_form import secure_form |
|
34 | 34 | from webhelpers.text import chop_at, collapse, convert_accented_entities, \ |
|
35 | 35 | convert_misc_entities, lchop, plural, rchop, remove_formatting, \ |
|
36 | 36 | replace_whitespace, urlify, truncate, wrap_paragraphs |
|
37 | 37 | from webhelpers.date import time_ago_in_words |
|
38 | 38 | from webhelpers.paginate import Page |
|
39 | 39 | from webhelpers.html.tags import _set_input_attrs, _set_id_attr, \ |
|
40 | 40 | convert_boolean_attrs, NotGiven, _make_safe_id_component |
|
41 | 41 | |
|
42 | 42 | from rhodecode.lib.annotate import annotate_highlight |
|
43 | 43 | from rhodecode.lib.utils import repo_name_slug |
|
44 | 44 | from rhodecode.lib.utils2 import str2bool, safe_unicode, safe_str, \ |
|
45 | 45 | get_changeset_safe, datetime_to_time, time_to_datetime, AttributeDict |
|
46 | 46 | from rhodecode.lib.markup_renderer import MarkupRenderer |
|
47 | 47 | from rhodecode.lib.vcs.exceptions import ChangesetDoesNotExistError |
|
48 | 48 | from rhodecode.lib.vcs.backends.base import BaseChangeset |
|
49 | 49 | from rhodecode.config.conf import DATE_FORMAT, DATETIME_FORMAT |
|
50 | 50 | from rhodecode.model.changeset_status import ChangesetStatusModel |
|
51 | 51 | from rhodecode.model.db import URL_SEP, Permission |
|
52 | 52 | |
|
53 | 53 | log = logging.getLogger(__name__) |
|
54 | 54 | |
|
55 | 55 | |
|
56 | 56 | html_escape_table = { |
|
57 | 57 | "&": "&", |
|
58 | 58 | '"': """, |
|
59 | 59 | "'": "'", |
|
60 | 60 | ">": ">", |
|
61 | 61 | "<": "<", |
|
62 | 62 | } |
|
63 | 63 | |
|
64 | 64 | |
|
65 | 65 | def html_escape(text): |
|
66 | 66 | """Produce entities within text.""" |
|
67 | 67 | return "".join(html_escape_table.get(c, c) for c in text) |
|
68 | 68 | |
|
69 | 69 | |
|
70 | 70 | def shorter(text, size=20): |
|
71 | 71 | postfix = '...' |
|
72 | 72 | if len(text) > size: |
|
73 | 73 | return text[:size - len(postfix)] + postfix |
|
74 | 74 | return text |
|
75 | 75 | |
|
76 | 76 | |
|
77 | 77 | def _reset(name, value=None, id=NotGiven, type="reset", **attrs): |
|
78 | 78 | """ |
|
79 | 79 | Reset button |
|
80 | 80 | """ |
|
81 | 81 | _set_input_attrs(attrs, type, name, value) |
|
82 | 82 | _set_id_attr(attrs, id, name) |
|
83 | 83 | convert_boolean_attrs(attrs, ["disabled"]) |
|
84 | 84 | return HTML.input(**attrs) |
|
85 | 85 | |
|
86 | 86 | reset = _reset |
|
87 | 87 | safeid = _make_safe_id_component |
|
88 | 88 | |
|
89 | 89 | |
|
90 | 90 | def FID(raw_id, path): |
|
91 | 91 | """ |
|
92 | 92 | Creates a uniqe ID for filenode based on it's hash of path and revision |
|
93 | 93 | it's safe to use in urls |
|
94 | 94 | |
|
95 | 95 | :param raw_id: |
|
96 | 96 | :param path: |
|
97 | 97 | """ |
|
98 | 98 | |
|
99 | 99 | return 'C-%s-%s' % (short_id(raw_id), md5(safe_str(path)).hexdigest()[:12]) |
|
100 | 100 | |
|
101 | 101 | |
|
102 | 102 | def get_token(): |
|
103 | 103 | """Return the current authentication token, creating one if one doesn't |
|
104 | 104 | already exist. |
|
105 | 105 | """ |
|
106 | 106 | token_key = "_authentication_token" |
|
107 | 107 | from pylons import session |
|
108 | 108 | if not token_key in session: |
|
109 | 109 | try: |
|
110 | 110 | token = hashlib.sha1(str(random.getrandbits(128))).hexdigest() |
|
111 | 111 | except AttributeError: # Python < 2.4 |
|
112 | 112 | token = hashlib.sha1(str(random.randrange(2 ** 128))).hexdigest() |
|
113 | 113 | session[token_key] = token |
|
114 | 114 | if hasattr(session, 'save'): |
|
115 | 115 | session.save() |
|
116 | 116 | return session[token_key] |
|
117 | 117 | |
|
118 | 118 | |
|
119 | 119 | class _GetError(object): |
|
120 | 120 | """Get error from form_errors, and represent it as span wrapped error |
|
121 | 121 | message |
|
122 | 122 | |
|
123 | 123 | :param field_name: field to fetch errors for |
|
124 | 124 | :param form_errors: form errors dict |
|
125 | 125 | """ |
|
126 | 126 | |
|
127 | 127 | def __call__(self, field_name, form_errors): |
|
128 | 128 | tmpl = """<span class="error_msg">%s</span>""" |
|
129 | 129 | if form_errors and field_name in form_errors: |
|
130 | 130 | return literal(tmpl % form_errors.get(field_name)) |
|
131 | 131 | |
|
132 | 132 | get_error = _GetError() |
|
133 | 133 | |
|
134 | 134 | |
|
135 | 135 | class _ToolTip(object): |
|
136 | 136 | |
|
137 | 137 | def __call__(self, tooltip_title, trim_at=50): |
|
138 | 138 | """ |
|
139 | 139 | Special function just to wrap our text into nice formatted |
|
140 | 140 | autowrapped text |
|
141 | 141 | |
|
142 | 142 | :param tooltip_title: |
|
143 | 143 | """ |
|
144 | 144 | tooltip_title = escape(tooltip_title) |
|
145 | 145 | tooltip_title = tooltip_title.replace('<', '<').replace('>', '>') |
|
146 | 146 | return tooltip_title |
|
147 | 147 | tooltip = _ToolTip() |
|
148 | 148 | |
|
149 | 149 | |
|
150 | 150 | class _FilesBreadCrumbs(object): |
|
151 | 151 | |
|
152 | 152 | def __call__(self, repo_name, rev, paths): |
|
153 | 153 | if isinstance(paths, str): |
|
154 | 154 | paths = safe_unicode(paths) |
|
155 | 155 | url_l = [link_to(repo_name, url('files_home', |
|
156 | 156 | repo_name=repo_name, |
|
157 | 157 | revision=rev, f_path=''), |
|
158 | 158 | class_='ypjax-link')] |
|
159 | 159 | paths_l = paths.split('/') |
|
160 | 160 | for cnt, p in enumerate(paths_l): |
|
161 | 161 | if p != '': |
|
162 | 162 | url_l.append(link_to(p, |
|
163 | 163 | url('files_home', |
|
164 | 164 | repo_name=repo_name, |
|
165 | 165 | revision=rev, |
|
166 | 166 | f_path='/'.join(paths_l[:cnt + 1]) |
|
167 | 167 | ), |
|
168 | 168 | class_='ypjax-link' |
|
169 | 169 | ) |
|
170 | 170 | ) |
|
171 | 171 | |
|
172 | 172 | return literal('/'.join(url_l)) |
|
173 | 173 | |
|
174 | 174 | files_breadcrumbs = _FilesBreadCrumbs() |
|
175 | 175 | |
|
176 | 176 | |
|
177 | 177 | class CodeHtmlFormatter(HtmlFormatter): |
|
178 | 178 | """ |
|
179 | 179 | My code Html Formatter for source codes |
|
180 | 180 | """ |
|
181 | 181 | |
|
182 | 182 | def wrap(self, source, outfile): |
|
183 | 183 | return self._wrap_div(self._wrap_pre(self._wrap_code(source))) |
|
184 | 184 | |
|
185 | 185 | def _wrap_code(self, source): |
|
186 | 186 | for cnt, it in enumerate(source): |
|
187 | 187 | i, t = it |
|
188 | 188 | t = '<div id="L%s">%s</div>' % (cnt + 1, t) |
|
189 | 189 | yield i, t |
|
190 | 190 | |
|
191 | 191 | def _wrap_tablelinenos(self, inner): |
|
192 | 192 | dummyoutfile = StringIO.StringIO() |
|
193 | 193 | lncount = 0 |
|
194 | 194 | for t, line in inner: |
|
195 | 195 | if t: |
|
196 | 196 | lncount += 1 |
|
197 | 197 | dummyoutfile.write(line) |
|
198 | 198 | |
|
199 | 199 | fl = self.linenostart |
|
200 | 200 | mw = len(str(lncount + fl - 1)) |
|
201 | 201 | sp = self.linenospecial |
|
202 | 202 | st = self.linenostep |
|
203 | 203 | la = self.lineanchors |
|
204 | 204 | aln = self.anchorlinenos |
|
205 | 205 | nocls = self.noclasses |
|
206 | 206 | if sp: |
|
207 | 207 | lines = [] |
|
208 | 208 | |
|
209 | 209 | for i in range(fl, fl + lncount): |
|
210 | 210 | if i % st == 0: |
|
211 | 211 | if i % sp == 0: |
|
212 | 212 | if aln: |
|
213 | 213 | lines.append('<a href="#%s%d" class="special">%*d</a>' % |
|
214 | 214 | (la, i, mw, i)) |
|
215 | 215 | else: |
|
216 | 216 | lines.append('<span class="special">%*d</span>' % (mw, i)) |
|
217 | 217 | else: |
|
218 | 218 | if aln: |
|
219 | 219 | lines.append('<a href="#%s%d">%*d</a>' % (la, i, mw, i)) |
|
220 | 220 | else: |
|
221 | 221 | lines.append('%*d' % (mw, i)) |
|
222 | 222 | else: |
|
223 | 223 | lines.append('') |
|
224 | 224 | ls = '\n'.join(lines) |
|
225 | 225 | else: |
|
226 | 226 | lines = [] |
|
227 | 227 | for i in range(fl, fl + lncount): |
|
228 | 228 | if i % st == 0: |
|
229 | 229 | if aln: |
|
230 | 230 | lines.append('<a href="#%s%d">%*d</a>' % (la, i, mw, i)) |
|
231 | 231 | else: |
|
232 | 232 | lines.append('%*d' % (mw, i)) |
|
233 | 233 | else: |
|
234 | 234 | lines.append('') |
|
235 | 235 | ls = '\n'.join(lines) |
|
236 | 236 | |
|
237 | 237 | # in case you wonder about the seemingly redundant <div> here: since the |
|
238 | 238 | # content in the other cell also is wrapped in a div, some browsers in |
|
239 | 239 | # some configurations seem to mess up the formatting... |
|
240 | 240 | if nocls: |
|
241 | 241 | yield 0, ('<table class="%stable">' % self.cssclass + |
|
242 | 242 | '<tr><td><div class="linenodiv" ' |
|
243 | 243 | 'style="background-color: #f0f0f0; padding-right: 10px">' |
|
244 | 244 | '<pre style="line-height: 125%">' + |
|
245 | 245 | ls + '</pre></div></td><td id="hlcode" class="code">') |
|
246 | 246 | else: |
|
247 | 247 | yield 0, ('<table class="%stable">' % self.cssclass + |
|
248 | 248 | '<tr><td class="linenos"><div class="linenodiv"><pre>' + |
|
249 | 249 | ls + '</pre></div></td><td id="hlcode" class="code">') |
|
250 | 250 | yield 0, dummyoutfile.getvalue() |
|
251 | 251 | yield 0, '</td></tr></table>' |
|
252 | 252 | |
|
253 | 253 | |
|
254 | 254 | def pygmentize(filenode, **kwargs): |
|
255 | 255 | """pygmentize function using pygments |
|
256 | 256 | |
|
257 | 257 | :param filenode: |
|
258 | 258 | """ |
|
259 | 259 | |
|
260 | 260 | return literal(code_highlight(filenode.content, |
|
261 | 261 | filenode.lexer, CodeHtmlFormatter(**kwargs))) |
|
262 | 262 | |
|
263 | 263 | |
|
264 | 264 | def pygmentize_annotation(repo_name, filenode, **kwargs): |
|
265 | 265 | """ |
|
266 | 266 | pygmentize function for annotation |
|
267 | 267 | |
|
268 | 268 | :param filenode: |
|
269 | 269 | """ |
|
270 | 270 | |
|
271 | 271 | color_dict = {} |
|
272 | 272 | |
|
273 | 273 | def gen_color(n=10000): |
|
274 | 274 | """generator for getting n of evenly distributed colors using |
|
275 | 275 | hsv color and golden ratio. It always return same order of colors |
|
276 | 276 | |
|
277 | 277 | :returns: RGB tuple |
|
278 | 278 | """ |
|
279 | 279 | |
|
280 | 280 | def hsv_to_rgb(h, s, v): |
|
281 | 281 | if s == 0.0: |
|
282 | 282 | return v, v, v |
|
283 | 283 | i = int(h * 6.0) # XXX assume int() truncates! |
|
284 | 284 | f = (h * 6.0) - i |
|
285 | 285 | p = v * (1.0 - s) |
|
286 | 286 | q = v * (1.0 - s * f) |
|
287 | 287 | t = v * (1.0 - s * (1.0 - f)) |
|
288 | 288 | i = i % 6 |
|
289 | 289 | if i == 0: |
|
290 | 290 | return v, t, p |
|
291 | 291 | if i == 1: |
|
292 | 292 | return q, v, p |
|
293 | 293 | if i == 2: |
|
294 | 294 | return p, v, t |
|
295 | 295 | if i == 3: |
|
296 | 296 | return p, q, v |
|
297 | 297 | if i == 4: |
|
298 | 298 | return t, p, v |
|
299 | 299 | if i == 5: |
|
300 | 300 | return v, p, q |
|
301 | 301 | |
|
302 | 302 | golden_ratio = 0.618033988749895 |
|
303 | 303 | h = 0.22717784590367374 |
|
304 | 304 | |
|
305 | 305 | for _ in xrange(n): |
|
306 | 306 | h += golden_ratio |
|
307 | 307 | h %= 1 |
|
308 | 308 | HSV_tuple = [h, 0.95, 0.95] |
|
309 | 309 | RGB_tuple = hsv_to_rgb(*HSV_tuple) |
|
310 | 310 | yield map(lambda x: str(int(x * 256)), RGB_tuple) |
|
311 | 311 | |
|
312 | 312 | cgenerator = gen_color() |
|
313 | 313 | |
|
314 | 314 | def get_color_string(cs): |
|
315 | 315 | if cs in color_dict: |
|
316 | 316 | col = color_dict[cs] |
|
317 | 317 | else: |
|
318 | 318 | col = color_dict[cs] = cgenerator.next() |
|
319 | 319 | return "color: rgb(%s)! important;" % (', '.join(col)) |
|
320 | 320 | |
|
321 | 321 | def url_func(repo_name): |
|
322 | 322 | |
|
323 | 323 | def _url_func(changeset): |
|
324 | 324 | author = changeset.author |
|
325 | 325 | date = changeset.date |
|
326 | 326 | message = tooltip(changeset.message) |
|
327 | 327 | |
|
328 | 328 | tooltip_html = ("<div style='font-size:0.8em'><b>Author:</b>" |
|
329 | 329 | " %s<br/><b>Date:</b> %s</b><br/><b>Message:" |
|
330 | 330 | "</b> %s<br/></div>") |
|
331 | 331 | |
|
332 | 332 | tooltip_html = tooltip_html % (author, date, message) |
|
333 | 333 | lnk_format = '%5s:%s' % ('r%s' % changeset.revision, |
|
334 | 334 | short_id(changeset.raw_id)) |
|
335 | 335 | uri = link_to( |
|
336 | 336 | lnk_format, |
|
337 | 337 | url('changeset_home', repo_name=repo_name, |
|
338 | 338 | revision=changeset.raw_id), |
|
339 | 339 | style=get_color_string(changeset.raw_id), |
|
340 | 340 | class_='tooltip', |
|
341 | 341 | title=tooltip_html |
|
342 | 342 | ) |
|
343 | 343 | |
|
344 | 344 | uri += '\n' |
|
345 | 345 | return uri |
|
346 | 346 | return _url_func |
|
347 | 347 | |
|
348 | 348 | return literal(annotate_highlight(filenode, url_func(repo_name), **kwargs)) |
|
349 | 349 | |
|
350 | 350 | |
|
351 | 351 | def is_following_repo(repo_name, user_id): |
|
352 | 352 | from rhodecode.model.scm import ScmModel |
|
353 | 353 | return ScmModel().is_following_repo(repo_name, user_id) |
|
354 | 354 | |
|
355 | 355 | flash = _Flash() |
|
356 | 356 | |
|
357 | 357 | #============================================================================== |
|
358 | 358 | # SCM FILTERS available via h. |
|
359 | 359 | #============================================================================== |
|
360 | 360 | from rhodecode.lib.vcs.utils import author_name, author_email |
|
361 | 361 | from rhodecode.lib.utils2 import credentials_filter, age as _age |
|
362 | 362 | from rhodecode.model.db import User, ChangesetStatus |
|
363 | 363 | |
|
364 | 364 | age = lambda x: _age(x) |
|
365 | 365 | capitalize = lambda x: x.capitalize() |
|
366 | 366 | email = author_email |
|
367 | 367 | short_id = lambda x: x[:12] |
|
368 | 368 | hide_credentials = lambda x: ''.join(credentials_filter(x)) |
|
369 | 369 | |
|
370 | 370 | |
|
371 | 371 | def fmt_date(date): |
|
372 | 372 | if date: |
|
373 | 373 | _fmt = _(u"%a, %d %b %Y %H:%M:%S").encode('utf8') |
|
374 | 374 | return date.strftime(_fmt).decode('utf8') |
|
375 | 375 | |
|
376 | 376 | return "" |
|
377 | 377 | |
|
378 | 378 | |
|
379 | 379 | def is_git(repository): |
|
380 | 380 | if hasattr(repository, 'alias'): |
|
381 | 381 | _type = repository.alias |
|
382 | 382 | elif hasattr(repository, 'repo_type'): |
|
383 | 383 | _type = repository.repo_type |
|
384 | 384 | else: |
|
385 | 385 | _type = repository |
|
386 | 386 | return _type == 'git' |
|
387 | 387 | |
|
388 | 388 | |
|
389 | 389 | def is_hg(repository): |
|
390 | 390 | if hasattr(repository, 'alias'): |
|
391 | 391 | _type = repository.alias |
|
392 | 392 | elif hasattr(repository, 'repo_type'): |
|
393 | 393 | _type = repository.repo_type |
|
394 | 394 | else: |
|
395 | 395 | _type = repository |
|
396 | 396 | return _type == 'hg' |
|
397 | 397 | |
|
398 | 398 | |
|
399 | 399 | def email_or_none(author): |
|
400 | 400 | # extract email from the commit string |
|
401 | 401 | _email = email(author) |
|
402 | 402 | if _email != '': |
|
403 | 403 | # check it against RhodeCode database, and use the MAIN email for this |
|
404 | 404 | # user |
|
405 | 405 | user = User.get_by_email(_email, case_insensitive=True, cache=True) |
|
406 | 406 | if user is not None: |
|
407 | 407 | return user.email |
|
408 | 408 | return _email |
|
409 | 409 | |
|
410 | 410 | # See if it contains a username we can get an email from |
|
411 | 411 | user = User.get_by_username(author_name(author), case_insensitive=True, |
|
412 | 412 | cache=True) |
|
413 | 413 | if user is not None: |
|
414 | 414 | return user.email |
|
415 | 415 | |
|
416 | 416 | # No valid email, not a valid user in the system, none! |
|
417 | 417 | return None |
|
418 | 418 | |
|
419 | 419 | |
|
420 | 420 | def person(author, show_attr="username_and_name"): |
|
421 | 421 | # attr to return from fetched user |
|
422 | 422 | person_getter = lambda usr: getattr(usr, show_attr) |
|
423 | 423 | |
|
424 | 424 | # Valid email in the attribute passed, see if they're in the system |
|
425 | 425 | _email = email(author) |
|
426 | 426 | if _email != '': |
|
427 | 427 | user = User.get_by_email(_email, case_insensitive=True, cache=True) |
|
428 | 428 | if user is not None: |
|
429 | 429 | return person_getter(user) |
|
430 | 430 | return _email |
|
431 | 431 | |
|
432 | 432 | # Maybe it's a username? |
|
433 | 433 | _author = author_name(author) |
|
434 | 434 | user = User.get_by_username(_author, case_insensitive=True, |
|
435 | 435 | cache=True) |
|
436 | 436 | if user is not None: |
|
437 | 437 | return person_getter(user) |
|
438 | 438 | |
|
439 | 439 | # Still nothing? Just pass back the author name then |
|
440 | 440 | return _author |
|
441 | 441 | |
|
442 | 442 | |
|
443 | 443 | def person_by_id(id_, show_attr="username_and_name"): |
|
444 | 444 | # attr to return from fetched user |
|
445 | 445 | person_getter = lambda usr: getattr(usr, show_attr) |
|
446 | 446 | |
|
447 | 447 | #maybe it's an ID ? |
|
448 | 448 | if str(id_).isdigit() or isinstance(id_, int): |
|
449 | 449 | id_ = int(id_) |
|
450 | 450 | user = User.get(id_) |
|
451 | 451 | if user is not None: |
|
452 | 452 | return person_getter(user) |
|
453 | 453 | return id_ |
|
454 | 454 | |
|
455 | 455 | |
|
456 | 456 | def desc_stylize(value): |
|
457 | 457 | """ |
|
458 | 458 | converts tags from value into html equivalent |
|
459 | 459 | |
|
460 | 460 | :param value: |
|
461 | 461 | """ |
|
462 | 462 | value = re.sub(r'\[see\ \=\>\ *([a-zA-Z0-9\/\=\?\&\ \:\/\.\-]*)\]', |
|
463 | 463 | '<div class="metatag" tag="see">see => \\1 </div>', value) |
|
464 | 464 | value = re.sub(r'\[license\ \=\>\ *([a-zA-Z0-9\/\=\?\&\ \:\/\.\-]*)\]', |
|
465 | 465 | '<div class="metatag" tag="license"><a href="http:\/\/www.opensource.org/licenses/\\1">\\1</a></div>', value) |
|
466 | 466 | value = re.sub(r'\[(requires|recommends|conflicts|base)\ \=\>\ *([a-zA-Z\-\/]*)\]', |
|
467 | 467 | '<div class="metatag" tag="\\1">\\1 => <a href="/\\2">\\2</a></div>', value) |
|
468 | 468 | value = re.sub(r'\[(lang|language)\ \=\>\ *([a-zA-Z\-\/\#\+]*)\]', |
|
469 | 469 | '<div class="metatag" tag="lang">\\2</div>', value) |
|
470 | 470 | value = re.sub(r'\[([a-z]+)\]', |
|
471 | 471 | '<div class="metatag" tag="\\1">\\1</div>', value) |
|
472 | 472 | |
|
473 | 473 | return value |
|
474 | 474 | |
|
475 | 475 | |
|
476 | 476 | def bool2icon(value): |
|
477 | 477 | """Returns True/False values represented as small html image of true/false |
|
478 | 478 | icons |
|
479 | 479 | |
|
480 | 480 | :param value: bool value |
|
481 | 481 | """ |
|
482 | 482 | |
|
483 | 483 | if value is True: |
|
484 | 484 | return HTML.tag('img', src=url("/images/icons/accept.png"), |
|
485 | 485 | alt=_('True')) |
|
486 | 486 | |
|
487 | 487 | if value is False: |
|
488 | 488 | return HTML.tag('img', src=url("/images/icons/cancel.png"), |
|
489 | 489 | alt=_('False')) |
|
490 | 490 | |
|
491 | 491 | return value |
|
492 | 492 | |
|
493 | 493 | |
|
494 | 494 | def action_parser(user_log, feed=False, parse_cs=False): |
|
495 | 495 | """ |
|
496 | 496 | This helper will action_map the specified string action into translated |
|
497 | 497 | fancy names with icons and links |
|
498 | 498 | |
|
499 | 499 | :param user_log: user log instance |
|
500 | 500 | :param feed: use output for feeds (no html and fancy icons) |
|
501 | 501 | :param parse_cs: parse Changesets into VCS instances |
|
502 | 502 | """ |
|
503 | 503 | |
|
504 | 504 | action = user_log.action |
|
505 | 505 | action_params = ' ' |
|
506 | 506 | |
|
507 | 507 | x = action.split(':') |
|
508 | 508 | |
|
509 | 509 | if len(x) > 1: |
|
510 | 510 | action, action_params = x |
|
511 | 511 | |
|
512 | 512 | def get_cs_links(): |
|
513 | 513 | revs_limit = 3 # display this amount always |
|
514 | 514 | revs_top_limit = 50 # show upto this amount of changesets hidden |
|
515 | 515 | revs_ids = action_params.split(',') |
|
516 | 516 | deleted = user_log.repository is None |
|
517 | 517 | if deleted: |
|
518 | 518 | return ','.join(revs_ids) |
|
519 | 519 | |
|
520 | 520 | repo_name = user_log.repository.repo_name |
|
521 | 521 | |
|
522 | 522 | def lnk(rev, repo_name): |
|
523 | 523 | if isinstance(rev, BaseChangeset) or isinstance(rev, AttributeDict): |
|
524 | 524 | lbl = '%s' % (rev.short_id[:8]) |
|
525 | 525 | _url = url('changeset_home', repo_name=repo_name, |
|
526 | 526 | revision=rev.raw_id) |
|
527 | 527 | title = tooltip(rev.message) |
|
528 | 528 | else: |
|
529 | 529 | ## changeset cannot be found/striped/removed etc. |
|
530 | 530 | lbl = ('%s' % rev)[:12] |
|
531 | 531 | _url = '#' |
|
532 | 532 | title = _('Changeset not found') |
|
533 | 533 | if parse_cs: |
|
534 | 534 | return link_to(lbl, _url, title=title, class_='tooltip') |
|
535 | 535 | return link_to(lbl, _url, raw_id=rev.raw_id, repo_name=repo_name, |
|
536 | 536 | class_='lazy-cs') |
|
537 | 537 | |
|
538 | 538 | revs = [] |
|
539 | 539 | if len(filter(lambda v: v != '', revs_ids)) > 0: |
|
540 | 540 | repo = None |
|
541 | 541 | for rev in revs_ids[:revs_top_limit]: |
|
542 | 542 | # we want parsed changesets, or new log store format is bad |
|
543 | 543 | if parse_cs: |
|
544 | 544 | try: |
|
545 | 545 | if repo is None: |
|
546 | 546 | repo = user_log.repository.scm_instance |
|
547 | 547 | _rev = repo.get_changeset(rev) |
|
548 | 548 | revs.append(_rev) |
|
549 | 549 | except ChangesetDoesNotExistError: |
|
550 | 550 | log.error('cannot find revision %s in this repo' % rev) |
|
551 | 551 | revs.append(rev) |
|
552 | 552 | continue |
|
553 | 553 | else: |
|
554 | 554 | _rev = AttributeDict({ |
|
555 | 555 | 'short_id': rev[:12], |
|
556 | 556 | 'raw_id': rev, |
|
557 | 557 | 'message': '', |
|
558 | 558 | }) |
|
559 | 559 | revs.append(_rev) |
|
560 | 560 | cs_links = [] |
|
561 | 561 | cs_links.append(" " + ', '.join( |
|
562 | 562 | [lnk(rev, repo_name) for rev in revs[:revs_limit]] |
|
563 | 563 | ) |
|
564 | 564 | ) |
|
565 | 565 | |
|
566 | 566 | compare_view = ( |
|
567 | 567 | ' <div class="compare_view tooltip" title="%s">' |
|
568 | 568 | '<a href="%s">%s</a> </div>' % ( |
|
569 | 569 | _('Show all combined changesets %s->%s') % ( |
|
570 | 570 | revs_ids[0][:12], revs_ids[-1][:12] |
|
571 | 571 | ), |
|
572 | 572 | url('changeset_home', repo_name=repo_name, |
|
573 | 573 | revision='%s...%s' % (revs_ids[0], revs_ids[-1]) |
|
574 | 574 | ), |
|
575 | 575 | _('compare view') |
|
576 | 576 | ) |
|
577 | 577 | ) |
|
578 | 578 | |
|
579 | 579 | # if we have exactly one more than normally displayed |
|
580 | 580 | # just display it, takes less space than displaying |
|
581 | 581 | # "and 1 more revisions" |
|
582 | 582 | if len(revs_ids) == revs_limit + 1: |
|
583 | 583 | rev = revs[revs_limit] |
|
584 | 584 | cs_links.append(", " + lnk(rev, repo_name)) |
|
585 | 585 | |
|
586 | 586 | # hidden-by-default ones |
|
587 | 587 | if len(revs_ids) > revs_limit + 1: |
|
588 | 588 | uniq_id = revs_ids[0] |
|
589 | 589 | html_tmpl = ( |
|
590 | 590 | '<span> %s <a class="show_more" id="_%s" ' |
|
591 | 591 | 'href="#more">%s</a> %s</span>' |
|
592 | 592 | ) |
|
593 | 593 | if not feed: |
|
594 | 594 | cs_links.append(html_tmpl % ( |
|
595 | 595 | _('and'), |
|
596 | 596 | uniq_id, _('%s more') % (len(revs_ids) - revs_limit), |
|
597 | 597 | _('revisions') |
|
598 | 598 | ) |
|
599 | 599 | ) |
|
600 | 600 | |
|
601 | 601 | if not feed: |
|
602 | 602 | html_tmpl = '<span id="%s" style="display:none">, %s </span>' |
|
603 | 603 | else: |
|
604 | 604 | html_tmpl = '<span id="%s"> %s </span>' |
|
605 | 605 | |
|
606 | 606 | morelinks = ', '.join( |
|
607 | 607 | [lnk(rev, repo_name) for rev in revs[revs_limit:]] |
|
608 | 608 | ) |
|
609 | 609 | |
|
610 | 610 | if len(revs_ids) > revs_top_limit: |
|
611 | 611 | morelinks += ', ...' |
|
612 | 612 | |
|
613 | 613 | cs_links.append(html_tmpl % (uniq_id, morelinks)) |
|
614 | 614 | if len(revs) > 1: |
|
615 | 615 | cs_links.append(compare_view) |
|
616 | 616 | return ''.join(cs_links) |
|
617 | 617 | |
|
618 | 618 | def get_fork_name(): |
|
619 | 619 | repo_name = action_params |
|
620 | 620 | _url = url('summary_home', repo_name=repo_name) |
|
621 | 621 | return _('fork name %s') % link_to(action_params, _url) |
|
622 | 622 | |
|
623 | 623 | def get_user_name(): |
|
624 | 624 | user_name = action_params |
|
625 | 625 | return user_name |
|
626 | 626 | |
|
627 | 627 | def get_users_group(): |
|
628 | 628 | group_name = action_params |
|
629 | 629 | return group_name |
|
630 | 630 | |
|
631 | 631 | def get_pull_request(): |
|
632 | 632 | pull_request_id = action_params |
|
633 | 633 | repo_name = user_log.repository.repo_name |
|
634 | 634 | return link_to(_('Pull request #%s') % pull_request_id, |
|
635 | 635 | url('pullrequest_show', repo_name=repo_name, |
|
636 | 636 | pull_request_id=pull_request_id)) |
|
637 | 637 | |
|
638 | 638 | # action : translated str, callback(extractor), icon |
|
639 | 639 | action_map = { |
|
640 | 640 | 'user_deleted_repo': (_('[deleted] repository'), |
|
641 | 641 | None, 'database_delete.png'), |
|
642 | 642 | 'user_created_repo': (_('[created] repository'), |
|
643 | 643 | None, 'database_add.png'), |
|
644 | 644 | 'user_created_fork': (_('[created] repository as fork'), |
|
645 | 645 | None, 'arrow_divide.png'), |
|
646 | 646 | 'user_forked_repo': (_('[forked] repository'), |
|
647 | 647 | get_fork_name, 'arrow_divide.png'), |
|
648 | 648 | 'user_updated_repo': (_('[updated] repository'), |
|
649 | 649 | None, 'database_edit.png'), |
|
650 | 650 | 'admin_deleted_repo': (_('[delete] repository'), |
|
651 | 651 | None, 'database_delete.png'), |
|
652 | 652 | 'admin_created_repo': (_('[created] repository'), |
|
653 | 653 | None, 'database_add.png'), |
|
654 | 654 | 'admin_forked_repo': (_('[forked] repository'), |
|
655 | 655 | None, 'arrow_divide.png'), |
|
656 | 656 | 'admin_updated_repo': (_('[updated] repository'), |
|
657 | 657 | None, 'database_edit.png'), |
|
658 | 658 | 'admin_created_user': (_('[created] user'), |
|
659 | 659 | get_user_name, 'user_add.png'), |
|
660 | 660 | 'admin_updated_user': (_('[updated] user'), |
|
661 | 661 | get_user_name, 'user_edit.png'), |
|
662 | 662 | 'admin_created_users_group': (_('[created] users group'), |
|
663 | 663 | get_users_group, 'group_add.png'), |
|
664 | 664 | 'admin_updated_users_group': (_('[updated] users group'), |
|
665 | 665 | get_users_group, 'group_edit.png'), |
|
666 | 666 | 'user_commented_revision': (_('[commented] on revision in repository'), |
|
667 | 667 | get_cs_links, 'comment_add.png'), |
|
668 | 668 | 'user_commented_pull_request': (_('[commented] on pull request for'), |
|
669 | 669 | get_pull_request, 'comment_add.png'), |
|
670 | 670 | 'user_closed_pull_request': (_('[closed] pull request for'), |
|
671 | 671 | get_pull_request, 'tick.png'), |
|
672 | 672 | 'push': (_('[pushed] into'), |
|
673 | 673 | get_cs_links, 'script_add.png'), |
|
674 | 674 | 'push_local': (_('[committed via RhodeCode] into repository'), |
|
675 | 675 | get_cs_links, 'script_edit.png'), |
|
676 | 676 | 'push_remote': (_('[pulled from remote] into repository'), |
|
677 | 677 | get_cs_links, 'connect.png'), |
|
678 | 678 | 'pull': (_('[pulled] from'), |
|
679 | 679 | None, 'down_16.png'), |
|
680 | 680 | 'started_following_repo': (_('[started following] repository'), |
|
681 | 681 | None, 'heart_add.png'), |
|
682 | 682 | 'stopped_following_repo': (_('[stopped following] repository'), |
|
683 | 683 | None, 'heart_delete.png'), |
|
684 | 684 | } |
|
685 | 685 | |
|
686 | 686 | action_str = action_map.get(action, action) |
|
687 | 687 | if feed: |
|
688 | 688 | action = action_str[0].replace('[', '').replace(']', '') |
|
689 | 689 | else: |
|
690 | 690 | action = action_str[0]\ |
|
691 | 691 | .replace('[', '<span class="journal_highlight">')\ |
|
692 | 692 | .replace(']', '</span>') |
|
693 | 693 | |
|
694 | 694 | action_params_func = lambda: "" |
|
695 | 695 | |
|
696 | 696 | if callable(action_str[1]): |
|
697 | 697 | action_params_func = action_str[1] |
|
698 | 698 | |
|
699 | 699 | def action_parser_icon(): |
|
700 | 700 | action = user_log.action |
|
701 | 701 | action_params = None |
|
702 | 702 | x = action.split(':') |
|
703 | 703 | |
|
704 | 704 | if len(x) > 1: |
|
705 | 705 | action, action_params = x |
|
706 | 706 | |
|
707 | 707 | tmpl = """<img src="%s%s" alt="%s"/>""" |
|
708 | 708 | ico = action_map.get(action, ['', '', ''])[2] |
|
709 | 709 | return literal(tmpl % ((url('/images/icons/')), ico, action)) |
|
710 | 710 | |
|
711 | 711 | # returned callbacks we need to call to get |
|
712 | 712 | return [lambda: literal(action), action_params_func, action_parser_icon] |
|
713 | 713 | |
|
714 | 714 | |
|
715 | 715 | |
|
716 | 716 | #============================================================================== |
|
717 | 717 | # PERMS |
|
718 | 718 | #============================================================================== |
|
719 | 719 | from rhodecode.lib.auth import HasPermissionAny, HasPermissionAll, \ |
|
720 | 720 | HasRepoPermissionAny, HasRepoPermissionAll |
|
721 | 721 | |
|
722 | 722 | |
|
723 | 723 | #============================================================================== |
|
724 | 724 | # GRAVATAR URL |
|
725 | 725 | #============================================================================== |
|
726 | 726 | |
|
727 | 727 | def gravatar_url(email_address, size=30): |
|
728 | 728 | from pylons import url ## doh, we need to re-import url to mock it later |
|
729 | 729 | if(str2bool(config['app_conf'].get('use_gravatar')) and |
|
730 | 730 | config['app_conf'].get('alternative_gravatar_url')): |
|
731 | 731 | tmpl = config['app_conf'].get('alternative_gravatar_url', '') |
|
732 | 732 | parsed_url = urlparse.urlparse(url.current(qualified=True)) |
|
733 | 733 | tmpl = tmpl.replace('{email}', email_address)\ |
|
734 | 734 | .replace('{md5email}', hashlib.md5(email_address.lower()).hexdigest()) \ |
|
735 | 735 | .replace('{netloc}', parsed_url.netloc)\ |
|
736 | 736 | .replace('{scheme}', parsed_url.scheme)\ |
|
737 | 737 | .replace('{size}', str(size)) |
|
738 | 738 | return tmpl |
|
739 | 739 | |
|
740 | 740 | if (not str2bool(config['app_conf'].get('use_gravatar')) or |
|
741 | 741 | not email_address or email_address == 'anonymous@rhodecode.org'): |
|
742 | 742 | f = lambda a, l: min(l, key=lambda x: abs(x - a)) |
|
743 | 743 | return url("/images/user%s.png" % f(size, [14, 16, 20, 24, 30])) |
|
744 | 744 | |
|
745 | 745 | ssl_enabled = 'https' == request.environ.get('wsgi.url_scheme') |
|
746 | 746 | default = 'identicon' |
|
747 | 747 | baseurl_nossl = "http://www.gravatar.com/avatar/" |
|
748 | 748 | baseurl_ssl = "https://secure.gravatar.com/avatar/" |
|
749 | 749 | baseurl = baseurl_ssl if ssl_enabled else baseurl_nossl |
|
750 | 750 | |
|
751 | 751 | if isinstance(email_address, unicode): |
|
752 | 752 | #hashlib crashes on unicode items |
|
753 | 753 | email_address = safe_str(email_address) |
|
754 | 754 | # construct the url |
|
755 | 755 | gravatar_url = baseurl + hashlib.md5(email_address.lower()).hexdigest() + "?" |
|
756 | 756 | gravatar_url += urllib.urlencode({'d': default, 's': str(size)}) |
|
757 | 757 | |
|
758 | 758 | return gravatar_url |
|
759 | 759 | |
|
760 | 760 | |
|
761 | 761 | #============================================================================== |
|
762 | 762 | # REPO PAGER, PAGER FOR REPOSITORY |
|
763 | 763 | #============================================================================== |
|
764 | 764 | class RepoPage(Page): |
|
765 | 765 | |
|
766 | 766 | def __init__(self, collection, page=1, items_per_page=20, |
|
767 | 767 | item_count=None, url=None, **kwargs): |
|
768 | 768 | |
|
769 | 769 | """Create a "RepoPage" instance. special pager for paging |
|
770 | 770 | repository |
|
771 | 771 | """ |
|
772 | 772 | self._url_generator = url |
|
773 | 773 | |
|
774 | 774 | # Safe the kwargs class-wide so they can be used in the pager() method |
|
775 | 775 | self.kwargs = kwargs |
|
776 | 776 | |
|
777 | 777 | # Save a reference to the collection |
|
778 | 778 | self.original_collection = collection |
|
779 | 779 | |
|
780 | 780 | self.collection = collection |
|
781 | 781 | |
|
782 | 782 | # The self.page is the number of the current page. |
|
783 | 783 | # The first page has the number 1! |
|
784 | 784 | try: |
|
785 | 785 | self.page = int(page) # make it int() if we get it as a string |
|
786 | 786 | except (ValueError, TypeError): |
|
787 | 787 | self.page = 1 |
|
788 | 788 | |
|
789 | 789 | self.items_per_page = items_per_page |
|
790 | 790 | |
|
791 | 791 | # Unless the user tells us how many items the collections has |
|
792 | 792 | # we calculate that ourselves. |
|
793 | 793 | if item_count is not None: |
|
794 | 794 | self.item_count = item_count |
|
795 | 795 | else: |
|
796 | 796 | self.item_count = len(self.collection) |
|
797 | 797 | |
|
798 | 798 | # Compute the number of the first and last available page |
|
799 | 799 | if self.item_count > 0: |
|
800 | 800 | self.first_page = 1 |
|
801 | 801 | self.page_count = int(math.ceil(float(self.item_count) / |
|
802 | 802 | self.items_per_page)) |
|
803 | 803 | self.last_page = self.first_page + self.page_count - 1 |
|
804 | 804 | |
|
805 | 805 | # Make sure that the requested page number is the range of |
|
806 | 806 | # valid pages |
|
807 | 807 | if self.page > self.last_page: |
|
808 | 808 | self.page = self.last_page |
|
809 | 809 | elif self.page < self.first_page: |
|
810 | 810 | self.page = self.first_page |
|
811 | 811 | |
|
812 | 812 | # Note: the number of items on this page can be less than |
|
813 | 813 | # items_per_page if the last page is not full |
|
814 | 814 | self.first_item = max(0, (self.item_count) - (self.page * |
|
815 | 815 | items_per_page)) |
|
816 | 816 | self.last_item = ((self.item_count - 1) - items_per_page * |
|
817 | 817 | (self.page - 1)) |
|
818 | 818 | |
|
819 | 819 | self.items = list(self.collection[self.first_item:self.last_item + 1]) |
|
820 | 820 | |
|
821 | 821 | # Links to previous and next page |
|
822 | 822 | if self.page > self.first_page: |
|
823 | 823 | self.previous_page = self.page - 1 |
|
824 | 824 | else: |
|
825 | 825 | self.previous_page = None |
|
826 | 826 | |
|
827 | 827 | if self.page < self.last_page: |
|
828 | 828 | self.next_page = self.page + 1 |
|
829 | 829 | else: |
|
830 | 830 | self.next_page = None |
|
831 | 831 | |
|
832 | 832 | # No items available |
|
833 | 833 | else: |
|
834 | 834 | self.first_page = None |
|
835 | 835 | self.page_count = 0 |
|
836 | 836 | self.last_page = None |
|
837 | 837 | self.first_item = None |
|
838 | 838 | self.last_item = None |
|
839 | 839 | self.previous_page = None |
|
840 | 840 | self.next_page = None |
|
841 | 841 | self.items = [] |
|
842 | 842 | |
|
843 | 843 | # This is a subclass of the 'list' type. Initialise the list now. |
|
844 | 844 | list.__init__(self, reversed(self.items)) |
|
845 | 845 | |
|
846 | 846 | |
|
847 | 847 | def changed_tooltip(nodes): |
|
848 | 848 | """ |
|
849 | 849 | Generates a html string for changed nodes in changeset page. |
|
850 | 850 | It limits the output to 30 entries |
|
851 | 851 | |
|
852 | 852 | :param nodes: LazyNodesGenerator |
|
853 | 853 | """ |
|
854 | 854 | if nodes: |
|
855 | 855 | pref = ': <br/> ' |
|
856 | 856 | suf = '' |
|
857 | 857 | if len(nodes) > 30: |
|
858 | 858 | suf = '<br/>' + _(' and %s more') % (len(nodes) - 30) |
|
859 | 859 | return literal(pref + '<br/> '.join([safe_unicode(x.path) |
|
860 | 860 | for x in nodes[:30]]) + suf) |
|
861 | 861 | else: |
|
862 | 862 | return ': ' + _('No Files') |
|
863 | 863 | |
|
864 | 864 | |
|
865 | 865 | def repo_link(groups_and_repos): |
|
866 | 866 | """ |
|
867 | 867 | Makes a breadcrumbs link to repo within a group |
|
868 | 868 | joins » on each group to create a fancy link |
|
869 | 869 | |
|
870 | 870 | ex:: |
|
871 | 871 | group >> subgroup >> repo |
|
872 | 872 | |
|
873 | 873 | :param groups_and_repos: |
|
874 | 874 | """ |
|
875 | 875 | groups, repo_name = groups_and_repos |
|
876 | 876 | |
|
877 | 877 | if not groups: |
|
878 | 878 | return repo_name |
|
879 | 879 | else: |
|
880 | 880 | def make_link(group): |
|
881 | 881 | return link_to(group.name, url('repos_group_home', |
|
882 | 882 | group_name=group.group_name)) |
|
883 | 883 | return literal(' » '.join(map(make_link, groups)) + \ |
|
884 | 884 | " » " + repo_name) |
|
885 | 885 | |
|
886 | 886 | |
|
887 | 887 | def fancy_file_stats(stats): |
|
888 | 888 | """ |
|
889 | 889 | Displays a fancy two colored bar for number of added/deleted |
|
890 | 890 | lines of code on file |
|
891 | 891 | |
|
892 | 892 | :param stats: two element list of added/deleted lines of code |
|
893 | 893 | """ |
|
894 | ||
|
895 | a, d, t = stats[0], stats[1], stats[0] + stats[1] | |
|
896 | width = 100 | |
|
897 | unit = float(width) / (t or 1) | |
|
898 | ||
|
899 | # needs > 9% of width to be visible or 0 to be hidden | |
|
900 | a_p = max(9, unit * a) if a > 0 else 0 | |
|
901 | d_p = max(9, unit * d) if d > 0 else 0 | |
|
902 | p_sum = a_p + d_p | |
|
903 | ||
|
904 | if p_sum > width: | |
|
905 | #adjust the percentage to be == 100% since we adjusted to 9 | |
|
906 | if a_p > d_p: | |
|
907 | a_p = a_p - (p_sum - width) | |
|
908 | else: | |
|
909 | d_p = d_p - (p_sum - width) | |
|
910 | ||
|
911 | a_v = a if a > 0 else '' | |
|
912 | d_v = d if d > 0 else '' | |
|
913 | ||
|
914 | def cgen(l_type): | |
|
894 | def cgen(l_type, a_v, d_v): | |
|
915 | 895 | mapping = {'tr': 'top-right-rounded-corner-mid', |
|
916 | 896 | 'tl': 'top-left-rounded-corner-mid', |
|
917 | 897 | 'br': 'bottom-right-rounded-corner-mid', |
|
918 | 898 | 'bl': 'bottom-left-rounded-corner-mid'} |
|
919 | 899 | map_getter = lambda x: mapping[x] |
|
920 | 900 | |
|
921 | 901 | if l_type == 'a' and d_v: |
|
922 | 902 | #case when added and deleted are present |
|
923 | 903 | return ' '.join(map(map_getter, ['tl', 'bl'])) |
|
924 | 904 | |
|
925 | 905 | if l_type == 'a' and not d_v: |
|
926 | 906 | return ' '.join(map(map_getter, ['tr', 'br', 'tl', 'bl'])) |
|
927 | 907 | |
|
928 | 908 | if l_type == 'd' and a_v: |
|
929 | 909 | return ' '.join(map(map_getter, ['tr', 'br'])) |
|
930 | 910 | |
|
931 | 911 | if l_type == 'd' and not a_v: |
|
932 | 912 | return ' '.join(map(map_getter, ['tr', 'br', 'tl', 'bl'])) |
|
933 | 913 | |
|
914 | a, d = stats[0], stats[1] | |
|
915 | width = 100 | |
|
916 | ||
|
917 | if a == 'b': | |
|
918 | #binary mode | |
|
919 | b_d = '<div class="bin%s %s" style="width:100%%">%s</div>' % (d, cgen('a', a_v='', d_v=0), 'bin') | |
|
920 | b_a = '<div class="bin1" style="width:0%%">%s</div>' % ('bin') | |
|
921 | return literal('<div style="width:%spx">%s%s</div>' % (width, b_a, b_d)) | |
|
922 | ||
|
923 | t = stats[0] + stats[1] | |
|
924 | unit = float(width) / (t or 1) | |
|
925 | ||
|
926 | # needs > 9% of width to be visible or 0 to be hidden | |
|
927 | a_p = max(9, unit * a) if a > 0 else 0 | |
|
928 | d_p = max(9, unit * d) if d > 0 else 0 | |
|
929 | p_sum = a_p + d_p | |
|
930 | ||
|
931 | if p_sum > width: | |
|
932 | #adjust the percentage to be == 100% since we adjusted to 9 | |
|
933 | if a_p > d_p: | |
|
934 | a_p = a_p - (p_sum - width) | |
|
935 | else: | |
|
936 | d_p = d_p - (p_sum - width) | |
|
937 | ||
|
938 | a_v = a if a > 0 else '' | |
|
939 | d_v = d if d > 0 else '' | |
|
940 | ||
|
934 | 941 | d_a = '<div class="added %s" style="width:%s%%">%s</div>' % ( |
|
935 | cgen('a'), a_p, a_v | |
|
942 | cgen('a', a_v, d_v), a_p, a_v | |
|
936 | 943 | ) |
|
937 | 944 | d_d = '<div class="deleted %s" style="width:%s%%">%s</div>' % ( |
|
938 | cgen('d'), d_p, d_v | |
|
945 | cgen('d', a_v, d_v), d_p, d_v | |
|
939 | 946 | ) |
|
940 | 947 | return literal('<div style="width:%spx">%s%s</div>' % (width, d_a, d_d)) |
|
941 | 948 | |
|
942 | 949 | |
|
943 | 950 | def urlify_text(text_): |
|
944 | 951 | |
|
945 | 952 | url_pat = re.compile(r'''(http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]''' |
|
946 | 953 | '''|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+)''') |
|
947 | 954 | |
|
948 | 955 | def url_func(match_obj): |
|
949 | 956 | url_full = match_obj.groups()[0] |
|
950 | 957 | return '<a href="%(url)s">%(url)s</a>' % ({'url': url_full}) |
|
951 | 958 | |
|
952 | 959 | return literal(url_pat.sub(url_func, text_)) |
|
953 | 960 | |
|
954 | 961 | |
|
955 | 962 | def urlify_changesets(text_, repository): |
|
956 | 963 | """ |
|
957 | 964 | Extract revision ids from changeset and make link from them |
|
958 | 965 | |
|
959 | 966 | :param text_: |
|
960 | 967 | :param repository: |
|
961 | 968 | """ |
|
962 | 969 | |
|
963 | 970 | URL_PAT = re.compile(r'([0-9a-fA-F]{12,})') |
|
964 | 971 | |
|
965 | 972 | def url_func(match_obj): |
|
966 | 973 | rev = match_obj.groups()[0] |
|
967 | 974 | pref = '' |
|
968 | 975 | if match_obj.group().startswith(' '): |
|
969 | 976 | pref = ' ' |
|
970 | 977 | tmpl = ( |
|
971 | 978 | '%(pref)s<a class="%(cls)s" href="%(url)s">' |
|
972 | 979 | '%(rev)s' |
|
973 | 980 | '</a>' |
|
974 | 981 | ) |
|
975 | 982 | return tmpl % { |
|
976 | 983 | 'pref': pref, |
|
977 | 984 | 'cls': 'revision-link', |
|
978 | 985 | 'url': url('changeset_home', repo_name=repository, revision=rev), |
|
979 | 986 | 'rev': rev, |
|
980 | 987 | } |
|
981 | 988 | |
|
982 | 989 | newtext = URL_PAT.sub(url_func, text_) |
|
983 | 990 | |
|
984 | 991 | return newtext |
|
985 | 992 | |
|
986 | 993 | |
|
987 | 994 | def urlify_commit(text_, repository=None, link_=None): |
|
988 | 995 | """ |
|
989 | 996 | Parses given text message and makes proper links. |
|
990 | 997 | issues are linked to given issue-server, and rest is a changeset link |
|
991 | 998 | if link_ is given, in other case it's a plain text |
|
992 | 999 | |
|
993 | 1000 | :param text_: |
|
994 | 1001 | :param repository: |
|
995 | 1002 | :param link_: changeset link |
|
996 | 1003 | """ |
|
997 | 1004 | import traceback |
|
998 | 1005 | |
|
999 | 1006 | def escaper(string): |
|
1000 | 1007 | return string.replace('<', '<').replace('>', '>') |
|
1001 | 1008 | |
|
1002 | 1009 | def linkify_others(t, l): |
|
1003 | 1010 | urls = re.compile(r'(\<a.*?\<\/a\>)',) |
|
1004 | 1011 | links = [] |
|
1005 | 1012 | for e in urls.split(t): |
|
1006 | 1013 | if not urls.match(e): |
|
1007 | 1014 | links.append('<a class="message-link" href="%s">%s</a>' % (l, e)) |
|
1008 | 1015 | else: |
|
1009 | 1016 | links.append(e) |
|
1010 | 1017 | |
|
1011 | 1018 | return ''.join(links) |
|
1012 | 1019 | |
|
1013 | 1020 | # urlify changesets - extrac revisions and make link out of them |
|
1014 | 1021 | newtext = urlify_changesets(escaper(text_), repository) |
|
1015 | 1022 | |
|
1016 | 1023 | try: |
|
1017 | 1024 | conf = config['app_conf'] |
|
1018 | 1025 | |
|
1019 | 1026 | # allow multiple issue servers to be used |
|
1020 | 1027 | valid_indices = [ |
|
1021 | 1028 | x.group(1) |
|
1022 | 1029 | for x in map(lambda x: re.match(r'issue_pat(.*)', x), conf.keys()) |
|
1023 | 1030 | if x and 'issue_server_link%s' % x.group(1) in conf |
|
1024 | 1031 | and 'issue_prefix%s' % x.group(1) in conf |
|
1025 | 1032 | ] |
|
1026 | 1033 | |
|
1027 | 1034 | log.debug('found issue server suffixes `%s` during valuation of: %s' |
|
1028 | 1035 | % (','.join(valid_indices), newtext)) |
|
1029 | 1036 | |
|
1030 | 1037 | for pattern_index in valid_indices: |
|
1031 | 1038 | ISSUE_PATTERN = conf.get('issue_pat%s' % pattern_index) |
|
1032 | 1039 | ISSUE_SERVER_LNK = conf.get('issue_server_link%s' % pattern_index) |
|
1033 | 1040 | ISSUE_PREFIX = conf.get('issue_prefix%s' % pattern_index) |
|
1034 | 1041 | |
|
1035 | 1042 | log.debug('pattern suffix `%s` PAT:%s SERVER_LINK:%s PREFIX:%s' |
|
1036 | 1043 | % (pattern_index, ISSUE_PATTERN, ISSUE_SERVER_LNK, |
|
1037 | 1044 | ISSUE_PREFIX)) |
|
1038 | 1045 | |
|
1039 | 1046 | URL_PAT = re.compile(r'%s' % ISSUE_PATTERN) |
|
1040 | 1047 | |
|
1041 | 1048 | def url_func(match_obj): |
|
1042 | 1049 | pref = '' |
|
1043 | 1050 | if match_obj.group().startswith(' '): |
|
1044 | 1051 | pref = ' ' |
|
1045 | 1052 | |
|
1046 | 1053 | issue_id = ''.join(match_obj.groups()) |
|
1047 | 1054 | tmpl = ( |
|
1048 | 1055 | '%(pref)s<a class="%(cls)s" href="%(url)s">' |
|
1049 | 1056 | '%(issue-prefix)s%(id-repr)s' |
|
1050 | 1057 | '</a>' |
|
1051 | 1058 | ) |
|
1052 | 1059 | url = ISSUE_SERVER_LNK.replace('{id}', issue_id) |
|
1053 | 1060 | if repository: |
|
1054 | 1061 | url = url.replace('{repo}', repository) |
|
1055 | 1062 | repo_name = repository.split(URL_SEP)[-1] |
|
1056 | 1063 | url = url.replace('{repo_name}', repo_name) |
|
1057 | 1064 | |
|
1058 | 1065 | return tmpl % { |
|
1059 | 1066 | 'pref': pref, |
|
1060 | 1067 | 'cls': 'issue-tracker-link', |
|
1061 | 1068 | 'url': url, |
|
1062 | 1069 | 'id-repr': issue_id, |
|
1063 | 1070 | 'issue-prefix': ISSUE_PREFIX, |
|
1064 | 1071 | 'serv': ISSUE_SERVER_LNK, |
|
1065 | 1072 | } |
|
1066 | 1073 | newtext = URL_PAT.sub(url_func, newtext) |
|
1067 | 1074 | log.debug('processed prefix:`%s` => %s' % (pattern_index, newtext)) |
|
1068 | 1075 | |
|
1069 | 1076 | # if we actually did something above |
|
1070 | 1077 | if link_: |
|
1071 | 1078 | # wrap not links into final link => link_ |
|
1072 | 1079 | newtext = linkify_others(newtext, link_) |
|
1073 | 1080 | except: |
|
1074 | 1081 | log.error(traceback.format_exc()) |
|
1075 | 1082 | pass |
|
1076 | 1083 | |
|
1077 | 1084 | return literal(newtext) |
|
1078 | 1085 | |
|
1079 | 1086 | |
|
1080 | 1087 | def rst(source): |
|
1081 | 1088 | return literal('<div class="rst-block">%s</div>' % |
|
1082 | 1089 | MarkupRenderer.rst(source)) |
|
1083 | 1090 | |
|
1084 | 1091 | |
|
1085 | 1092 | def rst_w_mentions(source): |
|
1086 | 1093 | """ |
|
1087 | 1094 | Wrapped rst renderer with @mention highlighting |
|
1088 | 1095 | |
|
1089 | 1096 | :param source: |
|
1090 | 1097 | """ |
|
1091 | 1098 | return literal('<div class="rst-block">%s</div>' % |
|
1092 | 1099 | MarkupRenderer.rst_with_mentions(source)) |
|
1093 | 1100 | |
|
1094 | 1101 | |
|
1095 | 1102 | def changeset_status(repo, revision): |
|
1096 | 1103 | return ChangesetStatusModel().get_status(repo, revision) |
|
1097 | 1104 | |
|
1098 | 1105 | |
|
1099 | 1106 | def changeset_status_lbl(changeset_status): |
|
1100 | 1107 | return dict(ChangesetStatus.STATUSES).get(changeset_status) |
|
1101 | 1108 | |
|
1102 | 1109 | |
|
1103 | 1110 | def get_permission_name(key): |
|
1104 | 1111 | return dict(Permission.PERMS).get(key) |
@@ -1,972 +1,972 b'' | |||
|
1 | 1 | # -*- coding: utf-8 -*- |
|
2 | 2 | """ |
|
3 | 3 | vcs.backends.base |
|
4 | 4 | ~~~~~~~~~~~~~~~~~ |
|
5 | 5 | |
|
6 | 6 | Base for all available scm backends |
|
7 | 7 | |
|
8 | 8 | :created_on: Apr 8, 2010 |
|
9 | 9 | :copyright: (c) 2010-2011 by Marcin Kuzminski, Lukasz Balcerzak. |
|
10 | 10 | """ |
|
11 | 11 | |
|
12 | 12 | |
|
13 | 13 | from itertools import chain |
|
14 | 14 | from rhodecode.lib.vcs.utils import author_name, author_email |
|
15 | 15 | from rhodecode.lib.vcs.utils.lazy import LazyProperty |
|
16 | 16 | from rhodecode.lib.vcs.utils.helpers import get_dict_for_attrs |
|
17 | 17 | from rhodecode.lib.vcs.conf import settings |
|
18 | 18 | |
|
19 | 19 | from rhodecode.lib.vcs.exceptions import ChangesetError, EmptyRepositoryError, \ |
|
20 | 20 | NodeAlreadyAddedError, NodeAlreadyChangedError, NodeAlreadyExistsError, \ |
|
21 | 21 | NodeAlreadyRemovedError, NodeDoesNotExistError, NodeNotChangedError, \ |
|
22 | 22 | RepositoryError |
|
23 | 23 | |
|
24 | 24 | |
|
25 | 25 | class BaseRepository(object): |
|
26 | 26 | """ |
|
27 | 27 | Base Repository for final backends |
|
28 | 28 | |
|
29 | 29 | **Attributes** |
|
30 | 30 | |
|
31 | 31 | ``DEFAULT_BRANCH_NAME`` |
|
32 | 32 | name of default branch (i.e. "trunk" for svn, "master" for git etc. |
|
33 | 33 | |
|
34 | 34 | ``scm`` |
|
35 | 35 | alias of scm, i.e. *git* or *hg* |
|
36 | 36 | |
|
37 | 37 | ``repo`` |
|
38 | 38 | object from external api |
|
39 | 39 | |
|
40 | 40 | ``revisions`` |
|
41 | 41 | list of all available revisions' ids, in ascending order |
|
42 | 42 | |
|
43 | 43 | ``changesets`` |
|
44 | 44 | storage dict caching returned changesets |
|
45 | 45 | |
|
46 | 46 | ``path`` |
|
47 | 47 | absolute path to the repository |
|
48 | 48 | |
|
49 | 49 | ``branches`` |
|
50 | 50 | branches as list of changesets |
|
51 | 51 | |
|
52 | 52 | ``tags`` |
|
53 | 53 | tags as list of changesets |
|
54 | 54 | """ |
|
55 | 55 | scm = None |
|
56 | 56 | DEFAULT_BRANCH_NAME = None |
|
57 | 57 | EMPTY_CHANGESET = '0' * 40 |
|
58 | 58 | |
|
59 | 59 | def __init__(self, repo_path, create=False, **kwargs): |
|
60 | 60 | """ |
|
61 | 61 | Initializes repository. Raises RepositoryError if repository could |
|
62 | 62 | not be find at the given ``repo_path`` or directory at ``repo_path`` |
|
63 | 63 | exists and ``create`` is set to True. |
|
64 | 64 | |
|
65 | 65 | :param repo_path: local path of the repository |
|
66 | 66 | :param create=False: if set to True, would try to craete repository. |
|
67 | 67 | :param src_url=None: if set, should be proper url from which repository |
|
68 | 68 | would be cloned; requires ``create`` parameter to be set to True - |
|
69 | 69 | raises RepositoryError if src_url is set and create evaluates to |
|
70 | 70 | False |
|
71 | 71 | """ |
|
72 | 72 | raise NotImplementedError |
|
73 | 73 | |
|
74 | 74 | def __str__(self): |
|
75 | 75 | return '<%s at %s>' % (self.__class__.__name__, self.path) |
|
76 | 76 | |
|
77 | 77 | def __repr__(self): |
|
78 | 78 | return self.__str__() |
|
79 | 79 | |
|
80 | 80 | def __len__(self): |
|
81 | 81 | return self.count() |
|
82 | 82 | |
|
83 | 83 | @LazyProperty |
|
84 | 84 | def alias(self): |
|
85 | 85 | for k, v in settings.BACKENDS.items(): |
|
86 | 86 | if v.split('.')[-1] == str(self.__class__.__name__): |
|
87 | 87 | return k |
|
88 | 88 | |
|
89 | 89 | @LazyProperty |
|
90 | 90 | def name(self): |
|
91 | 91 | raise NotImplementedError |
|
92 | 92 | |
|
93 | 93 | @LazyProperty |
|
94 | 94 | def owner(self): |
|
95 | 95 | raise NotImplementedError |
|
96 | 96 | |
|
97 | 97 | @LazyProperty |
|
98 | 98 | def description(self): |
|
99 | 99 | raise NotImplementedError |
|
100 | 100 | |
|
101 | 101 | @LazyProperty |
|
102 | 102 | def size(self): |
|
103 | 103 | """ |
|
104 | 104 | Returns combined size in bytes for all repository files |
|
105 | 105 | """ |
|
106 | 106 | |
|
107 | 107 | size = 0 |
|
108 | 108 | try: |
|
109 | 109 | tip = self.get_changeset() |
|
110 | 110 | for topnode, dirs, files in tip.walk('/'): |
|
111 | 111 | for f in files: |
|
112 | 112 | size += tip.get_file_size(f.path) |
|
113 | 113 | for dir in dirs: |
|
114 | 114 | for f in files: |
|
115 | 115 | size += tip.get_file_size(f.path) |
|
116 | 116 | |
|
117 | 117 | except RepositoryError, e: |
|
118 | 118 | pass |
|
119 | 119 | return size |
|
120 | 120 | |
|
121 | 121 | def is_valid(self): |
|
122 | 122 | """ |
|
123 | 123 | Validates repository. |
|
124 | 124 | """ |
|
125 | 125 | raise NotImplementedError |
|
126 | 126 | |
|
127 | 127 | def get_last_change(self): |
|
128 | 128 | self.get_changesets() |
|
129 | 129 | |
|
130 | 130 | #========================================================================== |
|
131 | 131 | # CHANGESETS |
|
132 | 132 | #========================================================================== |
|
133 | 133 | |
|
134 | 134 | def get_changeset(self, revision=None): |
|
135 | 135 | """ |
|
136 | 136 | Returns instance of ``Changeset`` class. If ``revision`` is None, most |
|
137 | 137 | recent changeset is returned. |
|
138 | 138 | |
|
139 | 139 | :raises ``EmptyRepositoryError``: if there are no revisions |
|
140 | 140 | """ |
|
141 | 141 | raise NotImplementedError |
|
142 | 142 | |
|
143 | 143 | def __iter__(self): |
|
144 | 144 | """ |
|
145 | 145 | Allows Repository objects to be iterated. |
|
146 | 146 | |
|
147 | 147 | *Requires* implementation of ``__getitem__`` method. |
|
148 | 148 | """ |
|
149 | 149 | for revision in self.revisions: |
|
150 | 150 | yield self.get_changeset(revision) |
|
151 | 151 | |
|
152 | 152 | def get_changesets(self, start=None, end=None, start_date=None, |
|
153 | 153 | end_date=None, branch_name=None, reverse=False): |
|
154 | 154 | """ |
|
155 | 155 | Returns iterator of ``MercurialChangeset`` objects from start to end |
|
156 | 156 | not inclusive This should behave just like a list, ie. end is not |
|
157 | 157 | inclusive |
|
158 | 158 | |
|
159 | 159 | :param start: None or str |
|
160 | 160 | :param end: None or str |
|
161 | 161 | :param start_date: |
|
162 | 162 | :param end_date: |
|
163 | 163 | :param branch_name: |
|
164 | 164 | :param reversed: |
|
165 | 165 | """ |
|
166 | 166 | raise NotImplementedError |
|
167 | 167 | |
|
168 | 168 | def __getslice__(self, i, j): |
|
169 | 169 | """ |
|
170 | 170 | Returns a iterator of sliced repository |
|
171 | 171 | """ |
|
172 | 172 | for rev in self.revisions[i:j]: |
|
173 | 173 | yield self.get_changeset(rev) |
|
174 | 174 | |
|
175 | 175 | def __getitem__(self, key): |
|
176 | 176 | return self.get_changeset(key) |
|
177 | 177 | |
|
178 | 178 | def count(self): |
|
179 | 179 | return len(self.revisions) |
|
180 | 180 | |
|
181 | 181 | def tag(self, name, user, revision=None, message=None, date=None, **opts): |
|
182 | 182 | """ |
|
183 | 183 | Creates and returns a tag for the given ``revision``. |
|
184 | 184 | |
|
185 | 185 | :param name: name for new tag |
|
186 | 186 | :param user: full username, i.e.: "Joe Doe <joe.doe@example.com>" |
|
187 | 187 | :param revision: changeset id for which new tag would be created |
|
188 | 188 | :param message: message of the tag's commit |
|
189 | 189 | :param date: date of tag's commit |
|
190 | 190 | |
|
191 | 191 | :raises TagAlreadyExistError: if tag with same name already exists |
|
192 | 192 | """ |
|
193 | 193 | raise NotImplementedError |
|
194 | 194 | |
|
195 | 195 | def remove_tag(self, name, user, message=None, date=None): |
|
196 | 196 | """ |
|
197 | 197 | Removes tag with the given ``name``. |
|
198 | 198 | |
|
199 | 199 | :param name: name of the tag to be removed |
|
200 | 200 | :param user: full username, i.e.: "Joe Doe <joe.doe@example.com>" |
|
201 | 201 | :param message: message of the tag's removal commit |
|
202 | 202 | :param date: date of tag's removal commit |
|
203 | 203 | |
|
204 | 204 | :raises TagDoesNotExistError: if tag with given name does not exists |
|
205 | 205 | """ |
|
206 | 206 | raise NotImplementedError |
|
207 | 207 | |
|
208 | 208 | def get_diff(self, rev1, rev2, path=None, ignore_whitespace=False, |
|
209 | 209 | context=3): |
|
210 | 210 | """ |
|
211 | 211 | Returns (git like) *diff*, as plain text. Shows changes introduced by |
|
212 | 212 | ``rev2`` since ``rev1``. |
|
213 | 213 | |
|
214 | 214 | :param rev1: Entry point from which diff is shown. Can be |
|
215 | 215 | ``self.EMPTY_CHANGESET`` - in this case, patch showing all |
|
216 | 216 | the changes since empty state of the repository until ``rev2`` |
|
217 | 217 | :param rev2: Until which revision changes should be shown. |
|
218 | 218 | :param ignore_whitespace: If set to ``True``, would not show whitespace |
|
219 | 219 | changes. Defaults to ``False``. |
|
220 | 220 | :param context: How many lines before/after changed lines should be |
|
221 | 221 | shown. Defaults to ``3``. |
|
222 | 222 | """ |
|
223 | 223 | raise NotImplementedError |
|
224 | 224 | |
|
225 | 225 | # ========== # |
|
226 | 226 | # COMMIT API # |
|
227 | 227 | # ========== # |
|
228 | 228 | |
|
229 | 229 | @LazyProperty |
|
230 | 230 | def in_memory_changeset(self): |
|
231 | 231 | """ |
|
232 | 232 | Returns ``InMemoryChangeset`` object for this repository. |
|
233 | 233 | """ |
|
234 | 234 | raise NotImplementedError |
|
235 | 235 | |
|
236 | 236 | def add(self, filenode, **kwargs): |
|
237 | 237 | """ |
|
238 | 238 | Commit api function that will add given ``FileNode`` into this |
|
239 | 239 | repository. |
|
240 | 240 | |
|
241 | 241 | :raises ``NodeAlreadyExistsError``: if there is a file with same path |
|
242 | 242 | already in repository |
|
243 | 243 | :raises ``NodeAlreadyAddedError``: if given node is already marked as |
|
244 | 244 | *added* |
|
245 | 245 | """ |
|
246 | 246 | raise NotImplementedError |
|
247 | 247 | |
|
248 | 248 | def remove(self, filenode, **kwargs): |
|
249 | 249 | """ |
|
250 | 250 | Commit api function that will remove given ``FileNode`` into this |
|
251 | 251 | repository. |
|
252 | 252 | |
|
253 | 253 | :raises ``EmptyRepositoryError``: if there are no changesets yet |
|
254 | 254 | :raises ``NodeDoesNotExistError``: if there is no file with given path |
|
255 | 255 | """ |
|
256 | 256 | raise NotImplementedError |
|
257 | 257 | |
|
258 | 258 | def commit(self, message, **kwargs): |
|
259 | 259 | """ |
|
260 | 260 | Persists current changes made on this repository and returns newly |
|
261 | 261 | created changeset. |
|
262 | 262 | |
|
263 | 263 | :raises ``NothingChangedError``: if no changes has been made |
|
264 | 264 | """ |
|
265 | 265 | raise NotImplementedError |
|
266 | 266 | |
|
267 | 267 | def get_state(self): |
|
268 | 268 | """ |
|
269 | 269 | Returns dictionary with ``added``, ``changed`` and ``removed`` lists |
|
270 | 270 | containing ``FileNode`` objects. |
|
271 | 271 | """ |
|
272 | 272 | raise NotImplementedError |
|
273 | 273 | |
|
274 | 274 | def get_config_value(self, section, name, config_file=None): |
|
275 | 275 | """ |
|
276 | 276 | Returns configuration value for a given [``section``] and ``name``. |
|
277 | 277 | |
|
278 | 278 | :param section: Section we want to retrieve value from |
|
279 | 279 | :param name: Name of configuration we want to retrieve |
|
280 | 280 | :param config_file: A path to file which should be used to retrieve |
|
281 | 281 | configuration from (might also be a list of file paths) |
|
282 | 282 | """ |
|
283 | 283 | raise NotImplementedError |
|
284 | 284 | |
|
285 | 285 | def get_user_name(self, config_file=None): |
|
286 | 286 | """ |
|
287 | 287 | Returns user's name from global configuration file. |
|
288 | 288 | |
|
289 | 289 | :param config_file: A path to file which should be used to retrieve |
|
290 | 290 | configuration from (might also be a list of file paths) |
|
291 | 291 | """ |
|
292 | 292 | raise NotImplementedError |
|
293 | 293 | |
|
294 | 294 | def get_user_email(self, config_file=None): |
|
295 | 295 | """ |
|
296 | 296 | Returns user's email from global configuration file. |
|
297 | 297 | |
|
298 | 298 | :param config_file: A path to file which should be used to retrieve |
|
299 | 299 | configuration from (might also be a list of file paths) |
|
300 | 300 | """ |
|
301 | 301 | raise NotImplementedError |
|
302 | 302 | |
|
303 | 303 | # =========== # |
|
304 | 304 | # WORKDIR API # |
|
305 | 305 | # =========== # |
|
306 | 306 | |
|
307 | 307 | @LazyProperty |
|
308 | 308 | def workdir(self): |
|
309 | 309 | """ |
|
310 | 310 | Returns ``Workdir`` instance for this repository. |
|
311 | 311 | """ |
|
312 | 312 | raise NotImplementedError |
|
313 | 313 | |
|
314 | 314 | |
|
315 | 315 | class BaseChangeset(object): |
|
316 | 316 | """ |
|
317 | 317 | Each backend should implement it's changeset representation. |
|
318 | 318 | |
|
319 | 319 | **Attributes** |
|
320 | 320 | |
|
321 | 321 | ``repository`` |
|
322 | 322 | repository object within which changeset exists |
|
323 | 323 | |
|
324 | 324 | ``id`` |
|
325 | 325 | may be ``raw_id`` or i.e. for mercurial's tip just ``tip`` |
|
326 | 326 | |
|
327 | 327 | ``raw_id`` |
|
328 | 328 | raw changeset representation (i.e. full 40 length sha for git |
|
329 | 329 | backend) |
|
330 | 330 | |
|
331 | 331 | ``short_id`` |
|
332 | 332 | shortened (if apply) version of ``raw_id``; it would be simple |
|
333 | 333 | shortcut for ``raw_id[:12]`` for git/mercurial backends or same |
|
334 | 334 | as ``raw_id`` for subversion |
|
335 | 335 | |
|
336 | 336 | ``revision`` |
|
337 | 337 | revision number as integer |
|
338 | 338 | |
|
339 | 339 | ``files`` |
|
340 | 340 | list of ``FileNode`` (``Node`` with NodeKind.FILE) objects |
|
341 | 341 | |
|
342 | 342 | ``dirs`` |
|
343 | 343 | list of ``DirNode`` (``Node`` with NodeKind.DIR) objects |
|
344 | 344 | |
|
345 | 345 | ``nodes`` |
|
346 | 346 | combined list of ``Node`` objects |
|
347 | 347 | |
|
348 | 348 | ``author`` |
|
349 | 349 | author of the changeset, as unicode |
|
350 | 350 | |
|
351 | 351 | ``message`` |
|
352 | 352 | message of the changeset, as unicode |
|
353 | 353 | |
|
354 | 354 | ``parents`` |
|
355 | 355 | list of parent changesets |
|
356 | 356 | |
|
357 | 357 | ``last`` |
|
358 | 358 | ``True`` if this is last changeset in repository, ``False`` |
|
359 | 359 | otherwise; trying to access this attribute while there is no |
|
360 | 360 | changesets would raise ``EmptyRepositoryError`` |
|
361 | 361 | """ |
|
362 | 362 | def __str__(self): |
|
363 | 363 | return '<%s at %s:%s>' % (self.__class__.__name__, self.revision, |
|
364 | 364 | self.short_id) |
|
365 | 365 | |
|
366 | 366 | def __repr__(self): |
|
367 | 367 | return self.__str__() |
|
368 | 368 | |
|
369 | 369 | def __unicode__(self): |
|
370 | 370 | return u'%s:%s' % (self.revision, self.short_id) |
|
371 | 371 | |
|
372 | 372 | def __eq__(self, other): |
|
373 | 373 | return self.raw_id == other.raw_id |
|
374 | 374 | |
|
375 | 375 | def __json__(self): |
|
376 | 376 | return dict( |
|
377 | 377 | short_id=self.short_id, |
|
378 | 378 | raw_id=self.raw_id, |
|
379 | 379 | message=self.message, |
|
380 | 380 | date=self.date, |
|
381 | 381 | author=self.author, |
|
382 | 382 | ) |
|
383 | 383 | |
|
384 | 384 | @LazyProperty |
|
385 | 385 | def last(self): |
|
386 | 386 | if self.repository is None: |
|
387 | 387 | raise ChangesetError("Cannot check if it's most recent revision") |
|
388 | 388 | return self.raw_id == self.repository.revisions[-1] |
|
389 | 389 | |
|
390 | 390 | @LazyProperty |
|
391 | 391 | def parents(self): |
|
392 | 392 | """ |
|
393 | 393 | Returns list of parents changesets. |
|
394 | 394 | """ |
|
395 | 395 | raise NotImplementedError |
|
396 | 396 | |
|
397 | 397 | @LazyProperty |
|
398 | 398 | def children(self): |
|
399 | 399 | """ |
|
400 | 400 | Returns list of children changesets. |
|
401 | 401 | """ |
|
402 | 402 | raise NotImplementedError |
|
403 | 403 | |
|
404 | 404 | @LazyProperty |
|
405 | 405 | def id(self): |
|
406 | 406 | """ |
|
407 | 407 | Returns string identifying this changeset. |
|
408 | 408 | """ |
|
409 | 409 | raise NotImplementedError |
|
410 | 410 | |
|
411 | 411 | @LazyProperty |
|
412 | 412 | def raw_id(self): |
|
413 | 413 | """ |
|
414 | 414 | Returns raw string identifying this changeset. |
|
415 | 415 | """ |
|
416 | 416 | raise NotImplementedError |
|
417 | 417 | |
|
418 | 418 | @LazyProperty |
|
419 | 419 | def short_id(self): |
|
420 | 420 | """ |
|
421 | 421 | Returns shortened version of ``raw_id`` attribute, as string, |
|
422 | 422 | identifying this changeset, useful for web representation. |
|
423 | 423 | """ |
|
424 | 424 | raise NotImplementedError |
|
425 | 425 | |
|
426 | 426 | @LazyProperty |
|
427 | 427 | def revision(self): |
|
428 | 428 | """ |
|
429 | 429 | Returns integer identifying this changeset. |
|
430 | 430 | |
|
431 | 431 | """ |
|
432 | 432 | raise NotImplementedError |
|
433 | 433 | |
|
434 | 434 | @LazyProperty |
|
435 | 435 | def author(self): |
|
436 | 436 | """ |
|
437 | 437 | Returns Author for given commit |
|
438 | 438 | """ |
|
439 | 439 | |
|
440 | 440 | raise NotImplementedError |
|
441 | 441 | |
|
442 | 442 | @LazyProperty |
|
443 | 443 | def author_name(self): |
|
444 | 444 | """ |
|
445 | 445 | Returns Author name for given commit |
|
446 | 446 | """ |
|
447 | 447 | |
|
448 | 448 | return author_name(self.author) |
|
449 | 449 | |
|
450 | 450 | @LazyProperty |
|
451 | 451 | def author_email(self): |
|
452 | 452 | """ |
|
453 | 453 | Returns Author email address for given commit |
|
454 | 454 | """ |
|
455 | 455 | |
|
456 | 456 | return author_email(self.author) |
|
457 | 457 | |
|
458 | 458 | def get_file_mode(self, path): |
|
459 | 459 | """ |
|
460 | 460 | Returns stat mode of the file at the given ``path``. |
|
461 | 461 | """ |
|
462 | 462 | raise NotImplementedError |
|
463 | 463 | |
|
464 | 464 | def get_file_content(self, path): |
|
465 | 465 | """ |
|
466 | 466 | Returns content of the file at the given ``path``. |
|
467 | 467 | """ |
|
468 | 468 | raise NotImplementedError |
|
469 | 469 | |
|
470 | 470 | def get_file_size(self, path): |
|
471 | 471 | """ |
|
472 | 472 | Returns size of the file at the given ``path``. |
|
473 | 473 | """ |
|
474 | 474 | raise NotImplementedError |
|
475 | 475 | |
|
476 | 476 | def get_file_changeset(self, path): |
|
477 | 477 | """ |
|
478 | 478 | Returns last commit of the file at the given ``path``. |
|
479 | 479 | """ |
|
480 | 480 | raise NotImplementedError |
|
481 | 481 | |
|
482 | 482 | def get_file_history(self, path): |
|
483 | 483 | """ |
|
484 | 484 | Returns history of file as reversed list of ``Changeset`` objects for |
|
485 | 485 | which file at given ``path`` has been modified. |
|
486 | 486 | """ |
|
487 | 487 | raise NotImplementedError |
|
488 | 488 | |
|
489 | 489 | def get_nodes(self, path): |
|
490 | 490 | """ |
|
491 | 491 | Returns combined ``DirNode`` and ``FileNode`` objects list representing |
|
492 | 492 | state of changeset at the given ``path``. |
|
493 | 493 | |
|
494 | 494 | :raises ``ChangesetError``: if node at the given ``path`` is not |
|
495 | 495 | instance of ``DirNode`` |
|
496 | 496 | """ |
|
497 | 497 | raise NotImplementedError |
|
498 | 498 | |
|
499 | 499 | def get_node(self, path): |
|
500 | 500 | """ |
|
501 | 501 | Returns ``Node`` object from the given ``path``. |
|
502 | 502 | |
|
503 | 503 | :raises ``NodeDoesNotExistError``: if there is no node at the given |
|
504 | 504 | ``path`` |
|
505 | 505 | """ |
|
506 | 506 | raise NotImplementedError |
|
507 | 507 | |
|
508 | 508 | def fill_archive(self, stream=None, kind='tgz', prefix=None): |
|
509 | 509 | """ |
|
510 | 510 | Fills up given stream. |
|
511 | 511 | |
|
512 | 512 | :param stream: file like object. |
|
513 | 513 | :param kind: one of following: ``zip``, ``tar``, ``tgz`` |
|
514 | 514 | or ``tbz2``. Default: ``tgz``. |
|
515 | 515 | :param prefix: name of root directory in archive. |
|
516 | 516 | Default is repository name and changeset's raw_id joined with dash. |
|
517 | 517 | |
|
518 | 518 | repo-tip.<kind> |
|
519 | 519 | """ |
|
520 | 520 | |
|
521 | 521 | raise NotImplementedError |
|
522 | 522 | |
|
523 | 523 | def get_chunked_archive(self, **kwargs): |
|
524 | 524 | """ |
|
525 | 525 | Returns iterable archive. Tiny wrapper around ``fill_archive`` method. |
|
526 | 526 | |
|
527 | 527 | :param chunk_size: extra parameter which controls size of returned |
|
528 | 528 | chunks. Default:8k. |
|
529 | 529 | """ |
|
530 | 530 | |
|
531 | 531 | chunk_size = kwargs.pop('chunk_size', 8192) |
|
532 | 532 | stream = kwargs.get('stream') |
|
533 | 533 | self.fill_archive(**kwargs) |
|
534 | 534 | while True: |
|
535 | 535 | data = stream.read(chunk_size) |
|
536 | 536 | if not data: |
|
537 | 537 | break |
|
538 | 538 | yield data |
|
539 | 539 | |
|
540 | 540 | @LazyProperty |
|
541 | 541 | def root(self): |
|
542 | 542 | """ |
|
543 | 543 | Returns ``RootNode`` object for this changeset. |
|
544 | 544 | """ |
|
545 | 545 | return self.get_node('') |
|
546 | 546 | |
|
547 | 547 | def next(self, branch=None): |
|
548 | 548 | """ |
|
549 | 549 | Returns next changeset from current, if branch is gives it will return |
|
550 | 550 | next changeset belonging to this branch |
|
551 | 551 | |
|
552 | 552 | :param branch: show changesets within the given named branch |
|
553 | 553 | """ |
|
554 | 554 | raise NotImplementedError |
|
555 | 555 | |
|
556 | 556 | def prev(self, branch=None): |
|
557 | 557 | """ |
|
558 | 558 | Returns previous changeset from current, if branch is gives it will |
|
559 | 559 | return previous changeset belonging to this branch |
|
560 | 560 | |
|
561 | 561 | :param branch: show changesets within the given named branch |
|
562 | 562 | """ |
|
563 | 563 | raise NotImplementedError |
|
564 | 564 | |
|
565 | 565 | @LazyProperty |
|
566 | 566 | def added(self): |
|
567 | 567 | """ |
|
568 | 568 | Returns list of added ``FileNode`` objects. |
|
569 | 569 | """ |
|
570 | 570 | raise NotImplementedError |
|
571 | 571 | |
|
572 | 572 | @LazyProperty |
|
573 | 573 | def changed(self): |
|
574 | 574 | """ |
|
575 | 575 | Returns list of modified ``FileNode`` objects. |
|
576 | 576 | """ |
|
577 | 577 | raise NotImplementedError |
|
578 | 578 | |
|
579 | 579 | @LazyProperty |
|
580 | 580 | def removed(self): |
|
581 | 581 | """ |
|
582 | 582 | Returns list of removed ``FileNode`` objects. |
|
583 | 583 | """ |
|
584 | 584 | raise NotImplementedError |
|
585 | 585 | |
|
586 | 586 | @LazyProperty |
|
587 | 587 | def size(self): |
|
588 | 588 | """ |
|
589 | 589 | Returns total number of bytes from contents of all filenodes. |
|
590 | 590 | """ |
|
591 | 591 | return sum((node.size for node in self.get_filenodes_generator())) |
|
592 | 592 | |
|
593 | 593 | def walk(self, topurl=''): |
|
594 | 594 | """ |
|
595 | 595 | Similar to os.walk method. Insted of filesystem it walks through |
|
596 | 596 | changeset starting at given ``topurl``. Returns generator of tuples |
|
597 | 597 | (topnode, dirnodes, filenodes). |
|
598 | 598 | """ |
|
599 | 599 | topnode = self.get_node(topurl) |
|
600 | 600 | yield (topnode, topnode.dirs, topnode.files) |
|
601 | 601 | for dirnode in topnode.dirs: |
|
602 | 602 | for tup in self.walk(dirnode.path): |
|
603 | 603 | yield tup |
|
604 | 604 | |
|
605 | 605 | def get_filenodes_generator(self): |
|
606 | 606 | """ |
|
607 | 607 | Returns generator that yields *all* file nodes. |
|
608 | 608 | """ |
|
609 | 609 | for topnode, dirs, files in self.walk(): |
|
610 | 610 | for node in files: |
|
611 | 611 | yield node |
|
612 | 612 | |
|
613 | 613 | def as_dict(self): |
|
614 | 614 | """ |
|
615 | 615 | Returns dictionary with changeset's attributes and their values. |
|
616 | 616 | """ |
|
617 | 617 | data = get_dict_for_attrs(self, ['id', 'raw_id', 'short_id', |
|
618 | 618 | 'revision', 'date', 'message']) |
|
619 | 619 | data['author'] = {'name': self.author_name, 'email': self.author_email} |
|
620 | 620 | data['added'] = [node.path for node in self.added] |
|
621 | 621 | data['changed'] = [node.path for node in self.changed] |
|
622 | 622 | data['removed'] = [node.path for node in self.removed] |
|
623 | 623 | return data |
|
624 | 624 | |
|
625 | 625 | |
|
626 | 626 | class BaseWorkdir(object): |
|
627 | 627 | """ |
|
628 | 628 | Working directory representation of single repository. |
|
629 | 629 | |
|
630 | 630 | :attribute: repository: repository object of working directory |
|
631 | 631 | """ |
|
632 | 632 | |
|
633 | 633 | def __init__(self, repository): |
|
634 | 634 | self.repository = repository |
|
635 | 635 | |
|
636 | 636 | def get_branch(self): |
|
637 | 637 | """ |
|
638 | 638 | Returns name of current branch. |
|
639 | 639 | """ |
|
640 | 640 | raise NotImplementedError |
|
641 | 641 | |
|
642 | 642 | def get_changeset(self): |
|
643 | 643 | """ |
|
644 | 644 | Returns current changeset. |
|
645 | 645 | """ |
|
646 | 646 | raise NotImplementedError |
|
647 | 647 | |
|
648 | 648 | def get_added(self): |
|
649 | 649 | """ |
|
650 | 650 | Returns list of ``FileNode`` objects marked as *new* in working |
|
651 | 651 | directory. |
|
652 | 652 | """ |
|
653 | 653 | raise NotImplementedError |
|
654 | 654 | |
|
655 | 655 | def get_changed(self): |
|
656 | 656 | """ |
|
657 | 657 | Returns list of ``FileNode`` objects *changed* in working directory. |
|
658 | 658 | """ |
|
659 | 659 | raise NotImplementedError |
|
660 | 660 | |
|
661 | 661 | def get_removed(self): |
|
662 | 662 | """ |
|
663 | 663 | Returns list of ``RemovedFileNode`` objects marked as *removed* in |
|
664 | 664 | working directory. |
|
665 | 665 | """ |
|
666 | 666 | raise NotImplementedError |
|
667 | 667 | |
|
668 | 668 | def get_untracked(self): |
|
669 | 669 | """ |
|
670 | 670 | Returns list of ``FileNode`` objects which are present within working |
|
671 | 671 | directory however are not tracked by repository. |
|
672 | 672 | """ |
|
673 | 673 | raise NotImplementedError |
|
674 | 674 | |
|
675 | 675 | def get_status(self): |
|
676 | 676 | """ |
|
677 | 677 | Returns dict with ``added``, ``changed``, ``removed`` and ``untracked`` |
|
678 | 678 | lists. |
|
679 | 679 | """ |
|
680 | 680 | raise NotImplementedError |
|
681 | 681 | |
|
682 | 682 | def commit(self, message, **kwargs): |
|
683 | 683 | """ |
|
684 | 684 | Commits local (from working directory) changes and returns newly |
|
685 | 685 | created |
|
686 | 686 | ``Changeset``. Updates repository's ``revisions`` list. |
|
687 | 687 | |
|
688 | 688 | :raises ``CommitError``: if any error occurs while committing |
|
689 | 689 | """ |
|
690 | 690 | raise NotImplementedError |
|
691 | 691 | |
|
692 | 692 | def update(self, revision=None): |
|
693 | 693 | """ |
|
694 | 694 | Fetches content of the given revision and populates it within working |
|
695 | 695 | directory. |
|
696 | 696 | """ |
|
697 | 697 | raise NotImplementedError |
|
698 | 698 | |
|
699 | 699 | def checkout_branch(self, branch=None): |
|
700 | 700 | """ |
|
701 | 701 | Checks out ``branch`` or the backend's default branch. |
|
702 | 702 | |
|
703 | 703 | Raises ``BranchDoesNotExistError`` if the branch does not exist. |
|
704 | 704 | """ |
|
705 | 705 | raise NotImplementedError |
|
706 | 706 | |
|
707 | 707 | |
|
708 | 708 | class BaseInMemoryChangeset(object): |
|
709 | 709 | """ |
|
710 | 710 | Represents differences between repository's state (most recent head) and |
|
711 | 711 | changes made *in place*. |
|
712 | 712 | |
|
713 | 713 | **Attributes** |
|
714 | 714 | |
|
715 | 715 | ``repository`` |
|
716 | 716 | repository object for this in-memory-changeset |
|
717 | 717 | |
|
718 | 718 | ``added`` |
|
719 | 719 | list of ``FileNode`` objects marked as *added* |
|
720 | 720 | |
|
721 | 721 | ``changed`` |
|
722 | 722 | list of ``FileNode`` objects marked as *changed* |
|
723 | 723 | |
|
724 | 724 | ``removed`` |
|
725 | 725 | list of ``FileNode`` or ``RemovedFileNode`` objects marked to be |
|
726 | 726 | *removed* |
|
727 | 727 | |
|
728 | 728 | ``parents`` |
|
729 | 729 | list of ``Changeset`` representing parents of in-memory changeset. |
|
730 | 730 | Should always be 2-element sequence. |
|
731 | 731 | |
|
732 | 732 | """ |
|
733 | 733 | |
|
734 | 734 | def __init__(self, repository): |
|
735 | 735 | self.repository = repository |
|
736 | 736 | self.added = [] |
|
737 | 737 | self.changed = [] |
|
738 | 738 | self.removed = [] |
|
739 | 739 | self.parents = [] |
|
740 | 740 | |
|
741 | 741 | def add(self, *filenodes): |
|
742 | 742 | """ |
|
743 | 743 | Marks given ``FileNode`` objects as *to be committed*. |
|
744 | 744 | |
|
745 | 745 | :raises ``NodeAlreadyExistsError``: if node with same path exists at |
|
746 | 746 | latest changeset |
|
747 | 747 | :raises ``NodeAlreadyAddedError``: if node with same path is already |
|
748 | 748 | marked as *added* |
|
749 | 749 | """ |
|
750 | 750 | # Check if not already marked as *added* first |
|
751 | 751 | for node in filenodes: |
|
752 | 752 | if node.path in (n.path for n in self.added): |
|
753 | 753 | raise NodeAlreadyAddedError("Such FileNode %s is already " |
|
754 | 754 | "marked for addition" % node.path) |
|
755 | 755 | for node in filenodes: |
|
756 | 756 | self.added.append(node) |
|
757 | 757 | |
|
758 | 758 | def change(self, *filenodes): |
|
759 | 759 | """ |
|
760 | 760 | Marks given ``FileNode`` objects to be *changed* in next commit. |
|
761 | 761 | |
|
762 | 762 | :raises ``EmptyRepositoryError``: if there are no changesets yet |
|
763 | 763 | :raises ``NodeAlreadyExistsError``: if node with same path is already |
|
764 | 764 | marked to be *changed* |
|
765 | 765 | :raises ``NodeAlreadyRemovedError``: if node with same path is already |
|
766 | 766 | marked to be *removed* |
|
767 | 767 | :raises ``NodeDoesNotExistError``: if node doesn't exist in latest |
|
768 | 768 | changeset |
|
769 | 769 | :raises ``NodeNotChangedError``: if node hasn't really be changed |
|
770 | 770 | """ |
|
771 | 771 | for node in filenodes: |
|
772 | 772 | if node.path in (n.path for n in self.removed): |
|
773 | 773 | raise NodeAlreadyRemovedError("Node at %s is already marked " |
|
774 | 774 | "as removed" % node.path) |
|
775 | 775 | try: |
|
776 | 776 | self.repository.get_changeset() |
|
777 | 777 | except EmptyRepositoryError: |
|
778 | 778 | raise EmptyRepositoryError("Nothing to change - try to *add* new " |
|
779 | 779 | "nodes rather than changing them") |
|
780 | 780 | for node in filenodes: |
|
781 | 781 | if node.path in (n.path for n in self.changed): |
|
782 | 782 | raise NodeAlreadyChangedError("Node at '%s' is already " |
|
783 | 783 | "marked as changed" % node.path) |
|
784 | 784 | self.changed.append(node) |
|
785 | 785 | |
|
786 | 786 | def remove(self, *filenodes): |
|
787 | 787 | """ |
|
788 | 788 | Marks given ``FileNode`` (or ``RemovedFileNode``) objects to be |
|
789 | 789 | *removed* in next commit. |
|
790 | 790 | |
|
791 | 791 | :raises ``NodeAlreadyRemovedError``: if node has been already marked to |
|
792 | 792 | be *removed* |
|
793 | 793 | :raises ``NodeAlreadyChangedError``: if node has been already marked to |
|
794 | 794 | be *changed* |
|
795 | 795 | """ |
|
796 | 796 | for node in filenodes: |
|
797 | 797 | if node.path in (n.path for n in self.removed): |
|
798 | 798 | raise NodeAlreadyRemovedError("Node is already marked to " |
|
799 | 799 | "for removal at %s" % node.path) |
|
800 | 800 | if node.path in (n.path for n in self.changed): |
|
801 | 801 | raise NodeAlreadyChangedError("Node is already marked to " |
|
802 | 802 | "be changed at %s" % node.path) |
|
803 | 803 | # We only mark node as *removed* - real removal is done by |
|
804 | 804 | # commit method |
|
805 | 805 | self.removed.append(node) |
|
806 | 806 | |
|
807 | 807 | def reset(self): |
|
808 | 808 | """ |
|
809 | 809 | Resets this instance to initial state (cleans ``added``, ``changed`` |
|
810 | 810 | and ``removed`` lists). |
|
811 | 811 | """ |
|
812 | 812 | self.added = [] |
|
813 | 813 | self.changed = [] |
|
814 | 814 | self.removed = [] |
|
815 | 815 | self.parents = [] |
|
816 | 816 | |
|
817 | 817 | def get_ipaths(self): |
|
818 | 818 | """ |
|
819 | 819 | Returns generator of paths from nodes marked as added, changed or |
|
820 | 820 | removed. |
|
821 | 821 | """ |
|
822 | 822 | for node in chain(self.added, self.changed, self.removed): |
|
823 | 823 | yield node.path |
|
824 | 824 | |
|
825 | 825 | def get_paths(self): |
|
826 | 826 | """ |
|
827 | 827 | Returns list of paths from nodes marked as added, changed or removed. |
|
828 | 828 | """ |
|
829 | 829 | return list(self.get_ipaths()) |
|
830 | 830 | |
|
831 | 831 | def check_integrity(self, parents=None): |
|
832 | 832 | """ |
|
833 | 833 | Checks in-memory changeset's integrity. Also, sets parents if not |
|
834 | 834 | already set. |
|
835 | 835 | |
|
836 | 836 | :raises CommitError: if any error occurs (i.e. |
|
837 | 837 | ``NodeDoesNotExistError``). |
|
838 | 838 | """ |
|
839 | 839 | if not self.parents: |
|
840 | 840 | parents = parents or [] |
|
841 | 841 | if len(parents) == 0: |
|
842 | 842 | try: |
|
843 | 843 | parents = [self.repository.get_changeset(), None] |
|
844 | 844 | except EmptyRepositoryError: |
|
845 | 845 | parents = [None, None] |
|
846 | 846 | elif len(parents) == 1: |
|
847 | 847 | parents += [None] |
|
848 | 848 | self.parents = parents |
|
849 | 849 | |
|
850 | 850 | # Local parents, only if not None |
|
851 | 851 | parents = [p for p in self.parents if p] |
|
852 | 852 | |
|
853 | 853 | # Check nodes marked as added |
|
854 | 854 | for p in parents: |
|
855 | 855 | for node in self.added: |
|
856 | 856 | try: |
|
857 | 857 | p.get_node(node.path) |
|
858 | 858 | except NodeDoesNotExistError: |
|
859 | 859 | pass |
|
860 | 860 | else: |
|
861 | 861 | raise NodeAlreadyExistsError("Node at %s already exists " |
|
862 | 862 | "at %s" % (node.path, p)) |
|
863 | 863 | |
|
864 | 864 | # Check nodes marked as changed |
|
865 | 865 | missing = set(self.changed) |
|
866 | 866 | not_changed = set(self.changed) |
|
867 | 867 | if self.changed and not parents: |
|
868 | 868 | raise NodeDoesNotExistError(str(self.changed[0].path)) |
|
869 | 869 | for p in parents: |
|
870 | 870 | for node in self.changed: |
|
871 | 871 | try: |
|
872 | 872 | old = p.get_node(node.path) |
|
873 | 873 | missing.remove(node) |
|
874 | 874 | if old.content != node.content: |
|
875 | 875 | not_changed.remove(node) |
|
876 | 876 | except NodeDoesNotExistError: |
|
877 | 877 | pass |
|
878 | 878 | if self.changed and missing: |
|
879 | 879 | raise NodeDoesNotExistError("Node at %s is missing " |
|
880 | 880 | "(parents: %s)" % (node.path, parents)) |
|
881 | 881 | |
|
882 | 882 | if self.changed and not_changed: |
|
883 | 883 | raise NodeNotChangedError("Node at %s wasn't actually changed " |
|
884 | 884 | "since parents' changesets: %s" % (not_changed.pop().path, |
|
885 | 885 | parents) |
|
886 | 886 | ) |
|
887 | 887 | |
|
888 | 888 | # Check nodes marked as removed |
|
889 | 889 | if self.removed and not parents: |
|
890 | 890 | raise NodeDoesNotExistError("Cannot remove node at %s as there " |
|
891 | 891 | "were no parents specified" % self.removed[0].path) |
|
892 | 892 | really_removed = set() |
|
893 | 893 | for p in parents: |
|
894 | 894 | for node in self.removed: |
|
895 | 895 | try: |
|
896 | 896 | p.get_node(node.path) |
|
897 | 897 | really_removed.add(node) |
|
898 | 898 | except ChangesetError: |
|
899 | 899 | pass |
|
900 | 900 | not_removed = set(self.removed) - really_removed |
|
901 | 901 | if not_removed: |
|
902 | 902 | raise NodeDoesNotExistError("Cannot remove node at %s from " |
|
903 | 903 | "following parents: %s" % (not_removed[0], parents)) |
|
904 | 904 | |
|
905 | 905 | def commit(self, message, author, parents=None, branch=None, date=None, |
|
906 | 906 | **kwargs): |
|
907 | 907 | """ |
|
908 | 908 | Performs in-memory commit (doesn't check workdir in any way) and |
|
909 | 909 | returns newly created ``Changeset``. Updates repository's |
|
910 | 910 | ``revisions``. |
|
911 | 911 | |
|
912 | 912 | .. note:: |
|
913 | 913 | While overriding this method each backend's should call |
|
914 | 914 | ``self.check_integrity(parents)`` in the first place. |
|
915 | 915 | |
|
916 | 916 | :param message: message of the commit |
|
917 | 917 | :param author: full username, i.e. "Joe Doe <joe.doe@example.com>" |
|
918 | 918 | :param parents: single parent or sequence of parents from which commit |
|
919 | 919 | would be derieved |
|
920 | 920 | :param date: ``datetime.datetime`` instance. Defaults to |
|
921 | 921 | ``datetime.datetime.now()``. |
|
922 | 922 | :param branch: branch name, as string. If none given, default backend's |
|
923 | 923 | branch would be used. |
|
924 | 924 | |
|
925 | 925 | :raises ``CommitError``: if any error occurs while committing |
|
926 | 926 | """ |
|
927 | 927 | raise NotImplementedError |
|
928 | 928 | |
|
929 | 929 | |
|
930 | 930 | class EmptyChangeset(BaseChangeset): |
|
931 | 931 | """ |
|
932 | 932 | An dummy empty changeset. It's possible to pass hash when creating |
|
933 | 933 | an EmptyChangeset |
|
934 | 934 | """ |
|
935 | 935 | |
|
936 | 936 | def __init__(self, cs='0' * 40, repo=None, requested_revision=None, |
|
937 | alias=None, message='', author='', date=''): | |
|
937 | alias=None, revision=-1, message='', author='', date=''): | |
|
938 | 938 | self._empty_cs = cs |
|
939 |
self.revision = |
|
|
939 | self.revision = revision | |
|
940 | 940 | self.message = message |
|
941 | 941 | self.author = author |
|
942 | 942 | self.date = date |
|
943 | 943 | self.repository = repo |
|
944 | 944 | self.requested_revision = requested_revision |
|
945 | 945 | self.alias = alias |
|
946 | 946 | |
|
947 | 947 | @LazyProperty |
|
948 | 948 | def raw_id(self): |
|
949 | 949 | """ |
|
950 | 950 | Returns raw string identifying this changeset, useful for web |
|
951 | 951 | representation. |
|
952 | 952 | """ |
|
953 | 953 | |
|
954 | 954 | return self._empty_cs |
|
955 | 955 | |
|
956 | 956 | @LazyProperty |
|
957 | 957 | def branch(self): |
|
958 | 958 | from rhodecode.lib.vcs.backends import get_backend |
|
959 | 959 | return get_backend(self.alias).DEFAULT_BRANCH_NAME |
|
960 | 960 | |
|
961 | 961 | @LazyProperty |
|
962 | 962 | def short_id(self): |
|
963 | 963 | return self.raw_id[:12] |
|
964 | 964 | |
|
965 | 965 | def get_file_changeset(self, path): |
|
966 | 966 | return self |
|
967 | 967 | |
|
968 | 968 | def get_file_content(self, path): |
|
969 | 969 | return u'' |
|
970 | 970 | |
|
971 | 971 | def get_file_size(self, path): |
|
972 | 972 | return 0 |
@@ -1,658 +1,659 b'' | |||
|
1 | 1 | # -*- coding: utf-8 -*- |
|
2 | 2 | """ |
|
3 | 3 | vcs.backends.git |
|
4 | 4 | ~~~~~~~~~~~~~~~~ |
|
5 | 5 | |
|
6 | 6 | Git backend implementation. |
|
7 | 7 | |
|
8 | 8 | :created_on: Apr 8, 2010 |
|
9 | 9 | :copyright: (c) 2010-2011 by Marcin Kuzminski, Lukasz Balcerzak. |
|
10 | 10 | """ |
|
11 | 11 | |
|
12 | 12 | import os |
|
13 | 13 | import re |
|
14 | 14 | import time |
|
15 | 15 | import posixpath |
|
16 | 16 | import logging |
|
17 | 17 | import traceback |
|
18 | 18 | import urllib |
|
19 | 19 | import urllib2 |
|
20 | 20 | from dulwich.repo import Repo, NotGitRepository |
|
21 | 21 | from dulwich.objects import Tag |
|
22 | 22 | from string import Template |
|
23 | 23 | from subprocess import Popen, PIPE |
|
24 | 24 | from rhodecode.lib.vcs.backends.base import BaseRepository |
|
25 | 25 | from rhodecode.lib.vcs.exceptions import BranchDoesNotExistError |
|
26 | 26 | from rhodecode.lib.vcs.exceptions import ChangesetDoesNotExistError |
|
27 | 27 | from rhodecode.lib.vcs.exceptions import EmptyRepositoryError |
|
28 | 28 | from rhodecode.lib.vcs.exceptions import RepositoryError |
|
29 | 29 | from rhodecode.lib.vcs.exceptions import TagAlreadyExistError |
|
30 | 30 | from rhodecode.lib.vcs.exceptions import TagDoesNotExistError |
|
31 | 31 | from rhodecode.lib.vcs.utils import safe_unicode, makedate, date_fromtimestamp |
|
32 | 32 | from rhodecode.lib.vcs.utils.lazy import LazyProperty |
|
33 | 33 | from rhodecode.lib.vcs.utils.ordered_dict import OrderedDict |
|
34 | 34 | from rhodecode.lib.vcs.utils.paths import abspath |
|
35 | 35 | from rhodecode.lib.vcs.utils.paths import get_user_home |
|
36 | 36 | from .workdir import GitWorkdir |
|
37 | 37 | from .changeset import GitChangeset |
|
38 | 38 | from .inmemory import GitInMemoryChangeset |
|
39 | 39 | from .config import ConfigFile |
|
40 | 40 | from rhodecode.lib import subprocessio |
|
41 | 41 | |
|
42 | 42 | |
|
43 | 43 | log = logging.getLogger(__name__) |
|
44 | 44 | |
|
45 | 45 | |
|
46 | 46 | class GitRepository(BaseRepository): |
|
47 | 47 | """ |
|
48 | 48 | Git repository backend. |
|
49 | 49 | """ |
|
50 | 50 | DEFAULT_BRANCH_NAME = 'master' |
|
51 | 51 | scm = 'git' |
|
52 | 52 | |
|
53 | 53 | def __init__(self, repo_path, create=False, src_url=None, |
|
54 | 54 | update_after_clone=False, bare=False): |
|
55 | 55 | |
|
56 | 56 | self.path = abspath(repo_path) |
|
57 | 57 | self._repo = self._get_repo(create, src_url, update_after_clone, bare) |
|
58 | 58 | #temporary set that to now at later we will move it to constructor |
|
59 | 59 | baseui = None |
|
60 | 60 | if baseui is None: |
|
61 | 61 | from mercurial.ui import ui |
|
62 | 62 | baseui = ui() |
|
63 | 63 | # patch the instance of GitRepo with an "FAKE" ui object to add |
|
64 | 64 | # compatibility layer with Mercurial |
|
65 | 65 | setattr(self._repo, 'ui', baseui) |
|
66 | 66 | |
|
67 | 67 | try: |
|
68 | 68 | self.head = self._repo.head() |
|
69 | 69 | except KeyError: |
|
70 | 70 | self.head = None |
|
71 | 71 | |
|
72 | 72 | self._config_files = [ |
|
73 | 73 | bare and abspath(self.path, 'config') or abspath(self.path, '.git', |
|
74 | 74 | 'config'), |
|
75 | 75 | abspath(get_user_home(), '.gitconfig'), |
|
76 | 76 | ] |
|
77 | 77 | self.bare = self._repo.bare |
|
78 | 78 | |
|
79 | 79 | @LazyProperty |
|
80 | 80 | def revisions(self): |
|
81 | 81 | """ |
|
82 | 82 | Returns list of revisions' ids, in ascending order. Being lazy |
|
83 | 83 | attribute allows external tools to inject shas from cache. |
|
84 | 84 | """ |
|
85 | 85 | return self._get_all_revisions() |
|
86 | 86 | |
|
87 | 87 | def run_git_command(self, cmd): |
|
88 | 88 | """ |
|
89 | 89 | Runs given ``cmd`` as git command and returns tuple |
|
90 | 90 | (returncode, stdout, stderr). |
|
91 | 91 | |
|
92 | 92 | .. note:: |
|
93 | 93 | This method exists only until log/blame functionality is implemented |
|
94 | 94 | at Dulwich (see https://bugs.launchpad.net/bugs/645142). Parsing |
|
95 | 95 | os command's output is road to hell... |
|
96 | 96 | |
|
97 | 97 | :param cmd: git command to be executed |
|
98 | 98 | """ |
|
99 | 99 | |
|
100 | 100 | _copts = ['-c', 'core.quotepath=false', ] |
|
101 | 101 | _str_cmd = False |
|
102 | 102 | if isinstance(cmd, basestring): |
|
103 | 103 | cmd = [cmd] |
|
104 | 104 | _str_cmd = True |
|
105 | 105 | |
|
106 | 106 | gitenv = os.environ |
|
107 | 107 | # need to clean fix GIT_DIR ! |
|
108 | 108 | if 'GIT_DIR' in gitenv: |
|
109 | 109 | del gitenv['GIT_DIR'] |
|
110 | 110 | gitenv['GIT_CONFIG_NOGLOBAL'] = '1' |
|
111 | 111 | |
|
112 | 112 | cmd = ['git'] + _copts + cmd |
|
113 | 113 | if _str_cmd: |
|
114 | 114 | cmd = ' '.join(cmd) |
|
115 | 115 | try: |
|
116 | 116 | opts = dict( |
|
117 | 117 | env=gitenv, |
|
118 | 118 | shell=False, |
|
119 | 119 | ) |
|
120 | 120 | if os.path.isdir(self.path): |
|
121 | 121 | opts['cwd'] = self.path |
|
122 | 122 | p = subprocessio.SubprocessIOChunker(cmd, **opts) |
|
123 | 123 | except (EnvironmentError, OSError), err: |
|
124 | 124 | log.error(traceback.format_exc()) |
|
125 | 125 | raise RepositoryError("Couldn't run git command (%s).\n" |
|
126 | 126 | "Original error was:%s" % (cmd, err)) |
|
127 | 127 | |
|
128 | 128 | return ''.join(p.output), ''.join(p.error) |
|
129 | 129 | |
|
130 | 130 | @classmethod |
|
131 | 131 | def _check_url(cls, url): |
|
132 | 132 | """ |
|
133 | 133 | Functon will check given url and try to verify if it's a valid |
|
134 | 134 | link. Sometimes it may happened that mercurial will issue basic |
|
135 | 135 | auth request that can cause whole API to hang when used from python |
|
136 | 136 | or other external calls. |
|
137 | 137 | |
|
138 | 138 | On failures it'll raise urllib2.HTTPError |
|
139 | 139 | """ |
|
140 | 140 | from mercurial.util import url as Url |
|
141 | 141 | |
|
142 | 142 | # those authnadlers are patched for python 2.6.5 bug an |
|
143 | 143 | # infinit looping when given invalid resources |
|
144 | 144 | from mercurial.url import httpbasicauthhandler, httpdigestauthhandler |
|
145 | 145 | |
|
146 | 146 | # check first if it's not an local url |
|
147 | 147 | if os.path.isdir(url) or url.startswith('file:'): |
|
148 | 148 | return True |
|
149 | 149 | |
|
150 | 150 | if('+' in url[:url.find('://')]): |
|
151 | 151 | url = url[url.find('+') + 1:] |
|
152 | 152 | |
|
153 | 153 | handlers = [] |
|
154 | 154 | test_uri, authinfo = Url(url).authinfo() |
|
155 | 155 | if not test_uri.endswith('info/refs'): |
|
156 | 156 | test_uri = test_uri.rstrip('/') + '/info/refs' |
|
157 | 157 | if authinfo: |
|
158 | 158 | #create a password manager |
|
159 | 159 | passmgr = urllib2.HTTPPasswordMgrWithDefaultRealm() |
|
160 | 160 | passmgr.add_password(*authinfo) |
|
161 | 161 | |
|
162 | 162 | handlers.extend((httpbasicauthhandler(passmgr), |
|
163 | 163 | httpdigestauthhandler(passmgr))) |
|
164 | 164 | |
|
165 | 165 | o = urllib2.build_opener(*handlers) |
|
166 | 166 | o.addheaders = [('User-Agent', 'git/1.7.8.0')] # fake some git |
|
167 | 167 | |
|
168 | 168 | q = {"service": 'git-upload-pack'} |
|
169 | 169 | qs = '?%s' % urllib.urlencode(q) |
|
170 | 170 | cu = "%s%s" % (test_uri, qs) |
|
171 | 171 | req = urllib2.Request(cu, None, {}) |
|
172 | 172 | |
|
173 | 173 | try: |
|
174 | 174 | resp = o.open(req) |
|
175 | 175 | return resp.code == 200 |
|
176 | 176 | except Exception, e: |
|
177 | 177 | # means it cannot be cloned |
|
178 | 178 | raise urllib2.URLError("[%s] %s" % (url, e)) |
|
179 | 179 | |
|
180 | 180 | def _get_repo(self, create, src_url=None, update_after_clone=False, |
|
181 | 181 | bare=False): |
|
182 | 182 | if create and os.path.exists(self.path): |
|
183 | 183 | raise RepositoryError("Location already exist") |
|
184 | 184 | if src_url and not create: |
|
185 | 185 | raise RepositoryError("Create should be set to True if src_url is " |
|
186 | 186 | "given (clone operation creates repository)") |
|
187 | 187 | try: |
|
188 | 188 | if create and src_url: |
|
189 | 189 | GitRepository._check_url(src_url) |
|
190 | 190 | self.clone(src_url, update_after_clone, bare) |
|
191 | 191 | return Repo(self.path) |
|
192 | 192 | elif create: |
|
193 | 193 | os.mkdir(self.path) |
|
194 | 194 | if bare: |
|
195 | 195 | return Repo.init_bare(self.path) |
|
196 | 196 | else: |
|
197 | 197 | return Repo.init(self.path) |
|
198 | 198 | else: |
|
199 | 199 | return Repo(self.path) |
|
200 | 200 | except (NotGitRepository, OSError), err: |
|
201 | 201 | raise RepositoryError(err) |
|
202 | 202 | |
|
203 | 203 | def _get_all_revisions(self): |
|
204 | 204 | # we must check if this repo is not empty, since later command |
|
205 | 205 | # fails if it is. And it's cheaper to ask than throw the subprocess |
|
206 | 206 | # errors |
|
207 | 207 | try: |
|
208 | 208 | self._repo.head() |
|
209 | 209 | except KeyError: |
|
210 | 210 | return [] |
|
211 | 211 | cmd = 'rev-list --all --reverse --date-order' |
|
212 | 212 | try: |
|
213 | 213 | so, se = self.run_git_command(cmd) |
|
214 | 214 | except RepositoryError: |
|
215 | 215 | # Can be raised for empty repositories |
|
216 | 216 | return [] |
|
217 | 217 | return so.splitlines() |
|
218 | 218 | |
|
219 | 219 | def _get_all_revisions2(self): |
|
220 | 220 | #alternate implementation using dulwich |
|
221 | 221 | includes = [x[1][0] for x in self._parsed_refs.iteritems() |
|
222 | 222 | if x[1][1] != 'T'] |
|
223 | 223 | return [c.commit.id for c in self._repo.get_walker(include=includes)] |
|
224 | 224 | |
|
225 | 225 | def _get_revision(self, revision): |
|
226 | 226 | """ |
|
227 | 227 | For git backend we always return integer here. This way we ensure |
|
228 | 228 | that changset's revision attribute would become integer. |
|
229 | 229 | """ |
|
230 | 230 | pattern = re.compile(r'^[[0-9a-fA-F]{12}|[0-9a-fA-F]{40}]$') |
|
231 | 231 | is_bstr = lambda o: isinstance(o, (str, unicode)) |
|
232 | 232 | is_null = lambda o: len(o) == revision.count('0') |
|
233 | 233 | |
|
234 | 234 | if len(self.revisions) == 0: |
|
235 | 235 | raise EmptyRepositoryError("There are no changesets yet") |
|
236 | 236 | |
|
237 | 237 | if revision in (None, '', 'tip', 'HEAD', 'head', -1): |
|
238 | 238 | revision = self.revisions[-1] |
|
239 | 239 | |
|
240 | 240 | if ((is_bstr(revision) and revision.isdigit() and len(revision) < 12) |
|
241 | 241 | or isinstance(revision, int) or is_null(revision)): |
|
242 | 242 | try: |
|
243 | 243 | revision = self.revisions[int(revision)] |
|
244 | 244 | except: |
|
245 | 245 | raise ChangesetDoesNotExistError("Revision %r does not exist " |
|
246 | 246 | "for this repository %s" % (revision, self)) |
|
247 | 247 | |
|
248 | 248 | elif is_bstr(revision): |
|
249 | 249 | # get by branch/tag name |
|
250 | 250 | _ref_revision = self._parsed_refs.get(revision) |
|
251 | 251 | _tags_shas = self.tags.values() |
|
252 | 252 | if _ref_revision: # and _ref_revision[1] in ['H', 'RH', 'T']: |
|
253 | 253 | return _ref_revision[0] |
|
254 | 254 | |
|
255 | 255 | # maybe it's a tag ? we don't have them in self.revisions |
|
256 | 256 | elif revision in _tags_shas: |
|
257 | 257 | return _tags_shas[_tags_shas.index(revision)] |
|
258 | 258 | |
|
259 | 259 | elif not pattern.match(revision) or revision not in self.revisions: |
|
260 | 260 | raise ChangesetDoesNotExistError("Revision %r does not exist " |
|
261 | 261 | "for this repository %s" % (revision, self)) |
|
262 | 262 | |
|
263 | 263 | # Ensure we return full id |
|
264 | 264 | if not pattern.match(str(revision)): |
|
265 | 265 | raise ChangesetDoesNotExistError("Given revision %r not recognized" |
|
266 | 266 | % revision) |
|
267 | 267 | return revision |
|
268 | 268 | |
|
269 | 269 | def _get_archives(self, archive_name='tip'): |
|
270 | 270 | |
|
271 | 271 | for i in [('zip', '.zip'), ('gz', '.tar.gz'), ('bz2', '.tar.bz2')]: |
|
272 | 272 | yield {"type": i[0], "extension": i[1], "node": archive_name} |
|
273 | 273 | |
|
274 | 274 | def _get_url(self, url): |
|
275 | 275 | """ |
|
276 | 276 | Returns normalized url. If schema is not given, would fall to |
|
277 | 277 | filesystem (``file:///``) schema. |
|
278 | 278 | """ |
|
279 | 279 | url = str(url) |
|
280 | 280 | if url != 'default' and not '://' in url: |
|
281 | 281 | url = ':///'.join(('file', url)) |
|
282 | 282 | return url |
|
283 | 283 | |
|
284 | 284 | @LazyProperty |
|
285 | 285 | def name(self): |
|
286 | 286 | return os.path.basename(self.path) |
|
287 | 287 | |
|
288 | 288 | @LazyProperty |
|
289 | 289 | def last_change(self): |
|
290 | 290 | """ |
|
291 | 291 | Returns last change made on this repository as datetime object |
|
292 | 292 | """ |
|
293 | 293 | return date_fromtimestamp(self._get_mtime(), makedate()[1]) |
|
294 | 294 | |
|
295 | 295 | def _get_mtime(self): |
|
296 | 296 | try: |
|
297 | 297 | return time.mktime(self.get_changeset().date.timetuple()) |
|
298 | 298 | except RepositoryError: |
|
299 | 299 | idx_loc = '' if self.bare else '.git' |
|
300 | 300 | # fallback to filesystem |
|
301 | 301 | in_path = os.path.join(self.path, idx_loc, "index") |
|
302 | 302 | he_path = os.path.join(self.path, idx_loc, "HEAD") |
|
303 | 303 | if os.path.exists(in_path): |
|
304 | 304 | return os.stat(in_path).st_mtime |
|
305 | 305 | else: |
|
306 | 306 | return os.stat(he_path).st_mtime |
|
307 | 307 | |
|
308 | 308 | @LazyProperty |
|
309 | 309 | def description(self): |
|
310 | 310 | idx_loc = '' if self.bare else '.git' |
|
311 | 311 | undefined_description = u'unknown' |
|
312 | 312 | description_path = os.path.join(self.path, idx_loc, 'description') |
|
313 | 313 | if os.path.isfile(description_path): |
|
314 | 314 | return safe_unicode(open(description_path).read()) |
|
315 | 315 | else: |
|
316 | 316 | return undefined_description |
|
317 | 317 | |
|
318 | 318 | @LazyProperty |
|
319 | 319 | def contact(self): |
|
320 | 320 | undefined_contact = u'Unknown' |
|
321 | 321 | return undefined_contact |
|
322 | 322 | |
|
323 | 323 | @property |
|
324 | 324 | def branches(self): |
|
325 | 325 | if not self.revisions: |
|
326 | 326 | return {} |
|
327 | 327 | sortkey = lambda ctx: ctx[0] |
|
328 | 328 | _branches = [(x[0], x[1][0]) |
|
329 | 329 | for x in self._parsed_refs.iteritems() if x[1][1] == 'H'] |
|
330 | 330 | return OrderedDict(sorted(_branches, key=sortkey, reverse=False)) |
|
331 | 331 | |
|
332 | 332 | @LazyProperty |
|
333 | 333 | def tags(self): |
|
334 | 334 | return self._get_tags() |
|
335 | 335 | |
|
336 | 336 | def _get_tags(self): |
|
337 | 337 | if not self.revisions: |
|
338 | 338 | return {} |
|
339 | 339 | |
|
340 | 340 | sortkey = lambda ctx: ctx[0] |
|
341 | 341 | _tags = [(x[0], x[1][0]) |
|
342 | 342 | for x in self._parsed_refs.iteritems() if x[1][1] == 'T'] |
|
343 | 343 | return OrderedDict(sorted(_tags, key=sortkey, reverse=True)) |
|
344 | 344 | |
|
345 | 345 | def tag(self, name, user, revision=None, message=None, date=None, |
|
346 | 346 | **kwargs): |
|
347 | 347 | """ |
|
348 | 348 | Creates and returns a tag for the given ``revision``. |
|
349 | 349 | |
|
350 | 350 | :param name: name for new tag |
|
351 | 351 | :param user: full username, i.e.: "Joe Doe <joe.doe@example.com>" |
|
352 | 352 | :param revision: changeset id for which new tag would be created |
|
353 | 353 | :param message: message of the tag's commit |
|
354 | 354 | :param date: date of tag's commit |
|
355 | 355 | |
|
356 | 356 | :raises TagAlreadyExistError: if tag with same name already exists |
|
357 | 357 | """ |
|
358 | 358 | if name in self.tags: |
|
359 | 359 | raise TagAlreadyExistError("Tag %s already exists" % name) |
|
360 | 360 | changeset = self.get_changeset(revision) |
|
361 | 361 | message = message or "Added tag %s for commit %s" % (name, |
|
362 | 362 | changeset.raw_id) |
|
363 | 363 | self._repo.refs["refs/tags/%s" % name] = changeset._commit.id |
|
364 | 364 | |
|
365 | 365 | self._parsed_refs = self._get_parsed_refs() |
|
366 | 366 | self.tags = self._get_tags() |
|
367 | 367 | return changeset |
|
368 | 368 | |
|
369 | 369 | def remove_tag(self, name, user, message=None, date=None): |
|
370 | 370 | """ |
|
371 | 371 | Removes tag with the given ``name``. |
|
372 | 372 | |
|
373 | 373 | :param name: name of the tag to be removed |
|
374 | 374 | :param user: full username, i.e.: "Joe Doe <joe.doe@example.com>" |
|
375 | 375 | :param message: message of the tag's removal commit |
|
376 | 376 | :param date: date of tag's removal commit |
|
377 | 377 | |
|
378 | 378 | :raises TagDoesNotExistError: if tag with given name does not exists |
|
379 | 379 | """ |
|
380 | 380 | if name not in self.tags: |
|
381 | 381 | raise TagDoesNotExistError("Tag %s does not exist" % name) |
|
382 | 382 | tagpath = posixpath.join(self._repo.refs.path, 'refs', 'tags', name) |
|
383 | 383 | try: |
|
384 | 384 | os.remove(tagpath) |
|
385 | 385 | self._parsed_refs = self._get_parsed_refs() |
|
386 | 386 | self.tags = self._get_tags() |
|
387 | 387 | except OSError, e: |
|
388 | 388 | raise RepositoryError(e.strerror) |
|
389 | 389 | |
|
390 | 390 | @LazyProperty |
|
391 | 391 | def _parsed_refs(self): |
|
392 | 392 | return self._get_parsed_refs() |
|
393 | 393 | |
|
394 | 394 | def _get_parsed_refs(self): |
|
395 | 395 | refs = self._repo.get_refs() |
|
396 | 396 | keys = [('refs/heads/', 'H'), |
|
397 | 397 | ('refs/remotes/origin/', 'RH'), |
|
398 | 398 | ('refs/tags/', 'T')] |
|
399 | 399 | _refs = {} |
|
400 | 400 | for ref, sha in refs.iteritems(): |
|
401 | 401 | for k, type_ in keys: |
|
402 | 402 | if ref.startswith(k): |
|
403 | 403 | _key = ref[len(k):] |
|
404 | 404 | if type_ == 'T': |
|
405 | 405 | obj = self._repo.get_object(sha) |
|
406 | 406 | if isinstance(obj, Tag): |
|
407 | 407 | sha = self._repo.get_object(sha).object[1] |
|
408 | 408 | _refs[_key] = [sha, type_] |
|
409 | 409 | break |
|
410 | 410 | return _refs |
|
411 | 411 | |
|
412 | 412 | def _heads(self, reverse=False): |
|
413 | 413 | refs = self._repo.get_refs() |
|
414 | 414 | heads = {} |
|
415 | 415 | |
|
416 | 416 | for key, val in refs.items(): |
|
417 | 417 | for ref_key in ['refs/heads/', 'refs/remotes/origin/']: |
|
418 | 418 | if key.startswith(ref_key): |
|
419 | 419 | n = key[len(ref_key):] |
|
420 | 420 | if n not in ['HEAD']: |
|
421 | 421 | heads[n] = val |
|
422 | 422 | |
|
423 | 423 | return heads if reverse else dict((y, x) for x, y in heads.iteritems()) |
|
424 | 424 | |
|
425 | 425 | def get_changeset(self, revision=None): |
|
426 | 426 | """ |
|
427 | 427 | Returns ``GitChangeset`` object representing commit from git repository |
|
428 | 428 | at the given revision or head (most recent commit) if None given. |
|
429 | 429 | """ |
|
430 | 430 | if isinstance(revision, GitChangeset): |
|
431 | 431 | return revision |
|
432 | 432 | revision = self._get_revision(revision) |
|
433 | 433 | changeset = GitChangeset(repository=self, revision=revision) |
|
434 | 434 | return changeset |
|
435 | 435 | |
|
436 | 436 | def get_changesets(self, start=None, end=None, start_date=None, |
|
437 | 437 | end_date=None, branch_name=None, reverse=False): |
|
438 | 438 | """ |
|
439 | 439 | Returns iterator of ``GitChangeset`` objects from start to end (both |
|
440 | 440 | are inclusive), in ascending date order (unless ``reverse`` is set). |
|
441 | 441 | |
|
442 | 442 | :param start: changeset ID, as str; first returned changeset |
|
443 | 443 | :param end: changeset ID, as str; last returned changeset |
|
444 | 444 | :param start_date: if specified, changesets with commit date less than |
|
445 | 445 | ``start_date`` would be filtered out from returned set |
|
446 | 446 | :param end_date: if specified, changesets with commit date greater than |
|
447 | 447 | ``end_date`` would be filtered out from returned set |
|
448 | 448 | :param branch_name: if specified, changesets not reachable from given |
|
449 | 449 | branch would be filtered out from returned set |
|
450 | 450 | :param reverse: if ``True``, returned generator would be reversed |
|
451 | 451 | (meaning that returned changesets would have descending date order) |
|
452 | 452 | |
|
453 | 453 | :raise BranchDoesNotExistError: If given ``branch_name`` does not |
|
454 | 454 | exist. |
|
455 | 455 | :raise ChangesetDoesNotExistError: If changeset for given ``start`` or |
|
456 | 456 | ``end`` could not be found. |
|
457 | 457 | |
|
458 | 458 | """ |
|
459 | 459 | if branch_name and branch_name not in self.branches: |
|
460 | 460 | raise BranchDoesNotExistError("Branch '%s' not found" \ |
|
461 | 461 | % branch_name) |
|
462 | 462 | # %H at format means (full) commit hash, initial hashes are retrieved |
|
463 | 463 | # in ascending date order |
|
464 | 464 | cmd_template = 'log --date-order --reverse --pretty=format:"%H"' |
|
465 | 465 | cmd_params = {} |
|
466 | 466 | if start_date: |
|
467 | 467 | cmd_template += ' --since "$since"' |
|
468 | 468 | cmd_params['since'] = start_date.strftime('%m/%d/%y %H:%M:%S') |
|
469 | 469 | if end_date: |
|
470 | 470 | cmd_template += ' --until "$until"' |
|
471 | 471 | cmd_params['until'] = end_date.strftime('%m/%d/%y %H:%M:%S') |
|
472 | 472 | if branch_name: |
|
473 | 473 | cmd_template += ' $branch_name' |
|
474 | 474 | cmd_params['branch_name'] = branch_name |
|
475 | 475 | else: |
|
476 | 476 | cmd_template += ' --all' |
|
477 | 477 | |
|
478 | 478 | cmd = Template(cmd_template).safe_substitute(**cmd_params) |
|
479 | 479 | revs = self.run_git_command(cmd)[0].splitlines() |
|
480 | 480 | start_pos = 0 |
|
481 | 481 | end_pos = len(revs) |
|
482 | 482 | if start: |
|
483 | 483 | _start = self._get_revision(start) |
|
484 | 484 | try: |
|
485 | 485 | start_pos = revs.index(_start) |
|
486 | 486 | except ValueError: |
|
487 | 487 | pass |
|
488 | 488 | |
|
489 | 489 | if end is not None: |
|
490 | 490 | _end = self._get_revision(end) |
|
491 | 491 | try: |
|
492 | 492 | end_pos = revs.index(_end) |
|
493 | 493 | except ValueError: |
|
494 | 494 | pass |
|
495 | 495 | |
|
496 | 496 | if None not in [start, end] and start_pos > end_pos: |
|
497 | 497 | raise RepositoryError('start cannot be after end') |
|
498 | 498 | |
|
499 | 499 | if end_pos is not None: |
|
500 | 500 | end_pos += 1 |
|
501 | 501 | |
|
502 | 502 | revs = revs[start_pos:end_pos] |
|
503 | 503 | if reverse: |
|
504 | 504 | revs = reversed(revs) |
|
505 | 505 | for rev in revs: |
|
506 | 506 | yield self.get_changeset(rev) |
|
507 | 507 | |
|
508 | 508 | def get_diff(self, rev1, rev2, path=None, ignore_whitespace=False, |
|
509 | 509 | context=3): |
|
510 | 510 | """ |
|
511 | 511 | Returns (git like) *diff*, as plain text. Shows changes introduced by |
|
512 | 512 | ``rev2`` since ``rev1``. |
|
513 | 513 | |
|
514 | 514 | :param rev1: Entry point from which diff is shown. Can be |
|
515 | 515 | ``self.EMPTY_CHANGESET`` - in this case, patch showing all |
|
516 | 516 | the changes since empty state of the repository until ``rev2`` |
|
517 | 517 | :param rev2: Until which revision changes should be shown. |
|
518 | 518 | :param ignore_whitespace: If set to ``True``, would not show whitespace |
|
519 | 519 | changes. Defaults to ``False``. |
|
520 | 520 | :param context: How many lines before/after changed lines should be |
|
521 | 521 | shown. Defaults to ``3``. |
|
522 | 522 | """ |
|
523 | flags = ['-U%s' % context] | |
|
523 | flags = ['-U%s' % context, '--full-index', '--binary', '-p', '-M', '--abbrev=40'] | |
|
524 | 524 | if ignore_whitespace: |
|
525 | 525 | flags.append('-w') |
|
526 | 526 | |
|
527 | 527 | if hasattr(rev1, 'raw_id'): |
|
528 | 528 | rev1 = getattr(rev1, 'raw_id') |
|
529 | 529 | |
|
530 | 530 | if hasattr(rev2, 'raw_id'): |
|
531 | 531 | rev2 = getattr(rev2, 'raw_id') |
|
532 | 532 | |
|
533 | 533 | if rev1 == self.EMPTY_CHANGESET: |
|
534 | 534 | rev2 = self.get_changeset(rev2).raw_id |
|
535 | 535 | cmd = ' '.join(['show'] + flags + [rev2]) |
|
536 | 536 | else: |
|
537 | 537 | rev1 = self.get_changeset(rev1).raw_id |
|
538 | 538 | rev2 = self.get_changeset(rev2).raw_id |
|
539 | 539 | cmd = ' '.join(['diff'] + flags + [rev1, rev2]) |
|
540 | 540 | |
|
541 | 541 | if path: |
|
542 | 542 | cmd += ' -- "%s"' % path |
|
543 | ||
|
543 | 544 | stdout, stderr = self.run_git_command(cmd) |
|
544 | 545 | # If we used 'show' command, strip first few lines (until actual diff |
|
545 | 546 | # starts) |
|
546 | 547 | if rev1 == self.EMPTY_CHANGESET: |
|
547 | 548 | lines = stdout.splitlines() |
|
548 | 549 | x = 0 |
|
549 | 550 | for line in lines: |
|
550 | 551 | if line.startswith('diff'): |
|
551 | 552 | break |
|
552 | 553 | x += 1 |
|
553 | 554 | # Append new line just like 'diff' command do |
|
554 | 555 | stdout = '\n'.join(lines[x:]) + '\n' |
|
555 | 556 | return stdout |
|
556 | 557 | |
|
557 | 558 | @LazyProperty |
|
558 | 559 | def in_memory_changeset(self): |
|
559 | 560 | """ |
|
560 | 561 | Returns ``GitInMemoryChangeset`` object for this repository. |
|
561 | 562 | """ |
|
562 | 563 | return GitInMemoryChangeset(self) |
|
563 | 564 | |
|
564 | 565 | def clone(self, url, update_after_clone=True, bare=False): |
|
565 | 566 | """ |
|
566 | 567 | Tries to clone changes from external location. |
|
567 | 568 | |
|
568 | 569 | :param update_after_clone: If set to ``False``, git won't checkout |
|
569 | 570 | working directory |
|
570 | 571 | :param bare: If set to ``True``, repository would be cloned into |
|
571 | 572 | *bare* git repository (no working directory at all). |
|
572 | 573 | """ |
|
573 | 574 | url = self._get_url(url) |
|
574 | 575 | cmd = ['clone'] |
|
575 | 576 | if bare: |
|
576 | 577 | cmd.append('--bare') |
|
577 | 578 | elif not update_after_clone: |
|
578 | 579 | cmd.append('--no-checkout') |
|
579 | 580 | cmd += ['--', '"%s"' % url, '"%s"' % self.path] |
|
580 | 581 | cmd = ' '.join(cmd) |
|
581 | 582 | # If error occurs run_git_command raises RepositoryError already |
|
582 | 583 | self.run_git_command(cmd) |
|
583 | 584 | |
|
584 | 585 | def pull(self, url): |
|
585 | 586 | """ |
|
586 | 587 | Tries to pull changes from external location. |
|
587 | 588 | """ |
|
588 | 589 | url = self._get_url(url) |
|
589 | 590 | cmd = ['pull'] |
|
590 | 591 | cmd.append("--ff-only") |
|
591 | 592 | cmd.append(url) |
|
592 | 593 | cmd = ' '.join(cmd) |
|
593 | 594 | # If error occurs run_git_command raises RepositoryError already |
|
594 | 595 | self.run_git_command(cmd) |
|
595 | 596 | |
|
596 | 597 | def fetch(self, url): |
|
597 | 598 | """ |
|
598 | 599 | Tries to pull changes from external location. |
|
599 | 600 | """ |
|
600 | 601 | url = self._get_url(url) |
|
601 | 602 | cmd = ['fetch'] |
|
602 | 603 | cmd.append(url) |
|
603 | 604 | cmd = ' '.join(cmd) |
|
604 | 605 | # If error occurs run_git_command raises RepositoryError already |
|
605 | 606 | self.run_git_command(cmd) |
|
606 | 607 | |
|
607 | 608 | @LazyProperty |
|
608 | 609 | def workdir(self): |
|
609 | 610 | """ |
|
610 | 611 | Returns ``Workdir`` instance for this repository. |
|
611 | 612 | """ |
|
612 | 613 | return GitWorkdir(self) |
|
613 | 614 | |
|
614 | 615 | def get_config_value(self, section, name, config_file=None): |
|
615 | 616 | """ |
|
616 | 617 | Returns configuration value for a given [``section``] and ``name``. |
|
617 | 618 | |
|
618 | 619 | :param section: Section we want to retrieve value from |
|
619 | 620 | :param name: Name of configuration we want to retrieve |
|
620 | 621 | :param config_file: A path to file which should be used to retrieve |
|
621 | 622 | configuration from (might also be a list of file paths) |
|
622 | 623 | """ |
|
623 | 624 | if config_file is None: |
|
624 | 625 | config_file = [] |
|
625 | 626 | elif isinstance(config_file, basestring): |
|
626 | 627 | config_file = [config_file] |
|
627 | 628 | |
|
628 | 629 | def gen_configs(): |
|
629 | 630 | for path in config_file + self._config_files: |
|
630 | 631 | try: |
|
631 | 632 | yield ConfigFile.from_path(path) |
|
632 | 633 | except (IOError, OSError, ValueError): |
|
633 | 634 | continue |
|
634 | 635 | |
|
635 | 636 | for config in gen_configs(): |
|
636 | 637 | try: |
|
637 | 638 | return config.get(section, name) |
|
638 | 639 | except KeyError: |
|
639 | 640 | continue |
|
640 | 641 | return None |
|
641 | 642 | |
|
642 | 643 | def get_user_name(self, config_file=None): |
|
643 | 644 | """ |
|
644 | 645 | Returns user's name from global configuration file. |
|
645 | 646 | |
|
646 | 647 | :param config_file: A path to file which should be used to retrieve |
|
647 | 648 | configuration from (might also be a list of file paths) |
|
648 | 649 | """ |
|
649 | 650 | return self.get_config_value('user', 'name', config_file) |
|
650 | 651 | |
|
651 | 652 | def get_user_email(self, config_file=None): |
|
652 | 653 | """ |
|
653 | 654 | Returns user's email from global configuration file. |
|
654 | 655 | |
|
655 | 656 | :param config_file: A path to file which should be used to retrieve |
|
656 | 657 | configuration from (might also be a list of file paths) |
|
657 | 658 | """ |
|
658 | 659 | return self.get_config_value('user', 'email', config_file) |
@@ -1,533 +1,536 b'' | |||
|
1 | 1 | import os |
|
2 | 2 | import time |
|
3 | 3 | import datetime |
|
4 | 4 | import urllib |
|
5 | 5 | import urllib2 |
|
6 | 6 | |
|
7 | 7 | from rhodecode.lib.vcs.backends.base import BaseRepository |
|
8 | 8 | from .workdir import MercurialWorkdir |
|
9 | 9 | from .changeset import MercurialChangeset |
|
10 | 10 | from .inmemory import MercurialInMemoryChangeset |
|
11 | 11 | |
|
12 | 12 | from rhodecode.lib.vcs.exceptions import BranchDoesNotExistError, \ |
|
13 | 13 | ChangesetDoesNotExistError, EmptyRepositoryError, RepositoryError, \ |
|
14 | 14 | VCSError, TagAlreadyExistError, TagDoesNotExistError |
|
15 | 15 | from rhodecode.lib.vcs.utils import author_email, author_name, date_fromtimestamp, \ |
|
16 | 16 | makedate, safe_unicode |
|
17 | 17 | from rhodecode.lib.vcs.utils.lazy import LazyProperty |
|
18 | 18 | from rhodecode.lib.vcs.utils.ordered_dict import OrderedDict |
|
19 | 19 | from rhodecode.lib.vcs.utils.paths import abspath |
|
20 | 20 | |
|
21 | 21 | from rhodecode.lib.vcs.utils.hgcompat import ui, nullid, match, patch, diffopts, clone, \ |
|
22 | 22 | get_contact, pull, localrepository, RepoLookupError, Abort, RepoError, hex |
|
23 | 23 | |
|
24 | 24 | |
|
25 | 25 | class MercurialRepository(BaseRepository): |
|
26 | 26 | """ |
|
27 | 27 | Mercurial repository backend |
|
28 | 28 | """ |
|
29 | 29 | DEFAULT_BRANCH_NAME = 'default' |
|
30 | 30 | scm = 'hg' |
|
31 | 31 | |
|
32 | 32 | def __init__(self, repo_path, create=False, baseui=None, src_url=None, |
|
33 | 33 | update_after_clone=False): |
|
34 | 34 | """ |
|
35 | 35 | Raises RepositoryError if repository could not be find at the given |
|
36 | 36 | ``repo_path``. |
|
37 | 37 | |
|
38 | 38 | :param repo_path: local path of the repository |
|
39 | 39 | :param create=False: if set to True, would try to create repository if |
|
40 | 40 | it does not exist rather than raising exception |
|
41 | 41 | :param baseui=None: user data |
|
42 | 42 | :param src_url=None: would try to clone repository from given location |
|
43 | 43 | :param update_after_clone=False: sets update of working copy after |
|
44 | 44 | making a clone |
|
45 | 45 | """ |
|
46 | 46 | |
|
47 | 47 | if not isinstance(repo_path, str): |
|
48 | 48 | raise VCSError('Mercurial backend requires repository path to ' |
|
49 | 49 | 'be instance of <str> got %s instead' % |
|
50 | 50 | type(repo_path)) |
|
51 | 51 | |
|
52 | 52 | self.path = abspath(repo_path) |
|
53 | 53 | self.baseui = baseui or ui.ui() |
|
54 | 54 | # We've set path and ui, now we can set _repo itself |
|
55 | 55 | self._repo = self._get_repo(create, src_url, update_after_clone) |
|
56 | 56 | |
|
57 | 57 | @property |
|
58 | 58 | def _empty(self): |
|
59 | 59 | """ |
|
60 | 60 | Checks if repository is empty without any changesets |
|
61 | 61 | """ |
|
62 | 62 | # TODO: Following raises errors when using InMemoryChangeset... |
|
63 | 63 | # return len(self._repo.changelog) == 0 |
|
64 | 64 | return len(self.revisions) == 0 |
|
65 | 65 | |
|
66 | 66 | @LazyProperty |
|
67 | 67 | def revisions(self): |
|
68 | 68 | """ |
|
69 | 69 | Returns list of revisions' ids, in ascending order. Being lazy |
|
70 | 70 | attribute allows external tools to inject shas from cache. |
|
71 | 71 | """ |
|
72 | 72 | return self._get_all_revisions() |
|
73 | 73 | |
|
74 | 74 | @LazyProperty |
|
75 | 75 | def name(self): |
|
76 | 76 | return os.path.basename(self.path) |
|
77 | 77 | |
|
78 | 78 | @LazyProperty |
|
79 | 79 | def branches(self): |
|
80 | 80 | return self._get_branches() |
|
81 | 81 | |
|
82 | 82 | def _get_branches(self, closed=False): |
|
83 | 83 | """ |
|
84 | 84 | Get's branches for this repository |
|
85 | 85 | Returns only not closed branches by default |
|
86 | 86 | |
|
87 | 87 | :param closed: return also closed branches for mercurial |
|
88 | 88 | """ |
|
89 | 89 | |
|
90 | 90 | if self._empty: |
|
91 | 91 | return {} |
|
92 | 92 | |
|
93 | 93 | def _branchtags(localrepo): |
|
94 | 94 | """ |
|
95 | 95 | Patched version of mercurial branchtags to not return the closed |
|
96 | 96 | branches |
|
97 | 97 | |
|
98 | 98 | :param localrepo: locarepository instance |
|
99 | 99 | """ |
|
100 | 100 | |
|
101 | 101 | bt = {} |
|
102 | 102 | bt_closed = {} |
|
103 | 103 | for bn, heads in localrepo.branchmap().iteritems(): |
|
104 | 104 | tip = heads[-1] |
|
105 | 105 | if 'close' in localrepo.changelog.read(tip)[5]: |
|
106 | 106 | bt_closed[bn] = tip |
|
107 | 107 | else: |
|
108 | 108 | bt[bn] = tip |
|
109 | 109 | |
|
110 | 110 | if closed: |
|
111 | 111 | bt.update(bt_closed) |
|
112 | 112 | return bt |
|
113 | 113 | |
|
114 | 114 | sortkey = lambda ctx: ctx[0] # sort by name |
|
115 | 115 | _branches = [(safe_unicode(n), hex(h),) for n, h in |
|
116 | 116 | _branchtags(self._repo).items()] |
|
117 | 117 | |
|
118 | 118 | return OrderedDict(sorted(_branches, key=sortkey, reverse=False)) |
|
119 | 119 | |
|
120 | 120 | @LazyProperty |
|
121 | 121 | def tags(self): |
|
122 | 122 | """ |
|
123 | 123 | Get's tags for this repository |
|
124 | 124 | """ |
|
125 | 125 | return self._get_tags() |
|
126 | 126 | |
|
127 | 127 | def _get_tags(self): |
|
128 | 128 | if self._empty: |
|
129 | 129 | return {} |
|
130 | 130 | |
|
131 | 131 | sortkey = lambda ctx: ctx[0] # sort by name |
|
132 | 132 | _tags = [(safe_unicode(n), hex(h),) for n, h in |
|
133 | 133 | self._repo.tags().items()] |
|
134 | 134 | |
|
135 | 135 | return OrderedDict(sorted(_tags, key=sortkey, reverse=True)) |
|
136 | 136 | |
|
137 | 137 | def tag(self, name, user, revision=None, message=None, date=None, |
|
138 | 138 | **kwargs): |
|
139 | 139 | """ |
|
140 | 140 | Creates and returns a tag for the given ``revision``. |
|
141 | 141 | |
|
142 | 142 | :param name: name for new tag |
|
143 | 143 | :param user: full username, i.e.: "Joe Doe <joe.doe@example.com>" |
|
144 | 144 | :param revision: changeset id for which new tag would be created |
|
145 | 145 | :param message: message of the tag's commit |
|
146 | 146 | :param date: date of tag's commit |
|
147 | 147 | |
|
148 | 148 | :raises TagAlreadyExistError: if tag with same name already exists |
|
149 | 149 | """ |
|
150 | 150 | if name in self.tags: |
|
151 | 151 | raise TagAlreadyExistError("Tag %s already exists" % name) |
|
152 | 152 | changeset = self.get_changeset(revision) |
|
153 | 153 | local = kwargs.setdefault('local', False) |
|
154 | 154 | |
|
155 | 155 | if message is None: |
|
156 | 156 | message = "Added tag %s for changeset %s" % (name, |
|
157 | 157 | changeset.short_id) |
|
158 | 158 | |
|
159 | 159 | if date is None: |
|
160 | 160 | date = datetime.datetime.now().ctime() |
|
161 | 161 | |
|
162 | 162 | try: |
|
163 | 163 | self._repo.tag(name, changeset._ctx.node(), message, local, user, |
|
164 | 164 | date) |
|
165 | 165 | except Abort, e: |
|
166 | 166 | raise RepositoryError(e.message) |
|
167 | 167 | |
|
168 | 168 | # Reinitialize tags |
|
169 | 169 | self.tags = self._get_tags() |
|
170 | 170 | tag_id = self.tags[name] |
|
171 | 171 | |
|
172 | 172 | return self.get_changeset(revision=tag_id) |
|
173 | 173 | |
|
174 | 174 | def remove_tag(self, name, user, message=None, date=None): |
|
175 | 175 | """ |
|
176 | 176 | Removes tag with the given ``name``. |
|
177 | 177 | |
|
178 | 178 | :param name: name of the tag to be removed |
|
179 | 179 | :param user: full username, i.e.: "Joe Doe <joe.doe@example.com>" |
|
180 | 180 | :param message: message of the tag's removal commit |
|
181 | 181 | :param date: date of tag's removal commit |
|
182 | 182 | |
|
183 | 183 | :raises TagDoesNotExistError: if tag with given name does not exists |
|
184 | 184 | """ |
|
185 | 185 | if name not in self.tags: |
|
186 | 186 | raise TagDoesNotExistError("Tag %s does not exist" % name) |
|
187 | 187 | if message is None: |
|
188 | 188 | message = "Removed tag %s" % name |
|
189 | 189 | if date is None: |
|
190 | 190 | date = datetime.datetime.now().ctime() |
|
191 | 191 | local = False |
|
192 | 192 | |
|
193 | 193 | try: |
|
194 | 194 | self._repo.tag(name, nullid, message, local, user, date) |
|
195 | 195 | self.tags = self._get_tags() |
|
196 | 196 | except Abort, e: |
|
197 | 197 | raise RepositoryError(e.message) |
|
198 | 198 | |
|
199 | 199 | @LazyProperty |
|
200 | 200 | def bookmarks(self): |
|
201 | 201 | """ |
|
202 | 202 | Get's bookmarks for this repository |
|
203 | 203 | """ |
|
204 | 204 | return self._get_bookmarks() |
|
205 | 205 | |
|
206 | 206 | def _get_bookmarks(self): |
|
207 | 207 | if self._empty: |
|
208 | 208 | return {} |
|
209 | 209 | |
|
210 | 210 | sortkey = lambda ctx: ctx[0] # sort by name |
|
211 | 211 | _bookmarks = [(safe_unicode(n), hex(h),) for n, h in |
|
212 | 212 | self._repo._bookmarks.items()] |
|
213 | 213 | return OrderedDict(sorted(_bookmarks, key=sortkey, reverse=True)) |
|
214 | 214 | |
|
215 | 215 | def _get_all_revisions(self): |
|
216 | 216 | |
|
217 | 217 | return map(lambda x: hex(x[7]), self._repo.changelog.index)[:-1] |
|
218 | 218 | |
|
219 | 219 | def get_diff(self, rev1, rev2, path='', ignore_whitespace=False, |
|
220 | 220 | context=3): |
|
221 | 221 | """ |
|
222 | 222 | Returns (git like) *diff*, as plain text. Shows changes introduced by |
|
223 | 223 | ``rev2`` since ``rev1``. |
|
224 | 224 | |
|
225 | 225 | :param rev1: Entry point from which diff is shown. Can be |
|
226 | 226 | ``self.EMPTY_CHANGESET`` - in this case, patch showing all |
|
227 | 227 | the changes since empty state of the repository until ``rev2`` |
|
228 | 228 | :param rev2: Until which revision changes should be shown. |
|
229 | 229 | :param ignore_whitespace: If set to ``True``, would not show whitespace |
|
230 | 230 | changes. Defaults to ``False``. |
|
231 | 231 | :param context: How many lines before/after changed lines should be |
|
232 | 232 | shown. Defaults to ``3``. |
|
233 | 233 | """ |
|
234 | 234 | if hasattr(rev1, 'raw_id'): |
|
235 | 235 | rev1 = getattr(rev1, 'raw_id') |
|
236 | 236 | |
|
237 | 237 | if hasattr(rev2, 'raw_id'): |
|
238 | 238 | rev2 = getattr(rev2, 'raw_id') |
|
239 | 239 | |
|
240 | 240 | # Check if given revisions are present at repository (may raise |
|
241 | 241 | # ChangesetDoesNotExistError) |
|
242 | 242 | if rev1 != self.EMPTY_CHANGESET: |
|
243 | 243 | self.get_changeset(rev1) |
|
244 | 244 | self.get_changeset(rev2) |
|
245 | if path: | |
|
246 | file_filter = match(self.path, '', [path]) | |
|
247 | else: | |
|
248 | file_filter = None | |
|
245 | 249 | |
|
246 | file_filter = match(self.path, '', [path]) | |
|
247 | 250 | return ''.join(patch.diff(self._repo, rev1, rev2, match=file_filter, |
|
248 | 251 | opts=diffopts(git=True, |
|
249 | 252 | ignorews=ignore_whitespace, |
|
250 | 253 | context=context))) |
|
251 | 254 | |
|
252 | 255 | @classmethod |
|
253 | 256 | def _check_url(cls, url): |
|
254 | 257 | """ |
|
255 | 258 | Function will check given url and try to verify if it's a valid |
|
256 | 259 | link. Sometimes it may happened that mercurial will issue basic |
|
257 | 260 | auth request that can cause whole API to hang when used from python |
|
258 | 261 | or other external calls. |
|
259 | 262 | |
|
260 | 263 | On failures it'll raise urllib2.HTTPError, return code 200 if url |
|
261 | 264 | is valid or True if it's a local path |
|
262 | 265 | """ |
|
263 | 266 | |
|
264 | 267 | from mercurial.util import url as Url |
|
265 | 268 | |
|
266 | 269 | # those authnadlers are patched for python 2.6.5 bug an |
|
267 | 270 | # infinit looping when given invalid resources |
|
268 | 271 | from mercurial.url import httpbasicauthhandler, httpdigestauthhandler |
|
269 | 272 | |
|
270 | 273 | # check first if it's not an local url |
|
271 | 274 | if os.path.isdir(url) or url.startswith('file:'): |
|
272 | 275 | return True |
|
273 | 276 | |
|
274 | 277 | if('+' in url[:url.find('://')]): |
|
275 | 278 | url = url[url.find('+') + 1:] |
|
276 | 279 | |
|
277 | 280 | handlers = [] |
|
278 | 281 | test_uri, authinfo = Url(url).authinfo() |
|
279 | 282 | |
|
280 | 283 | if authinfo: |
|
281 | 284 | #create a password manager |
|
282 | 285 | passmgr = urllib2.HTTPPasswordMgrWithDefaultRealm() |
|
283 | 286 | passmgr.add_password(*authinfo) |
|
284 | 287 | |
|
285 | 288 | handlers.extend((httpbasicauthhandler(passmgr), |
|
286 | 289 | httpdigestauthhandler(passmgr))) |
|
287 | 290 | |
|
288 | 291 | o = urllib2.build_opener(*handlers) |
|
289 | 292 | o.addheaders = [('Content-Type', 'application/mercurial-0.1'), |
|
290 | 293 | ('Accept', 'application/mercurial-0.1')] |
|
291 | 294 | |
|
292 | 295 | q = {"cmd": 'between'} |
|
293 | 296 | q.update({'pairs': "%s-%s" % ('0' * 40, '0' * 40)}) |
|
294 | 297 | qs = '?%s' % urllib.urlencode(q) |
|
295 | 298 | cu = "%s%s" % (test_uri, qs) |
|
296 | 299 | req = urllib2.Request(cu, None, {}) |
|
297 | 300 | |
|
298 | 301 | try: |
|
299 | 302 | resp = o.open(req) |
|
300 | 303 | return resp.code == 200 |
|
301 | 304 | except Exception, e: |
|
302 | 305 | # means it cannot be cloned |
|
303 | 306 | raise urllib2.URLError("[%s] %s" % (url, e)) |
|
304 | 307 | |
|
305 | 308 | def _get_repo(self, create, src_url=None, update_after_clone=False): |
|
306 | 309 | """ |
|
307 | 310 | Function will check for mercurial repository in given path and return |
|
308 | 311 | a localrepo object. If there is no repository in that path it will |
|
309 | 312 | raise an exception unless ``create`` parameter is set to True - in |
|
310 | 313 | that case repository would be created and returned. |
|
311 | 314 | If ``src_url`` is given, would try to clone repository from the |
|
312 | 315 | location at given clone_point. Additionally it'll make update to |
|
313 | 316 | working copy accordingly to ``update_after_clone`` flag |
|
314 | 317 | """ |
|
315 | 318 | |
|
316 | 319 | try: |
|
317 | 320 | if src_url: |
|
318 | 321 | url = str(self._get_url(src_url)) |
|
319 | 322 | opts = {} |
|
320 | 323 | if not update_after_clone: |
|
321 | 324 | opts.update({'noupdate': True}) |
|
322 | 325 | try: |
|
323 | 326 | MercurialRepository._check_url(url) |
|
324 | 327 | clone(self.baseui, url, self.path, **opts) |
|
325 | 328 | # except urllib2.URLError: |
|
326 | 329 | # raise Abort("Got HTTP 404 error") |
|
327 | 330 | except Exception: |
|
328 | 331 | raise |
|
329 | 332 | |
|
330 | 333 | # Don't try to create if we've already cloned repo |
|
331 | 334 | create = False |
|
332 | 335 | return localrepository(self.baseui, self.path, create=create) |
|
333 | 336 | except (Abort, RepoError), err: |
|
334 | 337 | if create: |
|
335 | 338 | msg = "Cannot create repository at %s. Original error was %s"\ |
|
336 | 339 | % (self.path, err) |
|
337 | 340 | else: |
|
338 | 341 | msg = "Not valid repository at %s. Original error was %s"\ |
|
339 | 342 | % (self.path, err) |
|
340 | 343 | raise RepositoryError(msg) |
|
341 | 344 | |
|
342 | 345 | @LazyProperty |
|
343 | 346 | def in_memory_changeset(self): |
|
344 | 347 | return MercurialInMemoryChangeset(self) |
|
345 | 348 | |
|
346 | 349 | @LazyProperty |
|
347 | 350 | def description(self): |
|
348 | 351 | undefined_description = u'unknown' |
|
349 | 352 | return safe_unicode(self._repo.ui.config('web', 'description', |
|
350 | 353 | undefined_description, untrusted=True)) |
|
351 | 354 | |
|
352 | 355 | @LazyProperty |
|
353 | 356 | def contact(self): |
|
354 | 357 | undefined_contact = u'Unknown' |
|
355 | 358 | return safe_unicode(get_contact(self._repo.ui.config) |
|
356 | 359 | or undefined_contact) |
|
357 | 360 | |
|
358 | 361 | @LazyProperty |
|
359 | 362 | def last_change(self): |
|
360 | 363 | """ |
|
361 | 364 | Returns last change made on this repository as datetime object |
|
362 | 365 | """ |
|
363 | 366 | return date_fromtimestamp(self._get_mtime(), makedate()[1]) |
|
364 | 367 | |
|
365 | 368 | def _get_mtime(self): |
|
366 | 369 | try: |
|
367 | 370 | return time.mktime(self.get_changeset().date.timetuple()) |
|
368 | 371 | except RepositoryError: |
|
369 | 372 | #fallback to filesystem |
|
370 | 373 | cl_path = os.path.join(self.path, '.hg', "00changelog.i") |
|
371 | 374 | st_path = os.path.join(self.path, '.hg', "store") |
|
372 | 375 | if os.path.exists(cl_path): |
|
373 | 376 | return os.stat(cl_path).st_mtime |
|
374 | 377 | else: |
|
375 | 378 | return os.stat(st_path).st_mtime |
|
376 | 379 | |
|
377 | 380 | def _get_hidden(self): |
|
378 | 381 | return self._repo.ui.configbool("web", "hidden", untrusted=True) |
|
379 | 382 | |
|
380 | 383 | def _get_revision(self, revision): |
|
381 | 384 | """ |
|
382 | 385 | Get's an ID revision given as str. This will always return a fill |
|
383 | 386 | 40 char revision number |
|
384 | 387 | |
|
385 | 388 | :param revision: str or int or None |
|
386 | 389 | """ |
|
387 | 390 | |
|
388 | 391 | if self._empty: |
|
389 | 392 | raise EmptyRepositoryError("There are no changesets yet") |
|
390 | 393 | |
|
391 | 394 | if revision in [-1, 'tip', None]: |
|
392 | 395 | revision = 'tip' |
|
393 | 396 | |
|
394 | 397 | try: |
|
395 | 398 | revision = hex(self._repo.lookup(revision)) |
|
396 | 399 | except (IndexError, ValueError, RepoLookupError, TypeError): |
|
397 | 400 | raise ChangesetDoesNotExistError("Revision %r does not " |
|
398 | 401 | "exist for this repository %s" \ |
|
399 | 402 | % (revision, self)) |
|
400 | 403 | return revision |
|
401 | 404 | |
|
402 | 405 | def _get_archives(self, archive_name='tip'): |
|
403 | 406 | allowed = self.baseui.configlist("web", "allow_archive", |
|
404 | 407 | untrusted=True) |
|
405 | 408 | for i in [('zip', '.zip'), ('gz', '.tar.gz'), ('bz2', '.tar.bz2')]: |
|
406 | 409 | if i[0] in allowed or self._repo.ui.configbool("web", |
|
407 | 410 | "allow" + i[0], |
|
408 | 411 | untrusted=True): |
|
409 | 412 | yield {"type": i[0], "extension": i[1], "node": archive_name} |
|
410 | 413 | |
|
411 | 414 | def _get_url(self, url): |
|
412 | 415 | """ |
|
413 | 416 | Returns normalized url. If schema is not given, would fall |
|
414 | 417 | to filesystem |
|
415 | 418 | (``file:///``) schema. |
|
416 | 419 | """ |
|
417 | 420 | url = str(url) |
|
418 | 421 | if url != 'default' and not '://' in url: |
|
419 | 422 | url = "file:" + urllib.pathname2url(url) |
|
420 | 423 | return url |
|
421 | 424 | |
|
422 | 425 | def get_changeset(self, revision=None): |
|
423 | 426 | """ |
|
424 | 427 | Returns ``MercurialChangeset`` object representing repository's |
|
425 | 428 | changeset at the given ``revision``. |
|
426 | 429 | """ |
|
427 | 430 | revision = self._get_revision(revision) |
|
428 | 431 | changeset = MercurialChangeset(repository=self, revision=revision) |
|
429 | 432 | return changeset |
|
430 | 433 | |
|
431 | 434 | def get_changesets(self, start=None, end=None, start_date=None, |
|
432 | 435 | end_date=None, branch_name=None, reverse=False): |
|
433 | 436 | """ |
|
434 | 437 | Returns iterator of ``MercurialChangeset`` objects from start to end |
|
435 | 438 | (both are inclusive) |
|
436 | 439 | |
|
437 | 440 | :param start: None, str, int or mercurial lookup format |
|
438 | 441 | :param end: None, str, int or mercurial lookup format |
|
439 | 442 | :param start_date: |
|
440 | 443 | :param end_date: |
|
441 | 444 | :param branch_name: |
|
442 | 445 | :param reversed: return changesets in reversed order |
|
443 | 446 | """ |
|
444 | 447 | |
|
445 | 448 | start_raw_id = self._get_revision(start) |
|
446 | 449 | start_pos = self.revisions.index(start_raw_id) if start else None |
|
447 | 450 | end_raw_id = self._get_revision(end) |
|
448 | 451 | end_pos = self.revisions.index(end_raw_id) if end else None |
|
449 | 452 | |
|
450 | 453 | if None not in [start, end] and start_pos > end_pos: |
|
451 | 454 | raise RepositoryError("start revision '%s' cannot be " |
|
452 | 455 | "after end revision '%s'" % (start, end)) |
|
453 | 456 | |
|
454 | 457 | if branch_name and branch_name not in self.branches.keys(): |
|
455 | 458 | raise BranchDoesNotExistError('Such branch %s does not exists for' |
|
456 | 459 | ' this repository' % branch_name) |
|
457 | 460 | if end_pos is not None: |
|
458 | 461 | end_pos += 1 |
|
459 | 462 | |
|
460 | 463 | slice_ = reversed(self.revisions[start_pos:end_pos]) if reverse else \ |
|
461 | 464 | self.revisions[start_pos:end_pos] |
|
462 | 465 | |
|
463 | 466 | for id_ in slice_: |
|
464 | 467 | cs = self.get_changeset(id_) |
|
465 | 468 | if branch_name and cs.branch != branch_name: |
|
466 | 469 | continue |
|
467 | 470 | if start_date and cs.date < start_date: |
|
468 | 471 | continue |
|
469 | 472 | if end_date and cs.date > end_date: |
|
470 | 473 | continue |
|
471 | 474 | |
|
472 | 475 | yield cs |
|
473 | 476 | |
|
474 | 477 | def pull(self, url): |
|
475 | 478 | """ |
|
476 | 479 | Tries to pull changes from external location. |
|
477 | 480 | """ |
|
478 | 481 | url = self._get_url(url) |
|
479 | 482 | try: |
|
480 | 483 | pull(self.baseui, self._repo, url) |
|
481 | 484 | except Abort, err: |
|
482 | 485 | # Propagate error but with vcs's type |
|
483 | 486 | raise RepositoryError(str(err)) |
|
484 | 487 | |
|
485 | 488 | @LazyProperty |
|
486 | 489 | def workdir(self): |
|
487 | 490 | """ |
|
488 | 491 | Returns ``Workdir`` instance for this repository. |
|
489 | 492 | """ |
|
490 | 493 | return MercurialWorkdir(self) |
|
491 | 494 | |
|
492 | 495 | def get_config_value(self, section, name, config_file=None): |
|
493 | 496 | """ |
|
494 | 497 | Returns configuration value for a given [``section``] and ``name``. |
|
495 | 498 | |
|
496 | 499 | :param section: Section we want to retrieve value from |
|
497 | 500 | :param name: Name of configuration we want to retrieve |
|
498 | 501 | :param config_file: A path to file which should be used to retrieve |
|
499 | 502 | configuration from (might also be a list of file paths) |
|
500 | 503 | """ |
|
501 | 504 | if config_file is None: |
|
502 | 505 | config_file = [] |
|
503 | 506 | elif isinstance(config_file, basestring): |
|
504 | 507 | config_file = [config_file] |
|
505 | 508 | |
|
506 | 509 | config = self._repo.ui |
|
507 | 510 | for path in config_file: |
|
508 | 511 | config.readconfig(path) |
|
509 | 512 | return config.config(section, name) |
|
510 | 513 | |
|
511 | 514 | def get_user_name(self, config_file=None): |
|
512 | 515 | """ |
|
513 | 516 | Returns user's name from global configuration file. |
|
514 | 517 | |
|
515 | 518 | :param config_file: A path to file which should be used to retrieve |
|
516 | 519 | configuration from (might also be a list of file paths) |
|
517 | 520 | """ |
|
518 | 521 | username = self.get_config_value('ui', 'username') |
|
519 | 522 | if username: |
|
520 | 523 | return author_name(username) |
|
521 | 524 | return None |
|
522 | 525 | |
|
523 | 526 | def get_user_email(self, config_file=None): |
|
524 | 527 | """ |
|
525 | 528 | Returns user's email from global configuration file. |
|
526 | 529 | |
|
527 | 530 | :param config_file: A path to file which should be used to retrieve |
|
528 | 531 | configuration from (might also be a list of file paths) |
|
529 | 532 | """ |
|
530 | 533 | username = self.get_config_value('ui', 'username') |
|
531 | 534 | if username: |
|
532 | 535 | return author_email(username) |
|
533 | 536 | return None |
@@ -1,4715 +1,4751 b'' | |||
|
1 | 1 | html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abbr,acronym,address,big,cite,code,del,dfn,em,font,img,ins,kbd,q,s,samp,small,strike,strong,sub,sup,tt,var,b,u,i,center,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td |
|
2 | 2 | { |
|
3 | 3 | border: 0; |
|
4 | 4 | outline: 0; |
|
5 | 5 | font-size: 100%; |
|
6 | 6 | vertical-align: baseline; |
|
7 | 7 | background: transparent; |
|
8 | 8 | margin: 0; |
|
9 | 9 | padding: 0; |
|
10 | 10 | } |
|
11 | 11 | |
|
12 | 12 | body { |
|
13 | 13 | line-height: 1; |
|
14 | 14 | height: 100%; |
|
15 | 15 | background: url("../images/background.png") repeat scroll 0 0 #B0B0B0; |
|
16 | 16 | font-family: Lucida Grande, Verdana, Lucida Sans Regular, |
|
17 | 17 | Lucida Sans Unicode, Arial, sans-serif; font-size : 12px; |
|
18 | 18 | color: #000; |
|
19 | 19 | margin: 0; |
|
20 | 20 | padding: 0; |
|
21 | 21 | font-size: 12px; |
|
22 | 22 | } |
|
23 | 23 | |
|
24 | 24 | ol,ul { |
|
25 | 25 | list-style: none; |
|
26 | 26 | } |
|
27 | 27 | |
|
28 | 28 | blockquote,q { |
|
29 | 29 | quotes: none; |
|
30 | 30 | } |
|
31 | 31 | |
|
32 | 32 | blockquote:before,blockquote:after,q:before,q:after { |
|
33 | 33 | content: none; |
|
34 | 34 | } |
|
35 | 35 | |
|
36 | 36 | :focus { |
|
37 | 37 | outline: 0; |
|
38 | 38 | } |
|
39 | 39 | |
|
40 | 40 | del { |
|
41 | 41 | text-decoration: line-through; |
|
42 | 42 | } |
|
43 | 43 | |
|
44 | 44 | table { |
|
45 | 45 | border-collapse: collapse; |
|
46 | 46 | border-spacing: 0; |
|
47 | 47 | } |
|
48 | 48 | |
|
49 | 49 | html { |
|
50 | 50 | height: 100%; |
|
51 | 51 | } |
|
52 | 52 | |
|
53 | 53 | a { |
|
54 | 54 | color: #003367; |
|
55 | 55 | text-decoration: none; |
|
56 | 56 | cursor: pointer; |
|
57 | 57 | } |
|
58 | 58 | |
|
59 | 59 | a:hover { |
|
60 | 60 | color: #316293; |
|
61 | 61 | text-decoration: underline; |
|
62 | 62 | } |
|
63 | 63 | |
|
64 | 64 | h1,h2,h3,h4,h5,h6, |
|
65 | 65 | div.h1,div.h2,div.h3,div.h4,div.h5,div.h6 { |
|
66 | 66 | color: #292929; |
|
67 | 67 | font-weight: 700; |
|
68 | 68 | } |
|
69 | 69 | |
|
70 | 70 | h1,div.h1 { |
|
71 | 71 | font-size: 22px; |
|
72 | 72 | } |
|
73 | 73 | |
|
74 | 74 | h2,div.h2 { |
|
75 | 75 | font-size: 20px; |
|
76 | 76 | } |
|
77 | 77 | |
|
78 | 78 | h3,div.h3 { |
|
79 | 79 | font-size: 18px; |
|
80 | 80 | } |
|
81 | 81 | |
|
82 | 82 | h4,div.h4 { |
|
83 | 83 | font-size: 16px; |
|
84 | 84 | } |
|
85 | 85 | |
|
86 | 86 | h5,div.h5 { |
|
87 | 87 | font-size: 14px; |
|
88 | 88 | } |
|
89 | 89 | |
|
90 | 90 | h6,div.h6 { |
|
91 | 91 | font-size: 11px; |
|
92 | 92 | } |
|
93 | 93 | |
|
94 | 94 | ul.circle { |
|
95 | 95 | list-style-type: circle; |
|
96 | 96 | } |
|
97 | 97 | |
|
98 | 98 | ul.disc { |
|
99 | 99 | list-style-type: disc; |
|
100 | 100 | } |
|
101 | 101 | |
|
102 | 102 | ul.square { |
|
103 | 103 | list-style-type: square; |
|
104 | 104 | } |
|
105 | 105 | |
|
106 | 106 | ol.lower-roman { |
|
107 | 107 | list-style-type: lower-roman; |
|
108 | 108 | } |
|
109 | 109 | |
|
110 | 110 | ol.upper-roman { |
|
111 | 111 | list-style-type: upper-roman; |
|
112 | 112 | } |
|
113 | 113 | |
|
114 | 114 | ol.lower-alpha { |
|
115 | 115 | list-style-type: lower-alpha; |
|
116 | 116 | } |
|
117 | 117 | |
|
118 | 118 | ol.upper-alpha { |
|
119 | 119 | list-style-type: upper-alpha; |
|
120 | 120 | } |
|
121 | 121 | |
|
122 | 122 | ol.decimal { |
|
123 | 123 | list-style-type: decimal; |
|
124 | 124 | } |
|
125 | 125 | |
|
126 | 126 | div.color { |
|
127 | 127 | clear: both; |
|
128 | 128 | overflow: hidden; |
|
129 | 129 | position: absolute; |
|
130 | 130 | background: #FFF; |
|
131 | 131 | margin: 7px 0 0 60px; |
|
132 | 132 | padding: 1px 1px 1px 0; |
|
133 | 133 | } |
|
134 | 134 | |
|
135 | 135 | div.color a { |
|
136 | 136 | width: 15px; |
|
137 | 137 | height: 15px; |
|
138 | 138 | display: block; |
|
139 | 139 | float: left; |
|
140 | 140 | margin: 0 0 0 1px; |
|
141 | 141 | padding: 0; |
|
142 | 142 | } |
|
143 | 143 | |
|
144 | 144 | div.options { |
|
145 | 145 | clear: both; |
|
146 | 146 | overflow: hidden; |
|
147 | 147 | position: absolute; |
|
148 | 148 | background: #FFF; |
|
149 | 149 | margin: 7px 0 0 162px; |
|
150 | 150 | padding: 0; |
|
151 | 151 | } |
|
152 | 152 | |
|
153 | 153 | div.options a { |
|
154 | 154 | height: 1%; |
|
155 | 155 | display: block; |
|
156 | 156 | text-decoration: none; |
|
157 | 157 | margin: 0; |
|
158 | 158 | padding: 3px 8px; |
|
159 | 159 | } |
|
160 | 160 | |
|
161 | 161 | .top-left-rounded-corner { |
|
162 | 162 | -webkit-border-top-left-radius: 8px; |
|
163 | 163 | -khtml-border-radius-topleft: 8px; |
|
164 | 164 | -moz-border-radius-topleft: 8px; |
|
165 | 165 | border-top-left-radius: 8px; |
|
166 | 166 | } |
|
167 | 167 | |
|
168 | 168 | .top-right-rounded-corner { |
|
169 | 169 | -webkit-border-top-right-radius: 8px; |
|
170 | 170 | -khtml-border-radius-topright: 8px; |
|
171 | 171 | -moz-border-radius-topright: 8px; |
|
172 | 172 | border-top-right-radius: 8px; |
|
173 | 173 | } |
|
174 | 174 | |
|
175 | 175 | .bottom-left-rounded-corner { |
|
176 | 176 | -webkit-border-bottom-left-radius: 8px; |
|
177 | 177 | -khtml-border-radius-bottomleft: 8px; |
|
178 | 178 | -moz-border-radius-bottomleft: 8px; |
|
179 | 179 | border-bottom-left-radius: 8px; |
|
180 | 180 | } |
|
181 | 181 | |
|
182 | 182 | .bottom-right-rounded-corner { |
|
183 | 183 | -webkit-border-bottom-right-radius: 8px; |
|
184 | 184 | -khtml-border-radius-bottomright: 8px; |
|
185 | 185 | -moz-border-radius-bottomright: 8px; |
|
186 | 186 | border-bottom-right-radius: 8px; |
|
187 | 187 | } |
|
188 | 188 | |
|
189 | 189 | .top-left-rounded-corner-mid { |
|
190 | 190 | -webkit-border-top-left-radius: 4px; |
|
191 | 191 | -khtml-border-radius-topleft: 4px; |
|
192 | 192 | -moz-border-radius-topleft: 4px; |
|
193 | 193 | border-top-left-radius: 4px; |
|
194 | 194 | } |
|
195 | 195 | |
|
196 | 196 | .top-right-rounded-corner-mid { |
|
197 | 197 | -webkit-border-top-right-radius: 4px; |
|
198 | 198 | -khtml-border-radius-topright: 4px; |
|
199 | 199 | -moz-border-radius-topright: 4px; |
|
200 | 200 | border-top-right-radius: 4px; |
|
201 | 201 | } |
|
202 | 202 | |
|
203 | 203 | .bottom-left-rounded-corner-mid { |
|
204 | 204 | -webkit-border-bottom-left-radius: 4px; |
|
205 | 205 | -khtml-border-radius-bottomleft: 4px; |
|
206 | 206 | -moz-border-radius-bottomleft: 4px; |
|
207 | 207 | border-bottom-left-radius: 4px; |
|
208 | 208 | } |
|
209 | 209 | |
|
210 | 210 | .bottom-right-rounded-corner-mid { |
|
211 | 211 | -webkit-border-bottom-right-radius: 4px; |
|
212 | 212 | -khtml-border-radius-bottomright: 4px; |
|
213 | 213 | -moz-border-radius-bottomright: 4px; |
|
214 | 214 | border-bottom-right-radius: 4px; |
|
215 | 215 | } |
|
216 | 216 | |
|
217 | 217 | .help-block { |
|
218 | 218 | color: #999999; |
|
219 | 219 | display: block; |
|
220 | 220 | margin-bottom: 0; |
|
221 | 221 | margin-top: 5px; |
|
222 | 222 | } |
|
223 | 223 | |
|
224 | 224 | .empty_data{ |
|
225 | 225 | color:#B9B9B9; |
|
226 | 226 | } |
|
227 | 227 | |
|
228 | 228 | a.permalink{ |
|
229 | 229 | visibility: hidden; |
|
230 | 230 | } |
|
231 | 231 | |
|
232 | 232 | a.permalink:hover{ |
|
233 | 233 | text-decoration: none; |
|
234 | 234 | } |
|
235 | 235 | |
|
236 | 236 | h1:hover > a.permalink, |
|
237 | 237 | h2:hover > a.permalink, |
|
238 | 238 | h3:hover > a.permalink, |
|
239 | 239 | h4:hover > a.permalink, |
|
240 | 240 | h5:hover > a.permalink, |
|
241 | 241 | h6:hover > a.permalink, |
|
242 | 242 | div:hover > a.permalink { |
|
243 | 243 | visibility: visible; |
|
244 | 244 | } |
|
245 | 245 | |
|
246 | 246 | #header { |
|
247 | 247 | margin: 0; |
|
248 | 248 | padding: 0 10px; |
|
249 | 249 | } |
|
250 | 250 | |
|
251 | 251 | #header ul#logged-user { |
|
252 | 252 | margin-bottom: 5px !important; |
|
253 | 253 | -webkit-border-radius: 0px 0px 8px 8px; |
|
254 | 254 | -khtml-border-radius: 0px 0px 8px 8px; |
|
255 | 255 | -moz-border-radius: 0px 0px 8px 8px; |
|
256 | 256 | border-radius: 0px 0px 8px 8px; |
|
257 | 257 | height: 37px; |
|
258 | 258 | background-color: #003B76; |
|
259 | 259 | background-repeat: repeat-x; |
|
260 | 260 | background-image: -khtml-gradient(linear, left top, left bottom, from(#003B76), to(#00376E) ); |
|
261 | 261 | background-image: -moz-linear-gradient(top, #003b76, #00376e); |
|
262 | 262 | background-image: -ms-linear-gradient(top, #003b76, #00376e); |
|
263 | 263 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #003b76), color-stop(100%, #00376e) ); |
|
264 | 264 | background-image: -webkit-linear-gradient(top, #003b76, #00376e); |
|
265 | 265 | background-image: -o-linear-gradient(top, #003b76, #00376e); |
|
266 | 266 | background-image: linear-gradient(top, #003b76, #00376e); |
|
267 | 267 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#003b76',endColorstr='#00376e', GradientType=0 ); |
|
268 | 268 | box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6); |
|
269 | 269 | } |
|
270 | 270 | |
|
271 | 271 | #header ul#logged-user li { |
|
272 | 272 | list-style: none; |
|
273 | 273 | float: left; |
|
274 | 274 | margin: 8px 0 0; |
|
275 | 275 | padding: 4px 12px; |
|
276 | 276 | border-left: 1px solid #316293; |
|
277 | 277 | } |
|
278 | 278 | |
|
279 | 279 | #header ul#logged-user li.first { |
|
280 | 280 | border-left: none; |
|
281 | 281 | margin: 4px; |
|
282 | 282 | } |
|
283 | 283 | |
|
284 | 284 | #header ul#logged-user li.first div.gravatar { |
|
285 | 285 | margin-top: -2px; |
|
286 | 286 | } |
|
287 | 287 | |
|
288 | 288 | #header ul#logged-user li.first div.account { |
|
289 | 289 | padding-top: 4px; |
|
290 | 290 | float: left; |
|
291 | 291 | } |
|
292 | 292 | |
|
293 | 293 | #header ul#logged-user li.last { |
|
294 | 294 | border-right: none; |
|
295 | 295 | } |
|
296 | 296 | |
|
297 | 297 | #header ul#logged-user li a { |
|
298 | 298 | color: #fff; |
|
299 | 299 | font-weight: 700; |
|
300 | 300 | text-decoration: none; |
|
301 | 301 | } |
|
302 | 302 | |
|
303 | 303 | #header ul#logged-user li a:hover { |
|
304 | 304 | text-decoration: underline; |
|
305 | 305 | } |
|
306 | 306 | |
|
307 | 307 | #header ul#logged-user li.highlight a { |
|
308 | 308 | color: #fff; |
|
309 | 309 | } |
|
310 | 310 | |
|
311 | 311 | #header ul#logged-user li.highlight a:hover { |
|
312 | 312 | color: #FFF; |
|
313 | 313 | } |
|
314 | 314 | |
|
315 | 315 | #header #header-inner { |
|
316 | 316 | min-height: 44px; |
|
317 | 317 | clear: both; |
|
318 | 318 | position: relative; |
|
319 | 319 | background-color: #003B76; |
|
320 | 320 | background-repeat: repeat-x; |
|
321 | 321 | background-image: -khtml-gradient(linear, left top, left bottom, from(#003B76), to(#00376E) ); |
|
322 | 322 | background-image: -moz-linear-gradient(top, #003b76, #00376e); |
|
323 | 323 | background-image: -ms-linear-gradient(top, #003b76, #00376e); |
|
324 | 324 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #003b76),color-stop(100%, #00376e) ); |
|
325 | 325 | background-image: -webkit-linear-gradient(top, #003b76, #00376e); |
|
326 | 326 | background-image: -o-linear-gradient(top, #003b76, #00376e); |
|
327 | 327 | background-image: linear-gradient(top, #003b76, #00376e); |
|
328 | 328 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#003b76',endColorstr='#00376e', GradientType=0 ); |
|
329 | 329 | margin: 0; |
|
330 | 330 | padding: 0; |
|
331 | 331 | display: block; |
|
332 | 332 | box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6); |
|
333 | 333 | -webkit-border-radius: 4px 4px 4px 4px; |
|
334 | 334 | -khtml-border-radius: 4px 4px 4px 4px; |
|
335 | 335 | -moz-border-radius: 4px 4px 4px 4px; |
|
336 | 336 | border-radius: 4px 4px 4px 4px; |
|
337 | 337 | } |
|
338 | 338 | #header #header-inner.hover{ |
|
339 | 339 | position: fixed !important; |
|
340 | 340 | width: 100% !important; |
|
341 | 341 | margin-left: -10px !important; |
|
342 | 342 | z-index: 10000; |
|
343 | 343 | -webkit-border-radius: 0px 0px 0px 0px; |
|
344 | 344 | -khtml-border-radius: 0px 0px 0px 0px; |
|
345 | 345 | -moz-border-radius: 0px 0px 0px 0px; |
|
346 | 346 | border-radius: 0px 0px 0px 0px; |
|
347 | 347 | } |
|
348 | 348 | |
|
349 | 349 | .ie7 #header #header-inner.hover, |
|
350 | 350 | .ie8 #header #header-inner.hover, |
|
351 | 351 | .ie9 #header #header-inner.hover |
|
352 | 352 | { |
|
353 | 353 | z-index: auto !important; |
|
354 | 354 | } |
|
355 | 355 | |
|
356 | 356 | .header-pos-fix, .anchor{ |
|
357 | 357 | margin-top: -46px; |
|
358 | 358 | padding-top: 46px; |
|
359 | 359 | } |
|
360 | 360 | |
|
361 | 361 | #header #header-inner #home a { |
|
362 | 362 | height: 40px; |
|
363 | 363 | width: 46px; |
|
364 | 364 | display: block; |
|
365 | 365 | background: url("../images/button_home.png"); |
|
366 | 366 | background-position: 0 0; |
|
367 | 367 | margin: 0; |
|
368 | 368 | padding: 0; |
|
369 | 369 | } |
|
370 | 370 | |
|
371 | 371 | #header #header-inner #home a:hover { |
|
372 | 372 | background-position: 0 -40px; |
|
373 | 373 | } |
|
374 | 374 | |
|
375 | 375 | #header #header-inner #logo { |
|
376 | 376 | float: left; |
|
377 | 377 | position: absolute; |
|
378 | 378 | } |
|
379 | 379 | |
|
380 | 380 | #header #header-inner #logo h1 { |
|
381 | 381 | color: #FFF; |
|
382 | 382 | font-size: 20px; |
|
383 | 383 | margin: 12px 0 0 13px; |
|
384 | 384 | padding: 0; |
|
385 | 385 | } |
|
386 | 386 | |
|
387 | 387 | #header #header-inner #logo a { |
|
388 | 388 | color: #fff; |
|
389 | 389 | text-decoration: none; |
|
390 | 390 | } |
|
391 | 391 | |
|
392 | 392 | #header #header-inner #logo a:hover { |
|
393 | 393 | color: #bfe3ff; |
|
394 | 394 | } |
|
395 | 395 | |
|
396 | 396 | #header #header-inner #quick,#header #header-inner #quick ul { |
|
397 | 397 | position: relative; |
|
398 | 398 | float: right; |
|
399 | 399 | list-style-type: none; |
|
400 | 400 | list-style-position: outside; |
|
401 | 401 | margin: 8px 8px 0 0; |
|
402 | 402 | padding: 0; |
|
403 | 403 | } |
|
404 | 404 | |
|
405 | 405 | #header #header-inner #quick li { |
|
406 | 406 | position: relative; |
|
407 | 407 | float: left; |
|
408 | 408 | margin: 0 5px 0 0; |
|
409 | 409 | padding: 0; |
|
410 | 410 | } |
|
411 | 411 | |
|
412 | 412 | #header #header-inner #quick li a.menu_link { |
|
413 | 413 | top: 0; |
|
414 | 414 | left: 0; |
|
415 | 415 | height: 1%; |
|
416 | 416 | display: block; |
|
417 | 417 | clear: both; |
|
418 | 418 | overflow: hidden; |
|
419 | 419 | color: #FFF; |
|
420 | 420 | font-weight: 700; |
|
421 | 421 | text-decoration: none; |
|
422 | 422 | background: #369; |
|
423 | 423 | padding: 0; |
|
424 | 424 | -webkit-border-radius: 4px 4px 4px 4px; |
|
425 | 425 | -khtml-border-radius: 4px 4px 4px 4px; |
|
426 | 426 | -moz-border-radius: 4px 4px 4px 4px; |
|
427 | 427 | border-radius: 4px 4px 4px 4px; |
|
428 | 428 | } |
|
429 | 429 | |
|
430 | 430 | #header #header-inner #quick li span.short { |
|
431 | 431 | padding: 9px 6px 8px 6px; |
|
432 | 432 | } |
|
433 | 433 | |
|
434 | 434 | #header #header-inner #quick li span { |
|
435 | 435 | top: 0; |
|
436 | 436 | right: 0; |
|
437 | 437 | height: 1%; |
|
438 | 438 | display: block; |
|
439 | 439 | float: left; |
|
440 | 440 | border-left: 1px solid #3f6f9f; |
|
441 | 441 | margin: 0; |
|
442 | 442 | padding: 10px 12px 8px 10px; |
|
443 | 443 | } |
|
444 | 444 | |
|
445 | 445 | #header #header-inner #quick li span.normal { |
|
446 | 446 | border: none; |
|
447 | 447 | padding: 10px 12px 8px; |
|
448 | 448 | } |
|
449 | 449 | |
|
450 | 450 | #header #header-inner #quick li span.icon { |
|
451 | 451 | top: 0; |
|
452 | 452 | left: 0; |
|
453 | 453 | border-left: none; |
|
454 | 454 | border-right: 1px solid #2e5c89; |
|
455 | 455 | padding: 8px 6px 4px; |
|
456 | 456 | } |
|
457 | 457 | |
|
458 | 458 | #header #header-inner #quick li span.icon_short { |
|
459 | 459 | top: 0; |
|
460 | 460 | left: 0; |
|
461 | 461 | border-left: none; |
|
462 | 462 | border-right: 1px solid #2e5c89; |
|
463 | 463 | padding: 8px 6px 4px; |
|
464 | 464 | } |
|
465 | 465 | |
|
466 | 466 | #header #header-inner #quick li span.icon img,#header #header-inner #quick li span.icon_short img |
|
467 | 467 | { |
|
468 | 468 | margin: 0px -2px 0px 0px; |
|
469 | 469 | } |
|
470 | 470 | |
|
471 | 471 | #header #header-inner #quick li a:hover { |
|
472 | 472 | background: #4e4e4e no-repeat top left; |
|
473 | 473 | } |
|
474 | 474 | |
|
475 | 475 | #header #header-inner #quick li a:hover span { |
|
476 | 476 | border-left: 1px solid #545454; |
|
477 | 477 | } |
|
478 | 478 | |
|
479 | 479 | #header #header-inner #quick li a:hover span.icon,#header #header-inner #quick li a:hover span.icon_short |
|
480 | 480 | { |
|
481 | 481 | border-left: none; |
|
482 | 482 | border-right: 1px solid #464646; |
|
483 | 483 | } |
|
484 | 484 | |
|
485 | 485 | #header #header-inner #quick ul { |
|
486 | 486 | top: 29px; |
|
487 | 487 | right: 0; |
|
488 | 488 | min-width: 200px; |
|
489 | 489 | display: none; |
|
490 | 490 | position: absolute; |
|
491 | 491 | background: #FFF; |
|
492 | 492 | border: 1px solid #666; |
|
493 | 493 | border-top: 1px solid #003367; |
|
494 | 494 | z-index: 100; |
|
495 | 495 | margin: 0px 0px 0px 0px; |
|
496 | 496 | padding: 0; |
|
497 | 497 | } |
|
498 | 498 | |
|
499 | 499 | #header #header-inner #quick ul.repo_switcher { |
|
500 | 500 | max-height: 275px; |
|
501 | 501 | overflow-x: hidden; |
|
502 | 502 | overflow-y: auto; |
|
503 | 503 | } |
|
504 | 504 | |
|
505 | 505 | #header #header-inner #quick ul.repo_switcher li.qfilter_rs { |
|
506 | 506 | float: none; |
|
507 | 507 | margin: 0; |
|
508 | 508 | border-bottom: 2px solid #003367; |
|
509 | 509 | } |
|
510 | 510 | |
|
511 | 511 | #header #header-inner #quick .repo_switcher_type { |
|
512 | 512 | position: absolute; |
|
513 | 513 | left: 0; |
|
514 | 514 | top: 9px; |
|
515 | 515 | } |
|
516 | 516 | |
|
517 | 517 | #header #header-inner #quick li ul li { |
|
518 | 518 | border-bottom: 1px solid #ddd; |
|
519 | 519 | } |
|
520 | 520 | |
|
521 | 521 | #header #header-inner #quick li ul li a { |
|
522 | 522 | width: 182px; |
|
523 | 523 | height: auto; |
|
524 | 524 | display: block; |
|
525 | 525 | float: left; |
|
526 | 526 | background: #FFF; |
|
527 | 527 | color: #003367; |
|
528 | 528 | font-weight: 400; |
|
529 | 529 | margin: 0; |
|
530 | 530 | padding: 7px 9px; |
|
531 | 531 | } |
|
532 | 532 | |
|
533 | 533 | #header #header-inner #quick li ul li a:hover { |
|
534 | 534 | color: #000; |
|
535 | 535 | background: #FFF; |
|
536 | 536 | } |
|
537 | 537 | |
|
538 | 538 | #header #header-inner #quick ul ul { |
|
539 | 539 | top: auto; |
|
540 | 540 | } |
|
541 | 541 | |
|
542 | 542 | #header #header-inner #quick li ul ul { |
|
543 | 543 | right: 200px; |
|
544 | 544 | max-height: 275px; |
|
545 | 545 | overflow: auto; |
|
546 | 546 | overflow-x: hidden; |
|
547 | 547 | white-space: normal; |
|
548 | 548 | } |
|
549 | 549 | |
|
550 | 550 | #header #header-inner #quick li ul li a.journal,#header #header-inner #quick li ul li a.journal:hover |
|
551 | 551 | { |
|
552 | 552 | background: url("../images/icons/book.png") no-repeat scroll 4px 9px |
|
553 | 553 | #FFF; |
|
554 | 554 | width: 167px; |
|
555 | 555 | margin: 0; |
|
556 | 556 | padding: 12px 9px 7px 24px; |
|
557 | 557 | } |
|
558 | 558 | |
|
559 | 559 | #header #header-inner #quick li ul li a.private_repo,#header #header-inner #quick li ul li a.private_repo:hover |
|
560 | 560 | { |
|
561 | 561 | background: url("../images/icons/lock.png") no-repeat scroll 4px 9px |
|
562 | 562 | #FFF; |
|
563 | 563 | min-width: 167px; |
|
564 | 564 | margin: 0; |
|
565 | 565 | padding: 12px 9px 7px 24px; |
|
566 | 566 | } |
|
567 | 567 | |
|
568 | 568 | #header #header-inner #quick li ul li a.public_repo,#header #header-inner #quick li ul li a.public_repo:hover |
|
569 | 569 | { |
|
570 | 570 | background: url("../images/icons/lock_open.png") no-repeat scroll 4px |
|
571 | 571 | 9px #FFF; |
|
572 | 572 | min-width: 167px; |
|
573 | 573 | margin: 0; |
|
574 | 574 | padding: 12px 9px 7px 24px; |
|
575 | 575 | } |
|
576 | 576 | |
|
577 | 577 | #header #header-inner #quick li ul li a.hg,#header #header-inner #quick li ul li a.hg:hover |
|
578 | 578 | { |
|
579 | 579 | background: url("../images/icons/hgicon.png") no-repeat scroll 4px 9px |
|
580 | 580 | #FFF; |
|
581 | 581 | min-width: 167px; |
|
582 | 582 | margin: 0 0 0 14px; |
|
583 | 583 | padding: 12px 9px 7px 24px; |
|
584 | 584 | } |
|
585 | 585 | |
|
586 | 586 | #header #header-inner #quick li ul li a.git,#header #header-inner #quick li ul li a.git:hover |
|
587 | 587 | { |
|
588 | 588 | background: url("../images/icons/giticon.png") no-repeat scroll 4px 9px |
|
589 | 589 | #FFF; |
|
590 | 590 | min-width: 167px; |
|
591 | 591 | margin: 0 0 0 14px; |
|
592 | 592 | padding: 12px 9px 7px 24px; |
|
593 | 593 | } |
|
594 | 594 | |
|
595 | 595 | #header #header-inner #quick li ul li a.repos,#header #header-inner #quick li ul li a.repos:hover |
|
596 | 596 | { |
|
597 | 597 | background: url("../images/icons/database_edit.png") no-repeat scroll |
|
598 | 598 | 4px 9px #FFF; |
|
599 | 599 | width: 167px; |
|
600 | 600 | margin: 0; |
|
601 | 601 | padding: 12px 9px 7px 24px; |
|
602 | 602 | } |
|
603 | 603 | |
|
604 | 604 | #header #header-inner #quick li ul li a.repos_groups,#header #header-inner #quick li ul li a.repos_groups:hover |
|
605 | 605 | { |
|
606 | 606 | background: url("../images/icons/database_link.png") no-repeat scroll |
|
607 | 607 | 4px 9px #FFF; |
|
608 | 608 | width: 167px; |
|
609 | 609 | margin: 0; |
|
610 | 610 | padding: 12px 9px 7px 24px; |
|
611 | 611 | } |
|
612 | 612 | |
|
613 | 613 | #header #header-inner #quick li ul li a.users,#header #header-inner #quick li ul li a.users:hover |
|
614 | 614 | { |
|
615 | 615 | background: #FFF url("../images/icons/user_edit.png") no-repeat 4px 9px; |
|
616 | 616 | width: 167px; |
|
617 | 617 | margin: 0; |
|
618 | 618 | padding: 12px 9px 7px 24px; |
|
619 | 619 | } |
|
620 | 620 | |
|
621 | 621 | #header #header-inner #quick li ul li a.groups,#header #header-inner #quick li ul li a.groups:hover |
|
622 | 622 | { |
|
623 | 623 | background: #FFF url("../images/icons/group_edit.png") no-repeat 4px 9px; |
|
624 | 624 | width: 167px; |
|
625 | 625 | margin: 0; |
|
626 | 626 | padding: 12px 9px 7px 24px; |
|
627 | 627 | } |
|
628 | 628 | |
|
629 | 629 | #header #header-inner #quick li ul li a.settings,#header #header-inner #quick li ul li a.settings:hover |
|
630 | 630 | { |
|
631 | 631 | background: #FFF url("../images/icons/cog.png") no-repeat 4px 9px; |
|
632 | 632 | width: 167px; |
|
633 | 633 | margin: 0; |
|
634 | 634 | padding: 12px 9px 7px 24px; |
|
635 | 635 | } |
|
636 | 636 | |
|
637 | 637 | #header #header-inner #quick li ul li a.permissions,#header #header-inner #quick li ul li a.permissions:hover |
|
638 | 638 | { |
|
639 | 639 | background: #FFF url("../images/icons/key.png") no-repeat 4px 9px; |
|
640 | 640 | width: 167px; |
|
641 | 641 | margin: 0; |
|
642 | 642 | padding: 12px 9px 7px 24px; |
|
643 | 643 | } |
|
644 | 644 | |
|
645 | 645 | #header #header-inner #quick li ul li a.ldap,#header #header-inner #quick li ul li a.ldap:hover |
|
646 | 646 | { |
|
647 | 647 | background: #FFF url("../images/icons/server_key.png") no-repeat 4px 9px; |
|
648 | 648 | width: 167px; |
|
649 | 649 | margin: 0; |
|
650 | 650 | padding: 12px 9px 7px 24px; |
|
651 | 651 | } |
|
652 | 652 | |
|
653 | 653 | #header #header-inner #quick li ul li a.fork,#header #header-inner #quick li ul li a.fork:hover |
|
654 | 654 | { |
|
655 | 655 | background: #FFF url("../images/icons/arrow_divide.png") no-repeat 4px |
|
656 | 656 | 9px; |
|
657 | 657 | width: 167px; |
|
658 | 658 | margin: 0; |
|
659 | 659 | padding: 12px 9px 7px 24px; |
|
660 | 660 | } |
|
661 | 661 | |
|
662 | 662 | #header #header-inner #quick li ul li a.locking_add,#header #header-inner #quick li ul li a.locking_add:hover |
|
663 | 663 | { |
|
664 | 664 | background: #FFF url("../images/icons/lock_add.png") no-repeat 4px |
|
665 | 665 | 9px; |
|
666 | 666 | width: 167px; |
|
667 | 667 | margin: 0; |
|
668 | 668 | padding: 12px 9px 7px 24px; |
|
669 | 669 | } |
|
670 | 670 | |
|
671 | 671 | #header #header-inner #quick li ul li a.locking_del,#header #header-inner #quick li ul li a.locking_del:hover |
|
672 | 672 | { |
|
673 | 673 | background: #FFF url("../images/icons/lock_delete.png") no-repeat 4px |
|
674 | 674 | 9px; |
|
675 | 675 | width: 167px; |
|
676 | 676 | margin: 0; |
|
677 | 677 | padding: 12px 9px 7px 24px; |
|
678 | 678 | } |
|
679 | 679 | |
|
680 | 680 | #header #header-inner #quick li ul li a.pull_request,#header #header-inner #quick li ul li a.pull_request:hover |
|
681 | 681 | { |
|
682 | 682 | background: #FFF url("../images/icons/arrow_join.png") no-repeat 4px |
|
683 | 683 | 9px; |
|
684 | 684 | width: 167px; |
|
685 | 685 | margin: 0; |
|
686 | 686 | padding: 12px 9px 7px 24px; |
|
687 | 687 | } |
|
688 | 688 | |
|
689 | 689 | #header #header-inner #quick li ul li a.compare_request,#header #header-inner #quick li ul li a.compare_request:hover |
|
690 | 690 | { |
|
691 | 691 | background: #FFF url("../images/icons/arrow_inout.png") no-repeat 4px |
|
692 | 692 | 9px; |
|
693 | 693 | width: 167px; |
|
694 | 694 | margin: 0; |
|
695 | 695 | padding: 12px 9px 7px 24px; |
|
696 | 696 | } |
|
697 | 697 | |
|
698 | 698 | #header #header-inner #quick li ul li a.search,#header #header-inner #quick li ul li a.search:hover |
|
699 | 699 | { |
|
700 | 700 | background: #FFF url("../images/icons/search_16.png") no-repeat 4px 9px; |
|
701 | 701 | width: 167px; |
|
702 | 702 | margin: 0; |
|
703 | 703 | padding: 12px 9px 7px 24px; |
|
704 | 704 | } |
|
705 | 705 | |
|
706 | 706 | #header #header-inner #quick li ul li a.delete,#header #header-inner #quick li ul li a.delete:hover |
|
707 | 707 | { |
|
708 | 708 | background: #FFF url("../images/icons/delete.png") no-repeat 4px 9px; |
|
709 | 709 | width: 167px; |
|
710 | 710 | margin: 0; |
|
711 | 711 | padding: 12px 9px 7px 24px; |
|
712 | 712 | } |
|
713 | 713 | |
|
714 | 714 | #header #header-inner #quick li ul li a.branches,#header #header-inner #quick li ul li a.branches:hover |
|
715 | 715 | { |
|
716 | 716 | background: #FFF url("../images/icons/arrow_branch.png") no-repeat 4px |
|
717 | 717 | 9px; |
|
718 | 718 | width: 167px; |
|
719 | 719 | margin: 0; |
|
720 | 720 | padding: 12px 9px 7px 24px; |
|
721 | 721 | } |
|
722 | 722 | |
|
723 | 723 | #header #header-inner #quick li ul li a.tags, |
|
724 | 724 | #header #header-inner #quick li ul li a.tags:hover{ |
|
725 | 725 | background: #FFF url("../images/icons/tag_blue.png") no-repeat 4px 9px; |
|
726 | 726 | width: 167px; |
|
727 | 727 | margin: 0; |
|
728 | 728 | padding: 12px 9px 7px 24px; |
|
729 | 729 | } |
|
730 | 730 | |
|
731 | 731 | #header #header-inner #quick li ul li a.bookmarks, |
|
732 | 732 | #header #header-inner #quick li ul li a.bookmarks:hover{ |
|
733 | 733 | background: #FFF url("../images/icons/tag_green.png") no-repeat 4px 9px; |
|
734 | 734 | width: 167px; |
|
735 | 735 | margin: 0; |
|
736 | 736 | padding: 12px 9px 7px 24px; |
|
737 | 737 | } |
|
738 | 738 | |
|
739 | 739 | #header #header-inner #quick li ul li a.admin, |
|
740 | 740 | #header #header-inner #quick li ul li a.admin:hover{ |
|
741 | 741 | background: #FFF url("../images/icons/cog_edit.png") no-repeat 4px 9px; |
|
742 | 742 | width: 167px; |
|
743 | 743 | margin: 0; |
|
744 | 744 | padding: 12px 9px 7px 24px; |
|
745 | 745 | } |
|
746 | 746 | |
|
747 | 747 | .groups_breadcrumbs a { |
|
748 | 748 | color: #fff; |
|
749 | 749 | } |
|
750 | 750 | |
|
751 | 751 | .groups_breadcrumbs a:hover { |
|
752 | 752 | color: #bfe3ff; |
|
753 | 753 | text-decoration: none; |
|
754 | 754 | } |
|
755 | 755 | |
|
756 | 756 | td.quick_repo_menu { |
|
757 | 757 | background: #FFF url("../images/vertical-indicator.png") 8px 50% no-repeat !important; |
|
758 | 758 | cursor: pointer; |
|
759 | 759 | width: 8px; |
|
760 | 760 | border: 1px solid transparent; |
|
761 | 761 | } |
|
762 | 762 | |
|
763 | 763 | td.quick_repo_menu.active { |
|
764 | 764 | background: url("../images/dt-arrow-dn.png") no-repeat scroll 5px 50% #FFFFFF !important; |
|
765 | 765 | border: 1px solid #003367; |
|
766 | 766 | box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); |
|
767 | 767 | cursor: pointer; |
|
768 | 768 | } |
|
769 | 769 | |
|
770 | 770 | td.quick_repo_menu .menu_items { |
|
771 | 771 | margin-top: 10px; |
|
772 | 772 | margin-left:-6px; |
|
773 | 773 | width: 150px; |
|
774 | 774 | position: absolute; |
|
775 | 775 | background-color: #FFF; |
|
776 | 776 | background: none repeat scroll 0 0 #FFFFFF; |
|
777 | 777 | border-color: #003367 #666666 #666666; |
|
778 | 778 | border-right: 1px solid #666666; |
|
779 | 779 | border-style: solid; |
|
780 | 780 | border-width: 1px; |
|
781 | 781 | box-shadow: 2px 8px 4px rgba(0, 0, 0, 0.2); |
|
782 | 782 | border-top-style: none; |
|
783 | 783 | } |
|
784 | 784 | |
|
785 | 785 | td.quick_repo_menu .menu_items li { |
|
786 | 786 | padding: 0 !important; |
|
787 | 787 | } |
|
788 | 788 | |
|
789 | 789 | td.quick_repo_menu .menu_items a { |
|
790 | 790 | display: block; |
|
791 | 791 | padding: 4px 12px 4px 8px; |
|
792 | 792 | } |
|
793 | 793 | |
|
794 | 794 | td.quick_repo_menu .menu_items a:hover { |
|
795 | 795 | background-color: #EEE; |
|
796 | 796 | text-decoration: none; |
|
797 | 797 | } |
|
798 | 798 | |
|
799 | 799 | td.quick_repo_menu .menu_items .icon img { |
|
800 | 800 | margin-bottom: -2px; |
|
801 | 801 | } |
|
802 | 802 | |
|
803 | 803 | td.quick_repo_menu .menu_items.hidden { |
|
804 | 804 | display: none; |
|
805 | 805 | } |
|
806 | 806 | |
|
807 | 807 | .yui-dt-first th { |
|
808 | 808 | text-align: left; |
|
809 | 809 | } |
|
810 | 810 | |
|
811 | 811 | /* |
|
812 | 812 | Copyright (c) 2011, Yahoo! Inc. All rights reserved. |
|
813 | 813 | Code licensed under the BSD License: |
|
814 | 814 | http://developer.yahoo.com/yui/license.html |
|
815 | 815 | version: 2.9.0 |
|
816 | 816 | */ |
|
817 | 817 | .yui-skin-sam .yui-dt-mask { |
|
818 | 818 | position: absolute; |
|
819 | 819 | z-index: 9500; |
|
820 | 820 | } |
|
821 | 821 | .yui-dt-tmp { |
|
822 | 822 | position: absolute; |
|
823 | 823 | left: -9000px; |
|
824 | 824 | } |
|
825 | 825 | .yui-dt-scrollable .yui-dt-bd { overflow: auto } |
|
826 | 826 | .yui-dt-scrollable .yui-dt-hd { |
|
827 | 827 | overflow: hidden; |
|
828 | 828 | position: relative; |
|
829 | 829 | } |
|
830 | 830 | .yui-dt-scrollable .yui-dt-bd thead tr, |
|
831 | 831 | .yui-dt-scrollable .yui-dt-bd thead th { |
|
832 | 832 | position: absolute; |
|
833 | 833 | left: -1500px; |
|
834 | 834 | } |
|
835 | 835 | .yui-dt-scrollable tbody { -moz-outline: 0 } |
|
836 | 836 | .yui-skin-sam thead .yui-dt-sortable { cursor: pointer } |
|
837 | 837 | .yui-skin-sam thead .yui-dt-draggable { cursor: move } |
|
838 | 838 | .yui-dt-coltarget { |
|
839 | 839 | position: absolute; |
|
840 | 840 | z-index: 999; |
|
841 | 841 | } |
|
842 | 842 | .yui-dt-hd { zoom: 1 } |
|
843 | 843 | th.yui-dt-resizeable .yui-dt-resizerliner { position: relative } |
|
844 | 844 | .yui-dt-resizer { |
|
845 | 845 | position: absolute; |
|
846 | 846 | right: 0; |
|
847 | 847 | bottom: 0; |
|
848 | 848 | height: 100%; |
|
849 | 849 | cursor: e-resize; |
|
850 | 850 | cursor: col-resize; |
|
851 | 851 | background-color: #CCC; |
|
852 | 852 | opacity: 0; |
|
853 | 853 | filter: alpha(opacity=0); |
|
854 | 854 | } |
|
855 | 855 | .yui-dt-resizerproxy { |
|
856 | 856 | visibility: hidden; |
|
857 | 857 | position: absolute; |
|
858 | 858 | z-index: 9000; |
|
859 | 859 | background-color: #CCC; |
|
860 | 860 | opacity: 0; |
|
861 | 861 | filter: alpha(opacity=0); |
|
862 | 862 | } |
|
863 | 863 | th.yui-dt-hidden .yui-dt-liner, |
|
864 | 864 | td.yui-dt-hidden .yui-dt-liner, |
|
865 | 865 | th.yui-dt-hidden .yui-dt-resizer { display: none } |
|
866 | 866 | .yui-dt-editor, |
|
867 | 867 | .yui-dt-editor-shim { |
|
868 | 868 | position: absolute; |
|
869 | 869 | z-index: 9000; |
|
870 | 870 | } |
|
871 | 871 | .yui-skin-sam .yui-dt table { |
|
872 | 872 | margin: 0; |
|
873 | 873 | padding: 0; |
|
874 | 874 | font-family: arial; |
|
875 | 875 | font-size: inherit; |
|
876 | 876 | border-collapse: separate; |
|
877 | 877 | *border-collapse: collapse; |
|
878 | 878 | border-spacing: 0; |
|
879 | 879 | border: 1px solid #7f7f7f; |
|
880 | 880 | } |
|
881 | 881 | .yui-skin-sam .yui-dt thead { border-spacing: 0 } |
|
882 | 882 | .yui-skin-sam .yui-dt caption { |
|
883 | 883 | color: #000; |
|
884 | 884 | font-size: 85%; |
|
885 | 885 | font-weight: normal; |
|
886 | 886 | font-style: italic; |
|
887 | 887 | line-height: 1; |
|
888 | 888 | padding: 1em 0; |
|
889 | 889 | text-align: center; |
|
890 | 890 | } |
|
891 | 891 | .yui-skin-sam .yui-dt th { background: #d8d8da url(../images/sprite.png) repeat-x 0 0 } |
|
892 | 892 | .yui-skin-sam .yui-dt th, |
|
893 | 893 | .yui-skin-sam .yui-dt th a { |
|
894 | 894 | font-weight: normal; |
|
895 | 895 | text-decoration: none; |
|
896 | 896 | color: #000; |
|
897 | 897 | vertical-align: bottom; |
|
898 | 898 | } |
|
899 | 899 | .yui-skin-sam .yui-dt th { |
|
900 | 900 | margin: 0; |
|
901 | 901 | padding: 0; |
|
902 | 902 | border: 0; |
|
903 | 903 | border-right: 1px solid #cbcbcb; |
|
904 | 904 | } |
|
905 | 905 | .yui-skin-sam .yui-dt tr.yui-dt-first td { border-top: 1px solid #7f7f7f } |
|
906 | 906 | .yui-skin-sam .yui-dt th .yui-dt-liner { white-space: nowrap } |
|
907 | 907 | .yui-skin-sam .yui-dt-liner { |
|
908 | 908 | margin: 0; |
|
909 | 909 | padding: 0; |
|
910 | 910 | } |
|
911 | 911 | .yui-skin-sam .yui-dt-coltarget { |
|
912 | 912 | width: 5px; |
|
913 | 913 | background-color: red; |
|
914 | 914 | } |
|
915 | 915 | .yui-skin-sam .yui-dt td { |
|
916 | 916 | margin: 0; |
|
917 | 917 | padding: 0; |
|
918 | 918 | border: 0; |
|
919 | 919 | border-right: 1px solid #cbcbcb; |
|
920 | 920 | text-align: left; |
|
921 | 921 | } |
|
922 | 922 | .yui-skin-sam .yui-dt-list td { border-right: 0 } |
|
923 | 923 | .yui-skin-sam .yui-dt-resizer { width: 6px } |
|
924 | 924 | .yui-skin-sam .yui-dt-mask { |
|
925 | 925 | background-color: #000; |
|
926 | 926 | opacity: .25; |
|
927 | 927 | filter: alpha(opacity=25); |
|
928 | 928 | } |
|
929 | 929 | .yui-skin-sam .yui-dt-message { background-color: #FFF } |
|
930 | 930 | .yui-skin-sam .yui-dt-scrollable table { border: 0 } |
|
931 | 931 | .yui-skin-sam .yui-dt-scrollable .yui-dt-hd { |
|
932 | 932 | border-left: 1px solid #7f7f7f; |
|
933 | 933 | border-top: 1px solid #7f7f7f; |
|
934 | 934 | border-right: 1px solid #7f7f7f; |
|
935 | 935 | } |
|
936 | 936 | .yui-skin-sam .yui-dt-scrollable .yui-dt-bd { |
|
937 | 937 | border-left: 1px solid #7f7f7f; |
|
938 | 938 | border-bottom: 1px solid #7f7f7f; |
|
939 | 939 | border-right: 1px solid #7f7f7f; |
|
940 | 940 | background-color: #FFF; |
|
941 | 941 | } |
|
942 | 942 | .yui-skin-sam .yui-dt-scrollable .yui-dt-data tr.yui-dt-last td { border-bottom: 1px solid #7f7f7f } |
|
943 | 943 | .yui-skin-sam th.yui-dt-asc, |
|
944 | 944 | .yui-skin-sam th.yui-dt-desc { background: url(../images/sprite.png) repeat-x 0 -100px } |
|
945 | 945 | .yui-skin-sam th.yui-dt-sortable .yui-dt-label { margin-right: 10px } |
|
946 | 946 | .yui-skin-sam th.yui-dt-asc .yui-dt-liner { background: url(../images/dt-arrow-up.png) no-repeat right } |
|
947 | 947 | .yui-skin-sam th.yui-dt-desc .yui-dt-liner { background: url(../images/dt-arrow-dn.png) no-repeat right } |
|
948 | 948 | tbody .yui-dt-editable { cursor: pointer } |
|
949 | 949 | .yui-dt-editor { |
|
950 | 950 | text-align: left; |
|
951 | 951 | background-color: #f2f2f2; |
|
952 | 952 | border: 1px solid #808080; |
|
953 | 953 | padding: 6px; |
|
954 | 954 | } |
|
955 | 955 | .yui-dt-editor label { |
|
956 | 956 | padding-left: 4px; |
|
957 | 957 | padding-right: 6px; |
|
958 | 958 | } |
|
959 | 959 | .yui-dt-editor .yui-dt-button { |
|
960 | 960 | padding-top: 6px; |
|
961 | 961 | text-align: right; |
|
962 | 962 | } |
|
963 | 963 | .yui-dt-editor .yui-dt-button button { |
|
964 | 964 | background: url(../images/sprite.png) repeat-x 0 0; |
|
965 | 965 | border: 1px solid #999; |
|
966 | 966 | width: 4em; |
|
967 | 967 | height: 1.8em; |
|
968 | 968 | margin-left: 6px; |
|
969 | 969 | } |
|
970 | 970 | .yui-dt-editor .yui-dt-button button.yui-dt-default { |
|
971 | 971 | background: url(../images/sprite.png) repeat-x 0 -1400px; |
|
972 | 972 | background-color: #5584e0; |
|
973 | 973 | border: 1px solid #304369; |
|
974 | 974 | color: #FFF; |
|
975 | 975 | } |
|
976 | 976 | .yui-dt-editor .yui-dt-button button:hover { |
|
977 | 977 | background: url(../images/sprite.png) repeat-x 0 -1300px; |
|
978 | 978 | color: #000; |
|
979 | 979 | } |
|
980 | 980 | .yui-dt-editor .yui-dt-button button:active { |
|
981 | 981 | background: url(../images/sprite.png) repeat-x 0 -1700px; |
|
982 | 982 | color: #000; |
|
983 | 983 | } |
|
984 | 984 | .yui-skin-sam tr.yui-dt-even { background-color: #FFF } |
|
985 | 985 | .yui-skin-sam tr.yui-dt-odd { background-color: #edf5ff } |
|
986 | 986 | .yui-skin-sam tr.yui-dt-even td.yui-dt-asc, |
|
987 | 987 | .yui-skin-sam tr.yui-dt-even td.yui-dt-desc { background-color: #edf5ff } |
|
988 | 988 | .yui-skin-sam tr.yui-dt-odd td.yui-dt-asc, |
|
989 | 989 | .yui-skin-sam tr.yui-dt-odd td.yui-dt-desc { background-color: #dbeaff } |
|
990 | 990 | .yui-skin-sam .yui-dt-list tr.yui-dt-even { background-color: #FFF } |
|
991 | 991 | .yui-skin-sam .yui-dt-list tr.yui-dt-odd { background-color: #FFF } |
|
992 | 992 | .yui-skin-sam .yui-dt-list tr.yui-dt-even td.yui-dt-asc, |
|
993 | 993 | .yui-skin-sam .yui-dt-list tr.yui-dt-even td.yui-dt-desc { background-color: #edf5ff } |
|
994 | 994 | .yui-skin-sam .yui-dt-list tr.yui-dt-odd td.yui-dt-asc, |
|
995 | 995 | .yui-skin-sam .yui-dt-list tr.yui-dt-odd td.yui-dt-desc { background-color: #edf5ff } |
|
996 | 996 | .yui-skin-sam th.yui-dt-highlighted, |
|
997 | 997 | .yui-skin-sam th.yui-dt-highlighted a { background-color: #b2d2ff } |
|
998 | 998 | .yui-skin-sam tr.yui-dt-highlighted, |
|
999 | 999 | .yui-skin-sam tr.yui-dt-highlighted td.yui-dt-asc, |
|
1000 | 1000 | .yui-skin-sam tr.yui-dt-highlighted td.yui-dt-desc, |
|
1001 | 1001 | .yui-skin-sam tr.yui-dt-even td.yui-dt-highlighted, |
|
1002 | 1002 | .yui-skin-sam tr.yui-dt-odd td.yui-dt-highlighted { |
|
1003 | 1003 | cursor: pointer; |
|
1004 | 1004 | background-color: #b2d2ff; |
|
1005 | 1005 | } |
|
1006 | 1006 | .yui-skin-sam .yui-dt-list th.yui-dt-highlighted, |
|
1007 | 1007 | .yui-skin-sam .yui-dt-list th.yui-dt-highlighted a { background-color: #b2d2ff } |
|
1008 | 1008 | .yui-skin-sam .yui-dt-list tr.yui-dt-highlighted, |
|
1009 | 1009 | .yui-skin-sam .yui-dt-list tr.yui-dt-highlighted td.yui-dt-asc, |
|
1010 | 1010 | .yui-skin-sam .yui-dt-list tr.yui-dt-highlighted td.yui-dt-desc, |
|
1011 | 1011 | .yui-skin-sam .yui-dt-list tr.yui-dt-even td.yui-dt-highlighted, |
|
1012 | 1012 | .yui-skin-sam .yui-dt-list tr.yui-dt-odd td.yui-dt-highlighted { |
|
1013 | 1013 | cursor: pointer; |
|
1014 | 1014 | background-color: #b2d2ff; |
|
1015 | 1015 | } |
|
1016 | 1016 | .yui-skin-sam th.yui-dt-selected, |
|
1017 | 1017 | .yui-skin-sam th.yui-dt-selected a { background-color: #446cd7 } |
|
1018 | 1018 | .yui-skin-sam tr.yui-dt-selected td, |
|
1019 | 1019 | .yui-skin-sam tr.yui-dt-selected td.yui-dt-asc, |
|
1020 | 1020 | .yui-skin-sam tr.yui-dt-selected td.yui-dt-desc { |
|
1021 | 1021 | background-color: #426fd9; |
|
1022 | 1022 | color: #FFF; |
|
1023 | 1023 | } |
|
1024 | 1024 | .yui-skin-sam tr.yui-dt-even td.yui-dt-selected, |
|
1025 | 1025 | .yui-skin-sam tr.yui-dt-odd td.yui-dt-selected { |
|
1026 | 1026 | background-color: #446cd7; |
|
1027 | 1027 | color: #FFF; |
|
1028 | 1028 | } |
|
1029 | 1029 | .yui-skin-sam .yui-dt-list th.yui-dt-selected, |
|
1030 | 1030 | .yui-skin-sam .yui-dt-list th.yui-dt-selected a { background-color: #446cd7 } |
|
1031 | 1031 | .yui-skin-sam .yui-dt-list tr.yui-dt-selected td, |
|
1032 | 1032 | .yui-skin-sam .yui-dt-list tr.yui-dt-selected td.yui-dt-asc, |
|
1033 | 1033 | .yui-skin-sam .yui-dt-list tr.yui-dt-selected td.yui-dt-desc { |
|
1034 | 1034 | background-color: #426fd9; |
|
1035 | 1035 | color: #FFF; |
|
1036 | 1036 | } |
|
1037 | 1037 | .yui-skin-sam .yui-dt-list tr.yui-dt-even td.yui-dt-selected, |
|
1038 | 1038 | .yui-skin-sam .yui-dt-list tr.yui-dt-odd td.yui-dt-selected { |
|
1039 | 1039 | background-color: #446cd7; |
|
1040 | 1040 | color: #FFF; |
|
1041 | 1041 | } |
|
1042 | 1042 | .yui-skin-sam .yui-dt-paginator { |
|
1043 | 1043 | display: block; |
|
1044 | 1044 | margin: 6px 0; |
|
1045 | 1045 | white-space: nowrap; |
|
1046 | 1046 | } |
|
1047 | 1047 | .yui-skin-sam .yui-dt-paginator .yui-dt-first, |
|
1048 | 1048 | .yui-skin-sam .yui-dt-paginator .yui-dt-last, |
|
1049 | 1049 | .yui-skin-sam .yui-dt-paginator .yui-dt-selected { padding: 2px 6px } |
|
1050 | 1050 | .yui-skin-sam .yui-dt-paginator a.yui-dt-first, |
|
1051 | 1051 | .yui-skin-sam .yui-dt-paginator a.yui-dt-last { text-decoration: none } |
|
1052 | 1052 | .yui-skin-sam .yui-dt-paginator .yui-dt-previous, |
|
1053 | 1053 | .yui-skin-sam .yui-dt-paginator .yui-dt-next { display: none } |
|
1054 | 1054 | .yui-skin-sam a.yui-dt-page { |
|
1055 | 1055 | border: 1px solid #cbcbcb; |
|
1056 | 1056 | padding: 2px 6px; |
|
1057 | 1057 | text-decoration: none; |
|
1058 | 1058 | background-color: #fff; |
|
1059 | 1059 | } |
|
1060 | 1060 | .yui-skin-sam .yui-dt-selected { |
|
1061 | 1061 | border: 1px solid #fff; |
|
1062 | 1062 | background-color: #fff; |
|
1063 | 1063 | } |
|
1064 | 1064 | |
|
1065 | 1065 | #content #left { |
|
1066 | 1066 | left: 0; |
|
1067 | 1067 | width: 280px; |
|
1068 | 1068 | position: absolute; |
|
1069 | 1069 | } |
|
1070 | 1070 | |
|
1071 | 1071 | #content #right { |
|
1072 | 1072 | margin: 0 60px 10px 290px; |
|
1073 | 1073 | } |
|
1074 | 1074 | |
|
1075 | 1075 | #content div.box { |
|
1076 | 1076 | clear: both; |
|
1077 | 1077 | overflow: hidden; |
|
1078 | 1078 | background: #fff; |
|
1079 | 1079 | margin: 0 0 10px; |
|
1080 | 1080 | padding: 0 0 10px; |
|
1081 | 1081 | -webkit-border-radius: 4px 4px 4px 4px; |
|
1082 | 1082 | -khtml-border-radius: 4px 4px 4px 4px; |
|
1083 | 1083 | -moz-border-radius: 4px 4px 4px 4px; |
|
1084 | 1084 | border-radius: 4px 4px 4px 4px; |
|
1085 | 1085 | box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6); |
|
1086 | 1086 | } |
|
1087 | 1087 | |
|
1088 | 1088 | #content div.box-left { |
|
1089 | 1089 | width: 49%; |
|
1090 | 1090 | clear: none; |
|
1091 | 1091 | float: left; |
|
1092 | 1092 | margin: 0 0 10px; |
|
1093 | 1093 | } |
|
1094 | 1094 | |
|
1095 | 1095 | #content div.box-right { |
|
1096 | 1096 | width: 49%; |
|
1097 | 1097 | clear: none; |
|
1098 | 1098 | float: right; |
|
1099 | 1099 | margin: 0 0 10px; |
|
1100 | 1100 | } |
|
1101 | 1101 | |
|
1102 | 1102 | #content div.box div.title { |
|
1103 | 1103 | clear: both; |
|
1104 | 1104 | overflow: hidden; |
|
1105 | 1105 | background-color: #003B76; |
|
1106 | 1106 | background-repeat: repeat-x; |
|
1107 | 1107 | background-image: -khtml-gradient(linear, left top, left bottom, from(#003B76), to(#00376E) ); |
|
1108 | 1108 | background-image: -moz-linear-gradient(top, #003b76, #00376e); |
|
1109 | 1109 | background-image: -ms-linear-gradient(top, #003b76, #00376e); |
|
1110 | 1110 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #003b76), color-stop(100%, #00376e) ); |
|
1111 | 1111 | background-image: -webkit-linear-gradient(top, #003b76, #00376e); |
|
1112 | 1112 | background-image: -o-linear-gradient(top, #003b76, #00376e); |
|
1113 | 1113 | background-image: linear-gradient(top, #003b76, #00376e); |
|
1114 | 1114 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#003b76', endColorstr='#00376e', GradientType=0 ); |
|
1115 | 1115 | margin: 0 0 20px; |
|
1116 | 1116 | padding: 0; |
|
1117 | 1117 | } |
|
1118 | 1118 | |
|
1119 | 1119 | #content div.box div.title h5 { |
|
1120 | 1120 | float: left; |
|
1121 | 1121 | border: none; |
|
1122 | 1122 | color: #fff; |
|
1123 | 1123 | text-transform: uppercase; |
|
1124 | 1124 | margin: 0; |
|
1125 | 1125 | padding: 11px 0 11px 10px; |
|
1126 | 1126 | } |
|
1127 | 1127 | |
|
1128 | 1128 | #content div.box div.title .link-white{ |
|
1129 | 1129 | color: #FFFFFF; |
|
1130 | 1130 | } |
|
1131 | 1131 | |
|
1132 | 1132 | #content div.box div.title .link-white.current{ |
|
1133 | 1133 | color: #BFE3FF; |
|
1134 | 1134 | } |
|
1135 | 1135 | |
|
1136 | 1136 | #content div.box div.title ul.links li { |
|
1137 | 1137 | list-style: none; |
|
1138 | 1138 | float: left; |
|
1139 | 1139 | margin: 0; |
|
1140 | 1140 | padding: 0; |
|
1141 | 1141 | } |
|
1142 | 1142 | |
|
1143 | 1143 | #content div.box div.title ul.links li a { |
|
1144 | 1144 | border-left: 1px solid #316293; |
|
1145 | 1145 | color: #FFFFFF; |
|
1146 | 1146 | display: block; |
|
1147 | 1147 | float: left; |
|
1148 | 1148 | font-size: 13px; |
|
1149 | 1149 | font-weight: 700; |
|
1150 | 1150 | height: 1%; |
|
1151 | 1151 | margin: 0; |
|
1152 | 1152 | padding: 11px 22px 12px; |
|
1153 | 1153 | text-decoration: none; |
|
1154 | 1154 | } |
|
1155 | 1155 | |
|
1156 | 1156 | #content div.box h1,#content div.box h2,#content div.box h3,#content div.box h4,#content div.box h5,#content div.box h6, |
|
1157 | 1157 | #content div.box div.h1,#content div.box div.h2,#content div.box div.h3,#content div.box div.h4,#content div.box div.h5,#content div.box div.h6 |
|
1158 | 1158 | |
|
1159 | 1159 | { |
|
1160 | 1160 | clear: both; |
|
1161 | 1161 | overflow: hidden; |
|
1162 | 1162 | border-bottom: 1px solid #DDD; |
|
1163 | 1163 | margin: 10px 20px; |
|
1164 | 1164 | padding: 0 0 15px; |
|
1165 | 1165 | } |
|
1166 | 1166 | |
|
1167 | 1167 | #content div.box p { |
|
1168 | 1168 | color: #5f5f5f; |
|
1169 | 1169 | font-size: 12px; |
|
1170 | 1170 | line-height: 150%; |
|
1171 | 1171 | margin: 0 24px 10px; |
|
1172 | 1172 | padding: 0; |
|
1173 | 1173 | } |
|
1174 | 1174 | |
|
1175 | 1175 | #content div.box blockquote { |
|
1176 | 1176 | border-left: 4px solid #DDD; |
|
1177 | 1177 | color: #5f5f5f; |
|
1178 | 1178 | font-size: 11px; |
|
1179 | 1179 | line-height: 150%; |
|
1180 | 1180 | margin: 0 34px; |
|
1181 | 1181 | padding: 0 0 0 14px; |
|
1182 | 1182 | } |
|
1183 | 1183 | |
|
1184 | 1184 | #content div.box blockquote p { |
|
1185 | 1185 | margin: 10px 0; |
|
1186 | 1186 | padding: 0; |
|
1187 | 1187 | } |
|
1188 | 1188 | |
|
1189 | 1189 | #content div.box dl { |
|
1190 | 1190 | margin: 10px 0px; |
|
1191 | 1191 | } |
|
1192 | 1192 | |
|
1193 | 1193 | #content div.box dt { |
|
1194 | 1194 | font-size: 12px; |
|
1195 | 1195 | margin: 0; |
|
1196 | 1196 | } |
|
1197 | 1197 | |
|
1198 | 1198 | #content div.box dd { |
|
1199 | 1199 | font-size: 12px; |
|
1200 | 1200 | margin: 0; |
|
1201 | 1201 | padding: 8px 0 8px 15px; |
|
1202 | 1202 | } |
|
1203 | 1203 | |
|
1204 | 1204 | #content div.box li { |
|
1205 | 1205 | font-size: 12px; |
|
1206 | 1206 | padding: 4px 0; |
|
1207 | 1207 | } |
|
1208 | 1208 | |
|
1209 | 1209 | #content div.box ul.disc,#content div.box ul.circle { |
|
1210 | 1210 | margin: 10px 24px 10px 38px; |
|
1211 | 1211 | } |
|
1212 | 1212 | |
|
1213 | 1213 | #content div.box ul.square { |
|
1214 | 1214 | margin: 10px 24px 10px 40px; |
|
1215 | 1215 | } |
|
1216 | 1216 | |
|
1217 | 1217 | #content div.box img.left { |
|
1218 | 1218 | border: none; |
|
1219 | 1219 | float: left; |
|
1220 | 1220 | margin: 10px 10px 10px 0; |
|
1221 | 1221 | } |
|
1222 | 1222 | |
|
1223 | 1223 | #content div.box img.right { |
|
1224 | 1224 | border: none; |
|
1225 | 1225 | float: right; |
|
1226 | 1226 | margin: 10px 0 10px 10px; |
|
1227 | 1227 | } |
|
1228 | 1228 | |
|
1229 | 1229 | #content div.box div.messages { |
|
1230 | 1230 | clear: both; |
|
1231 | 1231 | overflow: hidden; |
|
1232 | 1232 | margin: 0 20px; |
|
1233 | 1233 | padding: 0; |
|
1234 | 1234 | } |
|
1235 | 1235 | |
|
1236 | 1236 | #content div.box div.message { |
|
1237 | 1237 | clear: both; |
|
1238 | 1238 | overflow: hidden; |
|
1239 | 1239 | margin: 0; |
|
1240 | 1240 | padding: 5px 0; |
|
1241 | 1241 | white-space: pre-wrap; |
|
1242 | 1242 | } |
|
1243 | 1243 | #content div.box div.expand { |
|
1244 | 1244 | width: 110%; |
|
1245 | 1245 | height:14px; |
|
1246 | 1246 | font-size:10px; |
|
1247 | 1247 | text-align:center; |
|
1248 | 1248 | cursor: pointer; |
|
1249 | 1249 | color:#666; |
|
1250 | 1250 | |
|
1251 | 1251 | background:-webkit-gradient(linear,0% 50%,100% 50%,color-stop(0%,rgba(255,255,255,0)),color-stop(100%,rgba(64,96,128,0.1))); |
|
1252 | 1252 | background:-webkit-linear-gradient(top,rgba(255,255,255,0),rgba(64,96,128,0.1)); |
|
1253 | 1253 | background:-moz-linear-gradient(top,rgba(255,255,255,0),rgba(64,96,128,0.1)); |
|
1254 | 1254 | background:-o-linear-gradient(top,rgba(255,255,255,0),rgba(64,96,128,0.1)); |
|
1255 | 1255 | background:-ms-linear-gradient(top,rgba(255,255,255,0),rgba(64,96,128,0.1)); |
|
1256 | 1256 | background:linear-gradient(top,rgba(255,255,255,0),rgba(64,96,128,0.1)); |
|
1257 | 1257 | |
|
1258 | 1258 | display: none; |
|
1259 | 1259 | } |
|
1260 | 1260 | #content div.box div.expand .expandtext { |
|
1261 | 1261 | background-color: #ffffff; |
|
1262 | 1262 | padding: 2px; |
|
1263 | 1263 | border-radius: 2px; |
|
1264 | 1264 | } |
|
1265 | 1265 | |
|
1266 | 1266 | #content div.box div.message a { |
|
1267 | 1267 | font-weight: 400 !important; |
|
1268 | 1268 | } |
|
1269 | 1269 | |
|
1270 | 1270 | #content div.box div.message div.image { |
|
1271 | 1271 | float: left; |
|
1272 | 1272 | margin: 9px 0 0 5px; |
|
1273 | 1273 | padding: 6px; |
|
1274 | 1274 | } |
|
1275 | 1275 | |
|
1276 | 1276 | #content div.box div.message div.image img { |
|
1277 | 1277 | vertical-align: middle; |
|
1278 | 1278 | margin: 0; |
|
1279 | 1279 | } |
|
1280 | 1280 | |
|
1281 | 1281 | #content div.box div.message div.text { |
|
1282 | 1282 | float: left; |
|
1283 | 1283 | margin: 0; |
|
1284 | 1284 | padding: 9px 6px; |
|
1285 | 1285 | } |
|
1286 | 1286 | |
|
1287 | 1287 | #content div.box div.message div.dismiss a { |
|
1288 | 1288 | height: 16px; |
|
1289 | 1289 | width: 16px; |
|
1290 | 1290 | display: block; |
|
1291 | 1291 | background: url("../images/icons/cross.png") no-repeat; |
|
1292 | 1292 | margin: 15px 14px 0 0; |
|
1293 | 1293 | padding: 0; |
|
1294 | 1294 | } |
|
1295 | 1295 | |
|
1296 | 1296 | #content div.box div.message div.text h1,#content div.box div.message div.text h2,#content div.box div.message div.text h3,#content div.box div.message div.text h4,#content div.box div.message div.text h5,#content div.box div.message div.text h6 |
|
1297 | 1297 | { |
|
1298 | 1298 | border: none; |
|
1299 | 1299 | margin: 0; |
|
1300 | 1300 | padding: 0; |
|
1301 | 1301 | } |
|
1302 | 1302 | |
|
1303 | 1303 | #content div.box div.message div.text span { |
|
1304 | 1304 | height: 1%; |
|
1305 | 1305 | display: block; |
|
1306 | 1306 | margin: 0; |
|
1307 | 1307 | padding: 5px 0 0; |
|
1308 | 1308 | } |
|
1309 | 1309 | |
|
1310 | 1310 | #content div.box div.message-error { |
|
1311 | 1311 | height: 1%; |
|
1312 | 1312 | clear: both; |
|
1313 | 1313 | overflow: hidden; |
|
1314 | 1314 | background: #FBE3E4; |
|
1315 | 1315 | border: 1px solid #FBC2C4; |
|
1316 | 1316 | color: #860006; |
|
1317 | 1317 | } |
|
1318 | 1318 | |
|
1319 | 1319 | #content div.box div.message-error h6 { |
|
1320 | 1320 | color: #860006; |
|
1321 | 1321 | } |
|
1322 | 1322 | |
|
1323 | 1323 | #content div.box div.message-warning { |
|
1324 | 1324 | height: 1%; |
|
1325 | 1325 | clear: both; |
|
1326 | 1326 | overflow: hidden; |
|
1327 | 1327 | background: #FFF6BF; |
|
1328 | 1328 | border: 1px solid #FFD324; |
|
1329 | 1329 | color: #5f5200; |
|
1330 | 1330 | } |
|
1331 | 1331 | |
|
1332 | 1332 | #content div.box div.message-warning h6 { |
|
1333 | 1333 | color: #5f5200; |
|
1334 | 1334 | } |
|
1335 | 1335 | |
|
1336 | 1336 | #content div.box div.message-notice { |
|
1337 | 1337 | height: 1%; |
|
1338 | 1338 | clear: both; |
|
1339 | 1339 | overflow: hidden; |
|
1340 | 1340 | background: #8FBDE0; |
|
1341 | 1341 | border: 1px solid #6BACDE; |
|
1342 | 1342 | color: #003863; |
|
1343 | 1343 | } |
|
1344 | 1344 | |
|
1345 | 1345 | #content div.box div.message-notice h6 { |
|
1346 | 1346 | color: #003863; |
|
1347 | 1347 | } |
|
1348 | 1348 | |
|
1349 | 1349 | #content div.box div.message-success { |
|
1350 | 1350 | height: 1%; |
|
1351 | 1351 | clear: both; |
|
1352 | 1352 | overflow: hidden; |
|
1353 | 1353 | background: #E6EFC2; |
|
1354 | 1354 | border: 1px solid #C6D880; |
|
1355 | 1355 | color: #4e6100; |
|
1356 | 1356 | } |
|
1357 | 1357 | |
|
1358 | 1358 | #content div.box div.message-success h6 { |
|
1359 | 1359 | color: #4e6100; |
|
1360 | 1360 | } |
|
1361 | 1361 | |
|
1362 | 1362 | #content div.box div.form div.fields div.field { |
|
1363 | 1363 | height: 1%; |
|
1364 | 1364 | border-bottom: 1px solid #DDD; |
|
1365 | 1365 | clear: both; |
|
1366 | 1366 | margin: 0; |
|
1367 | 1367 | padding: 10px 0; |
|
1368 | 1368 | } |
|
1369 | 1369 | |
|
1370 | 1370 | #content div.box div.form div.fields div.field-first { |
|
1371 | 1371 | padding: 0 0 10px; |
|
1372 | 1372 | } |
|
1373 | 1373 | |
|
1374 | 1374 | #content div.box div.form div.fields div.field-noborder { |
|
1375 | 1375 | border-bottom: 0 !important; |
|
1376 | 1376 | } |
|
1377 | 1377 | |
|
1378 | 1378 | #content div.box div.form div.fields div.field span.error-message { |
|
1379 | 1379 | height: 1%; |
|
1380 | 1380 | display: inline-block; |
|
1381 | 1381 | color: red; |
|
1382 | 1382 | margin: 8px 0 0 4px; |
|
1383 | 1383 | padding: 0; |
|
1384 | 1384 | } |
|
1385 | 1385 | |
|
1386 | 1386 | #content div.box div.form div.fields div.field span.success { |
|
1387 | 1387 | height: 1%; |
|
1388 | 1388 | display: block; |
|
1389 | 1389 | color: #316309; |
|
1390 | 1390 | margin: 8px 0 0; |
|
1391 | 1391 | padding: 0; |
|
1392 | 1392 | } |
|
1393 | 1393 | |
|
1394 | 1394 | #content div.box div.form div.fields div.field div.label { |
|
1395 | 1395 | left: 70px; |
|
1396 | 1396 | width: 155px; |
|
1397 | 1397 | position: absolute; |
|
1398 | 1398 | margin: 0; |
|
1399 | 1399 | padding: 5px 0 0 0px; |
|
1400 | 1400 | } |
|
1401 | 1401 | |
|
1402 | 1402 | #content div.box div.form div.fields div.field div.label-summary { |
|
1403 | 1403 | left: 30px; |
|
1404 | 1404 | width: 155px; |
|
1405 | 1405 | position: absolute; |
|
1406 | 1406 | margin: 0; |
|
1407 | 1407 | padding: 0px 0 0 0px; |
|
1408 | 1408 | } |
|
1409 | 1409 | |
|
1410 | 1410 | #content div.box-left div.form div.fields div.field div.label, |
|
1411 | 1411 | #content div.box-right div.form div.fields div.field div.label, |
|
1412 | 1412 | #content div.box-left div.form div.fields div.field div.label, |
|
1413 | 1413 | #content div.box-left div.form div.fields div.field div.label-summary, |
|
1414 | 1414 | #content div.box-right div.form div.fields div.field div.label-summary, |
|
1415 | 1415 | #content div.box-left div.form div.fields div.field div.label-summary |
|
1416 | 1416 | { |
|
1417 | 1417 | clear: both; |
|
1418 | 1418 | overflow: hidden; |
|
1419 | 1419 | left: 0; |
|
1420 | 1420 | width: auto; |
|
1421 | 1421 | position: relative; |
|
1422 | 1422 | margin: 0; |
|
1423 | 1423 | padding: 0 0 8px; |
|
1424 | 1424 | } |
|
1425 | 1425 | |
|
1426 | 1426 | #content div.box div.form div.fields div.field div.label-select { |
|
1427 | 1427 | padding: 5px 0 0 5px; |
|
1428 | 1428 | } |
|
1429 | 1429 | |
|
1430 | 1430 | #content div.box-left div.form div.fields div.field div.label-select, |
|
1431 | 1431 | #content div.box-right div.form div.fields div.field div.label-select |
|
1432 | 1432 | { |
|
1433 | 1433 | padding: 0 0 8px; |
|
1434 | 1434 | } |
|
1435 | 1435 | |
|
1436 | 1436 | #content div.box-left div.form div.fields div.field div.label-textarea, |
|
1437 | 1437 | #content div.box-right div.form div.fields div.field div.label-textarea |
|
1438 | 1438 | { |
|
1439 | 1439 | padding: 0 0 8px !important; |
|
1440 | 1440 | } |
|
1441 | 1441 | |
|
1442 | 1442 | #content div.box div.form div.fields div.field div.label label,div.label label |
|
1443 | 1443 | { |
|
1444 | 1444 | color: #393939; |
|
1445 | 1445 | font-weight: 700; |
|
1446 | 1446 | } |
|
1447 | 1447 | #content div.box div.form div.fields div.field div.label label,div.label-summary label |
|
1448 | 1448 | { |
|
1449 | 1449 | color: #393939; |
|
1450 | 1450 | font-weight: 700; |
|
1451 | 1451 | } |
|
1452 | 1452 | #content div.box div.form div.fields div.field div.input { |
|
1453 | 1453 | margin: 0 0 0 200px; |
|
1454 | 1454 | } |
|
1455 | 1455 | |
|
1456 | 1456 | #content div.box div.form div.fields div.field div.input.summary { |
|
1457 | 1457 | margin: 0 0 0 110px; |
|
1458 | 1458 | } |
|
1459 | 1459 | #content div.box div.form div.fields div.field div.input.summary-short { |
|
1460 | 1460 | margin: 0 0 0 110px; |
|
1461 | 1461 | } |
|
1462 | 1462 | #content div.box div.form div.fields div.field div.file { |
|
1463 | 1463 | margin: 0 0 0 200px; |
|
1464 | 1464 | } |
|
1465 | 1465 | |
|
1466 | 1466 | #content div.box-left div.form div.fields div.field div.input,#content div.box-right div.form div.fields div.field div.input |
|
1467 | 1467 | { |
|
1468 | 1468 | margin: 0 0 0 0px; |
|
1469 | 1469 | } |
|
1470 | 1470 | |
|
1471 | 1471 | #content div.box div.form div.fields div.field div.input input, |
|
1472 | 1472 | .reviewer_ac input { |
|
1473 | 1473 | background: #FFF; |
|
1474 | 1474 | border-top: 1px solid #b3b3b3; |
|
1475 | 1475 | border-left: 1px solid #b3b3b3; |
|
1476 | 1476 | border-right: 1px solid #eaeaea; |
|
1477 | 1477 | border-bottom: 1px solid #eaeaea; |
|
1478 | 1478 | color: #000; |
|
1479 | 1479 | font-size: 11px; |
|
1480 | 1480 | margin: 0; |
|
1481 | 1481 | padding: 7px 7px 6px; |
|
1482 | 1482 | } |
|
1483 | 1483 | |
|
1484 | 1484 | #content div.box div.form div.fields div.field div.input input#clone_url, |
|
1485 | 1485 | #content div.box div.form div.fields div.field div.input input#clone_url_id |
|
1486 | 1486 | { |
|
1487 | 1487 | font-size: 16px; |
|
1488 | 1488 | padding: 2px; |
|
1489 | 1489 | } |
|
1490 | 1490 | |
|
1491 | 1491 | #content div.box div.form div.fields div.field div.file input { |
|
1492 | 1492 | background: none repeat scroll 0 0 #FFFFFF; |
|
1493 | 1493 | border-color: #B3B3B3 #EAEAEA #EAEAEA #B3B3B3; |
|
1494 | 1494 | border-style: solid; |
|
1495 | 1495 | border-width: 1px; |
|
1496 | 1496 | color: #000000; |
|
1497 | 1497 | font-size: 11px; |
|
1498 | 1498 | margin: 0; |
|
1499 | 1499 | padding: 7px 7px 6px; |
|
1500 | 1500 | } |
|
1501 | 1501 | |
|
1502 | 1502 | input.disabled { |
|
1503 | 1503 | background-color: #F5F5F5 !important; |
|
1504 | 1504 | } |
|
1505 | 1505 | #content div.box div.form div.fields div.field div.input input.small { |
|
1506 | 1506 | width: 30%; |
|
1507 | 1507 | } |
|
1508 | 1508 | |
|
1509 | 1509 | #content div.box div.form div.fields div.field div.input input.medium { |
|
1510 | 1510 | width: 55%; |
|
1511 | 1511 | } |
|
1512 | 1512 | |
|
1513 | 1513 | #content div.box div.form div.fields div.field div.input input.large { |
|
1514 | 1514 | width: 85%; |
|
1515 | 1515 | } |
|
1516 | 1516 | |
|
1517 | 1517 | #content div.box div.form div.fields div.field div.input input.date { |
|
1518 | 1518 | width: 177px; |
|
1519 | 1519 | } |
|
1520 | 1520 | |
|
1521 | 1521 | #content div.box div.form div.fields div.field div.input input.button { |
|
1522 | 1522 | background: #D4D0C8; |
|
1523 | 1523 | border-top: 1px solid #FFF; |
|
1524 | 1524 | border-left: 1px solid #FFF; |
|
1525 | 1525 | border-right: 1px solid #404040; |
|
1526 | 1526 | border-bottom: 1px solid #404040; |
|
1527 | 1527 | color: #000; |
|
1528 | 1528 | margin: 0; |
|
1529 | 1529 | padding: 4px 8px; |
|
1530 | 1530 | } |
|
1531 | 1531 | |
|
1532 | 1532 | #content div.box div.form div.fields div.field div.textarea { |
|
1533 | 1533 | border-top: 1px solid #b3b3b3; |
|
1534 | 1534 | border-left: 1px solid #b3b3b3; |
|
1535 | 1535 | border-right: 1px solid #eaeaea; |
|
1536 | 1536 | border-bottom: 1px solid #eaeaea; |
|
1537 | 1537 | margin: 0 0 0 200px; |
|
1538 | 1538 | padding: 10px; |
|
1539 | 1539 | } |
|
1540 | 1540 | |
|
1541 | 1541 | #content div.box div.form div.fields div.field div.textarea-editor { |
|
1542 | 1542 | border: 1px solid #ddd; |
|
1543 | 1543 | padding: 0; |
|
1544 | 1544 | } |
|
1545 | 1545 | |
|
1546 | 1546 | #content div.box div.form div.fields div.field div.textarea textarea { |
|
1547 | 1547 | width: 100%; |
|
1548 | 1548 | height: 220px; |
|
1549 | 1549 | overflow: hidden; |
|
1550 | 1550 | background: #FFF; |
|
1551 | 1551 | color: #000; |
|
1552 | 1552 | font-size: 11px; |
|
1553 | 1553 | outline: none; |
|
1554 | 1554 | border-width: 0; |
|
1555 | 1555 | margin: 0; |
|
1556 | 1556 | padding: 0; |
|
1557 | 1557 | } |
|
1558 | 1558 | |
|
1559 | 1559 | #content div.box-left div.form div.fields div.field div.textarea textarea,#content div.box-right div.form div.fields div.field div.textarea textarea |
|
1560 | 1560 | { |
|
1561 | 1561 | width: 100%; |
|
1562 | 1562 | height: 100px; |
|
1563 | 1563 | } |
|
1564 | 1564 | |
|
1565 | 1565 | #content div.box div.form div.fields div.field div.textarea table { |
|
1566 | 1566 | width: 100%; |
|
1567 | 1567 | border: none; |
|
1568 | 1568 | margin: 0; |
|
1569 | 1569 | padding: 0; |
|
1570 | 1570 | } |
|
1571 | 1571 | |
|
1572 | 1572 | #content div.box div.form div.fields div.field div.textarea table td { |
|
1573 | 1573 | background: #DDD; |
|
1574 | 1574 | border: none; |
|
1575 | 1575 | padding: 0; |
|
1576 | 1576 | } |
|
1577 | 1577 | |
|
1578 | 1578 | #content div.box div.form div.fields div.field div.textarea table td table |
|
1579 | 1579 | { |
|
1580 | 1580 | width: auto; |
|
1581 | 1581 | border: none; |
|
1582 | 1582 | margin: 0; |
|
1583 | 1583 | padding: 0; |
|
1584 | 1584 | } |
|
1585 | 1585 | |
|
1586 | 1586 | #content div.box div.form div.fields div.field div.textarea table td table td |
|
1587 | 1587 | { |
|
1588 | 1588 | font-size: 11px; |
|
1589 | 1589 | padding: 5px 5px 5px 0; |
|
1590 | 1590 | } |
|
1591 | 1591 | |
|
1592 | 1592 | #content div.box div.form div.fields div.field input[type=text]:focus, |
|
1593 | 1593 | #content div.box div.form div.fields div.field input[type=password]:focus, |
|
1594 | 1594 | #content div.box div.form div.fields div.field input[type=file]:focus, |
|
1595 | 1595 | #content div.box div.form div.fields div.field textarea:focus, |
|
1596 | 1596 | #content div.box div.form div.fields div.field select:focus, |
|
1597 | 1597 | .reviewer_ac input:focus |
|
1598 | 1598 | { |
|
1599 | 1599 | background: #f6f6f6; |
|
1600 | 1600 | border-color: #666; |
|
1601 | 1601 | } |
|
1602 | 1602 | |
|
1603 | 1603 | .reviewer_ac { |
|
1604 | 1604 | padding:10px |
|
1605 | 1605 | } |
|
1606 | 1606 | |
|
1607 | 1607 | div.form div.fields div.field div.button { |
|
1608 | 1608 | margin: 0; |
|
1609 | 1609 | padding: 0 0 0 8px; |
|
1610 | 1610 | } |
|
1611 | 1611 | #content div.box table.noborder { |
|
1612 | 1612 | border: 1px solid transparent; |
|
1613 | 1613 | } |
|
1614 | 1614 | |
|
1615 | 1615 | #content div.box table { |
|
1616 | 1616 | width: 100%; |
|
1617 | 1617 | border-collapse: separate; |
|
1618 | 1618 | margin: 0; |
|
1619 | 1619 | padding: 0; |
|
1620 | 1620 | border: 1px solid #eee; |
|
1621 | 1621 | -webkit-border-radius: 4px; |
|
1622 | 1622 | -moz-border-radius: 4px; |
|
1623 | 1623 | border-radius: 4px; |
|
1624 | 1624 | } |
|
1625 | 1625 | |
|
1626 | 1626 | #content div.box table th { |
|
1627 | 1627 | background: #eee; |
|
1628 | 1628 | border-bottom: 1px solid #ddd; |
|
1629 | 1629 | padding: 5px 0px 5px 5px; |
|
1630 | 1630 | } |
|
1631 | 1631 | |
|
1632 | 1632 | #content div.box table th.left { |
|
1633 | 1633 | text-align: left; |
|
1634 | 1634 | } |
|
1635 | 1635 | |
|
1636 | 1636 | #content div.box table th.right { |
|
1637 | 1637 | text-align: right; |
|
1638 | 1638 | } |
|
1639 | 1639 | |
|
1640 | 1640 | #content div.box table th.center { |
|
1641 | 1641 | text-align: center; |
|
1642 | 1642 | } |
|
1643 | 1643 | |
|
1644 | 1644 | #content div.box table th.selected { |
|
1645 | 1645 | vertical-align: middle; |
|
1646 | 1646 | padding: 0; |
|
1647 | 1647 | } |
|
1648 | 1648 | |
|
1649 | 1649 | #content div.box table td { |
|
1650 | 1650 | background: #fff; |
|
1651 | 1651 | border-bottom: 1px solid #cdcdcd; |
|
1652 | 1652 | vertical-align: middle; |
|
1653 | 1653 | padding: 5px; |
|
1654 | 1654 | } |
|
1655 | 1655 | |
|
1656 | 1656 | #content div.box table tr.selected td { |
|
1657 | 1657 | background: #FFC; |
|
1658 | 1658 | } |
|
1659 | 1659 | |
|
1660 | 1660 | #content div.box table td.selected { |
|
1661 | 1661 | width: 3%; |
|
1662 | 1662 | text-align: center; |
|
1663 | 1663 | vertical-align: middle; |
|
1664 | 1664 | padding: 0; |
|
1665 | 1665 | } |
|
1666 | 1666 | |
|
1667 | 1667 | #content div.box table td.action { |
|
1668 | 1668 | width: 45%; |
|
1669 | 1669 | text-align: left; |
|
1670 | 1670 | } |
|
1671 | 1671 | |
|
1672 | 1672 | #content div.box table td.date { |
|
1673 | 1673 | width: 33%; |
|
1674 | 1674 | text-align: center; |
|
1675 | 1675 | } |
|
1676 | 1676 | |
|
1677 | 1677 | #content div.box div.action { |
|
1678 | 1678 | float: right; |
|
1679 | 1679 | background: #FFF; |
|
1680 | 1680 | text-align: right; |
|
1681 | 1681 | margin: 10px 0 0; |
|
1682 | 1682 | padding: 0; |
|
1683 | 1683 | } |
|
1684 | 1684 | |
|
1685 | 1685 | #content div.box div.action select { |
|
1686 | 1686 | font-size: 11px; |
|
1687 | 1687 | margin: 0; |
|
1688 | 1688 | } |
|
1689 | 1689 | |
|
1690 | 1690 | #content div.box div.action .ui-selectmenu { |
|
1691 | 1691 | margin: 0; |
|
1692 | 1692 | padding: 0; |
|
1693 | 1693 | } |
|
1694 | 1694 | |
|
1695 | 1695 | #content div.box div.pagination { |
|
1696 | 1696 | height: 1%; |
|
1697 | 1697 | clear: both; |
|
1698 | 1698 | overflow: hidden; |
|
1699 | 1699 | margin: 10px 0 0; |
|
1700 | 1700 | padding: 0; |
|
1701 | 1701 | } |
|
1702 | 1702 | |
|
1703 | 1703 | #content div.box div.pagination ul.pager { |
|
1704 | 1704 | float: right; |
|
1705 | 1705 | text-align: right; |
|
1706 | 1706 | margin: 0; |
|
1707 | 1707 | padding: 0; |
|
1708 | 1708 | } |
|
1709 | 1709 | |
|
1710 | 1710 | #content div.box div.pagination ul.pager li { |
|
1711 | 1711 | height: 1%; |
|
1712 | 1712 | float: left; |
|
1713 | 1713 | list-style: none; |
|
1714 | 1714 | background: #ebebeb url("../images/pager.png") repeat-x; |
|
1715 | 1715 | border-top: 1px solid #dedede; |
|
1716 | 1716 | border-left: 1px solid #cfcfcf; |
|
1717 | 1717 | border-right: 1px solid #c4c4c4; |
|
1718 | 1718 | border-bottom: 1px solid #c4c4c4; |
|
1719 | 1719 | color: #4A4A4A; |
|
1720 | 1720 | font-weight: 700; |
|
1721 | 1721 | margin: 0 0 0 4px; |
|
1722 | 1722 | padding: 0; |
|
1723 | 1723 | } |
|
1724 | 1724 | |
|
1725 | 1725 | #content div.box div.pagination ul.pager li.separator { |
|
1726 | 1726 | padding: 6px; |
|
1727 | 1727 | } |
|
1728 | 1728 | |
|
1729 | 1729 | #content div.box div.pagination ul.pager li.current { |
|
1730 | 1730 | background: #b4b4b4 url("../images/pager_selected.png") repeat-x; |
|
1731 | 1731 | border-top: 1px solid #ccc; |
|
1732 | 1732 | border-left: 1px solid #bebebe; |
|
1733 | 1733 | border-right: 1px solid #b1b1b1; |
|
1734 | 1734 | border-bottom: 1px solid #afafaf; |
|
1735 | 1735 | color: #515151; |
|
1736 | 1736 | padding: 6px; |
|
1737 | 1737 | } |
|
1738 | 1738 | |
|
1739 | 1739 | #content div.box div.pagination ul.pager li a { |
|
1740 | 1740 | height: 1%; |
|
1741 | 1741 | display: block; |
|
1742 | 1742 | float: left; |
|
1743 | 1743 | color: #515151; |
|
1744 | 1744 | text-decoration: none; |
|
1745 | 1745 | margin: 0; |
|
1746 | 1746 | padding: 6px; |
|
1747 | 1747 | } |
|
1748 | 1748 | |
|
1749 | 1749 | #content div.box div.pagination ul.pager li a:hover,#content div.box div.pagination ul.pager li a:active |
|
1750 | 1750 | { |
|
1751 | 1751 | background: #b4b4b4 url("../images/pager_selected.png") repeat-x; |
|
1752 | 1752 | border-top: 1px solid #ccc; |
|
1753 | 1753 | border-left: 1px solid #bebebe; |
|
1754 | 1754 | border-right: 1px solid #b1b1b1; |
|
1755 | 1755 | border-bottom: 1px solid #afafaf; |
|
1756 | 1756 | margin: -1px; |
|
1757 | 1757 | } |
|
1758 | 1758 | |
|
1759 | 1759 | #content div.box div.pagination-wh { |
|
1760 | 1760 | height: 1%; |
|
1761 | 1761 | clear: both; |
|
1762 | 1762 | overflow: hidden; |
|
1763 | 1763 | text-align: right; |
|
1764 | 1764 | margin: 10px 0 0; |
|
1765 | 1765 | padding: 0; |
|
1766 | 1766 | } |
|
1767 | 1767 | |
|
1768 | 1768 | #content div.box div.pagination-right { |
|
1769 | 1769 | float: right; |
|
1770 | 1770 | } |
|
1771 | 1771 | |
|
1772 | 1772 | #content div.box div.pagination-wh a, |
|
1773 | 1773 | #content div.box div.pagination-wh span.pager_dotdot, |
|
1774 | 1774 | #content div.box div.pagination-wh span.yui-pg-previous, |
|
1775 | 1775 | #content div.box div.pagination-wh span.yui-pg-last, |
|
1776 | 1776 | #content div.box div.pagination-wh span.yui-pg-next, |
|
1777 | 1777 | #content div.box div.pagination-wh span.yui-pg-first |
|
1778 | 1778 | { |
|
1779 | 1779 | height: 1%; |
|
1780 | 1780 | float: left; |
|
1781 | 1781 | background: #ebebeb url("../images/pager.png") repeat-x; |
|
1782 | 1782 | border-top: 1px solid #dedede; |
|
1783 | 1783 | border-left: 1px solid #cfcfcf; |
|
1784 | 1784 | border-right: 1px solid #c4c4c4; |
|
1785 | 1785 | border-bottom: 1px solid #c4c4c4; |
|
1786 | 1786 | color: #4A4A4A; |
|
1787 | 1787 | font-weight: 700; |
|
1788 | 1788 | margin: 0 0 0 4px; |
|
1789 | 1789 | padding: 6px; |
|
1790 | 1790 | } |
|
1791 | 1791 | |
|
1792 | 1792 | #content div.box div.pagination-wh span.pager_curpage { |
|
1793 | 1793 | height: 1%; |
|
1794 | 1794 | float: left; |
|
1795 | 1795 | background: #b4b4b4 url("../images/pager_selected.png") repeat-x; |
|
1796 | 1796 | border-top: 1px solid #ccc; |
|
1797 | 1797 | border-left: 1px solid #bebebe; |
|
1798 | 1798 | border-right: 1px solid #b1b1b1; |
|
1799 | 1799 | border-bottom: 1px solid #afafaf; |
|
1800 | 1800 | color: #515151; |
|
1801 | 1801 | font-weight: 700; |
|
1802 | 1802 | margin: 0 0 0 4px; |
|
1803 | 1803 | padding: 6px; |
|
1804 | 1804 | } |
|
1805 | 1805 | |
|
1806 | 1806 | #content div.box div.pagination-wh a:hover,#content div.box div.pagination-wh a:active |
|
1807 | 1807 | { |
|
1808 | 1808 | background: #b4b4b4 url("../images/pager_selected.png") repeat-x; |
|
1809 | 1809 | border-top: 1px solid #ccc; |
|
1810 | 1810 | border-left: 1px solid #bebebe; |
|
1811 | 1811 | border-right: 1px solid #b1b1b1; |
|
1812 | 1812 | border-bottom: 1px solid #afafaf; |
|
1813 | 1813 | text-decoration: none; |
|
1814 | 1814 | } |
|
1815 | 1815 | |
|
1816 | 1816 | #content div.box div.traffic div.legend { |
|
1817 | 1817 | clear: both; |
|
1818 | 1818 | overflow: hidden; |
|
1819 | 1819 | border-bottom: 1px solid #ddd; |
|
1820 | 1820 | margin: 0 0 10px; |
|
1821 | 1821 | padding: 0 0 10px; |
|
1822 | 1822 | } |
|
1823 | 1823 | |
|
1824 | 1824 | #content div.box div.traffic div.legend h6 { |
|
1825 | 1825 | float: left; |
|
1826 | 1826 | border: none; |
|
1827 | 1827 | margin: 0; |
|
1828 | 1828 | padding: 0; |
|
1829 | 1829 | } |
|
1830 | 1830 | |
|
1831 | 1831 | #content div.box div.traffic div.legend li { |
|
1832 | 1832 | list-style: none; |
|
1833 | 1833 | float: left; |
|
1834 | 1834 | font-size: 11px; |
|
1835 | 1835 | margin: 0; |
|
1836 | 1836 | padding: 0 8px 0 4px; |
|
1837 | 1837 | } |
|
1838 | 1838 | |
|
1839 | 1839 | #content div.box div.traffic div.legend li.visits { |
|
1840 | 1840 | border-left: 12px solid #edc240; |
|
1841 | 1841 | } |
|
1842 | 1842 | |
|
1843 | 1843 | #content div.box div.traffic div.legend li.pageviews { |
|
1844 | 1844 | border-left: 12px solid #afd8f8; |
|
1845 | 1845 | } |
|
1846 | 1846 | |
|
1847 | 1847 | #content div.box div.traffic table { |
|
1848 | 1848 | width: auto; |
|
1849 | 1849 | } |
|
1850 | 1850 | |
|
1851 | 1851 | #content div.box div.traffic table td { |
|
1852 | 1852 | background: transparent; |
|
1853 | 1853 | border: none; |
|
1854 | 1854 | padding: 2px 3px 3px; |
|
1855 | 1855 | } |
|
1856 | 1856 | |
|
1857 | 1857 | #content div.box div.traffic table td.legendLabel { |
|
1858 | 1858 | padding: 0 3px 2px; |
|
1859 | 1859 | } |
|
1860 | 1860 | |
|
1861 | 1861 | #summary { |
|
1862 | 1862 | |
|
1863 | 1863 | } |
|
1864 | 1864 | |
|
1865 | 1865 | #summary .metatag { |
|
1866 | 1866 | display: inline-block; |
|
1867 | 1867 | padding: 3px 5px; |
|
1868 | 1868 | margin-bottom: 3px; |
|
1869 | 1869 | margin-right: 1px; |
|
1870 | 1870 | border-radius: 5px; |
|
1871 | 1871 | } |
|
1872 | 1872 | |
|
1873 | 1873 | #content div.box #summary p { |
|
1874 | 1874 | margin-bottom: -5px; |
|
1875 | 1875 | width: 600px; |
|
1876 | 1876 | white-space: pre-wrap; |
|
1877 | 1877 | } |
|
1878 | 1878 | |
|
1879 | 1879 | #content div.box #summary p:last-child { |
|
1880 | 1880 | margin-bottom: 9px; |
|
1881 | 1881 | } |
|
1882 | 1882 | |
|
1883 | 1883 | #content div.box #summary p:first-of-type { |
|
1884 | 1884 | margin-top: 9px; |
|
1885 | 1885 | } |
|
1886 | 1886 | |
|
1887 | 1887 | .metatag { |
|
1888 | 1888 | display: inline-block; |
|
1889 | 1889 | margin-right: 1px; |
|
1890 | 1890 | -webkit-border-radius: 4px 4px 4px 4px; |
|
1891 | 1891 | -khtml-border-radius: 4px 4px 4px 4px; |
|
1892 | 1892 | -moz-border-radius: 4px 4px 4px 4px; |
|
1893 | 1893 | border-radius: 4px 4px 4px 4px; |
|
1894 | 1894 | |
|
1895 | 1895 | border: solid 1px #9CF; |
|
1896 | 1896 | padding: 2px 3px 2px 3px !important; |
|
1897 | 1897 | background-color: #DEF; |
|
1898 | 1898 | } |
|
1899 | 1899 | |
|
1900 | 1900 | .metatag[tag="dead"] { |
|
1901 | 1901 | background-color: #E44; |
|
1902 | 1902 | } |
|
1903 | 1903 | |
|
1904 | 1904 | .metatag[tag="stale"] { |
|
1905 | 1905 | background-color: #EA4; |
|
1906 | 1906 | } |
|
1907 | 1907 | |
|
1908 | 1908 | .metatag[tag="featured"] { |
|
1909 | 1909 | background-color: #AEA; |
|
1910 | 1910 | } |
|
1911 | 1911 | |
|
1912 | 1912 | .metatag[tag="requires"] { |
|
1913 | 1913 | background-color: #9CF; |
|
1914 | 1914 | } |
|
1915 | 1915 | |
|
1916 | 1916 | .metatag[tag="recommends"] { |
|
1917 | 1917 | background-color: #BDF; |
|
1918 | 1918 | } |
|
1919 | 1919 | |
|
1920 | 1920 | .metatag[tag="lang"] { |
|
1921 | 1921 | background-color: #FAF474; |
|
1922 | 1922 | } |
|
1923 | 1923 | |
|
1924 | 1924 | .metatag[tag="license"] { |
|
1925 | 1925 | border: solid 1px #9CF; |
|
1926 | 1926 | background-color: #DEF; |
|
1927 | 1927 | target-new: tab !important; |
|
1928 | 1928 | } |
|
1929 | 1929 | .metatag[tag="see"] { |
|
1930 | 1930 | border: solid 1px #CBD; |
|
1931 | 1931 | background-color: #EDF; |
|
1932 | 1932 | } |
|
1933 | 1933 | |
|
1934 | 1934 | a.metatag[tag="license"]:hover { |
|
1935 | 1935 | background-color: #003367; |
|
1936 | 1936 | color: #FFF; |
|
1937 | 1937 | text-decoration: none; |
|
1938 | 1938 | } |
|
1939 | 1939 | |
|
1940 | 1940 | #summary .desc { |
|
1941 | 1941 | white-space: pre; |
|
1942 | 1942 | width: 100%; |
|
1943 | 1943 | } |
|
1944 | 1944 | |
|
1945 | 1945 | #summary .repo_name { |
|
1946 | 1946 | font-size: 1.6em; |
|
1947 | 1947 | font-weight: bold; |
|
1948 | 1948 | vertical-align: baseline; |
|
1949 | 1949 | clear: right |
|
1950 | 1950 | } |
|
1951 | 1951 | |
|
1952 | 1952 | #footer { |
|
1953 | 1953 | clear: both; |
|
1954 | 1954 | overflow: hidden; |
|
1955 | 1955 | text-align: right; |
|
1956 | 1956 | margin: 0; |
|
1957 | 1957 | padding: 0 10px 4px; |
|
1958 | 1958 | margin: -10px 0 0; |
|
1959 | 1959 | } |
|
1960 | 1960 | |
|
1961 | 1961 | #footer div#footer-inner { |
|
1962 | 1962 | background-color: #003B76; |
|
1963 | 1963 | background-repeat : repeat-x; |
|
1964 | 1964 | background-image : -khtml-gradient( linear, left top, left bottom, from(#003B76), to(#00376E)); |
|
1965 | 1965 | background-image : -moz-linear-gradient(top, #003b76, #00376e); |
|
1966 | 1966 | background-image : -ms-linear-gradient( top, #003b76, #00376e); |
|
1967 | 1967 | background-image : -webkit-gradient( linear, left top, left bottom, color-stop( 0%, #003b76), color-stop( 100%, #00376e)); |
|
1968 | 1968 | background-image : -webkit-linear-gradient( top, #003b76, #00376e)); |
|
1969 | 1969 | background-image : -o-linear-gradient( top, #003b76, #00376e)); |
|
1970 | 1970 | background-image : linear-gradient( top, #003b76, #00376e); |
|
1971 | 1971 | filter :progid : DXImageTransform.Microsoft.gradient ( startColorstr = '#003b76', endColorstr = '#00376e', GradientType = 0); |
|
1972 | 1972 | box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6); |
|
1973 | 1973 | -webkit-border-radius: 4px 4px 4px 4px; |
|
1974 | 1974 | -khtml-border-radius: 4px 4px 4px 4px; |
|
1975 | 1975 | -moz-border-radius: 4px 4px 4px 4px; |
|
1976 | 1976 | border-radius: 4px 4px 4px 4px; |
|
1977 | 1977 | } |
|
1978 | 1978 | |
|
1979 | 1979 | #footer div#footer-inner p { |
|
1980 | 1980 | padding: 15px 25px 15px 0; |
|
1981 | 1981 | color: #FFF; |
|
1982 | 1982 | font-weight: 700; |
|
1983 | 1983 | } |
|
1984 | 1984 | |
|
1985 | 1985 | #footer div#footer-inner .footer-link { |
|
1986 | 1986 | float: left; |
|
1987 | 1987 | padding-left: 10px; |
|
1988 | 1988 | } |
|
1989 | 1989 | |
|
1990 | 1990 | #footer div#footer-inner .footer-link a,#footer div#footer-inner .footer-link-right a |
|
1991 | 1991 | { |
|
1992 | 1992 | color: #FFF; |
|
1993 | 1993 | } |
|
1994 | 1994 | |
|
1995 | 1995 | #login div.title { |
|
1996 | 1996 | width: 420px; |
|
1997 | 1997 | clear: both; |
|
1998 | 1998 | overflow: hidden; |
|
1999 | 1999 | position: relative; |
|
2000 | 2000 | background-color: #003B76; |
|
2001 | 2001 | background-repeat : repeat-x; |
|
2002 | 2002 | background-image : -khtml-gradient( linear, left top, left bottom, from(#003B76), to(#00376E)); |
|
2003 | 2003 | background-image : -moz-linear-gradient( top, #003b76, #00376e); |
|
2004 | 2004 | background-image : -ms-linear-gradient( top, #003b76, #00376e); |
|
2005 | 2005 | background-image : -webkit-gradient( linear, left top, left bottom, color-stop( 0%, #003b76), color-stop( 100%, #00376e)); |
|
2006 | 2006 | background-image : -webkit-linear-gradient( top, #003b76, #00376e)); |
|
2007 | 2007 | background-image : -o-linear-gradient( top, #003b76, #00376e)); |
|
2008 | 2008 | background-image : linear-gradient( top, #003b76, #00376e); |
|
2009 | 2009 | filter : progid : DXImageTransform.Microsoft.gradient ( startColorstr = '#003b76', endColorstr = '#00376e', GradientType = 0); |
|
2010 | 2010 | margin: 0 auto; |
|
2011 | 2011 | padding: 0; |
|
2012 | 2012 | } |
|
2013 | 2013 | |
|
2014 | 2014 | #login div.inner { |
|
2015 | 2015 | width: 380px; |
|
2016 | 2016 | background: #FFF url("../images/login.png") no-repeat top left; |
|
2017 | 2017 | border-top: none; |
|
2018 | 2018 | border-bottom: none; |
|
2019 | 2019 | margin: 0 auto; |
|
2020 | 2020 | padding: 20px; |
|
2021 | 2021 | } |
|
2022 | 2022 | |
|
2023 | 2023 | #login div.form div.fields div.field div.label { |
|
2024 | 2024 | width: 173px; |
|
2025 | 2025 | float: left; |
|
2026 | 2026 | text-align: right; |
|
2027 | 2027 | margin: 2px 10px 0 0; |
|
2028 | 2028 | padding: 5px 0 0 5px; |
|
2029 | 2029 | } |
|
2030 | 2030 | |
|
2031 | 2031 | #login div.form div.fields div.field div.input input { |
|
2032 | 2032 | width: 176px; |
|
2033 | 2033 | background: #FFF; |
|
2034 | 2034 | border-top: 1px solid #b3b3b3; |
|
2035 | 2035 | border-left: 1px solid #b3b3b3; |
|
2036 | 2036 | border-right: 1px solid #eaeaea; |
|
2037 | 2037 | border-bottom: 1px solid #eaeaea; |
|
2038 | 2038 | color: #000; |
|
2039 | 2039 | font-size: 11px; |
|
2040 | 2040 | margin: 0; |
|
2041 | 2041 | padding: 7px 7px 6px; |
|
2042 | 2042 | } |
|
2043 | 2043 | |
|
2044 | 2044 | #login div.form div.fields div.buttons { |
|
2045 | 2045 | clear: both; |
|
2046 | 2046 | overflow: hidden; |
|
2047 | 2047 | border-top: 1px solid #DDD; |
|
2048 | 2048 | text-align: right; |
|
2049 | 2049 | margin: 0; |
|
2050 | 2050 | padding: 10px 0 0; |
|
2051 | 2051 | } |
|
2052 | 2052 | |
|
2053 | 2053 | #login div.form div.links { |
|
2054 | 2054 | clear: both; |
|
2055 | 2055 | overflow: hidden; |
|
2056 | 2056 | margin: 10px 0 0; |
|
2057 | 2057 | padding: 0 0 2px; |
|
2058 | 2058 | } |
|
2059 | 2059 | |
|
2060 | 2060 | .user-menu{ |
|
2061 | 2061 | margin: 0px !important; |
|
2062 | 2062 | float: left; |
|
2063 | 2063 | } |
|
2064 | 2064 | |
|
2065 | 2065 | .user-menu .container{ |
|
2066 | 2066 | padding:0px 4px 0px 4px; |
|
2067 | 2067 | margin: 0px 0px 0px 0px; |
|
2068 | 2068 | } |
|
2069 | 2069 | |
|
2070 | 2070 | .user-menu .gravatar{ |
|
2071 | 2071 | margin: 0px 0px 0px 0px; |
|
2072 | 2072 | cursor: pointer; |
|
2073 | 2073 | } |
|
2074 | 2074 | .user-menu .gravatar.enabled{ |
|
2075 | 2075 | background-color: #FDF784 !important; |
|
2076 | 2076 | } |
|
2077 | 2077 | .user-menu .gravatar:hover{ |
|
2078 | 2078 | background-color: #FDF784 !important; |
|
2079 | 2079 | } |
|
2080 | 2080 | #quick_login{ |
|
2081 | 2081 | min-height: 80px; |
|
2082 | 2082 | margin: 37px 0 0 -251px; |
|
2083 | 2083 | padding: 4px; |
|
2084 | 2084 | position: absolute; |
|
2085 | 2085 | width: 278px; |
|
2086 | 2086 | background-color: #003B76; |
|
2087 | 2087 | background-repeat: repeat-x; |
|
2088 | 2088 | background-image: -khtml-gradient(linear, left top, left bottom, from(#003B76), to(#00376E) ); |
|
2089 | 2089 | background-image: -moz-linear-gradient(top, #003b76, #00376e); |
|
2090 | 2090 | background-image: -ms-linear-gradient(top, #003b76, #00376e); |
|
2091 | 2091 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #003b76), color-stop(100%, #00376e) ); |
|
2092 | 2092 | background-image: -webkit-linear-gradient(top, #003b76, #00376e); |
|
2093 | 2093 | background-image: -o-linear-gradient(top, #003b76, #00376e); |
|
2094 | 2094 | background-image: linear-gradient(top, #003b76, #00376e); |
|
2095 | 2095 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#003b76', endColorstr='#00376e', GradientType=0 ); |
|
2096 | 2096 | |
|
2097 | 2097 | z-index: 999; |
|
2098 | 2098 | -webkit-border-radius: 0px 0px 4px 4px; |
|
2099 | 2099 | -khtml-border-radius: 0px 0px 4px 4px; |
|
2100 | 2100 | -moz-border-radius: 0px 0px 4px 4px; |
|
2101 | 2101 | border-radius: 0px 0px 4px 4px; |
|
2102 | 2102 | box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6); |
|
2103 | 2103 | } |
|
2104 | 2104 | #quick_login h4{ |
|
2105 | 2105 | color: #fff; |
|
2106 | 2106 | padding: 5px 0px 5px 14px; |
|
2107 | 2107 | } |
|
2108 | 2108 | |
|
2109 | 2109 | #quick_login .password_forgoten { |
|
2110 | 2110 | padding-right: 10px; |
|
2111 | 2111 | padding-top: 0px; |
|
2112 | 2112 | text-align: left; |
|
2113 | 2113 | } |
|
2114 | 2114 | |
|
2115 | 2115 | #quick_login .password_forgoten a { |
|
2116 | 2116 | font-size: 10px; |
|
2117 | 2117 | color: #fff; |
|
2118 | 2118 | } |
|
2119 | 2119 | |
|
2120 | 2120 | #quick_login .register { |
|
2121 | 2121 | padding-right: 10px; |
|
2122 | 2122 | padding-top: 5px; |
|
2123 | 2123 | text-align: left; |
|
2124 | 2124 | } |
|
2125 | 2125 | |
|
2126 | 2126 | #quick_login .register a { |
|
2127 | 2127 | font-size: 10px; |
|
2128 | 2128 | color: #fff; |
|
2129 | 2129 | } |
|
2130 | 2130 | |
|
2131 | 2131 | #quick_login .submit { |
|
2132 | 2132 | margin: -20px 0 0 0px; |
|
2133 | 2133 | position: absolute; |
|
2134 | 2134 | right: 15px; |
|
2135 | 2135 | } |
|
2136 | 2136 | |
|
2137 | 2137 | #quick_login .links_left{ |
|
2138 | 2138 | float: left; |
|
2139 | 2139 | } |
|
2140 | 2140 | #quick_login .links_right{ |
|
2141 | 2141 | float: right; |
|
2142 | 2142 | } |
|
2143 | 2143 | #quick_login .full_name{ |
|
2144 | 2144 | color: #FFFFFF; |
|
2145 | 2145 | font-weight: bold; |
|
2146 | 2146 | padding: 3px; |
|
2147 | 2147 | } |
|
2148 | 2148 | #quick_login .big_gravatar{ |
|
2149 | 2149 | padding:4px 0px 0px 6px; |
|
2150 | 2150 | } |
|
2151 | 2151 | #quick_login .inbox{ |
|
2152 | 2152 | padding:4px 0px 0px 6px; |
|
2153 | 2153 | color: #FFFFFF; |
|
2154 | 2154 | font-weight: bold; |
|
2155 | 2155 | } |
|
2156 | 2156 | #quick_login .inbox a{ |
|
2157 | 2157 | color: #FFFFFF; |
|
2158 | 2158 | } |
|
2159 | 2159 | #quick_login .email,#quick_login .email a{ |
|
2160 | 2160 | color: #FFFFFF; |
|
2161 | 2161 | padding: 3px; |
|
2162 | 2162 | |
|
2163 | 2163 | } |
|
2164 | 2164 | #quick_login .links .logout{ |
|
2165 | 2165 | |
|
2166 | 2166 | } |
|
2167 | 2167 | |
|
2168 | 2168 | #quick_login div.form div.fields { |
|
2169 | 2169 | padding-top: 2px; |
|
2170 | 2170 | padding-left: 10px; |
|
2171 | 2171 | } |
|
2172 | 2172 | |
|
2173 | 2173 | #quick_login div.form div.fields div.field { |
|
2174 | 2174 | padding: 5px; |
|
2175 | 2175 | } |
|
2176 | 2176 | |
|
2177 | 2177 | #quick_login div.form div.fields div.field div.label label { |
|
2178 | 2178 | color: #fff; |
|
2179 | 2179 | padding-bottom: 3px; |
|
2180 | 2180 | } |
|
2181 | 2181 | |
|
2182 | 2182 | #quick_login div.form div.fields div.field div.input input { |
|
2183 | 2183 | width: 236px; |
|
2184 | 2184 | background: #FFF; |
|
2185 | 2185 | border-top: 1px solid #b3b3b3; |
|
2186 | 2186 | border-left: 1px solid #b3b3b3; |
|
2187 | 2187 | border-right: 1px solid #eaeaea; |
|
2188 | 2188 | border-bottom: 1px solid #eaeaea; |
|
2189 | 2189 | color: #000; |
|
2190 | 2190 | font-size: 11px; |
|
2191 | 2191 | margin: 0; |
|
2192 | 2192 | padding: 5px 7px 4px; |
|
2193 | 2193 | } |
|
2194 | 2194 | |
|
2195 | 2195 | #quick_login div.form div.fields div.buttons { |
|
2196 | 2196 | clear: both; |
|
2197 | 2197 | overflow: hidden; |
|
2198 | 2198 | text-align: right; |
|
2199 | 2199 | margin: 0; |
|
2200 | 2200 | padding: 5px 14px 0px 5px; |
|
2201 | 2201 | } |
|
2202 | 2202 | |
|
2203 | 2203 | #quick_login div.form div.links { |
|
2204 | 2204 | clear: both; |
|
2205 | 2205 | overflow: hidden; |
|
2206 | 2206 | margin: 10px 0 0; |
|
2207 | 2207 | padding: 0 0 2px; |
|
2208 | 2208 | } |
|
2209 | 2209 | |
|
2210 | 2210 | #quick_login ol.links{ |
|
2211 | 2211 | display: block; |
|
2212 | 2212 | font-weight: bold; |
|
2213 | 2213 | list-style: none outside none; |
|
2214 | 2214 | text-align: right; |
|
2215 | 2215 | } |
|
2216 | 2216 | #quick_login ol.links li{ |
|
2217 | 2217 | line-height: 27px; |
|
2218 | 2218 | margin: 0; |
|
2219 | 2219 | padding: 0; |
|
2220 | 2220 | color: #fff; |
|
2221 | 2221 | display: block; |
|
2222 | 2222 | float:none !important; |
|
2223 | 2223 | } |
|
2224 | 2224 | |
|
2225 | 2225 | #quick_login ol.links li a{ |
|
2226 | 2226 | color: #fff; |
|
2227 | 2227 | display: block; |
|
2228 | 2228 | padding: 2px; |
|
2229 | 2229 | } |
|
2230 | 2230 | #quick_login ol.links li a:HOVER{ |
|
2231 | 2231 | background-color: inherit !important; |
|
2232 | 2232 | } |
|
2233 | 2233 | |
|
2234 | 2234 | #register div.title { |
|
2235 | 2235 | clear: both; |
|
2236 | 2236 | overflow: hidden; |
|
2237 | 2237 | position: relative; |
|
2238 | 2238 | background-color: #003B76; |
|
2239 | 2239 | background-repeat: repeat-x; |
|
2240 | 2240 | background-image: -khtml-gradient(linear, left top, left bottom, from(#003B76), to(#00376E) ); |
|
2241 | 2241 | background-image: -moz-linear-gradient(top, #003b76, #00376e); |
|
2242 | 2242 | background-image: -ms-linear-gradient(top, #003b76, #00376e); |
|
2243 | 2243 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #003b76), color-stop(100%, #00376e) ); |
|
2244 | 2244 | background-image: -webkit-linear-gradient(top, #003b76, #00376e); |
|
2245 | 2245 | background-image: -o-linear-gradient(top, #003b76, #00376e); |
|
2246 | 2246 | background-image: linear-gradient(top, #003b76, #00376e); |
|
2247 | 2247 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#003b76', |
|
2248 | 2248 | endColorstr='#00376e', GradientType=0 ); |
|
2249 | 2249 | margin: 0 auto; |
|
2250 | 2250 | padding: 0; |
|
2251 | 2251 | } |
|
2252 | 2252 | |
|
2253 | 2253 | #register div.inner { |
|
2254 | 2254 | background: #FFF; |
|
2255 | 2255 | border-top: none; |
|
2256 | 2256 | border-bottom: none; |
|
2257 | 2257 | margin: 0 auto; |
|
2258 | 2258 | padding: 20px; |
|
2259 | 2259 | } |
|
2260 | 2260 | |
|
2261 | 2261 | #register div.form div.fields div.field div.label { |
|
2262 | 2262 | width: 135px; |
|
2263 | 2263 | float: left; |
|
2264 | 2264 | text-align: right; |
|
2265 | 2265 | margin: 2px 10px 0 0; |
|
2266 | 2266 | padding: 5px 0 0 5px; |
|
2267 | 2267 | } |
|
2268 | 2268 | |
|
2269 | 2269 | #register div.form div.fields div.field div.input input { |
|
2270 | 2270 | width: 300px; |
|
2271 | 2271 | background: #FFF; |
|
2272 | 2272 | border-top: 1px solid #b3b3b3; |
|
2273 | 2273 | border-left: 1px solid #b3b3b3; |
|
2274 | 2274 | border-right: 1px solid #eaeaea; |
|
2275 | 2275 | border-bottom: 1px solid #eaeaea; |
|
2276 | 2276 | color: #000; |
|
2277 | 2277 | font-size: 11px; |
|
2278 | 2278 | margin: 0; |
|
2279 | 2279 | padding: 7px 7px 6px; |
|
2280 | 2280 | } |
|
2281 | 2281 | |
|
2282 | 2282 | #register div.form div.fields div.buttons { |
|
2283 | 2283 | clear: both; |
|
2284 | 2284 | overflow: hidden; |
|
2285 | 2285 | border-top: 1px solid #DDD; |
|
2286 | 2286 | text-align: left; |
|
2287 | 2287 | margin: 0; |
|
2288 | 2288 | padding: 10px 0 0 150px; |
|
2289 | 2289 | } |
|
2290 | 2290 | |
|
2291 | 2291 | #register div.form div.activation_msg { |
|
2292 | 2292 | padding-top: 4px; |
|
2293 | 2293 | padding-bottom: 4px; |
|
2294 | 2294 | } |
|
2295 | 2295 | |
|
2296 | 2296 | #journal .journal_day { |
|
2297 | 2297 | font-size: 20px; |
|
2298 | 2298 | padding: 10px 0px; |
|
2299 | 2299 | border-bottom: 2px solid #DDD; |
|
2300 | 2300 | margin-left: 10px; |
|
2301 | 2301 | margin-right: 10px; |
|
2302 | 2302 | } |
|
2303 | 2303 | |
|
2304 | 2304 | #journal .journal_container { |
|
2305 | 2305 | padding: 5px; |
|
2306 | 2306 | clear: both; |
|
2307 | 2307 | margin: 0px 5px 0px 10px; |
|
2308 | 2308 | } |
|
2309 | 2309 | |
|
2310 | 2310 | #journal .journal_action_container { |
|
2311 | 2311 | padding-left: 38px; |
|
2312 | 2312 | } |
|
2313 | 2313 | |
|
2314 | 2314 | #journal .journal_user { |
|
2315 | 2315 | color: #747474; |
|
2316 | 2316 | font-size: 14px; |
|
2317 | 2317 | font-weight: bold; |
|
2318 | 2318 | height: 30px; |
|
2319 | 2319 | } |
|
2320 | 2320 | |
|
2321 | 2321 | #journal .journal_icon { |
|
2322 | 2322 | clear: both; |
|
2323 | 2323 | float: left; |
|
2324 | 2324 | padding-right: 4px; |
|
2325 | 2325 | padding-top: 3px; |
|
2326 | 2326 | } |
|
2327 | 2327 | |
|
2328 | 2328 | #journal .journal_action { |
|
2329 | 2329 | padding-top: 4px; |
|
2330 | 2330 | min-height: 2px; |
|
2331 | 2331 | float: left |
|
2332 | 2332 | } |
|
2333 | 2333 | |
|
2334 | 2334 | #journal .journal_action_params { |
|
2335 | 2335 | clear: left; |
|
2336 | 2336 | padding-left: 22px; |
|
2337 | 2337 | } |
|
2338 | 2338 | |
|
2339 | 2339 | #journal .journal_repo { |
|
2340 | 2340 | float: left; |
|
2341 | 2341 | margin-left: 6px; |
|
2342 | 2342 | padding-top: 3px; |
|
2343 | 2343 | } |
|
2344 | 2344 | |
|
2345 | 2345 | #journal .date { |
|
2346 | 2346 | clear: both; |
|
2347 | 2347 | color: #777777; |
|
2348 | 2348 | font-size: 11px; |
|
2349 | 2349 | padding-left: 22px; |
|
2350 | 2350 | } |
|
2351 | 2351 | |
|
2352 | 2352 | #journal .journal_repo .journal_repo_name { |
|
2353 | 2353 | font-weight: bold; |
|
2354 | 2354 | font-size: 1.1em; |
|
2355 | 2355 | } |
|
2356 | 2356 | |
|
2357 | 2357 | #journal .compare_view { |
|
2358 | 2358 | padding: 5px 0px 5px 0px; |
|
2359 | 2359 | width: 95px; |
|
2360 | 2360 | } |
|
2361 | 2361 | |
|
2362 | 2362 | .journal_highlight { |
|
2363 | 2363 | font-weight: bold; |
|
2364 | 2364 | padding: 0 2px; |
|
2365 | 2365 | vertical-align: bottom; |
|
2366 | 2366 | } |
|
2367 | 2367 | |
|
2368 | 2368 | .trending_language_tbl,.trending_language_tbl td { |
|
2369 | 2369 | border: 0 !important; |
|
2370 | 2370 | margin: 0 !important; |
|
2371 | 2371 | padding: 0 !important; |
|
2372 | 2372 | } |
|
2373 | 2373 | |
|
2374 | 2374 | .trending_language_tbl,.trending_language_tbl tr { |
|
2375 | 2375 | border-spacing: 1px; |
|
2376 | 2376 | } |
|
2377 | 2377 | |
|
2378 | 2378 | .trending_language { |
|
2379 | 2379 | background-color: #003367; |
|
2380 | 2380 | color: #FFF; |
|
2381 | 2381 | display: block; |
|
2382 | 2382 | min-width: 20px; |
|
2383 | 2383 | text-decoration: none; |
|
2384 | 2384 | height: 12px; |
|
2385 | 2385 | margin-bottom: 0px; |
|
2386 | 2386 | margin-left: 5px; |
|
2387 | 2387 | white-space: pre; |
|
2388 | 2388 | padding: 3px; |
|
2389 | 2389 | } |
|
2390 | 2390 | |
|
2391 | 2391 | h3.files_location { |
|
2392 | 2392 | font-size: 1.8em; |
|
2393 | 2393 | font-weight: 700; |
|
2394 | 2394 | border-bottom: none !important; |
|
2395 | 2395 | margin: 10px 0 !important; |
|
2396 | 2396 | } |
|
2397 | 2397 | |
|
2398 | 2398 | #files_data dl dt { |
|
2399 | 2399 | float: left; |
|
2400 | 2400 | width: 60px; |
|
2401 | 2401 | margin: 0 !important; |
|
2402 | 2402 | padding: 5px; |
|
2403 | 2403 | } |
|
2404 | 2404 | |
|
2405 | 2405 | #files_data dl dd { |
|
2406 | 2406 | margin: 0 !important; |
|
2407 | 2407 | padding: 5px !important; |
|
2408 | 2408 | } |
|
2409 | 2409 | |
|
2410 | 2410 | .file_history{ |
|
2411 | 2411 | padding-top:10px; |
|
2412 | 2412 | font-size:16px; |
|
2413 | 2413 | } |
|
2414 | 2414 | .file_author{ |
|
2415 | 2415 | float: left; |
|
2416 | 2416 | } |
|
2417 | 2417 | |
|
2418 | 2418 | .file_author .item{ |
|
2419 | 2419 | float:left; |
|
2420 | 2420 | padding:5px; |
|
2421 | 2421 | color: #888; |
|
2422 | 2422 | } |
|
2423 | 2423 | |
|
2424 | 2424 | .tablerow0 { |
|
2425 | 2425 | background-color: #F8F8F8; |
|
2426 | 2426 | } |
|
2427 | 2427 | |
|
2428 | 2428 | .tablerow1 { |
|
2429 | 2429 | background-color: #FFFFFF; |
|
2430 | 2430 | } |
|
2431 | 2431 | |
|
2432 | 2432 | .changeset_id { |
|
2433 | 2433 | font-family: monospace; |
|
2434 | 2434 | color: #666666; |
|
2435 | 2435 | } |
|
2436 | 2436 | |
|
2437 | 2437 | .changeset_hash { |
|
2438 | 2438 | color: #000000; |
|
2439 | 2439 | } |
|
2440 | 2440 | |
|
2441 | 2441 | #changeset_content { |
|
2442 | 2442 | border-left: 1px solid #CCC; |
|
2443 | 2443 | border-right: 1px solid #CCC; |
|
2444 | 2444 | border-bottom: 1px solid #CCC; |
|
2445 | 2445 | padding: 5px; |
|
2446 | 2446 | } |
|
2447 | 2447 | |
|
2448 | 2448 | #changeset_compare_view_content { |
|
2449 | 2449 | border: 1px solid #CCC; |
|
2450 | 2450 | padding: 5px; |
|
2451 | 2451 | } |
|
2452 | 2452 | |
|
2453 | 2453 | #changeset_content .container { |
|
2454 | 2454 | min-height: 100px; |
|
2455 | 2455 | font-size: 1.2em; |
|
2456 | 2456 | overflow: hidden; |
|
2457 | 2457 | } |
|
2458 | 2458 | |
|
2459 | 2459 | #changeset_compare_view_content .compare_view_commits { |
|
2460 | 2460 | width: auto !important; |
|
2461 | 2461 | } |
|
2462 | 2462 | |
|
2463 | 2463 | #changeset_compare_view_content .compare_view_commits td { |
|
2464 | 2464 | padding: 0px 0px 0px 12px !important; |
|
2465 | 2465 | } |
|
2466 | 2466 | |
|
2467 | 2467 | #changeset_content .container .right { |
|
2468 | 2468 | float: right; |
|
2469 | 2469 | width: 20%; |
|
2470 | 2470 | text-align: right; |
|
2471 | 2471 | } |
|
2472 | 2472 | |
|
2473 | 2473 | #changeset_content .container .left .message { |
|
2474 | 2474 | white-space: pre-wrap; |
|
2475 | 2475 | } |
|
2476 | 2476 | #changeset_content .container .left .message a:hover { |
|
2477 | 2477 | text-decoration: none; |
|
2478 | 2478 | } |
|
2479 | 2479 | .cs_files .cur_cs { |
|
2480 | 2480 | margin: 10px 2px; |
|
2481 | 2481 | font-weight: bold; |
|
2482 | 2482 | } |
|
2483 | 2483 | |
|
2484 | 2484 | .cs_files .node { |
|
2485 | 2485 | float: left; |
|
2486 | 2486 | } |
|
2487 | 2487 | |
|
2488 | 2488 | .cs_files .changes { |
|
2489 | 2489 | float: right; |
|
2490 | 2490 | color:#003367; |
|
2491 | 2491 | |
|
2492 | 2492 | } |
|
2493 | 2493 | |
|
2494 | 2494 | .cs_files .changes .added { |
|
2495 | 2495 | background-color: #BBFFBB; |
|
2496 | 2496 | float: left; |
|
2497 | 2497 | text-align: center; |
|
2498 | 2498 | font-size: 9px; |
|
2499 | 2499 | padding: 2px 0px 2px 0px; |
|
2500 | 2500 | } |
|
2501 | 2501 | |
|
2502 | 2502 | .cs_files .changes .deleted { |
|
2503 | 2503 | background-color: #FF8888; |
|
2504 | 2504 | float: left; |
|
2505 | 2505 | text-align: center; |
|
2506 | 2506 | font-size: 9px; |
|
2507 | 2507 | padding: 2px 0px 2px 0px; |
|
2508 | 2508 | } |
|
2509 | /*new binary*/ | |
|
2510 | .cs_files .changes .bin1 { | |
|
2511 | background-color: #BBFFBB; | |
|
2512 | float: left; | |
|
2513 | text-align: center; | |
|
2514 | font-size: 9px; | |
|
2515 | padding: 2px 0px 2px 0px; | |
|
2516 | } | |
|
2517 | ||
|
2518 | /*deleted binary*/ | |
|
2519 | .cs_files .changes .bin2 { | |
|
2520 | background-color: #FF8888; | |
|
2521 | float: left; | |
|
2522 | text-align: center; | |
|
2523 | font-size: 9px; | |
|
2524 | padding: 2px 0px 2px 0px; | |
|
2525 | } | |
|
2526 | ||
|
2527 | /*mod binary*/ | |
|
2528 | .cs_files .changes .bin3 { | |
|
2529 | background-color: #DDDDDD; | |
|
2530 | float: left; | |
|
2531 | text-align: center; | |
|
2532 | font-size: 9px; | |
|
2533 | padding: 2px 0px 2px 0px; | |
|
2534 | } | |
|
2535 | ||
|
2536 | /*rename file*/ | |
|
2537 | .cs_files .changes .bin4 { | |
|
2538 | background-color: #6D99FF; | |
|
2539 | float: left; | |
|
2540 | text-align: center; | |
|
2541 | font-size: 9px; | |
|
2542 | padding: 2px 0px 2px 0px; | |
|
2543 | } | |
|
2544 | ||
|
2509 | 2545 | |
|
2510 | 2546 | .cs_files .cs_added,.cs_files .cs_A { |
|
2511 | 2547 | background: url("../images/icons/page_white_add.png") no-repeat scroll |
|
2512 | 2548 | 3px; |
|
2513 | 2549 | height: 16px; |
|
2514 | 2550 | padding-left: 20px; |
|
2515 | 2551 | margin-top: 7px; |
|
2516 | 2552 | text-align: left; |
|
2517 | 2553 | } |
|
2518 | 2554 | |
|
2519 | 2555 | .cs_files .cs_changed,.cs_files .cs_M { |
|
2520 | 2556 | background: url("../images/icons/page_white_edit.png") no-repeat scroll |
|
2521 | 2557 | 3px; |
|
2522 | 2558 | height: 16px; |
|
2523 | 2559 | padding-left: 20px; |
|
2524 | 2560 | margin-top: 7px; |
|
2525 | 2561 | text-align: left; |
|
2526 | 2562 | } |
|
2527 | 2563 | |
|
2528 | 2564 | .cs_files .cs_removed,.cs_files .cs_D { |
|
2529 | 2565 | background: url("../images/icons/page_white_delete.png") no-repeat |
|
2530 | 2566 | scroll 3px; |
|
2531 | 2567 | height: 16px; |
|
2532 | 2568 | padding-left: 20px; |
|
2533 | 2569 | margin-top: 7px; |
|
2534 | 2570 | text-align: left; |
|
2535 | 2571 | } |
|
2536 | 2572 | |
|
2537 | 2573 | #graph { |
|
2538 | 2574 | overflow: hidden; |
|
2539 | 2575 | } |
|
2540 | 2576 | |
|
2541 | 2577 | #graph_nodes { |
|
2542 | 2578 | float: left; |
|
2543 | 2579 | margin-right: 0px; |
|
2544 | 2580 | margin-top: 0px; |
|
2545 | 2581 | } |
|
2546 | 2582 | |
|
2547 | 2583 | #graph_content { |
|
2548 | 2584 | width: 80%; |
|
2549 | 2585 | float: left; |
|
2550 | 2586 | } |
|
2551 | 2587 | |
|
2552 | 2588 | #graph_content .container_header { |
|
2553 | 2589 | border-bottom: 1px solid #DDD; |
|
2554 | 2590 | padding: 10px; |
|
2555 | 2591 | height: 25px; |
|
2556 | 2592 | } |
|
2557 | 2593 | |
|
2558 | 2594 | #graph_content #rev_range_container { |
|
2559 | 2595 | float: left; |
|
2560 | 2596 | margin: 0px 0px 0px 3px; |
|
2561 | 2597 | } |
|
2562 | 2598 | |
|
2563 | 2599 | #graph_content #rev_range_clear { |
|
2564 | 2600 | float: left; |
|
2565 | 2601 | margin: 0px 0px 0px 3px; |
|
2566 | 2602 | } |
|
2567 | 2603 | |
|
2568 | 2604 | #graph_content .container { |
|
2569 | 2605 | border-bottom: 1px solid #DDD; |
|
2570 | 2606 | height: 56px; |
|
2571 | 2607 | overflow: hidden; |
|
2572 | 2608 | } |
|
2573 | 2609 | |
|
2574 | 2610 | #graph_content .container .right { |
|
2575 | 2611 | float: right; |
|
2576 | 2612 | width: 23%; |
|
2577 | 2613 | text-align: right; |
|
2578 | 2614 | } |
|
2579 | 2615 | |
|
2580 | 2616 | #graph_content .container .left { |
|
2581 | 2617 | float: left; |
|
2582 | 2618 | width: 25%; |
|
2583 | 2619 | padding-left: 5px; |
|
2584 | 2620 | } |
|
2585 | 2621 | |
|
2586 | 2622 | #graph_content .container .mid { |
|
2587 | 2623 | float: left; |
|
2588 | 2624 | width: 49%; |
|
2589 | 2625 | } |
|
2590 | 2626 | |
|
2591 | 2627 | |
|
2592 | 2628 | #graph_content .container .left .date { |
|
2593 | 2629 | color: #666; |
|
2594 | 2630 | padding-left: 22px; |
|
2595 | 2631 | font-size: 10px; |
|
2596 | 2632 | } |
|
2597 | 2633 | |
|
2598 | 2634 | #graph_content .container .left .author { |
|
2599 | 2635 | height: 22px; |
|
2600 | 2636 | } |
|
2601 | 2637 | |
|
2602 | 2638 | #graph_content .container .left .author .user { |
|
2603 | 2639 | color: #444444; |
|
2604 | 2640 | float: left; |
|
2605 | 2641 | margin-left: -4px; |
|
2606 | 2642 | margin-top: 4px; |
|
2607 | 2643 | } |
|
2608 | 2644 | |
|
2609 | 2645 | #graph_content .container .mid .message { |
|
2610 | 2646 | white-space: pre-wrap; |
|
2611 | 2647 | } |
|
2612 | 2648 | |
|
2613 | 2649 | #graph_content .container .mid .message a:hover{ |
|
2614 | 2650 | text-decoration: none; |
|
2615 | 2651 | } |
|
2616 | 2652 | #content #graph_content .message .revision-link, |
|
2617 | 2653 | #changeset_content .container .message .revision-link |
|
2618 | 2654 | { |
|
2619 | 2655 | color:#3F6F9F; |
|
2620 | 2656 | font-weight: bold !important; |
|
2621 | 2657 | } |
|
2622 | 2658 | |
|
2623 | 2659 | #content #graph_content .message .issue-tracker-link, |
|
2624 | 2660 | #changeset_content .container .message .issue-tracker-link{ |
|
2625 | 2661 | color:#3F6F9F; |
|
2626 | 2662 | font-weight: bold !important; |
|
2627 | 2663 | } |
|
2628 | 2664 | |
|
2629 | 2665 | .changeset-status-container{ |
|
2630 | 2666 | padding-right: 5px; |
|
2631 | 2667 | margin-top:1px; |
|
2632 | 2668 | float:right; |
|
2633 | 2669 | height:14px; |
|
2634 | 2670 | } |
|
2635 | 2671 | .code-header .changeset-status-container{ |
|
2636 | 2672 | float:left; |
|
2637 | 2673 | padding:2px 0px 0px 2px; |
|
2638 | 2674 | } |
|
2639 | 2675 | .changeset-status-container .changeset-status-lbl{ |
|
2640 | 2676 | color: rgb(136, 136, 136); |
|
2641 | 2677 | float: left; |
|
2642 | 2678 | padding: 3px 4px 0px 0px |
|
2643 | 2679 | } |
|
2644 | 2680 | .code-header .changeset-status-container .changeset-status-lbl{ |
|
2645 | 2681 | float: left; |
|
2646 | 2682 | padding: 0px 4px 0px 0px; |
|
2647 | 2683 | } |
|
2648 | 2684 | .changeset-status-container .changeset-status-ico{ |
|
2649 | 2685 | float: left; |
|
2650 | 2686 | } |
|
2651 | 2687 | .code-header .changeset-status-container .changeset-status-ico, .container .changeset-status-ico{ |
|
2652 | 2688 | float: left; |
|
2653 | 2689 | } |
|
2654 | 2690 | .right .comments-container{ |
|
2655 | 2691 | padding-right: 5px; |
|
2656 | 2692 | margin-top:1px; |
|
2657 | 2693 | float:right; |
|
2658 | 2694 | height:14px; |
|
2659 | 2695 | } |
|
2660 | 2696 | |
|
2661 | 2697 | .right .comments-cnt{ |
|
2662 | 2698 | float: left; |
|
2663 | 2699 | color: rgb(136, 136, 136); |
|
2664 | 2700 | padding-right: 2px; |
|
2665 | 2701 | } |
|
2666 | 2702 | |
|
2667 | 2703 | .right .changes{ |
|
2668 | 2704 | clear: both; |
|
2669 | 2705 | } |
|
2670 | 2706 | |
|
2671 | 2707 | .right .changes .changed_total { |
|
2672 | 2708 | display: block; |
|
2673 | 2709 | float: right; |
|
2674 | 2710 | text-align: center; |
|
2675 | 2711 | min-width: 45px; |
|
2676 | 2712 | cursor: pointer; |
|
2677 | 2713 | color: #444444; |
|
2678 | 2714 | background: #FEA; |
|
2679 | 2715 | -webkit-border-radius: 0px 0px 0px 6px; |
|
2680 | 2716 | -moz-border-radius: 0px 0px 0px 6px; |
|
2681 | 2717 | border-radius: 0px 0px 0px 6px; |
|
2682 | 2718 | padding: 1px; |
|
2683 | 2719 | } |
|
2684 | 2720 | |
|
2685 | 2721 | .right .changes .added,.changed,.removed { |
|
2686 | 2722 | display: block; |
|
2687 | 2723 | padding: 1px; |
|
2688 | 2724 | color: #444444; |
|
2689 | 2725 | float: right; |
|
2690 | 2726 | text-align: center; |
|
2691 | 2727 | min-width: 15px; |
|
2692 | 2728 | } |
|
2693 | 2729 | |
|
2694 | 2730 | .right .changes .added { |
|
2695 | 2731 | background: #CFC; |
|
2696 | 2732 | } |
|
2697 | 2733 | |
|
2698 | 2734 | .right .changes .changed { |
|
2699 | 2735 | background: #FEA; |
|
2700 | 2736 | } |
|
2701 | 2737 | |
|
2702 | 2738 | .right .changes .removed { |
|
2703 | 2739 | background: #FAA; |
|
2704 | 2740 | } |
|
2705 | 2741 | |
|
2706 | 2742 | .right .merge { |
|
2707 | 2743 | padding: 1px 3px 1px 3px; |
|
2708 | 2744 | background-color: #fca062; |
|
2709 | 2745 | font-size: 10px; |
|
2710 | 2746 | font-weight: bold; |
|
2711 | 2747 | color: #ffffff; |
|
2712 | 2748 | text-transform: uppercase; |
|
2713 | 2749 | white-space: nowrap; |
|
2714 | 2750 | -webkit-border-radius: 3px; |
|
2715 | 2751 | -moz-border-radius: 3px; |
|
2716 | 2752 | border-radius: 3px; |
|
2717 | 2753 | margin-right: 2px; |
|
2718 | 2754 | } |
|
2719 | 2755 | |
|
2720 | 2756 | .right .parent { |
|
2721 | 2757 | color: #666666; |
|
2722 | 2758 | clear:both; |
|
2723 | 2759 | } |
|
2724 | 2760 | .right .logtags{ |
|
2725 | 2761 | padding: 2px 2px 2px 2px; |
|
2726 | 2762 | } |
|
2727 | 2763 | .right .logtags .branchtag,.right .logtags .tagtag,.right .logtags .booktag{ |
|
2728 | 2764 | margin: 0px 2px; |
|
2729 | 2765 | } |
|
2730 | 2766 | |
|
2731 | 2767 | .right .logtags .branchtag,.logtags .branchtag { |
|
2732 | 2768 | padding: 1px 3px 1px 3px; |
|
2733 | 2769 | background-color: #bfbfbf; |
|
2734 | 2770 | font-size: 10px; |
|
2735 | 2771 | font-weight: bold; |
|
2736 | 2772 | color: #ffffff; |
|
2737 | 2773 | text-transform: uppercase; |
|
2738 | 2774 | white-space: nowrap; |
|
2739 | 2775 | -webkit-border-radius: 3px; |
|
2740 | 2776 | -moz-border-radius: 3px; |
|
2741 | 2777 | border-radius: 3px; |
|
2742 | 2778 | } |
|
2743 | 2779 | .right .logtags .branchtag a:hover,.logtags .branchtag a{ |
|
2744 | 2780 | color: #ffffff; |
|
2745 | 2781 | } |
|
2746 | 2782 | .right .logtags .branchtag a:hover,.logtags .branchtag a:hover{ |
|
2747 | 2783 | text-decoration: none; |
|
2748 | 2784 | color: #ffffff; |
|
2749 | 2785 | } |
|
2750 | 2786 | .right .logtags .tagtag,.logtags .tagtag { |
|
2751 | 2787 | padding: 1px 3px 1px 3px; |
|
2752 | 2788 | background-color: #62cffc; |
|
2753 | 2789 | font-size: 10px; |
|
2754 | 2790 | font-weight: bold; |
|
2755 | 2791 | color: #ffffff; |
|
2756 | 2792 | text-transform: uppercase; |
|
2757 | 2793 | white-space: nowrap; |
|
2758 | 2794 | -webkit-border-radius: 3px; |
|
2759 | 2795 | -moz-border-radius: 3px; |
|
2760 | 2796 | border-radius: 3px; |
|
2761 | 2797 | } |
|
2762 | 2798 | .right .logtags .tagtag a:hover,.logtags .tagtag a{ |
|
2763 | 2799 | color: #ffffff; |
|
2764 | 2800 | } |
|
2765 | 2801 | .right .logtags .tagtag a:hover,.logtags .tagtag a:hover{ |
|
2766 | 2802 | text-decoration: none; |
|
2767 | 2803 | color: #ffffff; |
|
2768 | 2804 | } |
|
2769 | 2805 | .right .logbooks .bookbook,.logbooks .bookbook,.right .logtags .bookbook,.logtags .bookbook { |
|
2770 | 2806 | padding: 1px 3px 1px 3px; |
|
2771 | 2807 | background-color: #46A546; |
|
2772 | 2808 | font-size: 10px; |
|
2773 | 2809 | font-weight: bold; |
|
2774 | 2810 | color: #ffffff; |
|
2775 | 2811 | text-transform: uppercase; |
|
2776 | 2812 | white-space: nowrap; |
|
2777 | 2813 | -webkit-border-radius: 3px; |
|
2778 | 2814 | -moz-border-radius: 3px; |
|
2779 | 2815 | border-radius: 3px; |
|
2780 | 2816 | } |
|
2781 | 2817 | .right .logbooks .bookbook,.logbooks .bookbook a,.right .logtags .bookbook,.logtags .bookbook a{ |
|
2782 | 2818 | color: #ffffff; |
|
2783 | 2819 | } |
|
2784 | 2820 | .right .logbooks .bookbook,.logbooks .bookbook a:hover,.right .logtags .bookbook,.logtags .bookbook a:hover{ |
|
2785 | 2821 | text-decoration: none; |
|
2786 | 2822 | color: #ffffff; |
|
2787 | 2823 | } |
|
2788 | 2824 | div.browserblock { |
|
2789 | 2825 | overflow: hidden; |
|
2790 | 2826 | border: 1px solid #ccc; |
|
2791 | 2827 | background: #f8f8f8; |
|
2792 | 2828 | font-size: 100%; |
|
2793 | 2829 | line-height: 125%; |
|
2794 | 2830 | padding: 0; |
|
2795 | 2831 | -webkit-border-radius: 6px 6px 0px 0px; |
|
2796 | 2832 | -moz-border-radius: 6px 6px 0px 0px; |
|
2797 | 2833 | border-radius: 6px 6px 0px 0px; |
|
2798 | 2834 | } |
|
2799 | 2835 | |
|
2800 | 2836 | div.browserblock .browser-header { |
|
2801 | 2837 | background: #FFF; |
|
2802 | 2838 | padding: 10px 0px 15px 0px; |
|
2803 | 2839 | width: 100%; |
|
2804 | 2840 | } |
|
2805 | 2841 | |
|
2806 | 2842 | div.browserblock .browser-nav { |
|
2807 | 2843 | float: left |
|
2808 | 2844 | } |
|
2809 | 2845 | |
|
2810 | 2846 | div.browserblock .browser-branch { |
|
2811 | 2847 | float: left; |
|
2812 | 2848 | } |
|
2813 | 2849 | |
|
2814 | 2850 | div.browserblock .browser-branch label { |
|
2815 | 2851 | color: #4A4A4A; |
|
2816 | 2852 | vertical-align: text-top; |
|
2817 | 2853 | } |
|
2818 | 2854 | |
|
2819 | 2855 | div.browserblock .browser-header span { |
|
2820 | 2856 | margin-left: 5px; |
|
2821 | 2857 | font-weight: 700; |
|
2822 | 2858 | } |
|
2823 | 2859 | |
|
2824 | 2860 | div.browserblock .browser-search { |
|
2825 | 2861 | clear: both; |
|
2826 | 2862 | padding: 8px 8px 0px 5px; |
|
2827 | 2863 | height: 20px; |
|
2828 | 2864 | } |
|
2829 | 2865 | |
|
2830 | 2866 | div.browserblock #node_filter_box { |
|
2831 | 2867 | |
|
2832 | 2868 | } |
|
2833 | 2869 | |
|
2834 | 2870 | div.browserblock .search_activate { |
|
2835 | 2871 | float: left |
|
2836 | 2872 | } |
|
2837 | 2873 | |
|
2838 | 2874 | div.browserblock .add_node { |
|
2839 | 2875 | float: left; |
|
2840 | 2876 | padding-left: 5px; |
|
2841 | 2877 | } |
|
2842 | 2878 | |
|
2843 | 2879 | div.browserblock .search_activate a:hover,div.browserblock .add_node a:hover |
|
2844 | 2880 | { |
|
2845 | 2881 | text-decoration: none !important; |
|
2846 | 2882 | } |
|
2847 | 2883 | |
|
2848 | 2884 | div.browserblock .browser-body { |
|
2849 | 2885 | background: #EEE; |
|
2850 | 2886 | border-top: 1px solid #CCC; |
|
2851 | 2887 | } |
|
2852 | 2888 | |
|
2853 | 2889 | table.code-browser { |
|
2854 | 2890 | border-collapse: collapse; |
|
2855 | 2891 | width: 100%; |
|
2856 | 2892 | } |
|
2857 | 2893 | |
|
2858 | 2894 | table.code-browser tr { |
|
2859 | 2895 | margin: 3px; |
|
2860 | 2896 | } |
|
2861 | 2897 | |
|
2862 | 2898 | table.code-browser thead th { |
|
2863 | 2899 | background-color: #EEE; |
|
2864 | 2900 | height: 20px; |
|
2865 | 2901 | font-size: 1.1em; |
|
2866 | 2902 | font-weight: 700; |
|
2867 | 2903 | text-align: left; |
|
2868 | 2904 | padding-left: 10px; |
|
2869 | 2905 | } |
|
2870 | 2906 | |
|
2871 | 2907 | table.code-browser tbody td { |
|
2872 | 2908 | padding-left: 10px; |
|
2873 | 2909 | height: 20px; |
|
2874 | 2910 | } |
|
2875 | 2911 | |
|
2876 | 2912 | table.code-browser .browser-file { |
|
2877 | 2913 | background: url("../images/icons/document_16.png") no-repeat scroll 3px; |
|
2878 | 2914 | height: 16px; |
|
2879 | 2915 | padding-left: 20px; |
|
2880 | 2916 | text-align: left; |
|
2881 | 2917 | } |
|
2882 | 2918 | .diffblock .changeset_header { |
|
2883 | 2919 | height: 16px; |
|
2884 | 2920 | } |
|
2885 | 2921 | .diffblock .changeset_file { |
|
2886 | 2922 | background: url("../images/icons/file.png") no-repeat scroll 3px; |
|
2887 | 2923 | text-align: left; |
|
2888 | 2924 | float: left; |
|
2889 | 2925 | padding: 2px 0px 2px 22px; |
|
2890 | 2926 | } |
|
2891 | 2927 | .diffblock .diff-menu-wrapper{ |
|
2892 | 2928 | float: left; |
|
2893 | 2929 | } |
|
2894 | 2930 | |
|
2895 | 2931 | .diffblock .diff-menu{ |
|
2896 | 2932 | position: absolute; |
|
2897 | 2933 | background: none repeat scroll 0 0 #FFFFFF; |
|
2898 | 2934 | border-color: #003367 #666666 #666666; |
|
2899 | 2935 | border-right: 1px solid #666666; |
|
2900 | 2936 | border-style: solid solid solid; |
|
2901 | 2937 | border-width: 1px; |
|
2902 | 2938 | box-shadow: 2px 8px 4px rgba(0, 0, 0, 0.2); |
|
2903 | 2939 | margin-top:5px; |
|
2904 | 2940 | margin-left:1px; |
|
2905 | 2941 | |
|
2906 | 2942 | } |
|
2907 | 2943 | .diffblock .diff-actions { |
|
2908 | 2944 | padding: 2px 0px 0px 2px; |
|
2909 | 2945 | float: left; |
|
2910 | 2946 | } |
|
2911 | 2947 | .diffblock .diff-menu ul li { |
|
2912 | 2948 | padding: 0px 0px 0px 0px !important; |
|
2913 | 2949 | } |
|
2914 | 2950 | .diffblock .diff-menu ul li a{ |
|
2915 | 2951 | display: block; |
|
2916 | 2952 | padding: 3px 8px 3px 8px !important; |
|
2917 | 2953 | } |
|
2918 | 2954 | .diffblock .diff-menu ul li a:hover{ |
|
2919 | 2955 | text-decoration: none; |
|
2920 | 2956 | background-color: #EEEEEE; |
|
2921 | 2957 | } |
|
2922 | 2958 | table.code-browser .browser-dir { |
|
2923 | 2959 | background: url("../images/icons/folder_16.png") no-repeat scroll 3px; |
|
2924 | 2960 | height: 16px; |
|
2925 | 2961 | padding-left: 20px; |
|
2926 | 2962 | text-align: left; |
|
2927 | 2963 | } |
|
2928 | 2964 | |
|
2929 | 2965 | table.code-browser .submodule-dir { |
|
2930 | 2966 | background: url("../images/icons/disconnect.png") no-repeat scroll 3px; |
|
2931 | 2967 | height: 16px; |
|
2932 | 2968 | padding-left: 20px; |
|
2933 | 2969 | text-align: left; |
|
2934 | 2970 | } |
|
2935 | 2971 | |
|
2936 | 2972 | |
|
2937 | 2973 | .box .search { |
|
2938 | 2974 | clear: both; |
|
2939 | 2975 | overflow: hidden; |
|
2940 | 2976 | margin: 0; |
|
2941 | 2977 | padding: 0 20px 10px; |
|
2942 | 2978 | } |
|
2943 | 2979 | |
|
2944 | 2980 | .box .search div.search_path { |
|
2945 | 2981 | background: none repeat scroll 0 0 #EEE; |
|
2946 | 2982 | border: 1px solid #CCC; |
|
2947 | 2983 | color: blue; |
|
2948 | 2984 | margin-bottom: 10px; |
|
2949 | 2985 | padding: 10px 0; |
|
2950 | 2986 | } |
|
2951 | 2987 | |
|
2952 | 2988 | .box .search div.search_path div.link { |
|
2953 | 2989 | font-weight: 700; |
|
2954 | 2990 | margin-left: 25px; |
|
2955 | 2991 | } |
|
2956 | 2992 | |
|
2957 | 2993 | .box .search div.search_path div.link a { |
|
2958 | 2994 | color: #003367; |
|
2959 | 2995 | cursor: pointer; |
|
2960 | 2996 | text-decoration: none; |
|
2961 | 2997 | } |
|
2962 | 2998 | |
|
2963 | 2999 | #path_unlock { |
|
2964 | 3000 | color: red; |
|
2965 | 3001 | font-size: 1.2em; |
|
2966 | 3002 | padding-left: 4px; |
|
2967 | 3003 | } |
|
2968 | 3004 | |
|
2969 | 3005 | .info_box span { |
|
2970 | 3006 | margin-left: 3px; |
|
2971 | 3007 | margin-right: 3px; |
|
2972 | 3008 | } |
|
2973 | 3009 | |
|
2974 | 3010 | .info_box .rev { |
|
2975 | 3011 | color: #003367; |
|
2976 | 3012 | font-size: 1.6em; |
|
2977 | 3013 | font-weight: bold; |
|
2978 | 3014 | vertical-align: sub; |
|
2979 | 3015 | } |
|
2980 | 3016 | |
|
2981 | 3017 | .info_box input#at_rev,.info_box input#size { |
|
2982 | 3018 | background: #FFF; |
|
2983 | 3019 | border-top: 1px solid #b3b3b3; |
|
2984 | 3020 | border-left: 1px solid #b3b3b3; |
|
2985 | 3021 | border-right: 1px solid #eaeaea; |
|
2986 | 3022 | border-bottom: 1px solid #eaeaea; |
|
2987 | 3023 | color: #000; |
|
2988 | 3024 | font-size: 12px; |
|
2989 | 3025 | margin: 0; |
|
2990 | 3026 | padding: 1px 5px 1px; |
|
2991 | 3027 | } |
|
2992 | 3028 | |
|
2993 | 3029 | .info_box input#view { |
|
2994 | 3030 | text-align: center; |
|
2995 | 3031 | padding: 4px 3px 2px 2px; |
|
2996 | 3032 | } |
|
2997 | 3033 | |
|
2998 | 3034 | .yui-overlay,.yui-panel-container { |
|
2999 | 3035 | visibility: hidden; |
|
3000 | 3036 | position: absolute; |
|
3001 | 3037 | z-index: 2; |
|
3002 | 3038 | } |
|
3003 | 3039 | |
|
3004 | 3040 | #tip-box { |
|
3005 | 3041 | position: absolute; |
|
3006 | 3042 | |
|
3007 | 3043 | background-color: #FFF; |
|
3008 | 3044 | border: 2px solid #003367; |
|
3009 | 3045 | font: 100% sans-serif; |
|
3010 | 3046 | width: auto; |
|
3011 | 3047 | opacity: 1px; |
|
3012 | 3048 | padding: 8px; |
|
3013 | 3049 | |
|
3014 | 3050 | white-space: pre-wrap; |
|
3015 | 3051 | -webkit-border-radius: 8px 8px 8px 8px; |
|
3016 | 3052 | -khtml-border-radius: 8px 8px 8px 8px; |
|
3017 | 3053 | -moz-border-radius: 8px 8px 8px 8px; |
|
3018 | 3054 | border-radius: 8px 8px 8px 8px; |
|
3019 | 3055 | box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6); |
|
3020 | 3056 | -moz-box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6); |
|
3021 | 3057 | -webkit-box-shadow: 0 2px 2px rgba(0, 0, 0, 0.6); |
|
3022 | 3058 | } |
|
3023 | 3059 | |
|
3024 | 3060 | .mentions-container{ |
|
3025 | 3061 | width: 90% !important; |
|
3026 | 3062 | } |
|
3027 | 3063 | .mentions-container .yui-ac-content{ |
|
3028 | 3064 | width: 100% !important; |
|
3029 | 3065 | } |
|
3030 | 3066 | |
|
3031 | 3067 | .ac { |
|
3032 | 3068 | vertical-align: top; |
|
3033 | 3069 | } |
|
3034 | 3070 | |
|
3035 | 3071 | .ac .yui-ac { |
|
3036 | 3072 | position: inherit; |
|
3037 | 3073 | font-size: 100%; |
|
3038 | 3074 | } |
|
3039 | 3075 | |
|
3040 | 3076 | .ac .perm_ac { |
|
3041 | 3077 | width: 20em; |
|
3042 | 3078 | } |
|
3043 | 3079 | |
|
3044 | 3080 | .ac .yui-ac-input { |
|
3045 | 3081 | width: 100%; |
|
3046 | 3082 | } |
|
3047 | 3083 | |
|
3048 | 3084 | .ac .yui-ac-container { |
|
3049 | 3085 | position: absolute; |
|
3050 | 3086 | top: 1.6em; |
|
3051 | 3087 | width: auto; |
|
3052 | 3088 | } |
|
3053 | 3089 | |
|
3054 | 3090 | .ac .yui-ac-content { |
|
3055 | 3091 | position: absolute; |
|
3056 | 3092 | border: 1px solid gray; |
|
3057 | 3093 | background: #fff; |
|
3058 | 3094 | z-index: 9050; |
|
3059 | 3095 | |
|
3060 | 3096 | } |
|
3061 | 3097 | |
|
3062 | 3098 | .ac .yui-ac-shadow { |
|
3063 | 3099 | position: absolute; |
|
3064 | 3100 | width: 100%; |
|
3065 | 3101 | background: #000; |
|
3066 | 3102 | -moz-opacity: 0.1px; |
|
3067 | 3103 | opacity: .10; |
|
3068 | 3104 | filter: alpha(opacity = 10); |
|
3069 | 3105 | z-index: 9049; |
|
3070 | 3106 | margin: .3em; |
|
3071 | 3107 | } |
|
3072 | 3108 | |
|
3073 | 3109 | .ac .yui-ac-content ul { |
|
3074 | 3110 | width: 100%; |
|
3075 | 3111 | margin: 0; |
|
3076 | 3112 | padding: 0; |
|
3077 | 3113 | z-index: 9050; |
|
3078 | 3114 | } |
|
3079 | 3115 | |
|
3080 | 3116 | .ac .yui-ac-content li { |
|
3081 | 3117 | cursor: default; |
|
3082 | 3118 | white-space: nowrap; |
|
3083 | 3119 | margin: 0; |
|
3084 | 3120 | padding: 2px 5px; |
|
3085 | 3121 | height: 18px; |
|
3086 | 3122 | z-index: 9050; |
|
3087 | 3123 | display: block; |
|
3088 | 3124 | width: auto !important; |
|
3089 | 3125 | } |
|
3090 | 3126 | |
|
3091 | 3127 | .ac .yui-ac-content li .ac-container-wrap{ |
|
3092 | 3128 | width: auto; |
|
3093 | 3129 | } |
|
3094 | 3130 | |
|
3095 | 3131 | .ac .yui-ac-content li.yui-ac-prehighlight { |
|
3096 | 3132 | background: #B3D4FF; |
|
3097 | 3133 | z-index: 9050; |
|
3098 | 3134 | } |
|
3099 | 3135 | |
|
3100 | 3136 | .ac .yui-ac-content li.yui-ac-highlight { |
|
3101 | 3137 | background: #556CB5; |
|
3102 | 3138 | color: #FFF; |
|
3103 | 3139 | z-index: 9050; |
|
3104 | 3140 | } |
|
3105 | 3141 | .ac .yui-ac-bd{ |
|
3106 | 3142 | z-index: 9050; |
|
3107 | 3143 | } |
|
3108 | 3144 | |
|
3109 | 3145 | .follow { |
|
3110 | 3146 | background: url("../images/icons/heart_add.png") no-repeat scroll 3px; |
|
3111 | 3147 | height: 16px; |
|
3112 | 3148 | width: 20px; |
|
3113 | 3149 | cursor: pointer; |
|
3114 | 3150 | display: block; |
|
3115 | 3151 | float: right; |
|
3116 | 3152 | margin-top: 2px; |
|
3117 | 3153 | } |
|
3118 | 3154 | |
|
3119 | 3155 | .following { |
|
3120 | 3156 | background: url("../images/icons/heart_delete.png") no-repeat scroll 3px; |
|
3121 | 3157 | height: 16px; |
|
3122 | 3158 | width: 20px; |
|
3123 | 3159 | cursor: pointer; |
|
3124 | 3160 | display: block; |
|
3125 | 3161 | float: right; |
|
3126 | 3162 | margin-top: 2px; |
|
3127 | 3163 | } |
|
3128 | 3164 | |
|
3129 | 3165 | .locking_locked{ |
|
3130 | 3166 | background: #FFF url("../images/icons/block_16.png") no-repeat scroll 3px; |
|
3131 | 3167 | height: 16px; |
|
3132 | 3168 | width: 20px; |
|
3133 | 3169 | cursor: pointer; |
|
3134 | 3170 | display: block; |
|
3135 | 3171 | float: right; |
|
3136 | 3172 | margin-top: 2px; |
|
3137 | 3173 | } |
|
3138 | 3174 | |
|
3139 | 3175 | .locking_unlocked{ |
|
3140 | 3176 | background: #FFF url("../images/icons/accept.png") no-repeat scroll 3px; |
|
3141 | 3177 | height: 16px; |
|
3142 | 3178 | width: 20px; |
|
3143 | 3179 | cursor: pointer; |
|
3144 | 3180 | display: block; |
|
3145 | 3181 | float: right; |
|
3146 | 3182 | margin-top: 2px; |
|
3147 | 3183 | } |
|
3148 | 3184 | |
|
3149 | 3185 | .currently_following { |
|
3150 | 3186 | padding-left: 10px; |
|
3151 | 3187 | padding-bottom: 5px; |
|
3152 | 3188 | } |
|
3153 | 3189 | |
|
3154 | 3190 | .add_icon { |
|
3155 | 3191 | background: url("../images/icons/add.png") no-repeat scroll 3px; |
|
3156 | 3192 | padding-left: 20px; |
|
3157 | 3193 | padding-top: 0px; |
|
3158 | 3194 | text-align: left; |
|
3159 | 3195 | } |
|
3160 | 3196 | |
|
3161 | 3197 | .accept_icon { |
|
3162 | 3198 | background: url("../images/icons/accept.png") no-repeat scroll 3px; |
|
3163 | 3199 | padding-left: 20px; |
|
3164 | 3200 | padding-top: 0px; |
|
3165 | 3201 | text-align: left; |
|
3166 | 3202 | } |
|
3167 | 3203 | |
|
3168 | 3204 | .edit_icon { |
|
3169 | 3205 | background: url("../images/icons/folder_edit.png") no-repeat scroll 3px; |
|
3170 | 3206 | padding-left: 20px; |
|
3171 | 3207 | padding-top: 0px; |
|
3172 | 3208 | text-align: left; |
|
3173 | 3209 | } |
|
3174 | 3210 | |
|
3175 | 3211 | .delete_icon { |
|
3176 | 3212 | background: url("../images/icons/delete.png") no-repeat scroll 3px; |
|
3177 | 3213 | padding-left: 20px; |
|
3178 | 3214 | padding-top: 0px; |
|
3179 | 3215 | text-align: left; |
|
3180 | 3216 | } |
|
3181 | 3217 | |
|
3182 | 3218 | .refresh_icon { |
|
3183 | 3219 | background: url("../images/icons/arrow_refresh.png") no-repeat scroll |
|
3184 | 3220 | 3px; |
|
3185 | 3221 | padding-left: 20px; |
|
3186 | 3222 | padding-top: 0px; |
|
3187 | 3223 | text-align: left; |
|
3188 | 3224 | } |
|
3189 | 3225 | |
|
3190 | 3226 | .pull_icon { |
|
3191 | 3227 | background: url("../images/icons/connect.png") no-repeat scroll 3px; |
|
3192 | 3228 | padding-left: 20px; |
|
3193 | 3229 | padding-top: 0px; |
|
3194 | 3230 | text-align: left; |
|
3195 | 3231 | } |
|
3196 | 3232 | |
|
3197 | 3233 | .rss_icon { |
|
3198 | 3234 | background: url("../images/icons/rss_16.png") no-repeat scroll 3px; |
|
3199 | 3235 | padding-left: 20px; |
|
3200 | 3236 | padding-top: 4px; |
|
3201 | 3237 | text-align: left; |
|
3202 | 3238 | font-size: 8px |
|
3203 | 3239 | } |
|
3204 | 3240 | |
|
3205 | 3241 | .atom_icon { |
|
3206 | 3242 | background: url("../images/icons/atom.png") no-repeat scroll 3px; |
|
3207 | 3243 | padding-left: 20px; |
|
3208 | 3244 | padding-top: 4px; |
|
3209 | 3245 | text-align: left; |
|
3210 | 3246 | font-size: 8px |
|
3211 | 3247 | } |
|
3212 | 3248 | |
|
3213 | 3249 | .archive_icon { |
|
3214 | 3250 | background: url("../images/icons/compress.png") no-repeat scroll 3px; |
|
3215 | 3251 | padding-left: 20px; |
|
3216 | 3252 | text-align: left; |
|
3217 | 3253 | padding-top: 1px; |
|
3218 | 3254 | } |
|
3219 | 3255 | |
|
3220 | 3256 | .start_following_icon { |
|
3221 | 3257 | background: url("../images/icons/heart_add.png") no-repeat scroll 3px; |
|
3222 | 3258 | padding-left: 20px; |
|
3223 | 3259 | text-align: left; |
|
3224 | 3260 | padding-top: 0px; |
|
3225 | 3261 | } |
|
3226 | 3262 | |
|
3227 | 3263 | .stop_following_icon { |
|
3228 | 3264 | background: url("../images/icons/heart_delete.png") no-repeat scroll 3px; |
|
3229 | 3265 | padding-left: 20px; |
|
3230 | 3266 | text-align: left; |
|
3231 | 3267 | padding-top: 0px; |
|
3232 | 3268 | } |
|
3233 | 3269 | |
|
3234 | 3270 | .action_button { |
|
3235 | 3271 | border: 0; |
|
3236 | 3272 | display: inline; |
|
3237 | 3273 | } |
|
3238 | 3274 | |
|
3239 | 3275 | .action_button:hover { |
|
3240 | 3276 | border: 0; |
|
3241 | 3277 | text-decoration: underline; |
|
3242 | 3278 | cursor: pointer; |
|
3243 | 3279 | } |
|
3244 | 3280 | |
|
3245 | 3281 | #switch_repos { |
|
3246 | 3282 | position: absolute; |
|
3247 | 3283 | height: 25px; |
|
3248 | 3284 | z-index: 1; |
|
3249 | 3285 | } |
|
3250 | 3286 | |
|
3251 | 3287 | #switch_repos select { |
|
3252 | 3288 | min-width: 150px; |
|
3253 | 3289 | max-height: 250px; |
|
3254 | 3290 | z-index: 1; |
|
3255 | 3291 | } |
|
3256 | 3292 | |
|
3257 | 3293 | .breadcrumbs { |
|
3258 | 3294 | border: medium none; |
|
3259 | 3295 | color: #FFF; |
|
3260 | 3296 | float: left; |
|
3261 | 3297 | text-transform: uppercase; |
|
3262 | 3298 | font-weight: 700; |
|
3263 | 3299 | font-size: 14px; |
|
3264 | 3300 | margin: 0; |
|
3265 | 3301 | padding: 11px 0 11px 10px; |
|
3266 | 3302 | } |
|
3267 | 3303 | |
|
3268 | 3304 | .breadcrumbs .hash { |
|
3269 | 3305 | text-transform: none; |
|
3270 | 3306 | color: #fff; |
|
3271 | 3307 | } |
|
3272 | 3308 | |
|
3273 | 3309 | .breadcrumbs a { |
|
3274 | 3310 | color: #FFF; |
|
3275 | 3311 | } |
|
3276 | 3312 | |
|
3277 | 3313 | .flash_msg { |
|
3278 | 3314 | |
|
3279 | 3315 | } |
|
3280 | 3316 | |
|
3281 | 3317 | .flash_msg ul { |
|
3282 | 3318 | |
|
3283 | 3319 | } |
|
3284 | 3320 | |
|
3285 | 3321 | .error_red { |
|
3286 | 3322 | color:red; |
|
3287 | 3323 | } |
|
3288 | 3324 | |
|
3289 | 3325 | .error_msg { |
|
3290 | 3326 | background-color: #c43c35; |
|
3291 | 3327 | background-repeat: repeat-x; |
|
3292 | 3328 | background-image: -khtml-gradient(linear, left top, left bottom, from(#ee5f5b), to(#c43c35) ); |
|
3293 | 3329 | background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35); |
|
3294 | 3330 | background-image: -ms-linear-gradient(top, #ee5f5b, #c43c35); |
|
3295 | 3331 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ee5f5b), color-stop(100%, #c43c35) ); |
|
3296 | 3332 | background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35); |
|
3297 | 3333 | background-image: -o-linear-gradient(top, #ee5f5b, #c43c35); |
|
3298 | 3334 | background-image: linear-gradient(top, #ee5f5b, #c43c35); |
|
3299 | 3335 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ee5f5b',endColorstr='#c43c35', GradientType=0 ); |
|
3300 | 3336 | border-color: #c43c35 #c43c35 #882a25; |
|
3301 | 3337 | } |
|
3302 | 3338 | |
|
3303 | 3339 | .warning_msg { |
|
3304 | 3340 | color: #404040 !important; |
|
3305 | 3341 | background-color: #eedc94; |
|
3306 | 3342 | background-repeat: repeat-x; |
|
3307 | 3343 | background-image: -khtml-gradient(linear, left top, left bottom, from(#fceec1), to(#eedc94) ); |
|
3308 | 3344 | background-image: -moz-linear-gradient(top, #fceec1, #eedc94); |
|
3309 | 3345 | background-image: -ms-linear-gradient(top, #fceec1, #eedc94); |
|
3310 | 3346 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #fceec1), color-stop(100%, #eedc94) ); |
|
3311 | 3347 | background-image: -webkit-linear-gradient(top, #fceec1, #eedc94); |
|
3312 | 3348 | background-image: -o-linear-gradient(top, #fceec1, #eedc94); |
|
3313 | 3349 | background-image: linear-gradient(top, #fceec1, #eedc94); |
|
3314 | 3350 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#fceec1', endColorstr='#eedc94', GradientType=0 ); |
|
3315 | 3351 | border-color: #eedc94 #eedc94 #e4c652; |
|
3316 | 3352 | } |
|
3317 | 3353 | |
|
3318 | 3354 | .success_msg { |
|
3319 | 3355 | background-color: #57a957; |
|
3320 | 3356 | background-repeat: repeat-x !important; |
|
3321 | 3357 | background-image: -khtml-gradient(linear, left top, left bottom, from(#62c462), to(#57a957) ); |
|
3322 | 3358 | background-image: -moz-linear-gradient(top, #62c462, #57a957); |
|
3323 | 3359 | background-image: -ms-linear-gradient(top, #62c462, #57a957); |
|
3324 | 3360 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #62c462), color-stop(100%, #57a957) ); |
|
3325 | 3361 | background-image: -webkit-linear-gradient(top, #62c462, #57a957); |
|
3326 | 3362 | background-image: -o-linear-gradient(top, #62c462, #57a957); |
|
3327 | 3363 | background-image: linear-gradient(top, #62c462, #57a957); |
|
3328 | 3364 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#62c462', endColorstr='#57a957', GradientType=0 ); |
|
3329 | 3365 | border-color: #57a957 #57a957 #3d773d; |
|
3330 | 3366 | } |
|
3331 | 3367 | |
|
3332 | 3368 | .notice_msg { |
|
3333 | 3369 | background-color: #339bb9; |
|
3334 | 3370 | background-repeat: repeat-x; |
|
3335 | 3371 | background-image: -khtml-gradient(linear, left top, left bottom, from(#5bc0de), to(#339bb9) ); |
|
3336 | 3372 | background-image: -moz-linear-gradient(top, #5bc0de, #339bb9); |
|
3337 | 3373 | background-image: -ms-linear-gradient(top, #5bc0de, #339bb9); |
|
3338 | 3374 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #5bc0de), color-stop(100%, #339bb9) ); |
|
3339 | 3375 | background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9); |
|
3340 | 3376 | background-image: -o-linear-gradient(top, #5bc0de, #339bb9); |
|
3341 | 3377 | background-image: linear-gradient(top, #5bc0de, #339bb9); |
|
3342 | 3378 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#5bc0de', endColorstr='#339bb9', GradientType=0 ); |
|
3343 | 3379 | border-color: #339bb9 #339bb9 #22697d; |
|
3344 | 3380 | } |
|
3345 | 3381 | |
|
3346 | 3382 | .success_msg,.error_msg,.notice_msg,.warning_msg { |
|
3347 | 3383 | font-size: 12px; |
|
3348 | 3384 | font-weight: 700; |
|
3349 | 3385 | min-height: 14px; |
|
3350 | 3386 | line-height: 14px; |
|
3351 | 3387 | margin-bottom: 10px; |
|
3352 | 3388 | margin-top: 0; |
|
3353 | 3389 | display: block; |
|
3354 | 3390 | overflow: auto; |
|
3355 | 3391 | padding: 6px 10px 6px 10px; |
|
3356 | 3392 | border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); |
|
3357 | 3393 | position: relative; |
|
3358 | 3394 | color: #FFF; |
|
3359 | 3395 | border-width: 1px; |
|
3360 | 3396 | border-style: solid; |
|
3361 | 3397 | -webkit-border-radius: 4px; |
|
3362 | 3398 | -moz-border-radius: 4px; |
|
3363 | 3399 | border-radius: 4px; |
|
3364 | 3400 | -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25); |
|
3365 | 3401 | -moz-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25); |
|
3366 | 3402 | box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.25); |
|
3367 | 3403 | } |
|
3368 | 3404 | |
|
3369 | 3405 | #msg_close { |
|
3370 | 3406 | background: transparent url("../icons/cross_grey_small.png") no-repeat scroll 0 0; |
|
3371 | 3407 | cursor: pointer; |
|
3372 | 3408 | height: 16px; |
|
3373 | 3409 | position: absolute; |
|
3374 | 3410 | right: 5px; |
|
3375 | 3411 | top: 5px; |
|
3376 | 3412 | width: 16px; |
|
3377 | 3413 | } |
|
3378 | 3414 | div#legend_data{ |
|
3379 | 3415 | padding-left:10px; |
|
3380 | 3416 | } |
|
3381 | 3417 | div#legend_container table{ |
|
3382 | 3418 | border: none !important; |
|
3383 | 3419 | } |
|
3384 | 3420 | div#legend_container table,div#legend_choices table { |
|
3385 | 3421 | width: auto !important; |
|
3386 | 3422 | } |
|
3387 | 3423 | |
|
3388 | 3424 | table#permissions_manage { |
|
3389 | 3425 | width: 0 !important; |
|
3390 | 3426 | } |
|
3391 | 3427 | |
|
3392 | 3428 | table#permissions_manage span.private_repo_msg { |
|
3393 | 3429 | font-size: 0.8em; |
|
3394 | 3430 | opacity: 0.6px; |
|
3395 | 3431 | } |
|
3396 | 3432 | |
|
3397 | 3433 | table#permissions_manage td.private_repo_msg { |
|
3398 | 3434 | font-size: 0.8em; |
|
3399 | 3435 | } |
|
3400 | 3436 | |
|
3401 | 3437 | table#permissions_manage tr#add_perm_input td { |
|
3402 | 3438 | vertical-align: middle; |
|
3403 | 3439 | } |
|
3404 | 3440 | |
|
3405 | 3441 | div.gravatar { |
|
3406 | 3442 | background-color: #FFF; |
|
3407 | 3443 | float: left; |
|
3408 | 3444 | margin-right: 0.7em; |
|
3409 | 3445 | padding: 1px 1px 1px 1px; |
|
3410 | 3446 | line-height:0; |
|
3411 | 3447 | -webkit-border-radius: 3px; |
|
3412 | 3448 | -khtml-border-radius: 3px; |
|
3413 | 3449 | -moz-border-radius: 3px; |
|
3414 | 3450 | border-radius: 3px; |
|
3415 | 3451 | } |
|
3416 | 3452 | |
|
3417 | 3453 | div.gravatar img { |
|
3418 | 3454 | -webkit-border-radius: 2px; |
|
3419 | 3455 | -khtml-border-radius: 2px; |
|
3420 | 3456 | -moz-border-radius: 2px; |
|
3421 | 3457 | border-radius: 2px; |
|
3422 | 3458 | } |
|
3423 | 3459 | |
|
3424 | 3460 | #header,#content,#footer { |
|
3425 | 3461 | min-width: 978px; |
|
3426 | 3462 | } |
|
3427 | 3463 | |
|
3428 | 3464 | #content { |
|
3429 | 3465 | clear: both; |
|
3430 | 3466 | overflow: hidden; |
|
3431 | 3467 | padding: 54px 10px 14px 10px; |
|
3432 | 3468 | } |
|
3433 | 3469 | |
|
3434 | 3470 | #content div.box div.title div.search { |
|
3435 | 3471 | |
|
3436 | 3472 | border-left: 1px solid #316293; |
|
3437 | 3473 | } |
|
3438 | 3474 | |
|
3439 | 3475 | #content div.box div.title div.search div.input input { |
|
3440 | 3476 | border: 1px solid #316293; |
|
3441 | 3477 | } |
|
3442 | 3478 | |
|
3443 | 3479 | .ui-btn{ |
|
3444 | 3480 | color: #515151; |
|
3445 | 3481 | background-color: #DADADA; |
|
3446 | 3482 | background-repeat: repeat-x; |
|
3447 | 3483 | background-image: -khtml-gradient(linear, left top, left bottom, from(#F4F4F4),to(#DADADA) ); |
|
3448 | 3484 | background-image: -moz-linear-gradient(top, #F4F4F4, #DADADA); |
|
3449 | 3485 | background-image: -ms-linear-gradient(top, #F4F4F4, #DADADA); |
|
3450 | 3486 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #F4F4F4),color-stop(100%, #DADADA) ); |
|
3451 | 3487 | background-image: -webkit-linear-gradient(top, #F4F4F4, #DADADA) ); |
|
3452 | 3488 | background-image: -o-linear-gradient(top, #F4F4F4, #DADADA) ); |
|
3453 | 3489 | background-image: linear-gradient(top, #F4F4F4, #DADADA); |
|
3454 | 3490 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#F4F4F4', endColorstr='#DADADA', GradientType=0); |
|
3455 | 3491 | |
|
3456 | 3492 | border-top: 1px solid #DDD; |
|
3457 | 3493 | border-left: 1px solid #c6c6c6; |
|
3458 | 3494 | border-right: 1px solid #DDD; |
|
3459 | 3495 | border-bottom: 1px solid #c6c6c6; |
|
3460 | 3496 | color: #515151; |
|
3461 | 3497 | outline: none; |
|
3462 | 3498 | margin: 0px 3px 3px 0px; |
|
3463 | 3499 | -webkit-border-radius: 4px 4px 4px 4px !important; |
|
3464 | 3500 | -khtml-border-radius: 4px 4px 4px 4px !important; |
|
3465 | 3501 | -moz-border-radius: 4px 4px 4px 4px !important; |
|
3466 | 3502 | border-radius: 4px 4px 4px 4px !important; |
|
3467 | 3503 | cursor: pointer !important; |
|
3468 | 3504 | padding: 3px 3px 3px 3px; |
|
3469 | 3505 | background-position: 0 -15px; |
|
3470 | 3506 | |
|
3471 | 3507 | } |
|
3472 | 3508 | .ui-btn.xsmall{ |
|
3473 | 3509 | padding: 1px 2px 1px 1px; |
|
3474 | 3510 | } |
|
3475 | 3511 | |
|
3476 | 3512 | .ui-btn.large{ |
|
3477 | 3513 | padding: 6px 12px; |
|
3478 | 3514 | } |
|
3479 | 3515 | |
|
3480 | 3516 | .ui-btn.clone{ |
|
3481 | 3517 | padding: 5px 2px 6px 1px; |
|
3482 | 3518 | margin: 0px -4px 3px 0px; |
|
3483 | 3519 | -webkit-border-radius: 4px 0px 0px 4px !important; |
|
3484 | 3520 | -khtml-border-radius: 4px 0px 0px 4px !important; |
|
3485 | 3521 | -moz-border-radius: 4px 0px 0px 4px !important; |
|
3486 | 3522 | border-radius: 4px 0px 0px 4px !important; |
|
3487 | 3523 | width: 100px; |
|
3488 | 3524 | text-align: center; |
|
3489 | 3525 | float: left; |
|
3490 | 3526 | position: absolute; |
|
3491 | 3527 | } |
|
3492 | 3528 | .ui-btn:focus { |
|
3493 | 3529 | outline: none; |
|
3494 | 3530 | } |
|
3495 | 3531 | .ui-btn:hover{ |
|
3496 | 3532 | background-position: 0 0px; |
|
3497 | 3533 | text-decoration: none; |
|
3498 | 3534 | color: #515151; |
|
3499 | 3535 | box-shadow: 0 1px 2px rgba(0, 0, 0, 0.25), 0 0 3px #FFFFFF !important; |
|
3500 | 3536 | } |
|
3501 | 3537 | |
|
3502 | 3538 | .ui-btn.red{ |
|
3503 | 3539 | color:#fff; |
|
3504 | 3540 | background-color: #c43c35; |
|
3505 | 3541 | background-repeat: repeat-x; |
|
3506 | 3542 | background-image: -khtml-gradient(linear, left top, left bottom, from(#ee5f5b), to(#c43c35)); |
|
3507 | 3543 | background-image: -moz-linear-gradient(top, #ee5f5b, #c43c35); |
|
3508 | 3544 | background-image: -ms-linear-gradient(top, #ee5f5b, #c43c35); |
|
3509 | 3545 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #ee5f5b), color-stop(100%, #c43c35)); |
|
3510 | 3546 | background-image: -webkit-linear-gradient(top, #ee5f5b, #c43c35); |
|
3511 | 3547 | background-image: -o-linear-gradient(top, #ee5f5b, #c43c35); |
|
3512 | 3548 | background-image: linear-gradient(top, #ee5f5b, #c43c35); |
|
3513 | 3549 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ee5f5b', endColorstr='#c43c35', GradientType=0); |
|
3514 | 3550 | border-color: #c43c35 #c43c35 #882a25; |
|
3515 | 3551 | border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); |
|
3516 | 3552 | } |
|
3517 | 3553 | |
|
3518 | 3554 | |
|
3519 | 3555 | .ui-btn.blue{ |
|
3520 | 3556 | color:#fff; |
|
3521 | 3557 | background-color: #339bb9; |
|
3522 | 3558 | background-repeat: repeat-x; |
|
3523 | 3559 | background-image: -khtml-gradient(linear, left top, left bottom, from(#5bc0de), to(#339bb9)); |
|
3524 | 3560 | background-image: -moz-linear-gradient(top, #5bc0de, #339bb9); |
|
3525 | 3561 | background-image: -ms-linear-gradient(top, #5bc0de, #339bb9); |
|
3526 | 3562 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #5bc0de), color-stop(100%, #339bb9)); |
|
3527 | 3563 | background-image: -webkit-linear-gradient(top, #5bc0de, #339bb9); |
|
3528 | 3564 | background-image: -o-linear-gradient(top, #5bc0de, #339bb9); |
|
3529 | 3565 | background-image: linear-gradient(top, #5bc0de, #339bb9); |
|
3530 | 3566 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#5bc0de', endColorstr='#339bb9', GradientType=0); |
|
3531 | 3567 | border-color: #339bb9 #339bb9 #22697d; |
|
3532 | 3568 | border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); |
|
3533 | 3569 | } |
|
3534 | 3570 | |
|
3535 | 3571 | .ui-btn.green{ |
|
3536 | 3572 | background-color: #57a957; |
|
3537 | 3573 | background-repeat: repeat-x; |
|
3538 | 3574 | background-image: -khtml-gradient(linear, left top, left bottom, from(#62c462), to(#57a957)); |
|
3539 | 3575 | background-image: -moz-linear-gradient(top, #62c462, #57a957); |
|
3540 | 3576 | background-image: -ms-linear-gradient(top, #62c462, #57a957); |
|
3541 | 3577 | background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #62c462), color-stop(100%, #57a957)); |
|
3542 | 3578 | background-image: -webkit-linear-gradient(top, #62c462, #57a957); |
|
3543 | 3579 | background-image: -o-linear-gradient(top, #62c462, #57a957); |
|
3544 | 3580 | background-image: linear-gradient(top, #62c462, #57a957); |
|
3545 | 3581 | filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#62c462', endColorstr='#57a957', GradientType=0); |
|
3546 | 3582 | border-color: #57a957 #57a957 #3d773d; |
|
3547 | 3583 | border-color: rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.1) rgba(0, 0, 0, 0.25); |
|
3548 | 3584 | } |
|
3549 | 3585 | |
|
3550 | 3586 | .ui-btn.active{ |
|
3551 | 3587 | font-weight: bold; |
|
3552 | 3588 | } |
|
3553 | 3589 | |
|
3554 | 3590 | ins,div.options a:hover { |
|
3555 | 3591 | text-decoration: none; |
|
3556 | 3592 | } |
|
3557 | 3593 | |
|
3558 | 3594 | img, |
|
3559 | 3595 | #header #header-inner #quick li a:hover span.normal, |
|
3560 | 3596 | #header #header-inner #quick li ul li.last, |
|
3561 | 3597 | #content div.box div.form div.fields div.field div.textarea table td table td a, |
|
3562 | 3598 | #clone_url, |
|
3563 | 3599 | #clone_url_id |
|
3564 | 3600 | { |
|
3565 | 3601 | border: none; |
|
3566 | 3602 | } |
|
3567 | 3603 | |
|
3568 | 3604 | img.icon,.right .merge img { |
|
3569 | 3605 | vertical-align: bottom; |
|
3570 | 3606 | } |
|
3571 | 3607 | |
|
3572 | 3608 | #header ul#logged-user,#content div.box div.title ul.links, |
|
3573 | 3609 | #content div.box div.message div.dismiss, |
|
3574 | 3610 | #content div.box div.traffic div.legend ul |
|
3575 | 3611 | { |
|
3576 | 3612 | float: right; |
|
3577 | 3613 | margin: 0; |
|
3578 | 3614 | padding: 0; |
|
3579 | 3615 | } |
|
3580 | 3616 | |
|
3581 | 3617 | #header #header-inner #home,#header #header-inner #logo, |
|
3582 | 3618 | #content div.box ul.left,#content div.box ol.left, |
|
3583 | 3619 | #content div.box div.pagination-left,div#commit_history, |
|
3584 | 3620 | div#legend_data,div#legend_container,div#legend_choices |
|
3585 | 3621 | { |
|
3586 | 3622 | float: left; |
|
3587 | 3623 | } |
|
3588 | 3624 | |
|
3589 | 3625 | #header #header-inner #quick li:hover ul ul, |
|
3590 | 3626 | #header #header-inner #quick li:hover ul ul ul, |
|
3591 | 3627 | #header #header-inner #quick li:hover ul ul ul ul, |
|
3592 | 3628 | #content #left #menu ul.closed,#content #left #menu li ul.collapsed,.yui-tt-shadow |
|
3593 | 3629 | { |
|
3594 | 3630 | display: none; |
|
3595 | 3631 | } |
|
3596 | 3632 | |
|
3597 | 3633 | #header #header-inner #quick li:hover ul,#header #header-inner #quick li li:hover ul,#header #header-inner #quick li li li:hover ul,#header #header-inner #quick li li li li:hover ul,#content #left #menu ul.opened,#content #left #menu li ul.expanded |
|
3598 | 3634 | { |
|
3599 | 3635 | display: block; |
|
3600 | 3636 | } |
|
3601 | 3637 | |
|
3602 | 3638 | #content div.graph { |
|
3603 | 3639 | padding: 0 10px 10px; |
|
3604 | 3640 | } |
|
3605 | 3641 | |
|
3606 | 3642 | #content div.box div.title ul.links li a:hover,#content div.box div.title ul.links li.ui-tabs-selected a |
|
3607 | 3643 | { |
|
3608 | 3644 | color: #bfe3ff; |
|
3609 | 3645 | } |
|
3610 | 3646 | |
|
3611 | 3647 | #content div.box ol.lower-roman,#content div.box ol.upper-roman,#content div.box ol.lower-alpha,#content div.box ol.upper-alpha,#content div.box ol.decimal |
|
3612 | 3648 | { |
|
3613 | 3649 | margin: 10px 24px 10px 44px; |
|
3614 | 3650 | } |
|
3615 | 3651 | |
|
3616 | 3652 | #content div.box div.form,#content div.box div.table,#content div.box div.traffic |
|
3617 | 3653 | { |
|
3618 | 3654 | clear: both; |
|
3619 | 3655 | overflow: hidden; |
|
3620 | 3656 | margin: 0; |
|
3621 | 3657 | padding: 0 20px 10px; |
|
3622 | 3658 | } |
|
3623 | 3659 | |
|
3624 | 3660 | #content div.box div.form div.fields,#login div.form,#login div.form div.fields,#register div.form,#register div.form div.fields |
|
3625 | 3661 | { |
|
3626 | 3662 | clear: both; |
|
3627 | 3663 | overflow: hidden; |
|
3628 | 3664 | margin: 0; |
|
3629 | 3665 | padding: 0; |
|
3630 | 3666 | } |
|
3631 | 3667 | |
|
3632 | 3668 | #content div.box div.form div.fields div.field div.label span,#login div.form div.fields div.field div.label span,#register div.form div.fields div.field div.label span |
|
3633 | 3669 | { |
|
3634 | 3670 | height: 1%; |
|
3635 | 3671 | display: block; |
|
3636 | 3672 | color: #363636; |
|
3637 | 3673 | margin: 0; |
|
3638 | 3674 | padding: 2px 0 0; |
|
3639 | 3675 | } |
|
3640 | 3676 | |
|
3641 | 3677 | #content div.box div.form div.fields div.field div.input input.error,#login div.form div.fields div.field div.input input.error,#register div.form div.fields div.field div.input input.error |
|
3642 | 3678 | { |
|
3643 | 3679 | background: #FBE3E4; |
|
3644 | 3680 | border-top: 1px solid #e1b2b3; |
|
3645 | 3681 | border-left: 1px solid #e1b2b3; |
|
3646 | 3682 | border-right: 1px solid #FBC2C4; |
|
3647 | 3683 | border-bottom: 1px solid #FBC2C4; |
|
3648 | 3684 | } |
|
3649 | 3685 | |
|
3650 | 3686 | #content div.box div.form div.fields div.field div.input input.success,#login div.form div.fields div.field div.input input.success,#register div.form div.fields div.field div.input input.success |
|
3651 | 3687 | { |
|
3652 | 3688 | background: #E6EFC2; |
|
3653 | 3689 | border-top: 1px solid #cebb98; |
|
3654 | 3690 | border-left: 1px solid #cebb98; |
|
3655 | 3691 | border-right: 1px solid #c6d880; |
|
3656 | 3692 | border-bottom: 1px solid #c6d880; |
|
3657 | 3693 | } |
|
3658 | 3694 | |
|
3659 | 3695 | #content div.box-left div.form div.fields div.field div.textarea,#content div.box-right div.form div.fields div.field div.textarea,#content div.box div.form div.fields div.field div.select select,#content div.box table th.selected input,#content div.box table td.selected input |
|
3660 | 3696 | { |
|
3661 | 3697 | margin: 0; |
|
3662 | 3698 | } |
|
3663 | 3699 | |
|
3664 | 3700 | #content div.box-left div.form div.fields div.field div.select,#content div.box-left div.form div.fields div.field div.checkboxes,#content div.box-left div.form div.fields div.field div.radios,#content div.box-right div.form div.fields div.field div.select,#content div.box-right div.form div.fields div.field div.checkboxes,#content div.box-right div.form div.fields div.field div.radios |
|
3665 | 3701 | { |
|
3666 | 3702 | margin: 0 0 0 0px !important; |
|
3667 | 3703 | padding: 0; |
|
3668 | 3704 | } |
|
3669 | 3705 | |
|
3670 | 3706 | #content div.box div.form div.fields div.field div.select,#content div.box div.form div.fields div.field div.checkboxes,#content div.box div.form div.fields div.field div.radios |
|
3671 | 3707 | { |
|
3672 | 3708 | margin: 0 0 0 200px; |
|
3673 | 3709 | padding: 0; |
|
3674 | 3710 | } |
|
3675 | 3711 | |
|
3676 | 3712 | #content div.box div.form div.fields div.field div.select a:hover,#content div.box div.form div.fields div.field div.select a.ui-selectmenu:hover,#content div.box div.action a:hover |
|
3677 | 3713 | { |
|
3678 | 3714 | color: #000; |
|
3679 | 3715 | text-decoration: none; |
|
3680 | 3716 | } |
|
3681 | 3717 | |
|
3682 | 3718 | #content div.box div.form div.fields div.field div.select a.ui-selectmenu-focus,#content div.box div.action a.ui-selectmenu-focus |
|
3683 | 3719 | { |
|
3684 | 3720 | border: 1px solid #666; |
|
3685 | 3721 | } |
|
3686 | 3722 | |
|
3687 | 3723 | #content div.box div.form div.fields div.field div.checkboxes div.checkbox,#content div.box div.form div.fields div.field div.radios div.radio |
|
3688 | 3724 | { |
|
3689 | 3725 | clear: both; |
|
3690 | 3726 | overflow: hidden; |
|
3691 | 3727 | margin: 0; |
|
3692 | 3728 | padding: 8px 0 2px; |
|
3693 | 3729 | } |
|
3694 | 3730 | |
|
3695 | 3731 | #content div.box div.form div.fields div.field div.checkboxes div.checkbox input,#content div.box div.form div.fields div.field div.radios div.radio input |
|
3696 | 3732 | { |
|
3697 | 3733 | float: left; |
|
3698 | 3734 | margin: 0; |
|
3699 | 3735 | } |
|
3700 | 3736 | |
|
3701 | 3737 | #content div.box div.form div.fields div.field div.checkboxes div.checkbox label,#content div.box div.form div.fields div.field div.radios div.radio label |
|
3702 | 3738 | { |
|
3703 | 3739 | height: 1%; |
|
3704 | 3740 | display: block; |
|
3705 | 3741 | float: left; |
|
3706 | 3742 | margin: 2px 0 0 4px; |
|
3707 | 3743 | } |
|
3708 | 3744 | |
|
3709 | 3745 | div.form div.fields div.field div.button input, |
|
3710 | 3746 | #content div.box div.form div.fields div.buttons input |
|
3711 | 3747 | div.form div.fields div.buttons input, |
|
3712 | 3748 | #content div.box div.action div.button input { |
|
3713 | 3749 | /*color: #000;*/ |
|
3714 | 3750 | font-size: 11px; |
|
3715 | 3751 | font-weight: 700; |
|
3716 | 3752 | margin: 0; |
|
3717 | 3753 | } |
|
3718 | 3754 | |
|
3719 | 3755 | input.ui-button { |
|
3720 | 3756 | background: #e5e3e3 url("../images/button.png") repeat-x; |
|
3721 | 3757 | border-top: 1px solid #DDD; |
|
3722 | 3758 | border-left: 1px solid #c6c6c6; |
|
3723 | 3759 | border-right: 1px solid #DDD; |
|
3724 | 3760 | border-bottom: 1px solid #c6c6c6; |
|
3725 | 3761 | color: #515151 !important; |
|
3726 | 3762 | outline: none; |
|
3727 | 3763 | margin: 0; |
|
3728 | 3764 | padding: 6px 12px; |
|
3729 | 3765 | -webkit-border-radius: 4px 4px 4px 4px; |
|
3730 | 3766 | -khtml-border-radius: 4px 4px 4px 4px; |
|
3731 | 3767 | -moz-border-radius: 4px 4px 4px 4px; |
|
3732 | 3768 | border-radius: 4px 4px 4px 4px; |
|
3733 | 3769 | box-shadow: 0 1px 0 #ececec; |
|
3734 | 3770 | cursor: pointer; |
|
3735 | 3771 | } |
|
3736 | 3772 | |
|
3737 | 3773 | input.ui-button:hover { |
|
3738 | 3774 | background: #b4b4b4 url("../images/button_selected.png") repeat-x; |
|
3739 | 3775 | border-top: 1px solid #ccc; |
|
3740 | 3776 | border-left: 1px solid #bebebe; |
|
3741 | 3777 | border-right: 1px solid #b1b1b1; |
|
3742 | 3778 | border-bottom: 1px solid #afafaf; |
|
3743 | 3779 | } |
|
3744 | 3780 | |
|
3745 | 3781 | div.form div.fields div.field div.highlight,#content div.box div.form div.fields div.buttons div.highlight |
|
3746 | 3782 | { |
|
3747 | 3783 | display: inline; |
|
3748 | 3784 | } |
|
3749 | 3785 | |
|
3750 | 3786 | #content div.box div.form div.fields div.buttons,div.form div.fields div.buttons |
|
3751 | 3787 | { |
|
3752 | 3788 | margin: 10px 0 0 200px; |
|
3753 | 3789 | padding: 0; |
|
3754 | 3790 | } |
|
3755 | 3791 | |
|
3756 | 3792 | #content div.box-left div.form div.fields div.buttons,#content div.box-right div.form div.fields div.buttons,div.box-left div.form div.fields div.buttons,div.box-right div.form div.fields div.buttons |
|
3757 | 3793 | { |
|
3758 | 3794 | margin: 10px 0 0; |
|
3759 | 3795 | } |
|
3760 | 3796 | |
|
3761 | 3797 | #content div.box table td.user,#content div.box table td.address { |
|
3762 | 3798 | width: 10%; |
|
3763 | 3799 | text-align: center; |
|
3764 | 3800 | } |
|
3765 | 3801 | |
|
3766 | 3802 | #content div.box div.action div.button,#login div.form div.fields div.field div.input div.link,#register div.form div.fields div.field div.input div.link |
|
3767 | 3803 | { |
|
3768 | 3804 | text-align: right; |
|
3769 | 3805 | margin: 6px 0 0; |
|
3770 | 3806 | padding: 0; |
|
3771 | 3807 | } |
|
3772 | 3808 | |
|
3773 | 3809 | #content div.box div.action div.button input.ui-state-hover,#login div.form div.fields div.buttons input.ui-state-hover,#register div.form div.fields div.buttons input.ui-state-hover |
|
3774 | 3810 | { |
|
3775 | 3811 | background: #b4b4b4 url("../images/button_selected.png") repeat-x; |
|
3776 | 3812 | border-top: 1px solid #ccc; |
|
3777 | 3813 | border-left: 1px solid #bebebe; |
|
3778 | 3814 | border-right: 1px solid #b1b1b1; |
|
3779 | 3815 | border-bottom: 1px solid #afafaf; |
|
3780 | 3816 | color: #515151; |
|
3781 | 3817 | margin: 0; |
|
3782 | 3818 | padding: 6px 12px; |
|
3783 | 3819 | } |
|
3784 | 3820 | |
|
3785 | 3821 | #content div.box div.pagination div.results,#content div.box div.pagination-wh div.results |
|
3786 | 3822 | { |
|
3787 | 3823 | text-align: left; |
|
3788 | 3824 | float: left; |
|
3789 | 3825 | margin: 0; |
|
3790 | 3826 | padding: 0; |
|
3791 | 3827 | } |
|
3792 | 3828 | |
|
3793 | 3829 | #content div.box div.pagination div.results span,#content div.box div.pagination-wh div.results span |
|
3794 | 3830 | { |
|
3795 | 3831 | height: 1%; |
|
3796 | 3832 | display: block; |
|
3797 | 3833 | float: left; |
|
3798 | 3834 | background: #ebebeb url("../images/pager.png") repeat-x; |
|
3799 | 3835 | border-top: 1px solid #dedede; |
|
3800 | 3836 | border-left: 1px solid #cfcfcf; |
|
3801 | 3837 | border-right: 1px solid #c4c4c4; |
|
3802 | 3838 | border-bottom: 1px solid #c4c4c4; |
|
3803 | 3839 | color: #4A4A4A; |
|
3804 | 3840 | font-weight: 700; |
|
3805 | 3841 | margin: 0; |
|
3806 | 3842 | padding: 6px 8px; |
|
3807 | 3843 | } |
|
3808 | 3844 | |
|
3809 | 3845 | #content div.box div.pagination ul.pager li.disabled,#content div.box div.pagination-wh a.disabled |
|
3810 | 3846 | { |
|
3811 | 3847 | color: #B4B4B4; |
|
3812 | 3848 | padding: 6px; |
|
3813 | 3849 | } |
|
3814 | 3850 | |
|
3815 | 3851 | #login,#register { |
|
3816 | 3852 | width: 520px; |
|
3817 | 3853 | margin: 10% auto 0; |
|
3818 | 3854 | padding: 0; |
|
3819 | 3855 | } |
|
3820 | 3856 | |
|
3821 | 3857 | #login div.color,#register div.color { |
|
3822 | 3858 | clear: both; |
|
3823 | 3859 | overflow: hidden; |
|
3824 | 3860 | background: #FFF; |
|
3825 | 3861 | margin: 10px auto 0; |
|
3826 | 3862 | padding: 3px 3px 3px 0; |
|
3827 | 3863 | } |
|
3828 | 3864 | |
|
3829 | 3865 | #login div.color a,#register div.color a { |
|
3830 | 3866 | width: 20px; |
|
3831 | 3867 | height: 20px; |
|
3832 | 3868 | display: block; |
|
3833 | 3869 | float: left; |
|
3834 | 3870 | margin: 0 0 0 3px; |
|
3835 | 3871 | padding: 0; |
|
3836 | 3872 | } |
|
3837 | 3873 | |
|
3838 | 3874 | #login div.title h5,#register div.title h5 { |
|
3839 | 3875 | color: #fff; |
|
3840 | 3876 | margin: 10px; |
|
3841 | 3877 | padding: 0; |
|
3842 | 3878 | } |
|
3843 | 3879 | |
|
3844 | 3880 | #login div.form div.fields div.field,#register div.form div.fields div.field |
|
3845 | 3881 | { |
|
3846 | 3882 | clear: both; |
|
3847 | 3883 | overflow: hidden; |
|
3848 | 3884 | margin: 0; |
|
3849 | 3885 | padding: 0 0 10px; |
|
3850 | 3886 | } |
|
3851 | 3887 | |
|
3852 | 3888 | #login div.form div.fields div.field span.error-message,#register div.form div.fields div.field span.error-message |
|
3853 | 3889 | { |
|
3854 | 3890 | height: 1%; |
|
3855 | 3891 | display: block; |
|
3856 | 3892 | color: red; |
|
3857 | 3893 | margin: 8px 0 0; |
|
3858 | 3894 | padding: 0; |
|
3859 | 3895 | max-width: 320px; |
|
3860 | 3896 | } |
|
3861 | 3897 | |
|
3862 | 3898 | #login div.form div.fields div.field div.label label,#register div.form div.fields div.field div.label label |
|
3863 | 3899 | { |
|
3864 | 3900 | color: #000; |
|
3865 | 3901 | font-weight: 700; |
|
3866 | 3902 | } |
|
3867 | 3903 | |
|
3868 | 3904 | #login div.form div.fields div.field div.input,#register div.form div.fields div.field div.input |
|
3869 | 3905 | { |
|
3870 | 3906 | float: left; |
|
3871 | 3907 | margin: 0; |
|
3872 | 3908 | padding: 0; |
|
3873 | 3909 | } |
|
3874 | 3910 | |
|
3875 | 3911 | #login div.form div.fields div.field div.checkbox,#register div.form div.fields div.field div.checkbox |
|
3876 | 3912 | { |
|
3877 | 3913 | margin: 0 0 0 184px; |
|
3878 | 3914 | padding: 0; |
|
3879 | 3915 | } |
|
3880 | 3916 | |
|
3881 | 3917 | #login div.form div.fields div.field div.checkbox label,#register div.form div.fields div.field div.checkbox label |
|
3882 | 3918 | { |
|
3883 | 3919 | color: #565656; |
|
3884 | 3920 | font-weight: 700; |
|
3885 | 3921 | } |
|
3886 | 3922 | |
|
3887 | 3923 | #login div.form div.fields div.buttons input,#register div.form div.fields div.buttons input |
|
3888 | 3924 | { |
|
3889 | 3925 | color: #000; |
|
3890 | 3926 | font-size: 1em; |
|
3891 | 3927 | font-weight: 700; |
|
3892 | 3928 | margin: 0; |
|
3893 | 3929 | } |
|
3894 | 3930 | |
|
3895 | 3931 | #changeset_content .container .wrapper,#graph_content .container .wrapper |
|
3896 | 3932 | { |
|
3897 | 3933 | width: 600px; |
|
3898 | 3934 | } |
|
3899 | 3935 | |
|
3900 | 3936 | #changeset_content .container .left { |
|
3901 | 3937 | float: left; |
|
3902 | 3938 | width: 75%; |
|
3903 | 3939 | padding-left: 5px; |
|
3904 | 3940 | } |
|
3905 | 3941 | |
|
3906 | 3942 | #changeset_content .container .left .date,.ac .match { |
|
3907 | 3943 | font-weight: 700; |
|
3908 | 3944 | padding-top: 5px; |
|
3909 | 3945 | padding-bottom: 5px; |
|
3910 | 3946 | } |
|
3911 | 3947 | |
|
3912 | 3948 | div#legend_container table td,div#legend_choices table td { |
|
3913 | 3949 | border: none !important; |
|
3914 | 3950 | height: 20px !important; |
|
3915 | 3951 | padding: 0 !important; |
|
3916 | 3952 | } |
|
3917 | 3953 | |
|
3918 | 3954 | .q_filter_box { |
|
3919 | 3955 | -webkit-box-shadow: rgba(0,0,0,0.07) 0 1px 2px inset; |
|
3920 | 3956 | -webkit-border-radius: 4px; |
|
3921 | 3957 | -moz-border-radius: 4px; |
|
3922 | 3958 | border-radius: 4px; |
|
3923 | 3959 | border: 0 none; |
|
3924 | 3960 | color: #AAAAAA; |
|
3925 | 3961 | margin-bottom: -4px; |
|
3926 | 3962 | margin-top: -4px; |
|
3927 | 3963 | padding-left: 3px; |
|
3928 | 3964 | } |
|
3929 | 3965 | |
|
3930 | 3966 | #node_filter { |
|
3931 | 3967 | border: 0px solid #545454; |
|
3932 | 3968 | color: #AAAAAA; |
|
3933 | 3969 | padding-left: 3px; |
|
3934 | 3970 | } |
|
3935 | 3971 | |
|
3936 | 3972 | |
|
3937 | 3973 | .group_members_wrap{ |
|
3938 | 3974 | min-height: 85px; |
|
3939 | 3975 | padding-left: 20px; |
|
3940 | 3976 | } |
|
3941 | 3977 | |
|
3942 | 3978 | .group_members .group_member{ |
|
3943 | 3979 | height: 30px; |
|
3944 | 3980 | padding:0px 0px 0px 0px; |
|
3945 | 3981 | } |
|
3946 | 3982 | |
|
3947 | 3983 | .reviewers_member{ |
|
3948 | 3984 | height: 15px; |
|
3949 | 3985 | padding:0px 0px 0px 10px; |
|
3950 | 3986 | } |
|
3951 | 3987 | |
|
3952 | 3988 | .emails_wrap{ |
|
3953 | 3989 | padding: 0px 20px; |
|
3954 | 3990 | } |
|
3955 | 3991 | |
|
3956 | 3992 | .emails_wrap .email_entry{ |
|
3957 | 3993 | height: 30px; |
|
3958 | 3994 | padding:0px 0px 0px 10px; |
|
3959 | 3995 | } |
|
3960 | 3996 | .emails_wrap .email_entry .email{ |
|
3961 | 3997 | float: left |
|
3962 | 3998 | } |
|
3963 | 3999 | .emails_wrap .email_entry .email_action{ |
|
3964 | 4000 | float: left |
|
3965 | 4001 | } |
|
3966 | 4002 | |
|
3967 | 4003 | /*README STYLE*/ |
|
3968 | 4004 | |
|
3969 | 4005 | div.readme { |
|
3970 | 4006 | padding:0px; |
|
3971 | 4007 | } |
|
3972 | 4008 | |
|
3973 | 4009 | div.readme h2 { |
|
3974 | 4010 | font-weight: normal; |
|
3975 | 4011 | } |
|
3976 | 4012 | |
|
3977 | 4013 | div.readme .readme_box { |
|
3978 | 4014 | background-color: #fafafa; |
|
3979 | 4015 | } |
|
3980 | 4016 | |
|
3981 | 4017 | div.readme .readme_box { |
|
3982 | 4018 | clear:both; |
|
3983 | 4019 | overflow:hidden; |
|
3984 | 4020 | margin:0; |
|
3985 | 4021 | padding:0 20px 10px; |
|
3986 | 4022 | } |
|
3987 | 4023 | |
|
3988 | 4024 | div.readme .readme_box h1, div.readme .readme_box h2, div.readme .readme_box h3, div.readme .readme_box h4, div.readme .readme_box h5, div.readme .readme_box h6 { |
|
3989 | 4025 | border-bottom: 0 !important; |
|
3990 | 4026 | margin: 0 !important; |
|
3991 | 4027 | padding: 0 !important; |
|
3992 | 4028 | line-height: 1.5em !important; |
|
3993 | 4029 | } |
|
3994 | 4030 | |
|
3995 | 4031 | |
|
3996 | 4032 | div.readme .readme_box h1:first-child { |
|
3997 | 4033 | padding-top: .25em !important; |
|
3998 | 4034 | } |
|
3999 | 4035 | |
|
4000 | 4036 | div.readme .readme_box h2, div.readme .readme_box h3 { |
|
4001 | 4037 | margin: 1em 0 !important; |
|
4002 | 4038 | } |
|
4003 | 4039 | |
|
4004 | 4040 | div.readme .readme_box h2 { |
|
4005 | 4041 | margin-top: 1.5em !important; |
|
4006 | 4042 | border-top: 4px solid #e0e0e0 !important; |
|
4007 | 4043 | padding-top: .5em !important; |
|
4008 | 4044 | } |
|
4009 | 4045 | |
|
4010 | 4046 | div.readme .readme_box p { |
|
4011 | 4047 | color: black !important; |
|
4012 | 4048 | margin: 1em 0 !important; |
|
4013 | 4049 | line-height: 1.5em !important; |
|
4014 | 4050 | } |
|
4015 | 4051 | |
|
4016 | 4052 | div.readme .readme_box ul { |
|
4017 | 4053 | list-style: disc !important; |
|
4018 | 4054 | margin: 1em 0 1em 2em !important; |
|
4019 | 4055 | } |
|
4020 | 4056 | |
|
4021 | 4057 | div.readme .readme_box ol { |
|
4022 | 4058 | list-style: decimal; |
|
4023 | 4059 | margin: 1em 0 1em 2em !important; |
|
4024 | 4060 | } |
|
4025 | 4061 | |
|
4026 | 4062 | div.readme .readme_box pre, code { |
|
4027 | 4063 | font: 12px "Bitstream Vera Sans Mono","Courier",monospace; |
|
4028 | 4064 | } |
|
4029 | 4065 | |
|
4030 | 4066 | div.readme .readme_box code { |
|
4031 | 4067 | font-size: 12px !important; |
|
4032 | 4068 | background-color: ghostWhite !important; |
|
4033 | 4069 | color: #444 !important; |
|
4034 | 4070 | padding: 0 .2em !important; |
|
4035 | 4071 | border: 1px solid #dedede !important; |
|
4036 | 4072 | } |
|
4037 | 4073 | |
|
4038 | 4074 | div.readme .readme_box pre code { |
|
4039 | 4075 | padding: 0 !important; |
|
4040 | 4076 | font-size: 12px !important; |
|
4041 | 4077 | background-color: #eee !important; |
|
4042 | 4078 | border: none !important; |
|
4043 | 4079 | } |
|
4044 | 4080 | |
|
4045 | 4081 | div.readme .readme_box pre { |
|
4046 | 4082 | margin: 1em 0; |
|
4047 | 4083 | font-size: 12px; |
|
4048 | 4084 | background-color: #eee; |
|
4049 | 4085 | border: 1px solid #ddd; |
|
4050 | 4086 | padding: 5px; |
|
4051 | 4087 | color: #444; |
|
4052 | 4088 | overflow: auto; |
|
4053 | 4089 | -webkit-box-shadow: rgba(0,0,0,0.07) 0 1px 2px inset; |
|
4054 | 4090 | -webkit-border-radius: 3px; |
|
4055 | 4091 | -moz-border-radius: 3px; |
|
4056 | 4092 | border-radius: 3px; |
|
4057 | 4093 | } |
|
4058 | 4094 | |
|
4059 | 4095 | |
|
4060 | 4096 | /** RST STYLE **/ |
|
4061 | 4097 | |
|
4062 | 4098 | |
|
4063 | 4099 | div.rst-block { |
|
4064 | 4100 | padding:0px; |
|
4065 | 4101 | } |
|
4066 | 4102 | |
|
4067 | 4103 | div.rst-block h2 { |
|
4068 | 4104 | font-weight: normal; |
|
4069 | 4105 | } |
|
4070 | 4106 | |
|
4071 | 4107 | div.rst-block { |
|
4072 | 4108 | background-color: #fafafa; |
|
4073 | 4109 | } |
|
4074 | 4110 | |
|
4075 | 4111 | div.rst-block { |
|
4076 | 4112 | clear:both; |
|
4077 | 4113 | overflow:hidden; |
|
4078 | 4114 | margin:0; |
|
4079 | 4115 | padding:0 20px 10px; |
|
4080 | 4116 | } |
|
4081 | 4117 | |
|
4082 | 4118 | div.rst-block h1, div.rst-block h2, div.rst-block h3, div.rst-block h4, div.rst-block h5, div.rst-block h6 { |
|
4083 | 4119 | border-bottom: 0 !important; |
|
4084 | 4120 | margin: 0 !important; |
|
4085 | 4121 | padding: 0 !important; |
|
4086 | 4122 | line-height: 1.5em !important; |
|
4087 | 4123 | } |
|
4088 | 4124 | |
|
4089 | 4125 | |
|
4090 | 4126 | div.rst-block h1:first-child { |
|
4091 | 4127 | padding-top: .25em !important; |
|
4092 | 4128 | } |
|
4093 | 4129 | |
|
4094 | 4130 | div.rst-block h2, div.rst-block h3 { |
|
4095 | 4131 | margin: 1em 0 !important; |
|
4096 | 4132 | } |
|
4097 | 4133 | |
|
4098 | 4134 | div.rst-block h2 { |
|
4099 | 4135 | margin-top: 1.5em !important; |
|
4100 | 4136 | border-top: 4px solid #e0e0e0 !important; |
|
4101 | 4137 | padding-top: .5em !important; |
|
4102 | 4138 | } |
|
4103 | 4139 | |
|
4104 | 4140 | div.rst-block p { |
|
4105 | 4141 | color: black !important; |
|
4106 | 4142 | margin: 1em 0 !important; |
|
4107 | 4143 | line-height: 1.5em !important; |
|
4108 | 4144 | } |
|
4109 | 4145 | |
|
4110 | 4146 | div.rst-block ul { |
|
4111 | 4147 | list-style: disc !important; |
|
4112 | 4148 | margin: 1em 0 1em 2em !important; |
|
4113 | 4149 | } |
|
4114 | 4150 | |
|
4115 | 4151 | div.rst-block ol { |
|
4116 | 4152 | list-style: decimal; |
|
4117 | 4153 | margin: 1em 0 1em 2em !important; |
|
4118 | 4154 | } |
|
4119 | 4155 | |
|
4120 | 4156 | div.rst-block pre, code { |
|
4121 | 4157 | font: 12px "Bitstream Vera Sans Mono","Courier",monospace; |
|
4122 | 4158 | } |
|
4123 | 4159 | |
|
4124 | 4160 | div.rst-block code { |
|
4125 | 4161 | font-size: 12px !important; |
|
4126 | 4162 | background-color: ghostWhite !important; |
|
4127 | 4163 | color: #444 !important; |
|
4128 | 4164 | padding: 0 .2em !important; |
|
4129 | 4165 | border: 1px solid #dedede !important; |
|
4130 | 4166 | } |
|
4131 | 4167 | |
|
4132 | 4168 | div.rst-block pre code { |
|
4133 | 4169 | padding: 0 !important; |
|
4134 | 4170 | font-size: 12px !important; |
|
4135 | 4171 | background-color: #eee !important; |
|
4136 | 4172 | border: none !important; |
|
4137 | 4173 | } |
|
4138 | 4174 | |
|
4139 | 4175 | div.rst-block pre { |
|
4140 | 4176 | margin: 1em 0; |
|
4141 | 4177 | font-size: 12px; |
|
4142 | 4178 | background-color: #eee; |
|
4143 | 4179 | border: 1px solid #ddd; |
|
4144 | 4180 | padding: 5px; |
|
4145 | 4181 | color: #444; |
|
4146 | 4182 | overflow: auto; |
|
4147 | 4183 | -webkit-box-shadow: rgba(0,0,0,0.07) 0 1px 2px inset; |
|
4148 | 4184 | -webkit-border-radius: 3px; |
|
4149 | 4185 | -moz-border-radius: 3px; |
|
4150 | 4186 | border-radius: 3px; |
|
4151 | 4187 | } |
|
4152 | 4188 | |
|
4153 | 4189 | |
|
4154 | 4190 | /** comment main **/ |
|
4155 | 4191 | .comments { |
|
4156 | 4192 | padding:10px 20px; |
|
4157 | 4193 | } |
|
4158 | 4194 | |
|
4159 | 4195 | .comments .comment { |
|
4160 | 4196 | border: 1px solid #ddd; |
|
4161 | 4197 | margin-top: 10px; |
|
4162 | 4198 | -webkit-border-radius: 4px; |
|
4163 | 4199 | -moz-border-radius: 4px; |
|
4164 | 4200 | border-radius: 4px; |
|
4165 | 4201 | } |
|
4166 | 4202 | |
|
4167 | 4203 | .comments .comment .meta { |
|
4168 | 4204 | background: #f8f8f8; |
|
4169 | 4205 | padding: 4px; |
|
4170 | 4206 | border-bottom: 1px solid #ddd; |
|
4171 | 4207 | height: 18px; |
|
4172 | 4208 | } |
|
4173 | 4209 | |
|
4174 | 4210 | .comments .comment .meta img { |
|
4175 | 4211 | vertical-align: middle; |
|
4176 | 4212 | } |
|
4177 | 4213 | |
|
4178 | 4214 | .comments .comment .meta .user { |
|
4179 | 4215 | font-weight: bold; |
|
4180 | 4216 | float: left; |
|
4181 | 4217 | padding: 4px 2px 2px 2px; |
|
4182 | 4218 | } |
|
4183 | 4219 | |
|
4184 | 4220 | .comments .comment .meta .date { |
|
4185 | 4221 | float: left; |
|
4186 | 4222 | padding:4px 4px 0px 4px; |
|
4187 | 4223 | } |
|
4188 | 4224 | |
|
4189 | 4225 | .comments .comment .text { |
|
4190 | 4226 | background-color: #FAFAFA; |
|
4191 | 4227 | } |
|
4192 | 4228 | .comment .text div.rst-block p { |
|
4193 | 4229 | margin: 0.5em 0px !important; |
|
4194 | 4230 | } |
|
4195 | 4231 | |
|
4196 | 4232 | .comments .comments-number{ |
|
4197 | 4233 | padding:0px 0px 10px 0px; |
|
4198 | 4234 | font-weight: bold; |
|
4199 | 4235 | color: #666; |
|
4200 | 4236 | font-size: 16px; |
|
4201 | 4237 | } |
|
4202 | 4238 | |
|
4203 | 4239 | /** comment form **/ |
|
4204 | 4240 | |
|
4205 | 4241 | .status-block{ |
|
4206 | 4242 | height:80px; |
|
4207 | 4243 | clear:both |
|
4208 | 4244 | } |
|
4209 | 4245 | |
|
4210 | 4246 | .comment-form .clearfix{ |
|
4211 | 4247 | background: #EEE; |
|
4212 | 4248 | -webkit-border-radius: 4px; |
|
4213 | 4249 | -moz-border-radius: 4px; |
|
4214 | 4250 | border-radius: 4px; |
|
4215 | 4251 | padding: 10px; |
|
4216 | 4252 | } |
|
4217 | 4253 | |
|
4218 | 4254 | div.comment-form { |
|
4219 | 4255 | margin-top: 20px; |
|
4220 | 4256 | } |
|
4221 | 4257 | |
|
4222 | 4258 | .comment-form strong { |
|
4223 | 4259 | display: block; |
|
4224 | 4260 | margin-bottom: 15px; |
|
4225 | 4261 | } |
|
4226 | 4262 | |
|
4227 | 4263 | .comment-form textarea { |
|
4228 | 4264 | width: 100%; |
|
4229 | 4265 | height: 100px; |
|
4230 | 4266 | font-family: 'Monaco', 'Courier', 'Courier New', monospace; |
|
4231 | 4267 | } |
|
4232 | 4268 | |
|
4233 | 4269 | form.comment-form { |
|
4234 | 4270 | margin-top: 10px; |
|
4235 | 4271 | margin-left: 10px; |
|
4236 | 4272 | } |
|
4237 | 4273 | |
|
4238 | 4274 | .comment-form-submit { |
|
4239 | 4275 | margin-top: 5px; |
|
4240 | 4276 | margin-left: 525px; |
|
4241 | 4277 | } |
|
4242 | 4278 | |
|
4243 | 4279 | .file-comments { |
|
4244 | 4280 | display: none; |
|
4245 | 4281 | } |
|
4246 | 4282 | |
|
4247 | 4283 | .comment-form .comment { |
|
4248 | 4284 | margin-left: 10px; |
|
4249 | 4285 | } |
|
4250 | 4286 | |
|
4251 | 4287 | .comment-form .comment-help{ |
|
4252 | 4288 | padding: 0px 0px 5px 0px; |
|
4253 | 4289 | color: #666; |
|
4254 | 4290 | } |
|
4255 | 4291 | |
|
4256 | 4292 | .comment-form .comment-button{ |
|
4257 | 4293 | padding-top:5px; |
|
4258 | 4294 | } |
|
4259 | 4295 | |
|
4260 | 4296 | .add-another-button { |
|
4261 | 4297 | margin-left: 10px; |
|
4262 | 4298 | margin-top: 10px; |
|
4263 | 4299 | margin-bottom: 10px; |
|
4264 | 4300 | } |
|
4265 | 4301 | |
|
4266 | 4302 | .comment .buttons { |
|
4267 | 4303 | float: right; |
|
4268 | 4304 | padding:2px 2px 0px 0px; |
|
4269 | 4305 | } |
|
4270 | 4306 | |
|
4271 | 4307 | |
|
4272 | 4308 | .show-inline-comments{ |
|
4273 | 4309 | position: relative; |
|
4274 | 4310 | top:1px |
|
4275 | 4311 | } |
|
4276 | 4312 | |
|
4277 | 4313 | /** comment inline form **/ |
|
4278 | 4314 | .comment-inline-form .overlay{ |
|
4279 | 4315 | display: none; |
|
4280 | 4316 | } |
|
4281 | 4317 | .comment-inline-form .overlay.submitting{ |
|
4282 | 4318 | display:block; |
|
4283 | 4319 | background: none repeat scroll 0 0 white; |
|
4284 | 4320 | font-size: 16px; |
|
4285 | 4321 | opacity: 0.5; |
|
4286 | 4322 | position: absolute; |
|
4287 | 4323 | text-align: center; |
|
4288 | 4324 | vertical-align: top; |
|
4289 | 4325 | |
|
4290 | 4326 | } |
|
4291 | 4327 | .comment-inline-form .overlay.submitting .overlay-text{ |
|
4292 | 4328 | width:100%; |
|
4293 | 4329 | margin-top:5%; |
|
4294 | 4330 | } |
|
4295 | 4331 | |
|
4296 | 4332 | .comment-inline-form .clearfix{ |
|
4297 | 4333 | background: #EEE; |
|
4298 | 4334 | -webkit-border-radius: 4px; |
|
4299 | 4335 | -moz-border-radius: 4px; |
|
4300 | 4336 | border-radius: 4px; |
|
4301 | 4337 | padding: 5px; |
|
4302 | 4338 | } |
|
4303 | 4339 | |
|
4304 | 4340 | div.comment-inline-form { |
|
4305 | 4341 | padding:4px 0px 6px 0px; |
|
4306 | 4342 | } |
|
4307 | 4343 | |
|
4308 | 4344 | |
|
4309 | 4345 | tr.hl-comment{ |
|
4310 | 4346 | /* |
|
4311 | 4347 | background-color: #FFFFCC !important; |
|
4312 | 4348 | */ |
|
4313 | 4349 | } |
|
4314 | 4350 | |
|
4315 | 4351 | /* |
|
4316 | 4352 | tr.hl-comment pre { |
|
4317 | 4353 | border-top: 2px solid #FFEE33; |
|
4318 | 4354 | border-left: 2px solid #FFEE33; |
|
4319 | 4355 | border-right: 2px solid #FFEE33; |
|
4320 | 4356 | } |
|
4321 | 4357 | */ |
|
4322 | 4358 | |
|
4323 | 4359 | .comment-inline-form strong { |
|
4324 | 4360 | display: block; |
|
4325 | 4361 | margin-bottom: 15px; |
|
4326 | 4362 | } |
|
4327 | 4363 | |
|
4328 | 4364 | .comment-inline-form textarea { |
|
4329 | 4365 | width: 100%; |
|
4330 | 4366 | height: 100px; |
|
4331 | 4367 | font-family: 'Monaco', 'Courier', 'Courier New', monospace; |
|
4332 | 4368 | } |
|
4333 | 4369 | |
|
4334 | 4370 | form.comment-inline-form { |
|
4335 | 4371 | margin-top: 10px; |
|
4336 | 4372 | margin-left: 10px; |
|
4337 | 4373 | } |
|
4338 | 4374 | |
|
4339 | 4375 | .comment-inline-form-submit { |
|
4340 | 4376 | margin-top: 5px; |
|
4341 | 4377 | margin-left: 525px; |
|
4342 | 4378 | } |
|
4343 | 4379 | |
|
4344 | 4380 | .file-comments { |
|
4345 | 4381 | display: none; |
|
4346 | 4382 | } |
|
4347 | 4383 | |
|
4348 | 4384 | .comment-inline-form .comment { |
|
4349 | 4385 | margin-left: 10px; |
|
4350 | 4386 | } |
|
4351 | 4387 | |
|
4352 | 4388 | .comment-inline-form .comment-help{ |
|
4353 | 4389 | padding: 0px 0px 2px 0px; |
|
4354 | 4390 | color: #666666; |
|
4355 | 4391 | font-size: 10px; |
|
4356 | 4392 | } |
|
4357 | 4393 | |
|
4358 | 4394 | .comment-inline-form .comment-button{ |
|
4359 | 4395 | padding-top:5px; |
|
4360 | 4396 | } |
|
4361 | 4397 | |
|
4362 | 4398 | /** comment inline **/ |
|
4363 | 4399 | .inline-comments { |
|
4364 | 4400 | padding:10px 20px; |
|
4365 | 4401 | } |
|
4366 | 4402 | |
|
4367 | 4403 | .inline-comments div.rst-block { |
|
4368 | 4404 | clear:both; |
|
4369 | 4405 | overflow:hidden; |
|
4370 | 4406 | margin:0; |
|
4371 | 4407 | padding:0 20px 0px; |
|
4372 | 4408 | } |
|
4373 | 4409 | .inline-comments .comment { |
|
4374 | 4410 | border: 1px solid #ddd; |
|
4375 | 4411 | -webkit-border-radius: 4px; |
|
4376 | 4412 | -moz-border-radius: 4px; |
|
4377 | 4413 | border-radius: 4px; |
|
4378 | 4414 | margin: 3px 3px 5px 5px; |
|
4379 | 4415 | background-color: #FAFAFA; |
|
4380 | 4416 | } |
|
4381 | 4417 | .inline-comments .add-comment { |
|
4382 | 4418 | padding: 2px 4px 8px 5px; |
|
4383 | 4419 | } |
|
4384 | 4420 | |
|
4385 | 4421 | .inline-comments .comment-wrapp{ |
|
4386 | 4422 | padding:1px; |
|
4387 | 4423 | } |
|
4388 | 4424 | .inline-comments .comment .meta { |
|
4389 | 4425 | background: #f8f8f8; |
|
4390 | 4426 | padding: 4px; |
|
4391 | 4427 | border-bottom: 1px solid #ddd; |
|
4392 | 4428 | height: 20px; |
|
4393 | 4429 | } |
|
4394 | 4430 | |
|
4395 | 4431 | .inline-comments .comment .meta img { |
|
4396 | 4432 | vertical-align: middle; |
|
4397 | 4433 | } |
|
4398 | 4434 | |
|
4399 | 4435 | .inline-comments .comment .meta .user { |
|
4400 | 4436 | font-weight: bold; |
|
4401 | 4437 | float:left; |
|
4402 | 4438 | padding: 3px; |
|
4403 | 4439 | } |
|
4404 | 4440 | |
|
4405 | 4441 | .inline-comments .comment .meta .date { |
|
4406 | 4442 | float:left; |
|
4407 | 4443 | padding: 3px; |
|
4408 | 4444 | } |
|
4409 | 4445 | |
|
4410 | 4446 | .inline-comments .comment .text { |
|
4411 | 4447 | background-color: #FAFAFA; |
|
4412 | 4448 | } |
|
4413 | 4449 | |
|
4414 | 4450 | .inline-comments .comments-number{ |
|
4415 | 4451 | padding:0px 0px 10px 0px; |
|
4416 | 4452 | font-weight: bold; |
|
4417 | 4453 | color: #666; |
|
4418 | 4454 | font-size: 16px; |
|
4419 | 4455 | } |
|
4420 | 4456 | .inline-comments-button .add-comment{ |
|
4421 | 4457 | margin:2px 0px 8px 5px !important |
|
4422 | 4458 | } |
|
4423 | 4459 | |
|
4424 | 4460 | |
|
4425 | 4461 | .notification-paginator{ |
|
4426 | 4462 | padding: 0px 0px 4px 16px; |
|
4427 | 4463 | float: left; |
|
4428 | 4464 | } |
|
4429 | 4465 | |
|
4430 | 4466 | .notifications{ |
|
4431 | 4467 | border-radius: 4px 4px 4px 4px; |
|
4432 | 4468 | -webkit-border-radius: 4px; |
|
4433 | 4469 | -moz-border-radius: 4px; |
|
4434 | 4470 | float: right; |
|
4435 | 4471 | margin: 20px 0px 0px 0px; |
|
4436 | 4472 | position: absolute; |
|
4437 | 4473 | text-align: center; |
|
4438 | 4474 | width: 26px; |
|
4439 | 4475 | z-index: 1000; |
|
4440 | 4476 | } |
|
4441 | 4477 | .notifications a{ |
|
4442 | 4478 | color:#888 !important; |
|
4443 | 4479 | display: block; |
|
4444 | 4480 | font-size: 10px; |
|
4445 | 4481 | background-color: #DEDEDE !important; |
|
4446 | 4482 | border-radius: 2px !important; |
|
4447 | 4483 | -webkit-border-radius: 2px !important; |
|
4448 | 4484 | -moz-border-radius: 2px !important; |
|
4449 | 4485 | } |
|
4450 | 4486 | .notifications a:hover{ |
|
4451 | 4487 | text-decoration: none !important; |
|
4452 | 4488 | background-color: #EEEFFF !important; |
|
4453 | 4489 | } |
|
4454 | 4490 | .notification-header{ |
|
4455 | 4491 | padding-top:6px; |
|
4456 | 4492 | } |
|
4457 | 4493 | .notification-header .desc{ |
|
4458 | 4494 | font-size: 16px; |
|
4459 | 4495 | height: 24px; |
|
4460 | 4496 | float: left |
|
4461 | 4497 | } |
|
4462 | 4498 | .notification-list .container.unread{ |
|
4463 | 4499 | background: none repeat scroll 0 0 rgba(255, 255, 180, 0.6); |
|
4464 | 4500 | } |
|
4465 | 4501 | .notification-header .gravatar{ |
|
4466 | 4502 | background: none repeat scroll 0 0 transparent; |
|
4467 | 4503 | padding: 0px 0px 0px 8px; |
|
4468 | 4504 | } |
|
4469 | 4505 | .notification-list .container .notification-header .desc{ |
|
4470 | 4506 | font-weight: bold; |
|
4471 | 4507 | font-size: 17px; |
|
4472 | 4508 | } |
|
4473 | 4509 | .notification-table{ |
|
4474 | 4510 | border: 1px solid #ccc; |
|
4475 | 4511 | -webkit-border-radius: 6px 6px 6px 6px; |
|
4476 | 4512 | -moz-border-radius: 6px 6px 6px 6px; |
|
4477 | 4513 | border-radius: 6px 6px 6px 6px; |
|
4478 | 4514 | clear: both; |
|
4479 | 4515 | margin: 0px 20px 0px 20px; |
|
4480 | 4516 | } |
|
4481 | 4517 | .notification-header .delete-notifications{ |
|
4482 | 4518 | float: right; |
|
4483 | 4519 | padding-top: 8px; |
|
4484 | 4520 | cursor: pointer; |
|
4485 | 4521 | } |
|
4486 | 4522 | .notification-header .read-notifications{ |
|
4487 | 4523 | float: right; |
|
4488 | 4524 | padding-top: 8px; |
|
4489 | 4525 | cursor: pointer; |
|
4490 | 4526 | } |
|
4491 | 4527 | .notification-subject{ |
|
4492 | 4528 | clear:both; |
|
4493 | 4529 | border-bottom: 1px solid #eee; |
|
4494 | 4530 | padding:5px 0px 5px 38px; |
|
4495 | 4531 | } |
|
4496 | 4532 | |
|
4497 | 4533 | .notification-body{ |
|
4498 | 4534 | clear:both; |
|
4499 | 4535 | margin: 34px 2px 2px 8px |
|
4500 | 4536 | } |
|
4501 | 4537 | |
|
4502 | 4538 | /**** |
|
4503 | 4539 | PULL REQUESTS |
|
4504 | 4540 | *****/ |
|
4505 | 4541 | .pullrequests_section_head { |
|
4506 | 4542 | padding:10px 10px 10px 0px; |
|
4507 | 4543 | font-size:16px; |
|
4508 | 4544 | font-weight: bold; |
|
4509 | 4545 | } |
|
4510 | 4546 | |
|
4511 | 4547 | /**** |
|
4512 | 4548 | PERMS |
|
4513 | 4549 | *****/ |
|
4514 | 4550 | #perms .perms_section_head { |
|
4515 | 4551 | padding:10px 10px 10px 0px; |
|
4516 | 4552 | font-size:16px; |
|
4517 | 4553 | font-weight: bold; |
|
4518 | 4554 | } |
|
4519 | 4555 | |
|
4520 | 4556 | #perms .perm_tag{ |
|
4521 | 4557 | padding: 1px 3px 1px 3px; |
|
4522 | 4558 | font-size: 10px; |
|
4523 | 4559 | font-weight: bold; |
|
4524 | 4560 | text-transform: uppercase; |
|
4525 | 4561 | white-space: nowrap; |
|
4526 | 4562 | -webkit-border-radius: 3px; |
|
4527 | 4563 | -moz-border-radius: 3px; |
|
4528 | 4564 | border-radius: 3px; |
|
4529 | 4565 | } |
|
4530 | 4566 | |
|
4531 | 4567 | #perms .perm_tag.admin{ |
|
4532 | 4568 | background-color: #B94A48; |
|
4533 | 4569 | color: #ffffff; |
|
4534 | 4570 | } |
|
4535 | 4571 | |
|
4536 | 4572 | #perms .perm_tag.write{ |
|
4537 | 4573 | background-color: #B94A48; |
|
4538 | 4574 | color: #ffffff; |
|
4539 | 4575 | } |
|
4540 | 4576 | |
|
4541 | 4577 | #perms .perm_tag.read{ |
|
4542 | 4578 | background-color: #468847; |
|
4543 | 4579 | color: #ffffff; |
|
4544 | 4580 | } |
|
4545 | 4581 | |
|
4546 | 4582 | #perms .perm_tag.none{ |
|
4547 | 4583 | background-color: #bfbfbf; |
|
4548 | 4584 | color: #ffffff; |
|
4549 | 4585 | } |
|
4550 | 4586 | |
|
4551 | 4587 | .perm-gravatar{ |
|
4552 | 4588 | vertical-align:middle; |
|
4553 | 4589 | padding:2px; |
|
4554 | 4590 | } |
|
4555 | 4591 | .perm-gravatar-ac{ |
|
4556 | 4592 | vertical-align:middle; |
|
4557 | 4593 | padding:2px; |
|
4558 | 4594 | width: 14px; |
|
4559 | 4595 | height: 14px; |
|
4560 | 4596 | } |
|
4561 | 4597 | |
|
4562 | 4598 | /***************************************************************************** |
|
4563 | 4599 | DIFFS CSS |
|
4564 | 4600 | ******************************************************************************/ |
|
4565 | 4601 | |
|
4566 | 4602 | div.diffblock { |
|
4567 | 4603 | overflow: auto; |
|
4568 | 4604 | padding: 0px; |
|
4569 | 4605 | border: 1px solid #ccc; |
|
4570 | 4606 | background: #f8f8f8; |
|
4571 | 4607 | font-size: 100%; |
|
4572 | 4608 | line-height: 100%; |
|
4573 | 4609 | /* new */ |
|
4574 | 4610 | line-height: 125%; |
|
4575 | 4611 | -webkit-border-radius: 6px 6px 0px 0px; |
|
4576 | 4612 | -moz-border-radius: 6px 6px 0px 0px; |
|
4577 | 4613 | border-radius: 6px 6px 0px 0px; |
|
4578 | 4614 | } |
|
4579 | 4615 | div.diffblock.margined{ |
|
4580 | 4616 | margin: 0px 20px 0px 20px; |
|
4581 | 4617 | } |
|
4582 | 4618 | div.diffblock .code-header{ |
|
4583 | 4619 | border-bottom: 1px solid #CCCCCC; |
|
4584 | 4620 | background: #EEEEEE; |
|
4585 | 4621 | padding:10px 0 10px 0; |
|
4586 | 4622 | height: 14px; |
|
4587 | 4623 | } |
|
4588 | 4624 | div.diffblock .code-header.cv{ |
|
4589 | 4625 | height: 34px; |
|
4590 | 4626 | } |
|
4591 | 4627 | div.diffblock .code-header-title{ |
|
4592 | 4628 | padding: 0px 0px 10px 5px !important; |
|
4593 | 4629 | margin: 0 !important; |
|
4594 | 4630 | } |
|
4595 | 4631 | div.diffblock .code-header .hash{ |
|
4596 | 4632 | float: left; |
|
4597 | 4633 | padding: 2px 0 0 2px; |
|
4598 | 4634 | } |
|
4599 | 4635 | div.diffblock .code-header .date{ |
|
4600 | 4636 | float:left; |
|
4601 | 4637 | text-transform: uppercase; |
|
4602 | 4638 | padding: 2px 0px 0px 2px; |
|
4603 | 4639 | } |
|
4604 | 4640 | div.diffblock .code-header div{ |
|
4605 | 4641 | margin-left:4px; |
|
4606 | 4642 | font-weight: bold; |
|
4607 | 4643 | font-size: 14px; |
|
4608 | 4644 | } |
|
4609 | 4645 | div.diffblock .code-body{ |
|
4610 | 4646 | background: #FFFFFF; |
|
4611 | 4647 | } |
|
4612 | 4648 | div.diffblock pre.raw{ |
|
4613 | 4649 | background: #FFFFFF; |
|
4614 | 4650 | color:#000000; |
|
4615 | 4651 | } |
|
4616 | 4652 | table.code-difftable{ |
|
4617 | 4653 | border-collapse: collapse; |
|
4618 | 4654 | width: 99%; |
|
4619 | 4655 | } |
|
4620 | 4656 | table.code-difftable td { |
|
4621 | 4657 | padding: 0 !important; |
|
4622 | 4658 | background: none !important; |
|
4623 | 4659 | border:0 !important; |
|
4624 | 4660 | vertical-align: none !important; |
|
4625 | 4661 | } |
|
4626 | 4662 | table.code-difftable .context{ |
|
4627 | 4663 | background:none repeat scroll 0 0 #DDE7EF; |
|
4628 | 4664 | } |
|
4629 | 4665 | table.code-difftable .add{ |
|
4630 | 4666 | background:none repeat scroll 0 0 #DDFFDD; |
|
4631 | 4667 | } |
|
4632 | 4668 | table.code-difftable .add ins{ |
|
4633 | 4669 | background:none repeat scroll 0 0 #AAFFAA; |
|
4634 | 4670 | text-decoration:none; |
|
4635 | 4671 | } |
|
4636 | 4672 | table.code-difftable .del{ |
|
4637 | 4673 | background:none repeat scroll 0 0 #FFDDDD; |
|
4638 | 4674 | } |
|
4639 | 4675 | table.code-difftable .del del{ |
|
4640 | 4676 | background:none repeat scroll 0 0 #FFAAAA; |
|
4641 | 4677 | text-decoration:none; |
|
4642 | 4678 | } |
|
4643 | 4679 | |
|
4644 | 4680 | /** LINE NUMBERS **/ |
|
4645 | 4681 | table.code-difftable .lineno{ |
|
4646 | 4682 | |
|
4647 | 4683 | padding-left:2px; |
|
4648 | 4684 | padding-right:2px; |
|
4649 | 4685 | text-align:right; |
|
4650 | 4686 | width:32px; |
|
4651 | 4687 | -moz-user-select:none; |
|
4652 | 4688 | -webkit-user-select: none; |
|
4653 | 4689 | border-right: 1px solid #CCC !important; |
|
4654 | 4690 | border-left: 0px solid #CCC !important; |
|
4655 | 4691 | border-top: 0px solid #CCC !important; |
|
4656 | 4692 | border-bottom: none !important; |
|
4657 | 4693 | vertical-align: middle !important; |
|
4658 | 4694 | |
|
4659 | 4695 | } |
|
4660 | 4696 | table.code-difftable .lineno.new { |
|
4661 | 4697 | } |
|
4662 | 4698 | table.code-difftable .lineno.old { |
|
4663 | 4699 | } |
|
4664 | 4700 | table.code-difftable .lineno a{ |
|
4665 | 4701 | color:#747474 !important; |
|
4666 | 4702 | font:11px "Bitstream Vera Sans Mono",Monaco,"Courier New",Courier,monospace !important; |
|
4667 | 4703 | letter-spacing:-1px; |
|
4668 | 4704 | text-align:right; |
|
4669 | 4705 | padding-right: 2px; |
|
4670 | 4706 | cursor: pointer; |
|
4671 | 4707 | display: block; |
|
4672 | 4708 | width: 32px; |
|
4673 | 4709 | } |
|
4674 | 4710 | |
|
4675 | 4711 | table.code-difftable .lineno-inline{ |
|
4676 | 4712 | background:none repeat scroll 0 0 #FFF !important; |
|
4677 | 4713 | padding-left:2px; |
|
4678 | 4714 | padding-right:2px; |
|
4679 | 4715 | text-align:right; |
|
4680 | 4716 | width:30px; |
|
4681 | 4717 | -moz-user-select:none; |
|
4682 | 4718 | -webkit-user-select: none; |
|
4683 | 4719 | } |
|
4684 | 4720 | |
|
4685 | 4721 | /** CODE **/ |
|
4686 | 4722 | table.code-difftable .code { |
|
4687 | 4723 | display: block; |
|
4688 | 4724 | width: 100%; |
|
4689 | 4725 | } |
|
4690 | 4726 | table.code-difftable .code td{ |
|
4691 | 4727 | margin:0; |
|
4692 | 4728 | padding:0; |
|
4693 | 4729 | } |
|
4694 | 4730 | table.code-difftable .code pre{ |
|
4695 | 4731 | margin:0; |
|
4696 | 4732 | padding:0; |
|
4697 | 4733 | height: 17px; |
|
4698 | 4734 | line-height: 17px; |
|
4699 | 4735 | } |
|
4700 | 4736 | |
|
4701 | 4737 | |
|
4702 | 4738 | .diffblock.margined.comm .line .code:hover{ |
|
4703 | 4739 | background-color:#FFFFCC !important; |
|
4704 | 4740 | cursor: pointer !important; |
|
4705 | 4741 | background-image:url("../images/icons/comment_add.png") !important; |
|
4706 | 4742 | background-repeat:no-repeat !important; |
|
4707 | 4743 | background-position: right !important; |
|
4708 | 4744 | background-position: 0% 50% !important; |
|
4709 | 4745 | } |
|
4710 | 4746 | .diffblock.margined.comm .line .code.no-comment:hover{ |
|
4711 | 4747 | background-image: none !important; |
|
4712 | 4748 | cursor: auto !important; |
|
4713 | 4749 | background-color: inherit !important; |
|
4714 | 4750 | |
|
4715 | 4751 | } |
@@ -1,185 +1,190 b'' | |||
|
1 | 1 | ## -*- coding: utf-8 -*- |
|
2 | 2 | |
|
3 | 3 | <%inherit file="/base/base.html"/> |
|
4 | 4 | |
|
5 | 5 | <%def name="title()"> |
|
6 | 6 | ${_('%s Changeset') % c.repo_name} - r${c.changeset.revision}:${h.short_id(c.changeset.raw_id)} - ${c.rhodecode_name} |
|
7 | 7 | </%def> |
|
8 | 8 | |
|
9 | 9 | <%def name="breadcrumbs_links()"> |
|
10 | 10 | ${h.link_to(_(u'Home'),h.url('/'))} |
|
11 | 11 | » |
|
12 | 12 | ${h.link_to(c.repo_name,h.url('summary_home',repo_name=c.repo_name))} |
|
13 | 13 | » |
|
14 | 14 | ${_('Changeset')} - <span class='hash'>r${c.changeset.revision}:${h.short_id(c.changeset.raw_id)}</span> |
|
15 | 15 | </%def> |
|
16 | 16 | |
|
17 | 17 | <%def name="page_nav()"> |
|
18 | 18 | ${self.menu('changelog')} |
|
19 | 19 | </%def> |
|
20 | 20 | |
|
21 | 21 | <%def name="main()"> |
|
22 | 22 | <div class="box"> |
|
23 | 23 | <!-- box / title --> |
|
24 | 24 | <div class="title"> |
|
25 | 25 | ${self.breadcrumbs()} |
|
26 | 26 | </div> |
|
27 | <script> | |
|
28 | var _USERS_AC_DATA = ${c.users_array|n}; | |
|
29 | var _GROUPS_AC_DATA = ${c.users_groups_array|n}; | |
|
30 | AJAX_COMMENT_URL = "${url('changeset_comment',repo_name=c.repo_name,revision=c.changeset.raw_id)}"; | |
|
31 | AJAX_COMMENT_DELETE_URL = "${url('changeset_comment_delete',repo_name=c.repo_name,comment_id='__COMMENT_ID__')}"; | |
|
32 | </script> | |
|
27 | 33 | <div class="table"> |
|
28 | 34 | <div class="diffblock"> |
|
29 | 35 | <div class="code-header"> |
|
30 | 36 | <div class="hash"> |
|
31 | 37 | r${c.changeset.revision}:${h.short_id(c.changeset.raw_id)} |
|
32 | 38 | </div> |
|
33 | 39 | <div class="date"> |
|
34 | 40 | ${h.fmt_date(c.changeset.date)} |
|
35 | 41 | </div> |
|
36 | 42 | <div class="changeset-status-container"> |
|
37 | 43 | %if c.statuses: |
|
38 | 44 | <div title="${_('Changeset status')}" class="changeset-status-lbl">[${h.changeset_status_lbl(c.statuses[0])}]</div> |
|
39 | 45 | <div class="changeset-status-ico"><img src="${h.url('/images/icons/flag_status_%s.png' % c.statuses[0])}" /></div> |
|
40 | 46 | %endif |
|
41 | 47 | </div> |
|
42 | 48 | <div class="diff-actions"> |
|
43 |
<a href="${h.url('raw_changeset_home',repo_name=c.repo_name,revision=c.changeset.raw_id,diff=' |
|
|
49 | <a href="${h.url('raw_changeset_home',repo_name=c.repo_name,revision=c.changeset.raw_id,diff='raw')}" class="tooltip" title="${h.tooltip(_('raw diff'))}"><img class="icon" src="${h.url('/images/icons/page_white.png')}"/></a> | |
|
44 | 50 | <a href="${h.url('raw_changeset_home',repo_name=c.repo_name,revision=c.changeset.raw_id,diff='download')}" class="tooltip" title="${h.tooltip(_('download diff'))}"><img class="icon" src="${h.url('/images/icons/page_white_get.png')}"/></a> |
|
45 | 51 | ${c.ignorews_url(request.GET)} |
|
46 | 52 | ${c.context_url(request.GET)} |
|
47 | 53 | </div> |
|
48 | 54 | <div class="comments-number" style="float:right;padding-right:5px">${ungettext("%d comment", "%d comments", len(c.comments)) % len(c.comments)} ${ungettext("(%d inline)", "(%d inline)", c.inline_cnt) % c.inline_cnt}</div> |
|
49 | 55 | </div> |
|
50 | 56 | </div> |
|
51 | 57 | <div id="changeset_content"> |
|
52 | 58 | <div class="container"> |
|
53 | 59 | <div class="left"> |
|
54 | 60 | <div class="author"> |
|
55 | 61 | <div class="gravatar"> |
|
56 | 62 | <img alt="gravatar" src="${h.gravatar_url(h.email_or_none(c.changeset.author),20)}"/> |
|
57 | 63 | </div> |
|
58 | 64 | <span>${h.person(c.changeset.author)}</span><br/> |
|
59 | 65 | <span><a href="mailto:${h.email_or_none(c.changeset.author)}">${h.email_or_none(c.changeset.author)}</a></span><br/> |
|
60 | 66 | </div> |
|
61 | 67 | <div class="message">${h.urlify_commit(c.changeset.message, c.repo_name)}</div> |
|
62 | 68 | </div> |
|
63 | 69 | <div class="right"> |
|
64 | 70 | <div class="changes"> |
|
65 | 71 | % if len(c.changeset.affected_files) <= c.affected_files_cut_off: |
|
66 | 72 | <span class="removed" title="${_('removed')}">${len(c.changeset.removed)}</span> |
|
67 | 73 | <span class="changed" title="${_('changed')}">${len(c.changeset.changed)}</span> |
|
68 | 74 | <span class="added" title="${_('added')}">${len(c.changeset.added)}</span> |
|
69 | 75 | % else: |
|
70 | 76 | <span class="removed" title="${_('affected %s files') % len(c.changeset.affected_files)}">!</span> |
|
71 | 77 | <span class="changed" title="${_('affected %s files') % len(c.changeset.affected_files)}">!</span> |
|
72 | 78 | <span class="added" title="${_('affected %s files') % len(c.changeset.affected_files)}">!</span> |
|
73 | 79 | % endif |
|
74 | 80 | </div> |
|
75 | 81 | |
|
76 | 82 | %if c.changeset.parents: |
|
77 | 83 | %for p_cs in reversed(c.changeset.parents): |
|
78 | 84 | <div class="parent">${_('Parent')} |
|
79 | 85 | <span class="changeset_id">${p_cs.revision}:<span class="changeset_hash">${h.link_to(h.short_id(p_cs.raw_id), |
|
80 | 86 | h.url('changeset_home',repo_name=c.repo_name,revision=p_cs.raw_id),title=p_cs.message)}</span></span> |
|
81 | 87 | </div> |
|
82 | 88 | %endfor |
|
83 | 89 | %else: |
|
84 | 90 | <div class="parent">${_('No parents')}</div> |
|
85 | 91 | %endif |
|
86 | 92 | <span class="logtags"> |
|
87 | 93 | %if len(c.changeset.parents)>1: |
|
88 | 94 | <span class="merge">${_('merge')}</span> |
|
89 | 95 | %endif |
|
90 | 96 | %if c.changeset.branch: |
|
91 | 97 | <span class="branchtag" title="${'%s %s' % (_('branch'),c.changeset.branch)}"> |
|
92 | 98 | ${h.link_to(c.changeset.branch,h.url('files_home',repo_name=c.repo_name,revision=c.changeset.raw_id))} |
|
93 | 99 | </span> |
|
94 | 100 | %endif |
|
95 | 101 | %for tag in c.changeset.tags: |
|
96 | 102 | <span class="tagtag" title="${'%s %s' % (_('tag'),tag)}"> |
|
97 | 103 | ${h.link_to(tag,h.url('files_home',repo_name=c.repo_name,revision=c.changeset.raw_id))}</span> |
|
98 | 104 | %endfor |
|
99 | 105 | </span> |
|
100 | 106 | </div> |
|
101 | 107 | </div> |
|
102 | 108 | <span> |
|
109 | % if c.limited_diff: | |
|
110 | ${_('%s files affected:') % (len(c.changeset.affected_files))} | |
|
111 | % else: | |
|
103 | 112 | ${_('%s files affected with %s insertions and %s deletions:') % (len(c.changeset.affected_files),c.lines_added,c.lines_deleted)} |
|
113 | %endif | |
|
104 | 114 |
|
|
105 | 115 | <div class="cs_files"> |
|
106 | %for change,filenode,diff,cs1,cs2,stat in c.changes: | |
|
116 | %for FID, (cs1, cs2, change, path, diff, stats) in c.changes[c.changeset.raw_id].iteritems(): | |
|
107 | 117 |
|
|
108 | 118 |
|
|
109 | %if change != 'removed': | |
|
110 | ${h.link_to(h.safe_unicode(filenode.path),c.anchor_url(filenode.changeset.raw_id,filenode.path,request.GET)+"_target")} | |
|
111 | %else: | |
|
112 | ${h.link_to(h.safe_unicode(filenode.path),h.url.current(anchor=h.FID('',filenode.path)))} | |
|
113 | %endif | |
|
119 | <a href="#${FID}">${h.safe_unicode(path)}</a> | |
|
114 | 120 |
|
|
115 |
|
|
|
121 | <div class="changes">${h.fancy_file_stats(stats)}</div> | |
|
116 | 122 |
|
|
117 | 123 |
|
|
118 |
|
|
|
119 |
|
|
|
124 | % if c.limited_diff: | |
|
125 | <h5>${_('Changeset was too big and was cut off...')}</h5> | |
|
120 | 126 |
|
|
121 | 127 | </div> |
|
122 | 128 | </div> |
|
123 | 129 | |
|
124 | 130 | </div> |
|
125 | <script> | |
|
126 | var _USERS_AC_DATA = ${c.users_array|n}; | |
|
127 | var _GROUPS_AC_DATA = ${c.users_groups_array|n}; | |
|
128 | AJAX_COMMENT_URL = "${url('changeset_comment',repo_name=c.repo_name,revision=c.changeset.raw_id)}"; | |
|
129 | AJAX_COMMENT_DELETE_URL = "${url('changeset_comment_delete',repo_name=c.repo_name,comment_id='__COMMENT_ID__')}"; | |
|
130 | </script> | |
|
131 | ||
|
131 | 132 | ## diff block |
|
132 | 133 | <%namespace name="diff_block" file="/changeset/diff_block.html"/> |
|
133 | ${diff_block.diff_block(c.changes)} | |
|
134 | ${diff_block.diff_block(c.changes[c.changeset.raw_id])} | |
|
135 | ||
|
136 | % if c.limited_diff: | |
|
137 | <h4>${_('Changeset was too big and was cut off...')}</h4> | |
|
138 | % endif | |
|
134 | 139 | |
|
135 | 140 | ## template for inline comment form |
|
136 | 141 | <%namespace name="comment" file="/changeset/changeset_file_comment.html"/> |
|
137 | 142 | ${comment.comment_inline_form()} |
|
138 | 143 | |
|
139 | 144 | ## render comments and inlines |
|
140 | 145 | ${comment.generate_comments()} |
|
141 | 146 | |
|
142 | 147 | ## main comment form and it status |
|
143 | 148 | ${comment.comments(h.url('changeset_comment', repo_name=c.repo_name, revision=c.changeset.raw_id), |
|
144 | 149 | h.changeset_status(c.rhodecode_db_repo, c.changeset.raw_id))} |
|
145 | 150 | |
|
146 | 151 | ## FORM FOR MAKING JS ACTION AS CHANGESET COMMENTS |
|
147 | 152 | <script type="text/javascript"> |
|
148 | 153 | YUE.onDOMReady(function(){ |
|
149 | 154 | YUE.on(YUQ('.show-inline-comments'),'change',function(e){ |
|
150 | 155 | var show = 'none'; |
|
151 | 156 | var target = e.currentTarget; |
|
152 | 157 | if(target == null){ |
|
153 | 158 | target = this; |
|
154 | 159 | } |
|
155 | 160 | if(target.checked){ |
|
156 | 161 | var show = '' |
|
157 | 162 | } |
|
158 | 163 | var boxid = YUD.getAttribute(target,'id_for'); |
|
159 | 164 | var comments = YUQ('#{0} .inline-comments'.format(boxid)); |
|
160 | 165 | for(c in comments){ |
|
161 | 166 | YUD.setStyle(comments[c],'display',show); |
|
162 | 167 | } |
|
163 | 168 | var btns = YUQ('#{0} .inline-comments-button'.format(boxid)); |
|
164 | 169 | for(c in btns){ |
|
165 | 170 | YUD.setStyle(btns[c],'display',show); |
|
166 | 171 | } |
|
167 | 172 | }) |
|
168 | 173 | |
|
169 | 174 | YUE.on(YUQ('.line'),'click',function(e){ |
|
170 | 175 | var tr = e.currentTarget; |
|
171 | 176 | if(tr == null){ |
|
172 | 177 | tr = this; |
|
173 | 178 | } |
|
174 | 179 | injectInlineForm(tr); |
|
175 | 180 | }); |
|
176 | 181 | |
|
177 | 182 | // inject comments into they proper positions |
|
178 | 183 | var file_comments = YUQ('.inline-comment-placeholder'); |
|
179 | 184 | renderInlineComments(file_comments); |
|
180 | 185 | }) |
|
181 | 186 | |
|
182 | 187 | </script> |
|
183 | 188 | |
|
184 | 189 | </div> |
|
185 | 190 | </%def> |
@@ -1,122 +1,122 b'' | |||
|
1 | 1 | ## -*- coding: utf-8 -*- |
|
2 | 2 | <%inherit file="/base/base.html"/> |
|
3 | 3 | |
|
4 | 4 | <%def name="title()"> |
|
5 | 5 | ${_('%s Changesets') % c.repo_name} - r${c.cs_ranges[0].revision}:${h.short_id(c.cs_ranges[0].raw_id)} -> r${c.cs_ranges[-1].revision}:${h.short_id(c.cs_ranges[-1].raw_id)} - ${c.rhodecode_name} |
|
6 | 6 | </%def> |
|
7 | 7 | |
|
8 | 8 | <%def name="breadcrumbs_links()"> |
|
9 | 9 | ${h.link_to(_(u'Home'),h.url('/'))} |
|
10 | 10 | » |
|
11 | 11 | ${h.link_to(c.repo_name,h.url('summary_home',repo_name=c.repo_name))} |
|
12 | 12 | » |
|
13 | 13 | ${_('Changesets')} - r${c.cs_ranges[0].revision}:${h.short_id(c.cs_ranges[0].raw_id)} -> r${c.cs_ranges[-1].revision}:${h.short_id(c.cs_ranges[-1].raw_id)} |
|
14 | 14 | </%def> |
|
15 | 15 | |
|
16 | 16 | <%def name="page_nav()"> |
|
17 | 17 | ${self.menu('changelog')} |
|
18 | 18 | </%def> |
|
19 | 19 | |
|
20 | 20 | <%def name="main()"> |
|
21 | 21 | <div class="box"> |
|
22 | 22 | <!-- box / title --> |
|
23 | 23 | <div class="title"> |
|
24 | 24 | ${self.breadcrumbs()} |
|
25 | 25 | </div> |
|
26 | 26 | <div class="table"> |
|
27 | 27 | <div id="body" class="diffblock"> |
|
28 | 28 | <div class="code-header cv"> |
|
29 | 29 | <h3 class="code-header-title">${_('Compare View')}</h3> |
|
30 | 30 | <div> |
|
31 | 31 | ${_('Changesets')} - r${c.cs_ranges[0].revision}:${h.short_id(c.cs_ranges[0].raw_id)} -> r${c.cs_ranges[-1].revision}:${h.short_id(c.cs_ranges[-1].raw_id)} |
|
32 | 32 | </div> |
|
33 | 33 | </div> |
|
34 | 34 | </div> |
|
35 | 35 | <div id="changeset_compare_view_content"> |
|
36 | 36 | <div class="container"> |
|
37 | 37 | <table class="compare_view_commits noborder"> |
|
38 | 38 | %for cnt,cs in enumerate(c.cs_ranges): |
|
39 | 39 | <tr> |
|
40 | 40 | <td><div class="gravatar"><img alt="gravatar" src="${h.gravatar_url(h.email_or_none(cs.author),14)}"/></div></td> |
|
41 | 41 | <td>${h.link_to('r%s:%s' % (cs.revision,h.short_id(cs.raw_id)),h.url('changeset_home',repo_name=c.repo_name,revision=cs.raw_id))}</td> |
|
42 | 42 | <td><div class="author">${h.person(cs.author)}</div></td> |
|
43 | 43 | <td><span class="tooltip" title="${h.age(cs.date)}">${cs.date}</span></td> |
|
44 | 44 | <td> |
|
45 | 45 | %if c.statuses: |
|
46 | 46 | <div title="${h.tooltip(_('Changeset status'))}" class="changeset-status-ico"><img src="${h.url('/images/icons/flag_status_%s.png' % c.statuses[cnt])}" /></div> |
|
47 | 47 | %endif |
|
48 | 48 | </td> |
|
49 | 49 | <td><div class="message">${h.urlify_commit(h.wrap_paragraphs(cs.message),c.repo_name)}</div></td> |
|
50 | 50 | </tr> |
|
51 | 51 | %endfor |
|
52 | 52 | </table> |
|
53 | 53 | </div> |
|
54 | 54 | <div style="font-size:1.1em;font-weight: bold;clear:both;padding-top:10px">${_('Files affected')}</div> |
|
55 | 55 | <div class="cs_files"> |
|
56 | 56 | %for cs in c.cs_ranges: |
|
57 | 57 | <div class="cur_cs">${h.link_to('r%s:%s' % (cs.revision,h.short_id(cs.raw_id)),h.url('changeset_home',repo_name=c.repo_name,revision=cs.raw_id))}</div> |
|
58 |
%for change, |
|
|
59 |
<div class="cs_${change}">${h.link_to(h.safe_unicode( |
|
|
58 | %for FID, (cs1, cs2, change, path, diff, stats) in c.changes[cs.raw_id].iteritems(): | |
|
59 | <div class="cs_${change}">${h.link_to(h.safe_unicode(path),h.url.current(anchor=FID))}</div> | |
|
60 | 60 | %endfor |
|
61 | 61 | %endfor |
|
62 | 62 | </div> |
|
63 | 63 | </div> |
|
64 | 64 | |
|
65 | 65 | </div> |
|
66 | 66 | <%namespace name="comment" file="/changeset/changeset_file_comment.html"/> |
|
67 | 67 | <%namespace name="diff_block" file="/changeset/diff_block.html"/> |
|
68 | 68 | %for cs in c.cs_ranges: |
|
69 | 69 | ##${comment.comment_inline_form(cs)} |
|
70 | 70 | ## diff block |
|
71 | 71 | <div class="h3"> |
|
72 | 72 | <a class="tooltip" title="${h.tooltip(cs.message)}" href="${h.url('changeset_home',repo_name=c.repo_name,revision=cs.raw_id)}">${'r%s:%s' % (cs.revision,h.short_id(cs.raw_id))}</a> |
|
73 | 73 | <div class="gravatar"> |
|
74 | 74 | <img alt="gravatar" src="${h.gravatar_url(h.email_or_none(cs.author),20)}"/> |
|
75 | 75 | </div> |
|
76 | 76 | <div class="right"> |
|
77 | 77 | <span class="logtags"> |
|
78 | 78 | %if len(cs.parents)>1: |
|
79 | 79 | <span class="merge">${_('merge')}</span> |
|
80 | 80 | %endif |
|
81 | 81 | %if cs.branch: |
|
82 | 82 | <span class="branchtag" title="${'%s %s' % (_('branch'),cs.branch)}"> |
|
83 | 83 | ${h.link_to(h.shorter(cs.branch),h.url('files_home',repo_name=c.repo_name,revision=cs.raw_id))} |
|
84 | 84 | </span> |
|
85 | 85 | %endif |
|
86 | 86 | %if h.is_hg(c.rhodecode_repo): |
|
87 | 87 | %for book in cs.bookmarks: |
|
88 | 88 | <span class="bookbook" title="${'%s %s' % (_('bookmark'),book)}"> |
|
89 | 89 | ${h.link_to(h.shorter(book),h.url('files_home',repo_name=c.repo_name,revision=cs.raw_id))} |
|
90 | 90 | </span> |
|
91 | 91 | %endfor |
|
92 | 92 | %endif |
|
93 | 93 | %for tag in cs.tags: |
|
94 | 94 | <span class="tagtag" title="${'%s %s' % (_('tag'),tag)}"> |
|
95 | 95 | ${h.link_to(h.shorter(tag),h.url('files_home',repo_name=c.repo_name,revision=cs.raw_id))}</span> |
|
96 | 96 | %endfor |
|
97 | 97 | </span> |
|
98 | 98 | </div> |
|
99 | 99 | </div> |
|
100 | 100 | ${diff_block.diff_block(c.changes[cs.raw_id])} |
|
101 | 101 | ##${comment.comments(cs)} |
|
102 | 102 | |
|
103 | 103 | %endfor |
|
104 | 104 | <script type="text/javascript"> |
|
105 | 105 | |
|
106 | 106 | YUE.onDOMReady(function(){ |
|
107 | 107 | |
|
108 | 108 | YUE.on(YUQ('.diff-menu-activate'),'click',function(e){ |
|
109 | 109 | var act = e.currentTarget.nextElementSibling; |
|
110 | 110 | |
|
111 | 111 | if(YUD.hasClass(act,'active')){ |
|
112 | 112 | YUD.removeClass(act,'active'); |
|
113 | 113 | YUD.setStyle(act,'display','none'); |
|
114 | 114 | }else{ |
|
115 | 115 | YUD.addClass(act,'active'); |
|
116 | 116 | YUD.setStyle(act,'display',''); |
|
117 | 117 | } |
|
118 | 118 | }); |
|
119 | 119 | }) |
|
120 | 120 | </script> |
|
121 | 121 | </div> |
|
122 | 122 | </%def> |
@@ -1,61 +1,61 b'' | |||
|
1 | 1 | ## -*- coding: utf-8 -*- |
|
2 | 2 | ##usage: |
|
3 | 3 | ## <%namespace name="diff_block" file="/changeset/diff_block.html"/> |
|
4 | 4 | ## ${diff_block.diff_block(change)} |
|
5 | 5 | ## |
|
6 | 6 | <%def name="diff_block(change)"> |
|
7 | 7 | |
|
8 | %for op,filenode,diff,cs1,cs2,stat in change: | |
|
9 | %if op !='removed': | |
|
10 |
<div id="${ |
|
|
11 |
<div id="${ |
|
|
8 | %for FID,(cs1, cs2, change, path, diff, stats) in change.iteritems(): | |
|
9 | ##%if op !='removed': | |
|
10 | <div id="${FID}_target" style="clear:both;margin-top:25px"></div> | |
|
11 | <div id="${FID}" class="diffblock margined comm"> | |
|
12 | 12 | <div class="code-header"> |
|
13 | 13 | <div class="changeset_header"> |
|
14 | 14 | <div class="changeset_file"> |
|
15 |
${h.link_to_if(change!='removed',h.safe_unicode( |
|
|
16 |
revision= |
|
|
15 | ${h.link_to_if(change!='removed',h.safe_unicode(path),h.url('files_home',repo_name=c.repo_name, | |
|
16 | revision=cs2,f_path=h.safe_unicode(path)))} | |
|
17 | 17 | </div> |
|
18 | 18 | <div class="diff-actions"> |
|
19 |
<a href="${h.url('files_diff_home',repo_name=c.repo_name,f_path=h.safe_unicode( |
|
|
20 |
<a href="${h.url('files_diff_home',repo_name=c.repo_name,f_path=h.safe_unicode( |
|
|
21 |
<a href="${h.url('files_diff_home',repo_name=c.repo_name,f_path=h.safe_unicode( |
|
|
22 |
${c.ignorews_url(request.GET, h.FID( |
|
|
23 |
${c.context_url(request.GET, h.FID( |
|
|
19 | <a href="${h.url('files_diff_home',repo_name=c.repo_name,f_path=h.safe_unicode(path),diff2=cs2,diff1=cs1,diff='diff',fulldiff=1)}" class="tooltip" title="${h.tooltip(_('diff'))}"><img class="icon" src="${h.url('/images/icons/page_white_go.png')}"/></a> | |
|
20 | <a href="${h.url('files_diff_home',repo_name=c.repo_name,f_path=h.safe_unicode(path),diff2=cs2,diff1=cs1,diff='raw')}" class="tooltip" title="${h.tooltip(_('raw diff'))}"><img class="icon" src="${h.url('/images/icons/page_white.png')}"/></a> | |
|
21 | <a href="${h.url('files_diff_home',repo_name=c.repo_name,f_path=h.safe_unicode(path),diff2=cs2,diff1=cs1,diff='download')}" class="tooltip" title="${h.tooltip(_('download diff'))}"><img class="icon" src="${h.url('/images/icons/page_white_get.png')}"/></a> | |
|
22 | ${c.ignorews_url(request.GET, h.FID(cs2,path))} | |
|
23 | ${c.context_url(request.GET, h.FID(cs2,path))} | |
|
24 | 24 | </div> |
|
25 | 25 | <span style="float:right;margin-top:-3px"> |
|
26 | 26 | <label> |
|
27 | 27 | ${_('show inline comments')} |
|
28 |
${h.checkbox('',checked="checked",class_="show-inline-comments",id_for=h.FID( |
|
|
28 | ${h.checkbox('',checked="checked",class_="show-inline-comments",id_for=h.FID(cs2,path))} | |
|
29 | 29 | </label> |
|
30 | 30 | </span> |
|
31 | 31 | </div> |
|
32 | 32 | </div> |
|
33 | 33 | <div class="code-body"> |
|
34 |
<div class="full_f_path" path="${h.safe_unicode( |
|
|
34 | <div class="full_f_path" path="${h.safe_unicode(path)}"></div> | |
|
35 | 35 | ${diff|n} |
|
36 | 36 | </div> |
|
37 | 37 | </div> |
|
38 | %endif | |
|
38 | ##%endif | |
|
39 | 39 | %endfor |
|
40 | 40 | |
|
41 | 41 | </%def> |
|
42 | 42 | |
|
43 | 43 | <%def name="diff_block_simple(change)"> |
|
44 | 44 | |
|
45 | 45 | %for op,filenode_path,diff in change: |
|
46 | 46 | <div id="${h.FID('',filenode_path)}_target" style="clear:both;margin-top:25px"></div> |
|
47 | 47 | <div id="${h.FID('',filenode_path)}" class="diffblock margined comm"> |
|
48 | 48 | <div class="code-header"> |
|
49 | 49 | <div class="changeset_header"> |
|
50 | 50 | <div class="changeset_file"> |
|
51 | 51 | <a href="#">${h.safe_unicode(filenode_path)}</a> |
|
52 | 52 | </div> |
|
53 | 53 | </div> |
|
54 | 54 | </div> |
|
55 | 55 | <div class="code-body"> |
|
56 | 56 | <div class="full_f_path" path="${h.safe_unicode(filenode_path)}"></div> |
|
57 | 57 | ${diff|n} |
|
58 | 58 | </div> |
|
59 | 59 | </div> |
|
60 | 60 | %endfor |
|
61 | 61 | </%def> |
@@ -1,9 +1,11 b'' | |||
|
1 |
%if h.is_hg(c. |
|
|
2 |
# ${c. |
|
|
1 | %if h.is_hg(c.rhodecode_repo): | |
|
2 | # ${c.rhodecode_repo.alias.upper()} changeset patch | |
|
3 | 3 | # User ${c.changeset.author|n} |
|
4 | 4 | # Date ${c.changeset.date} |
|
5 | 5 | # Node ID ${c.changeset.raw_id} |
|
6 | 6 | ${c.parent_tmpl} |
|
7 | 7 | ${c.changeset.message} |
|
8 | 8 | %endif |
|
9 | ${c.diffs|n} | |
|
9 | %for FID, (cs1, cs2, change, path, diff, stats) in c.changes[c.changeset.raw_id].iteritems(): | |
|
10 | ${diff|n} | |
|
11 | %endfor |
|
1 | NO CONTENT: modified file | |
The requested commit or file is too big and content was truncated. Show full diff |
|
1 | NO CONTENT: modified file | |
The requested commit or file is too big and content was truncated. Show full diff |
|
1 | NO CONTENT: modified file | |
The requested commit or file is too big and content was truncated. Show full diff |
General Comments 0
You need to be logged in to leave comments.
Login now