##// END OF EJS Templates
assets: convert pylons static files to pyramid static_url, fixes #3504
dan -
r454:a3b0830f default
parent child Browse files
Show More
@@ -1,612 +1,612 b''
1 1 ################################################################################
2 2 ################################################################################
3 3 # RhodeCode Enterprise - configuration file #
4 4 # Built-in functions and variables #
5 5 # The %(here)s variable will be replaced with the parent directory of this file#
6 6 # #
7 7 ################################################################################
8 8
9 9 [DEFAULT]
10 10 debug = true
11 11 ################################################################################
12 12 ## Uncomment and replace with the email address which should receive ##
13 13 ## any error reports after an application crash ##
14 14 ## Additionally these settings will be used by the RhodeCode mailing system ##
15 15 ################################################################################
16 16 #email_to = admin@localhost
17 17 #error_email_from = paste_error@localhost
18 18 #app_email_from = rhodecode-noreply@localhost
19 19 #error_message =
20 20 #email_prefix = [RhodeCode]
21 21
22 22 #smtp_server = mail.server.com
23 23 #smtp_username =
24 24 #smtp_password =
25 25 #smtp_port =
26 26 #smtp_use_tls = false
27 27 #smtp_use_ssl = true
28 28 ## Specify available auth parameters here (e.g. LOGIN PLAIN CRAM-MD5, etc.)
29 29 #smtp_auth =
30 30
31 31 [server:main]
32 32 ## COMMON ##
33 33 host = 127.0.0.1
34 34 port = 5000
35 35
36 36 ##################################
37 37 ## WAITRESS WSGI SERVER ##
38 38 ## Recommended for Development ##
39 39 ##################################
40 40 use = egg:waitress#main
41 41 ## number of worker threads
42 42 threads = 5
43 43 ## MAX BODY SIZE 100GB
44 44 max_request_body_size = 107374182400
45 45 ## Use poll instead of select, fixes file descriptors limits problems.
46 46 ## May not work on old windows systems.
47 47 asyncore_use_poll = true
48 48
49 49
50 50 ##########################
51 51 ## GUNICORN WSGI SERVER ##
52 52 ##########################
53 53 ## run with gunicorn --log-config <inifile.ini> --paste <inifile.ini>
54 54 #use = egg:gunicorn#main
55 55 ## Sets the number of process workers. You must set `instance_id = *`
56 56 ## when this option is set to more than one worker, recommended
57 57 ## value is (2 * NUMBER_OF_CPUS + 1), eg 2CPU = 5 workers
58 58 ## The `instance_id = *` must be set in the [app:main] section below
59 59 #workers = 2
60 60 ## number of threads for each of the worker, must be set to 1 for gevent
61 61 ## generally recommened to be at 1
62 62 #threads = 1
63 63 ## process name
64 64 #proc_name = rhodecode
65 65 ## type of worker class, one of sync, gevent
66 66 ## recommended for bigger setup is using of of other than sync one
67 67 #worker_class = sync
68 68 ## The maximum number of simultaneous clients. Valid only for Gevent
69 69 #worker_connections = 10
70 70 ## max number of requests that worker will handle before being gracefully
71 71 ## restarted, could prevent memory leaks
72 72 #max_requests = 1000
73 73 #max_requests_jitter = 30
74 74 ## amount of time a worker can spend with handling a request before it
75 75 ## gets killed and restarted. Set to 6hrs
76 76 #timeout = 21600
77 77
78 78
79 79 ## prefix middleware for RhodeCode, disables force_https flag.
80 80 ## allows to set RhodeCode under a prefix in server.
81 81 ## eg https://server.com/<prefix>. Enable `filter-with =` option below as well.
82 82 #[filter:proxy-prefix]
83 83 #use = egg:PasteDeploy#prefix
84 84 #prefix = /<your-prefix>
85 85
86 86 [app:main]
87 87 use = egg:rhodecode-enterprise-ce
88 88 ## enable proxy prefix middleware, defined below
89 89 #filter-with = proxy-prefix
90 90
91 91 # During development the we want to have the debug toolbar enabled
92 92 pyramid.includes =
93 93 pyramid_debugtoolbar
94 94 rhodecode.utils.debugtoolbar
95 95 rhodecode.lib.middleware.request_wrapper
96 96
97 97 pyramid.reload_templates = true
98 98
99 99 debugtoolbar.hosts = 0.0.0.0/0
100 100 debugtoolbar.exclude_prefixes =
101 101 /css
102 102 /fonts
103 103 /images
104 104 /js
105 105
106 106 ## RHODECODE PLUGINS ##
107 107 rhodecode.includes =
108 108 rhodecode.api
109 109
110 110
111 111 # api prefix url
112 112 rhodecode.api.url = /_admin/api
113 113
114 114
115 115 ## END RHODECODE PLUGINS ##
116 116
117 117 ## encryption key used to encrypt social plugin tokens,
118 118 ## remote_urls with credentials etc, if not set it defaults to
119 119 ## `beaker.session.secret`
120 120 #rhodecode.encrypted_values.secret =
121 121
122 122 ## decryption strict mode (enabled by default). It controls if decryption raises
123 123 ## `SignatureVerificationError` in case of wrong key, or damaged encryption data.
124 124 #rhodecode.encrypted_values.strict = false
125 125
126 126 full_stack = true
127 127
128 ## Serve static files via RhodeCode, disable to serve them via HTTP server
129 static_files = true
128 ## Return gzipped responses
129 gzip_responses = true
130 130
131 131 # autogenerate javascript routes file on startup
132 132 generate_js_files = false
133 133
134 134 ## Optional Languages
135 135 ## en(default), be, de, es, fr, it, ja, pl, pt, ru, zh
136 136 lang = en
137 137
138 138 ## perform a full repository scan on each server start, this should be
139 139 ## set to false after first startup, to allow faster server restarts.
140 140 startup.import_repos = false
141 141
142 142 ## Uncomment and set this path to use archive download cache.
143 143 ## Once enabled, generated archives will be cached at this location
144 144 ## and served from the cache during subsequent requests for the same archive of
145 145 ## the repository.
146 146 #archive_cache_dir = /tmp/tarballcache
147 147
148 148 ## change this to unique ID for security
149 149 app_instance_uuid = rc-production
150 150
151 151 ## cut off limit for large diffs (size in bytes)
152 152 cut_off_limit_diff = 1024000
153 153 cut_off_limit_file = 256000
154 154
155 155 ## use cache version of scm repo everywhere
156 156 vcs_full_cache = true
157 157
158 158 ## force https in RhodeCode, fixes https redirects, assumes it's always https
159 159 ## Normally this is controlled by proper http flags sent from http server
160 160 force_https = false
161 161
162 162 ## use Strict-Transport-Security headers
163 163 use_htsts = false
164 164
165 165 ## number of commits stats will parse on each iteration
166 166 commit_parse_limit = 25
167 167
168 168 ## git rev filter option, --all is the default filter, if you need to
169 169 ## hide all refs in changelog switch this to --branches --tags
170 170 git_rev_filter = --branches --tags
171 171
172 172 # Set to true if your repos are exposed using the dumb protocol
173 173 git_update_server_info = false
174 174
175 175 ## RSS/ATOM feed options
176 176 rss_cut_off_limit = 256000
177 177 rss_items_per_page = 10
178 178 rss_include_diff = false
179 179
180 180 ## gist URL alias, used to create nicer urls for gist. This should be an
181 181 ## url that does rewrites to _admin/gists/<gistid>.
182 182 ## example: http://gist.rhodecode.org/{gistid}. Empty means use the internal
183 183 ## RhodeCode url, ie. http[s]://rhodecode.server/_admin/gists/<gistid>
184 184 gist_alias_url =
185 185
186 186 ## List of controllers (using glob pattern syntax) that AUTH TOKENS could be
187 187 ## used for access.
188 188 ## Adding ?auth_token = <token> to the url authenticates this request as if it
189 189 ## came from the the logged in user who own this authentication token.
190 190 ##
191 191 ## Syntax is <ControllerClass>:<function_pattern>.
192 192 ## To enable access to raw_files put `FilesController:raw`.
193 193 ## To enable access to patches add `ChangesetController:changeset_patch`.
194 194 ## The list should be "," separated and on a single line.
195 195 ##
196 196 ## Recommended controllers to enable:
197 197 # ChangesetController:changeset_patch,
198 198 # ChangesetController:changeset_raw,
199 199 # FilesController:raw,
200 200 # FilesController:archivefile,
201 201 # GistsController:*,
202 202 api_access_controllers_whitelist =
203 203
204 204 ## default encoding used to convert from and to unicode
205 205 ## can be also a comma separated list of encoding in case of mixed encodings
206 206 default_encoding = UTF-8
207 207
208 208 ## instance-id prefix
209 209 ## a prefix key for this instance used for cache invalidation when running
210 210 ## multiple instances of rhodecode, make sure it's globally unique for
211 211 ## all running rhodecode instances. Leave empty if you don't use it
212 212 instance_id =
213 213
214 214 ## Fallback authentication plugin. Set this to a plugin ID to force the usage
215 215 ## of an authentication plugin also if it is disabled by it's settings.
216 216 ## This could be useful if you are unable to log in to the system due to broken
217 217 ## authentication settings. Then you can enable e.g. the internal rhodecode auth
218 218 ## module to log in again and fix the settings.
219 219 ##
220 220 ## Available builtin plugin IDs (hash is part of the ID):
221 221 ## egg:rhodecode-enterprise-ce#rhodecode
222 222 ## egg:rhodecode-enterprise-ce#pam
223 223 ## egg:rhodecode-enterprise-ce#ldap
224 224 ## egg:rhodecode-enterprise-ce#jasig_cas
225 225 ## egg:rhodecode-enterprise-ce#headers
226 226 ## egg:rhodecode-enterprise-ce#crowd
227 227 #rhodecode.auth_plugin_fallback = egg:rhodecode-enterprise-ce#rhodecode
228 228
229 229 ## alternative return HTTP header for failed authentication. Default HTTP
230 230 ## response is 401 HTTPUnauthorized. Currently HG clients have troubles with
231 231 ## handling that causing a series of failed authentication calls.
232 232 ## Set this variable to 403 to return HTTPForbidden, or any other HTTP code
233 233 ## This will be served instead of default 401 on bad authnetication
234 234 auth_ret_code =
235 235
236 236 ## use special detection method when serving auth_ret_code, instead of serving
237 237 ## ret_code directly, use 401 initially (Which triggers credentials prompt)
238 238 ## and then serve auth_ret_code to clients
239 239 auth_ret_code_detection = false
240 240
241 241 ## locking return code. When repository is locked return this HTTP code. 2XX
242 242 ## codes don't break the transactions while 4XX codes do
243 243 lock_ret_code = 423
244 244
245 245 ## allows to change the repository location in settings page
246 246 allow_repo_location_change = true
247 247
248 248 ## allows to setup custom hooks in settings page
249 249 allow_custom_hooks_settings = true
250 250
251 251 ## generated license token, goto license page in RhodeCode settings to obtain
252 252 ## new token
253 253 license_token =
254 254
255 255 ## supervisor connection uri, for managing supervisor and logs.
256 256 supervisor.uri =
257 257 ## supervisord group name/id we only want this RC instance to handle
258 258 supervisor.group_id = dev
259 259
260 260 ## Display extended labs settings
261 261 labs_settings_active = true
262 262
263 263 ####################################
264 264 ### CELERY CONFIG ####
265 265 ####################################
266 266 use_celery = false
267 267 broker.host = localhost
268 268 broker.vhost = rabbitmqhost
269 269 broker.port = 5672
270 270 broker.user = rabbitmq
271 271 broker.password = qweqwe
272 272
273 273 celery.imports = rhodecode.lib.celerylib.tasks
274 274
275 275 celery.result.backend = amqp
276 276 celery.result.dburi = amqp://
277 277 celery.result.serialier = json
278 278
279 279 #celery.send.task.error.emails = true
280 280 #celery.amqp.task.result.expires = 18000
281 281
282 282 celeryd.concurrency = 2
283 283 #celeryd.log.file = celeryd.log
284 284 celeryd.log.level = debug
285 285 celeryd.max.tasks.per.child = 1
286 286
287 287 ## tasks will never be sent to the queue, but executed locally instead.
288 288 celery.always.eager = false
289 289
290 290 ####################################
291 291 ### BEAKER CACHE ####
292 292 ####################################
293 293 # default cache dir for templates. Putting this into a ramdisk
294 294 ## can boost performance, eg. %(here)s/data_ramdisk
295 295 cache_dir = %(here)s/data
296 296
297 297 ## locking and default file storage for Beaker. Putting this into a ramdisk
298 298 ## can boost performance, eg. %(here)s/data_ramdisk/cache/beaker_data
299 299 beaker.cache.data_dir = %(here)s/data/cache/beaker_data
300 300 beaker.cache.lock_dir = %(here)s/data/cache/beaker_lock
301 301
302 302 beaker.cache.regions = super_short_term, short_term, long_term, sql_cache_short, auth_plugins, repo_cache_long
303 303
304 304 beaker.cache.super_short_term.type = memory
305 305 beaker.cache.super_short_term.expire = 10
306 306 beaker.cache.super_short_term.key_length = 256
307 307
308 308 beaker.cache.short_term.type = memory
309 309 beaker.cache.short_term.expire = 60
310 310 beaker.cache.short_term.key_length = 256
311 311
312 312 beaker.cache.long_term.type = memory
313 313 beaker.cache.long_term.expire = 36000
314 314 beaker.cache.long_term.key_length = 256
315 315
316 316 beaker.cache.sql_cache_short.type = memory
317 317 beaker.cache.sql_cache_short.expire = 10
318 318 beaker.cache.sql_cache_short.key_length = 256
319 319
320 320 # default is memory cache, configure only if required
321 321 # using multi-node or multi-worker setup
322 322 #beaker.cache.auth_plugins.type = ext:database
323 323 #beaker.cache.auth_plugins.lock_dir = %(here)s/data/cache/auth_plugin_lock
324 324 #beaker.cache.auth_plugins.url = postgresql://postgres:secret@localhost/rhodecode
325 325 #beaker.cache.auth_plugins.url = mysql://root:secret@127.0.0.1/rhodecode
326 326 #beaker.cache.auth_plugins.sa.pool_recycle = 3600
327 327 #beaker.cache.auth_plugins.sa.pool_size = 10
328 328 #beaker.cache.auth_plugins.sa.max_overflow = 0
329 329
330 330 beaker.cache.repo_cache_long.type = memorylru_base
331 331 beaker.cache.repo_cache_long.max_items = 4096
332 332 beaker.cache.repo_cache_long.expire = 2592000
333 333
334 334 # default is memorylru_base cache, configure only if required
335 335 # using multi-node or multi-worker setup
336 336 #beaker.cache.repo_cache_long.type = ext:memcached
337 337 #beaker.cache.repo_cache_long.url = localhost:11211
338 338 #beaker.cache.repo_cache_long.expire = 1209600
339 339 #beaker.cache.repo_cache_long.key_length = 256
340 340
341 341 ####################################
342 342 ### BEAKER SESSION ####
343 343 ####################################
344 344
345 345 ## .session.type is type of storage options for the session, current allowed
346 346 ## types are file, ext:memcached, ext:database, and memory (default).
347 347 beaker.session.type = file
348 348 beaker.session.data_dir = %(here)s/data/sessions/data
349 349
350 350 ## db based session, fast, and allows easy management over logged in users ##
351 351 #beaker.session.type = ext:database
352 352 #beaker.session.table_name = db_session
353 353 #beaker.session.sa.url = postgresql://postgres:secret@localhost/rhodecode
354 354 #beaker.session.sa.url = mysql://root:secret@127.0.0.1/rhodecode
355 355 #beaker.session.sa.pool_recycle = 3600
356 356 #beaker.session.sa.echo = false
357 357
358 358 beaker.session.key = rhodecode
359 359 beaker.session.secret = develop-rc-uytcxaz
360 360 beaker.session.lock_dir = %(here)s/data/sessions/lock
361 361
362 362 ## Secure encrypted cookie. Requires AES and AES python libraries
363 363 ## you must disable beaker.session.secret to use this
364 364 #beaker.session.encrypt_key = <key_for_encryption>
365 365 #beaker.session.validate_key = <validation_key>
366 366
367 367 ## sets session as invalid(also logging out user) if it haven not been
368 368 ## accessed for given amount of time in seconds
369 369 beaker.session.timeout = 2592000
370 370 beaker.session.httponly = true
371 371 #beaker.session.cookie_path = /<your-prefix>
372 372
373 373 ## uncomment for https secure cookie
374 374 beaker.session.secure = false
375 375
376 376 ## auto save the session to not to use .save()
377 377 beaker.session.auto = false
378 378
379 379 ## default cookie expiration time in seconds, set to `true` to set expire
380 380 ## at browser close
381 381 #beaker.session.cookie_expires = 3600
382 382
383 383 ###################################
384 384 ## SEARCH INDEXING CONFIGURATION ##
385 385 ###################################
386 386 ## Full text search indexer is available in rhodecode-tools under
387 387 ## `rhodecode-tools index` command
388 388
389 389 # WHOOSH Backend, doesn't require additional services to run
390 390 # it works good with few dozen repos
391 391 search.module = rhodecode.lib.index.whoosh
392 392 search.location = %(here)s/data/index
393 393
394 394 ###################################
395 395 ## APPENLIGHT CONFIG ##
396 396 ###################################
397 397
398 398 ## Appenlight is tailored to work with RhodeCode, see
399 399 ## http://appenlight.com for details how to obtain an account
400 400
401 401 ## appenlight integration enabled
402 402 appenlight = false
403 403
404 404 appenlight.server_url = https://api.appenlight.com
405 405 appenlight.api_key = YOUR_API_KEY
406 406 #appenlight.transport_config = https://api.appenlight.com?threaded=1&timeout=5
407 407
408 408 # used for JS client
409 409 appenlight.api_public_key = YOUR_API_PUBLIC_KEY
410 410
411 411 ## TWEAK AMOUNT OF INFO SENT HERE
412 412
413 413 ## enables 404 error logging (default False)
414 414 appenlight.report_404 = false
415 415
416 416 ## time in seconds after request is considered being slow (default 1)
417 417 appenlight.slow_request_time = 1
418 418
419 419 ## record slow requests in application
420 420 ## (needs to be enabled for slow datastore recording and time tracking)
421 421 appenlight.slow_requests = true
422 422
423 423 ## enable hooking to application loggers
424 424 appenlight.logging = true
425 425
426 426 ## minimum log level for log capture
427 427 appenlight.logging.level = WARNING
428 428
429 429 ## send logs only from erroneous/slow requests
430 430 ## (saves API quota for intensive logging)
431 431 appenlight.logging_on_error = false
432 432
433 433 ## list of additonal keywords that should be grabbed from environ object
434 434 ## can be string with comma separated list of words in lowercase
435 435 ## (by default client will always send following info:
436 436 ## 'REMOTE_USER', 'REMOTE_ADDR', 'SERVER_NAME', 'CONTENT_TYPE' + all keys that
437 437 ## start with HTTP* this list be extended with additional keywords here
438 438 appenlight.environ_keys_whitelist =
439 439
440 440 ## list of keywords that should be blanked from request object
441 441 ## can be string with comma separated list of words in lowercase
442 442 ## (by default client will always blank keys that contain following words
443 443 ## 'password', 'passwd', 'pwd', 'auth_tkt', 'secret', 'csrf'
444 444 ## this list be extended with additional keywords set here
445 445 appenlight.request_keys_blacklist =
446 446
447 447 ## list of namespaces that should be ignores when gathering log entries
448 448 ## can be string with comma separated list of namespaces
449 449 ## (by default the client ignores own entries: appenlight_client.client)
450 450 appenlight.log_namespace_blacklist =
451 451
452 452
453 453 ################################################################################
454 454 ## WARNING: *THE LINE BELOW MUST BE UNCOMMENTED ON A PRODUCTION ENVIRONMENT* ##
455 455 ## Debug mode will enable the interactive debugging tool, allowing ANYONE to ##
456 456 ## execute malicious code after an exception is raised. ##
457 457 ################################################################################
458 458 #set debug = false
459 459
460 460
461 461 ##############
462 462 ## STYLING ##
463 463 ##############
464 464 debug_style = true
465 465
466 466 #########################################################
467 467 ### DB CONFIGS - EACH DB WILL HAVE IT'S OWN CONFIG ###
468 468 #########################################################
469 469 sqlalchemy.db1.url = sqlite:///%(here)s/rhodecode.db?timeout=30
470 470 #sqlalchemy.db1.url = postgresql://postgres:qweqwe@localhost/rhodecode
471 471 #sqlalchemy.db1.url = mysql://root:qweqwe@localhost/rhodecode
472 472
473 473 # see sqlalchemy docs for other advanced settings
474 474
475 475 ## print the sql statements to output
476 476 sqlalchemy.db1.echo = false
477 477 ## recycle the connections after this ammount of seconds
478 478 sqlalchemy.db1.pool_recycle = 3600
479 479 sqlalchemy.db1.convert_unicode = true
480 480
481 481 ## the number of connections to keep open inside the connection pool.
482 482 ## 0 indicates no limit
483 483 #sqlalchemy.db1.pool_size = 5
484 484
485 485 ## the number of connections to allow in connection pool "overflow", that is
486 486 ## connections that can be opened above and beyond the pool_size setting,
487 487 ## which defaults to five.
488 488 #sqlalchemy.db1.max_overflow = 10
489 489
490 490
491 491 ##################
492 492 ### VCS CONFIG ###
493 493 ##################
494 494 vcs.server.enable = true
495 495 vcs.server = localhost:9900
496 496
497 497 ## Web server connectivity protocol, responsible for web based VCS operatations
498 498 ## Available protocols are:
499 499 ## `pyro4` - using pyro4 server
500 500 ## `http` - using http-rpc backend
501 501 #vcs.server.protocol = http
502 502
503 503 ## Push/Pull operations protocol, available options are:
504 504 ## `pyro4` - using pyro4 server
505 505 ## `rhodecode.lib.middleware.utils.scm_app_http` - Http based, recommended
506 506 ## `vcsserver.scm_app` - internal app (EE only)
507 507 #vcs.scm_app_implementation = rhodecode.lib.middleware.utils.scm_app_http
508 508
509 509 ## Push/Pull operations hooks protocol, available options are:
510 510 ## `pyro4` - using pyro4 server
511 511 ## `http` - using http-rpc backend
512 512 #vcs.hooks.protocol = http
513 513
514 514 vcs.server.log_level = debug
515 515 ## Start VCSServer with this instance as a subprocess, usefull for development
516 516 vcs.start_server = true
517 517 vcs.backends = hg, git, svn
518 518 vcs.connection_timeout = 3600
519 519 ## Compatibility version when creating SVN repositories. Defaults to newest version when commented out.
520 520 ## Available options are: pre-1.4-compatible, pre-1.5-compatible, pre-1.6-compatible, pre-1.8-compatible
521 521 #vcs.svn.compatible_version = pre-1.8-compatible
522 522
523 523 ################################
524 524 ### LOGGING CONFIGURATION ####
525 525 ################################
526 526 [loggers]
527 527 keys = root, routes, rhodecode, sqlalchemy, beaker, pyro4, templates
528 528
529 529 [handlers]
530 530 keys = console, console_sql
531 531
532 532 [formatters]
533 533 keys = generic, color_formatter, color_formatter_sql
534 534
535 535 #############
536 536 ## LOGGERS ##
537 537 #############
538 538 [logger_root]
539 539 level = NOTSET
540 540 handlers = console
541 541
542 542 [logger_routes]
543 543 level = DEBUG
544 544 handlers =
545 545 qualname = routes.middleware
546 546 ## "level = DEBUG" logs the route matched and routing variables.
547 547 propagate = 1
548 548
549 549 [logger_beaker]
550 550 level = DEBUG
551 551 handlers =
552 552 qualname = beaker.container
553 553 propagate = 1
554 554
555 555 [logger_pyro4]
556 556 level = DEBUG
557 557 handlers =
558 558 qualname = Pyro4
559 559 propagate = 1
560 560
561 561 [logger_templates]
562 562 level = INFO
563 563 handlers =
564 564 qualname = pylons.templating
565 565 propagate = 1
566 566
567 567 [logger_rhodecode]
568 568 level = DEBUG
569 569 handlers =
570 570 qualname = rhodecode
571 571 propagate = 1
572 572
573 573 [logger_sqlalchemy]
574 574 level = INFO
575 575 handlers = console_sql
576 576 qualname = sqlalchemy.engine
577 577 propagate = 0
578 578
579 579 ##############
580 580 ## HANDLERS ##
581 581 ##############
582 582
583 583 [handler_console]
584 584 class = StreamHandler
585 585 args = (sys.stderr,)
586 586 level = DEBUG
587 587 formatter = color_formatter
588 588
589 589 [handler_console_sql]
590 590 class = StreamHandler
591 591 args = (sys.stderr,)
592 592 level = DEBUG
593 593 formatter = color_formatter_sql
594 594
595 595 ################
596 596 ## FORMATTERS ##
597 597 ################
598 598
599 599 [formatter_generic]
600 600 class = rhodecode.lib.logging_formatter.Pyro4AwareFormatter
601 601 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
602 602 datefmt = %Y-%m-%d %H:%M:%S
603 603
604 604 [formatter_color_formatter]
605 605 class = rhodecode.lib.logging_formatter.ColorFormatter
606 606 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
607 607 datefmt = %Y-%m-%d %H:%M:%S
608 608
609 609 [formatter_color_formatter_sql]
610 610 class = rhodecode.lib.logging_formatter.ColorFormatterSql
611 611 format = %(asctime)s.%(msecs)03d %(levelname)-5.5s [%(name)s] %(message)s
612 612 datefmt = %Y-%m-%d %H:%M:%S
@@ -1,387 +1,367 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2010-2016 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 21 """
22 22 Pylons middleware initialization
23 23 """
24 24 import logging
25 25
26 26 from paste.registry import RegistryManager
27 27 from paste.gzipper import make_gzip_middleware
28 28 from pylons.wsgiapp import PylonsApp
29 29 from pyramid.authorization import ACLAuthorizationPolicy
30 30 from pyramid.config import Configurator
31 31 from pyramid.static import static_view
32 32 from pyramid.settings import asbool, aslist
33 33 from pyramid.wsgi import wsgiapp
34 34 from pyramid.httpexceptions import HTTPError, HTTPInternalServerError
35 35 import pyramid.httpexceptions as httpexceptions
36 36 from pyramid.renderers import render_to_response, render
37 37 from routes.middleware import RoutesMiddleware
38 38 import routes.util
39 39
40 40 import rhodecode
41 41 import rhodecode.integrations # do not remove this as it registers celery tasks
42 42 from rhodecode.config import patches
43 43 from rhodecode.config.environment import (
44 44 load_environment, load_pyramid_environment)
45 45 from rhodecode.lib.middleware import csrf
46 46 from rhodecode.lib.middleware.appenlight import wrap_in_appenlight_if_enabled
47 47 from rhodecode.lib.middleware.disable_vcs import DisableVCSPagesWrapper
48 48 from rhodecode.lib.middleware.https_fixup import HttpsFixup
49 49 from rhodecode.lib.middleware.vcs import VCSMiddleware
50 50 from rhodecode.lib.plugins.utils import register_rhodecode_plugin
51 51
52 52
53 53 log = logging.getLogger(__name__)
54 54
55 55
56 56 def make_app(global_conf, full_stack=True, static_files=True, **app_conf):
57 57 """Create a Pylons WSGI application and return it
58 58
59 59 ``global_conf``
60 60 The inherited configuration for this application. Normally from
61 61 the [DEFAULT] section of the Paste ini file.
62 62
63 63 ``full_stack``
64 64 Whether or not this application provides a full WSGI stack (by
65 65 default, meaning it handles its own exceptions and errors).
66 66 Disable full_stack when this application is "managed" by
67 67 another WSGI middleware.
68 68
69 69 ``app_conf``
70 70 The application's local configuration. Normally specified in
71 71 the [app:<name>] section of the Paste ini file (where <name>
72 72 defaults to main).
73 73
74 74 """
75 75 # Apply compatibility patches
76 76 patches.kombu_1_5_1_python_2_7_11()
77 77 patches.inspect_getargspec()
78 78
79 79 # Configure the Pylons environment
80 80 config = load_environment(global_conf, app_conf)
81 81
82 82 # The Pylons WSGI app
83 83 app = PylonsApp(config=config)
84 84 if rhodecode.is_test:
85 85 app = csrf.CSRFDetector(app)
86 86
87 87 expected_origin = config.get('expected_origin')
88 88 if expected_origin:
89 89 # The API can be accessed from other Origins.
90 90 app = csrf.OriginChecker(app, expected_origin,
91 91 skip_urls=[routes.util.url_for('api')])
92 92
93 93
94 94 if asbool(full_stack):
95 95
96 96 # Appenlight monitoring and error handler
97 97 app, appenlight_client = wrap_in_appenlight_if_enabled(app, config)
98 98
99 99 # we want our low level middleware to get to the request ASAP. We don't
100 100 # need any pylons stack middleware in them
101 101 app = VCSMiddleware(app, config, appenlight_client)
102 102
103 103 # Establish the Registry for this application
104 104 app = RegistryManager(app)
105 105
106 106 app.config = config
107 107
108 108 return app
109 109
110 110
111 111 def make_pyramid_app(global_config, **settings):
112 112 """
113 113 Constructs the WSGI application based on Pyramid and wraps the Pylons based
114 114 application.
115 115
116 116 Specials:
117 117
118 118 * We migrate from Pylons to Pyramid. While doing this, we keep both
119 119 frameworks functional. This involves moving some WSGI middlewares around
120 120 and providing access to some data internals, so that the old code is
121 121 still functional.
122 122
123 123 * The application can also be integrated like a plugin via the call to
124 124 `includeme`. This is accompanied with the other utility functions which
125 125 are called. Changing this should be done with great care to not break
126 126 cases when these fragments are assembled from another place.
127 127
128 128 """
129 129 # The edition string should be available in pylons too, so we add it here
130 130 # before copying the settings.
131 131 settings.setdefault('rhodecode.edition', 'Community Edition')
132 132
133 133 # As long as our Pylons application does expect "unprepared" settings, make
134 134 # sure that we keep an unmodified copy. This avoids unintentional change of
135 135 # behavior in the old application.
136 136 settings_pylons = settings.copy()
137 137
138 138 sanitize_settings_and_apply_defaults(settings)
139 139 config = Configurator(settings=settings)
140 140 add_pylons_compat_data(config.registry, global_config, settings_pylons)
141 141
142 142 load_pyramid_environment(global_config, settings)
143 143
144 144 includeme(config)
145 145 includeme_last(config)
146 146 pyramid_app = config.make_wsgi_app()
147 147 pyramid_app = wrap_app_in_wsgi_middlewares(pyramid_app, config)
148 148 return pyramid_app
149 149
150 150
151 151 def add_pylons_compat_data(registry, global_config, settings):
152 152 """
153 153 Attach data to the registry to support the Pylons integration.
154 154 """
155 155 registry._pylons_compat_global_config = global_config
156 156 registry._pylons_compat_settings = settings
157 157
158 158
159 159 def webob_to_pyramid_http_response(webob_response):
160 160 ResponseClass = httpexceptions.status_map[webob_response.status_int]
161 161 pyramid_response = ResponseClass(webob_response.status)
162 162 pyramid_response.status = webob_response.status
163 163 pyramid_response.headers.update(webob_response.headers)
164 164 if pyramid_response.headers['content-type'] == 'text/html':
165 165 pyramid_response.headers['content-type'] = 'text/html; charset=UTF-8'
166 166 return pyramid_response
167 167
168 168
169 169 def error_handler(exception, request):
170 170 # TODO: dan: replace the old pylons error controller with this
171 171 from rhodecode.model.settings import SettingsModel
172 172 from rhodecode.lib.utils2 import AttributeDict
173 173
174 174 try:
175 175 rc_config = SettingsModel().get_all_settings()
176 176 except Exception:
177 177 log.exception('failed to fetch settings')
178 178 rc_config = {}
179 179
180 180 base_response = HTTPInternalServerError()
181 181 # prefer original exception for the response since it may have headers set
182 182 if isinstance(exception, HTTPError):
183 183 base_response = exception
184 184
185 185 c = AttributeDict()
186 186 c.error_message = base_response.status
187 187 c.error_explanation = base_response.explanation or str(base_response)
188 188 c.visual = AttributeDict()
189 189
190 190 c.visual.rhodecode_support_url = (
191 191 request.registry.settings.get('rhodecode_support_url') or
192 192 request.route_url('rhodecode_support')
193 193 )
194 194 c.redirect_time = 0
195 195 c.rhodecode_name = rc_config.get('rhodecode_title', '')
196 196 if not c.rhodecode_name:
197 197 c.rhodecode_name = 'Rhodecode'
198 198
199 199 response = render_to_response(
200 200 '/errors/error_document.html', {'c': c}, request=request,
201 201 response=base_response)
202 202
203 203 return response
204 204
205 205
206 206 def includeme(config):
207 207 settings = config.registry.settings
208 208
209 209 if asbool(settings.get('appenlight', 'false')):
210 210 config.include('appenlight_client.ext.pyramid_tween')
211 211
212 212 # Includes which are required. The application would fail without them.
213 213 config.include('pyramid_mako')
214 214 config.include('pyramid_beaker')
215 215 config.include('rhodecode.admin')
216 216 config.include('rhodecode.authentication')
217 217 config.include('rhodecode.integrations')
218 218 config.include('rhodecode.login')
219 219 config.include('rhodecode.tweens')
220 220 config.include('rhodecode.api')
221 221 config.add_route(
222 222 'rhodecode_support', 'https://rhodecode.com/help/', static=True)
223 223
224 224 # Set the authorization policy.
225 225 authz_policy = ACLAuthorizationPolicy()
226 226 config.set_authorization_policy(authz_policy)
227 227
228 228 # Set the default renderer for HTML templates to mako.
229 229 config.add_mako_renderer('.html')
230 230
231 231 # plugin information
232 232 config.registry.rhodecode_plugins = {}
233 233
234 234 config.add_directive(
235 235 'register_rhodecode_plugin', register_rhodecode_plugin)
236 236 # include RhodeCode plugins
237 237 includes = aslist(settings.get('rhodecode.includes', []))
238 238 for inc in includes:
239 239 config.include(inc)
240 240
241 241 pylons_app = make_app(
242 242 config.registry._pylons_compat_global_config,
243 243 **config.registry._pylons_compat_settings)
244 244 config.registry._pylons_compat_config = pylons_app.config
245 245
246 246 pylons_app_as_view = wsgiapp(pylons_app)
247 247
248 248 # Protect from VCS Server error related pages when server is not available
249 249 vcs_server_enabled = asbool(settings.get('vcs.server.enable', 'true'))
250 250 if not vcs_server_enabled:
251 251 pylons_app_as_view = DisableVCSPagesWrapper(pylons_app_as_view)
252 252
253 253
254 254 def pylons_app_with_error_handler(context, request):
255 255 """
256 256 Handle exceptions from rc pylons app:
257 257
258 258 - old webob type exceptions get converted to pyramid exceptions
259 259 - pyramid exceptions are passed to the error handler view
260 260 """
261 261 try:
262 262 response = pylons_app_as_view(context, request)
263 263 if 400 <= response.status_int <= 599: # webob type error responses
264 264 return error_handler(
265 265 webob_to_pyramid_http_response(response), request)
266 266 except HTTPError as e: # pyramid type exceptions
267 267 return error_handler(e, request)
268 268 except Exception:
269 269 if settings.get('debugtoolbar.enabled', False):
270 270 raise
271 271 return error_handler(HTTPInternalServerError(), request)
272 272 return response
273 273
274 274 # This is the glue which allows us to migrate in chunks. By registering the
275 275 # pylons based application as the "Not Found" view in Pyramid, we will
276 276 # fallback to the old application each time the new one does not yet know
277 277 # how to handle a request.
278 278 config.add_notfound_view(pylons_app_with_error_handler)
279 279
280 280 if not settings.get('debugtoolbar.enabled', False):
281 281 # if no toolbar, then any exception gets caught and rendered
282 282 config.add_view(error_handler, context=Exception)
283 283
284 284 config.add_view(error_handler, context=HTTPError)
285 285
286 286
287 287 def includeme_last(config):
288 288 """
289 289 The static file catchall needs to be last in the view configuration.
290 290 """
291 291 settings = config.registry.settings
292
293 # Note: johbo: I would prefer to register a prefix for static files at some
294 # point, e.g. move them under '_static/'. This would fully avoid that we
295 # can have name clashes with a repository name. Imaging someone calling his
296 # repo "css" ;-) Also having an external web server to serve out the static
297 # files seems to be easier to set up if they have a common prefix.
298 #
299 # Example: config.add_static_view('_static', path='rhodecode:public')
300 #
301 # It might be an option to register both paths for a while and then migrate
302 # over to the new location.
303
304 # Serving static files with a catchall.
305 if settings['static_files']:
306 config.add_route('catchall_static', '/*subpath')
307 config.add_view(
308 static_view('rhodecode:public'), route_name='catchall_static')
292 config.add_static_view('_static', path='rhodecode:public')
309 293
310 294
311 295 def wrap_app_in_wsgi_middlewares(pyramid_app, config):
312 296 """
313 297 Apply outer WSGI middlewares around the application.
314 298
315 299 Part of this has been moved up from the Pylons layer, so that the
316 300 data is also available if old Pylons code is hit through an already ported
317 301 view.
318 302 """
319 303 settings = config.registry.settings
320 304
321 305 # enable https redirects based on HTTP_X_URL_SCHEME set by proxy
322 306 pyramid_app = HttpsFixup(pyramid_app, settings)
323 307
324 308 # Add RoutesMiddleware to support the pylons compatibility tween during
325 309
326 310 # migration to pyramid.
327 311 pyramid_app = RoutesMiddleware(
328 312 pyramid_app, config.registry._pylons_compat_config['routes.map'])
329 313
330 314 if asbool(settings.get('appenlight', 'false')):
331 315 pyramid_app, _ = wrap_in_appenlight_if_enabled(
332 316 pyramid_app, config.registry._pylons_compat_config)
333 317
334 # TODO: johbo: Don't really see why we enable the gzip middleware when
335 # serving static files, might be something that should have its own setting
336 # as well?
337 if settings['static_files']:
318 if asbool(settings.get('gzip_responses', 'true')):
338 319 pyramid_app = make_gzip_middleware(
339 320 pyramid_app, settings, compress_level=1)
340 321
341 322 return pyramid_app
342 323
343 324
344 325 def sanitize_settings_and_apply_defaults(settings):
345 326 """
346 327 Applies settings defaults and does all type conversion.
347 328
348 329 We would move all settings parsing and preparation into this place, so that
349 330 we have only one place left which deals with this part. The remaining parts
350 331 of the application would start to rely fully on well prepared settings.
351 332
352 333 This piece would later be split up per topic to avoid a big fat monster
353 334 function.
354 335 """
355 336
356 337 # Pyramid's mako renderer has to search in the templates folder so that the
357 338 # old templates still work. Ported and new templates are expected to use
358 339 # real asset specifications for the includes.
359 340 mako_directories = settings.setdefault('mako.directories', [
360 341 # Base templates of the original Pylons application
361 342 'rhodecode:templates',
362 343 ])
363 344 log.debug(
364 345 "Using the following Mako template directories: %s",
365 346 mako_directories)
366 347
367 348 # Default includes, possible to change as a user
368 349 pyramid_includes = settings.setdefault('pyramid.includes', [
369 350 'rhodecode.lib.middleware.request_wrapper',
370 351 ])
371 352 log.debug(
372 353 "Using the following pyramid.includes: %s",
373 354 pyramid_includes)
374 355
375 356 # TODO: johbo: Re-think this, usually the call to config.include
376 357 # should allow to pass in a prefix.
377 358 settings.setdefault('rhodecode.api.url', '/_admin/api')
378 359
379 360 _bool_setting(settings, 'vcs.server.enable', 'true')
380 _bool_setting(settings, 'static_files', 'true')
381 361 _bool_setting(settings, 'is_test', 'false')
382 362
383 363 return settings
384 364
385 365
386 366 def _bool_setting(settings, name, default):
387 367 settings[name] = asbool(settings.get(name, default))
@@ -1,1931 +1,1947 b''
1 1 # -*- coding: utf-8 -*-
2 2
3 3 # Copyright (C) 2010-2016 RhodeCode GmbH
4 4 #
5 5 # This program is free software: you can redistribute it and/or modify
6 6 # it under the terms of the GNU Affero General Public License, version 3
7 7 # (only), as published by the Free Software Foundation.
8 8 #
9 9 # This program is distributed in the hope that it will be useful,
10 10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 12 # GNU General Public License for more details.
13 13 #
14 14 # You should have received a copy of the GNU Affero General Public License
15 15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
16 16 #
17 17 # This program is dual-licensed. If you wish to learn more about the
18 18 # RhodeCode Enterprise Edition, including its added features, Support services,
19 19 # and proprietary license terms, please see https://rhodecode.com/licenses/
20 20
21 21 """
22 22 Helper functions
23 23
24 24 Consists of functions to typically be used within templates, but also
25 25 available to Controllers. This module is available to both as 'h'.
26 26 """
27 27
28 28 import random
29 29 import hashlib
30 30 import StringIO
31 31 import urllib
32 32 import math
33 33 import logging
34 34 import re
35 35 import urlparse
36 36 import time
37 37 import string
38 38 import hashlib
39 39 import pygments
40 40
41 41 from datetime import datetime
42 42 from functools import partial
43 43 from pygments.formatters.html import HtmlFormatter
44 44 from pygments import highlight as code_highlight
45 45 from pygments.lexers import (
46 46 get_lexer_by_name, get_lexer_for_filename, get_lexer_for_mimetype)
47 47 from pylons import url as pylons_url
48 48 from pylons.i18n.translation import _, ungettext
49 49 from pyramid.threadlocal import get_current_request
50 50
51 51 from webhelpers.html import literal, HTML, escape
52 52 from webhelpers.html.tools import *
53 53 from webhelpers.html.builder import make_tag
54 54 from webhelpers.html.tags import auto_discovery_link, checkbox, css_classes, \
55 55 end_form, file, form as wh_form, hidden, image, javascript_link, link_to, \
56 56 link_to_if, link_to_unless, ol, required_legend, select, stylesheet_link, \
57 57 submit, text, password, textarea, title, ul, xml_declaration, radio
58 58 from webhelpers.html.tools import auto_link, button_to, highlight, \
59 59 js_obfuscate, mail_to, strip_links, strip_tags, tag_re
60 60 from webhelpers.pylonslib import Flash as _Flash
61 61 from webhelpers.text import chop_at, collapse, convert_accented_entities, \
62 62 convert_misc_entities, lchop, plural, rchop, remove_formatting, \
63 63 replace_whitespace, urlify, truncate, wrap_paragraphs
64 64 from webhelpers.date import time_ago_in_words
65 65 from webhelpers.paginate import Page as _Page
66 66 from webhelpers.html.tags import _set_input_attrs, _set_id_attr, \
67 67 convert_boolean_attrs, NotGiven, _make_safe_id_component
68 68 from webhelpers2.number import format_byte_size
69 69
70 70 from rhodecode.lib.annotate import annotate_highlight
71 71 from rhodecode.lib.action_parser import action_parser
72 72 from rhodecode.lib.ext_json import json
73 73 from rhodecode.lib.utils import repo_name_slug, get_custom_lexer
74 74 from rhodecode.lib.utils2 import str2bool, safe_unicode, safe_str, \
75 75 get_commit_safe, datetime_to_time, time_to_datetime, time_to_utcdatetime, \
76 76 AttributeDict, safe_int, md5, md5_safe
77 77 from rhodecode.lib.markup_renderer import MarkupRenderer
78 78 from rhodecode.lib.vcs.exceptions import CommitDoesNotExistError
79 79 from rhodecode.lib.vcs.backends.base import BaseChangeset, EmptyCommit
80 80 from rhodecode.config.conf import DATE_FORMAT, DATETIME_FORMAT
81 81 from rhodecode.model.changeset_status import ChangesetStatusModel
82 82 from rhodecode.model.db import Permission, User, Repository
83 83 from rhodecode.model.repo_group import RepoGroupModel
84 84 from rhodecode.model.settings import IssueTrackerSettingsModel
85 85
86 86 log = logging.getLogger(__name__)
87 87
88
88 89 DEFAULT_USER = User.DEFAULT_USER
89 90 DEFAULT_USER_EMAIL = User.DEFAULT_USER_EMAIL
90 91
92
91 93 def url(*args, **kw):
92 94 return pylons_url(*args, **kw)
93 95
96
94 97 def pylons_url_current(*args, **kw):
95 98 """
96 99 This function overrides pylons.url.current() which returns the current
97 100 path so that it will also work from a pyramid only context. This
98 101 should be removed once port to pyramid is complete.
99 102 """
100 103 if not args and not kw:
101 104 request = get_current_request()
102 105 return request.path
103 106 return pylons_url.current(*args, **kw)
104 107
105 108 url.current = pylons_url_current
106 109
107 110
111 def asset(path, ver=None):
112 """
113 Helper to generate a static asset file path for rhodecode assets
114
115 eg. h.asset('images/image.png', ver='3923')
116
117 :param path: path of asset
118 :param ver: optional version query param to append as ?ver=
119 """
120 request = get_current_request()
121 return request.static_url('rhodecode:public/{}'.format(path), ver=ver)
122
123
108 124 def html_escape(text, html_escape_table=None):
109 125 """Produce entities within text."""
110 126 if not html_escape_table:
111 127 html_escape_table = {
112 128 "&": "&amp;",
113 129 '"': "&quot;",
114 130 "'": "&apos;",
115 131 ">": "&gt;",
116 132 "<": "&lt;",
117 133 }
118 134 return "".join(html_escape_table.get(c, c) for c in text)
119 135
120 136
121 137 def chop_at_smart(s, sub, inclusive=False, suffix_if_chopped=None):
122 138 """
123 139 Truncate string ``s`` at the first occurrence of ``sub``.
124 140
125 141 If ``inclusive`` is true, truncate just after ``sub`` rather than at it.
126 142 """
127 143 suffix_if_chopped = suffix_if_chopped or ''
128 144 pos = s.find(sub)
129 145 if pos == -1:
130 146 return s
131 147
132 148 if inclusive:
133 149 pos += len(sub)
134 150
135 151 chopped = s[:pos]
136 152 left = s[pos:].strip()
137 153
138 154 if left and suffix_if_chopped:
139 155 chopped += suffix_if_chopped
140 156
141 157 return chopped
142 158
143 159
144 160 def shorter(text, size=20):
145 161 postfix = '...'
146 162 if len(text) > size:
147 163 return text[:size - len(postfix)] + postfix
148 164 return text
149 165
150 166
151 167 def _reset(name, value=None, id=NotGiven, type="reset", **attrs):
152 168 """
153 169 Reset button
154 170 """
155 171 _set_input_attrs(attrs, type, name, value)
156 172 _set_id_attr(attrs, id, name)
157 173 convert_boolean_attrs(attrs, ["disabled"])
158 174 return HTML.input(**attrs)
159 175
160 176 reset = _reset
161 177 safeid = _make_safe_id_component
162 178
163 179
164 180 def branding(name, length=40):
165 181 return truncate(name, length, indicator="")
166 182
167 183
168 184 def FID(raw_id, path):
169 185 """
170 186 Creates a unique ID for filenode based on it's hash of path and commit
171 187 it's safe to use in urls
172 188
173 189 :param raw_id:
174 190 :param path:
175 191 """
176 192
177 193 return 'c-%s-%s' % (short_id(raw_id), md5_safe(path)[:12])
178 194
179 195
180 196 class _GetError(object):
181 197 """Get error from form_errors, and represent it as span wrapped error
182 198 message
183 199
184 200 :param field_name: field to fetch errors for
185 201 :param form_errors: form errors dict
186 202 """
187 203
188 204 def __call__(self, field_name, form_errors):
189 205 tmpl = """<span class="error_msg">%s</span>"""
190 206 if form_errors and field_name in form_errors:
191 207 return literal(tmpl % form_errors.get(field_name))
192 208
193 209 get_error = _GetError()
194 210
195 211
196 212 class _ToolTip(object):
197 213
198 214 def __call__(self, tooltip_title, trim_at=50):
199 215 """
200 216 Special function just to wrap our text into nice formatted
201 217 autowrapped text
202 218
203 219 :param tooltip_title:
204 220 """
205 221 tooltip_title = escape(tooltip_title)
206 222 tooltip_title = tooltip_title.replace('<', '&lt;').replace('>', '&gt;')
207 223 return tooltip_title
208 224 tooltip = _ToolTip()
209 225
210 226
211 227 def files_breadcrumbs(repo_name, commit_id, file_path):
212 228 if isinstance(file_path, str):
213 229 file_path = safe_unicode(file_path)
214 230
215 231 # TODO: johbo: Is this always a url like path, or is this operating
216 232 # system dependent?
217 233 path_segments = file_path.split('/')
218 234
219 235 repo_name_html = escape(repo_name)
220 236 if len(path_segments) == 1 and path_segments[0] == '':
221 237 url_segments = [repo_name_html]
222 238 else:
223 239 url_segments = [
224 240 link_to(
225 241 repo_name_html,
226 242 url('files_home',
227 243 repo_name=repo_name,
228 244 revision=commit_id,
229 245 f_path=''),
230 246 class_='pjax-link')]
231 247
232 248 last_cnt = len(path_segments) - 1
233 249 for cnt, segment in enumerate(path_segments):
234 250 if not segment:
235 251 continue
236 252 segment_html = escape(segment)
237 253
238 254 if cnt != last_cnt:
239 255 url_segments.append(
240 256 link_to(
241 257 segment_html,
242 258 url('files_home',
243 259 repo_name=repo_name,
244 260 revision=commit_id,
245 261 f_path='/'.join(path_segments[:cnt + 1])),
246 262 class_='pjax-link'))
247 263 else:
248 264 url_segments.append(segment_html)
249 265
250 266 return literal('/'.join(url_segments))
251 267
252 268
253 269 class CodeHtmlFormatter(HtmlFormatter):
254 270 """
255 271 My code Html Formatter for source codes
256 272 """
257 273
258 274 def wrap(self, source, outfile):
259 275 return self._wrap_div(self._wrap_pre(self._wrap_code(source)))
260 276
261 277 def _wrap_code(self, source):
262 278 for cnt, it in enumerate(source):
263 279 i, t = it
264 280 t = '<div id="L%s">%s</div>' % (cnt + 1, t)
265 281 yield i, t
266 282
267 283 def _wrap_tablelinenos(self, inner):
268 284 dummyoutfile = StringIO.StringIO()
269 285 lncount = 0
270 286 for t, line in inner:
271 287 if t:
272 288 lncount += 1
273 289 dummyoutfile.write(line)
274 290
275 291 fl = self.linenostart
276 292 mw = len(str(lncount + fl - 1))
277 293 sp = self.linenospecial
278 294 st = self.linenostep
279 295 la = self.lineanchors
280 296 aln = self.anchorlinenos
281 297 nocls = self.noclasses
282 298 if sp:
283 299 lines = []
284 300
285 301 for i in range(fl, fl + lncount):
286 302 if i % st == 0:
287 303 if i % sp == 0:
288 304 if aln:
289 305 lines.append('<a href="#%s%d" class="special">%*d</a>' %
290 306 (la, i, mw, i))
291 307 else:
292 308 lines.append('<span class="special">%*d</span>' % (mw, i))
293 309 else:
294 310 if aln:
295 311 lines.append('<a href="#%s%d">%*d</a>' % (la, i, mw, i))
296 312 else:
297 313 lines.append('%*d' % (mw, i))
298 314 else:
299 315 lines.append('')
300 316 ls = '\n'.join(lines)
301 317 else:
302 318 lines = []
303 319 for i in range(fl, fl + lncount):
304 320 if i % st == 0:
305 321 if aln:
306 322 lines.append('<a href="#%s%d">%*d</a>' % (la, i, mw, i))
307 323 else:
308 324 lines.append('%*d' % (mw, i))
309 325 else:
310 326 lines.append('')
311 327 ls = '\n'.join(lines)
312 328
313 329 # in case you wonder about the seemingly redundant <div> here: since the
314 330 # content in the other cell also is wrapped in a div, some browsers in
315 331 # some configurations seem to mess up the formatting...
316 332 if nocls:
317 333 yield 0, ('<table class="%stable">' % self.cssclass +
318 334 '<tr><td><div class="linenodiv" '
319 335 'style="background-color: #f0f0f0; padding-right: 10px">'
320 336 '<pre style="line-height: 125%">' +
321 337 ls + '</pre></div></td><td id="hlcode" class="code">')
322 338 else:
323 339 yield 0, ('<table class="%stable">' % self.cssclass +
324 340 '<tr><td class="linenos"><div class="linenodiv"><pre>' +
325 341 ls + '</pre></div></td><td id="hlcode" class="code">')
326 342 yield 0, dummyoutfile.getvalue()
327 343 yield 0, '</td></tr></table>'
328 344
329 345
330 346 class SearchContentCodeHtmlFormatter(CodeHtmlFormatter):
331 347 def __init__(self, **kw):
332 348 # only show these line numbers if set
333 349 self.only_lines = kw.pop('only_line_numbers', [])
334 350 self.query_terms = kw.pop('query_terms', [])
335 351 self.max_lines = kw.pop('max_lines', 5)
336 352 self.line_context = kw.pop('line_context', 3)
337 353 self.url = kw.pop('url', None)
338 354
339 355 super(CodeHtmlFormatter, self).__init__(**kw)
340 356
341 357 def _wrap_code(self, source):
342 358 for cnt, it in enumerate(source):
343 359 i, t = it
344 360 t = '<pre>%s</pre>' % t
345 361 yield i, t
346 362
347 363 def _wrap_tablelinenos(self, inner):
348 364 yield 0, '<table class="code-highlight %stable">' % self.cssclass
349 365
350 366 last_shown_line_number = 0
351 367 current_line_number = 1
352 368
353 369 for t, line in inner:
354 370 if not t:
355 371 yield t, line
356 372 continue
357 373
358 374 if current_line_number in self.only_lines:
359 375 if last_shown_line_number + 1 != current_line_number:
360 376 yield 0, '<tr>'
361 377 yield 0, '<td class="line">...</td>'
362 378 yield 0, '<td id="hlcode" class="code"></td>'
363 379 yield 0, '</tr>'
364 380
365 381 yield 0, '<tr>'
366 382 if self.url:
367 383 yield 0, '<td class="line"><a href="%s#L%i">%i</a></td>' % (
368 384 self.url, current_line_number, current_line_number)
369 385 else:
370 386 yield 0, '<td class="line"><a href="">%i</a></td>' % (
371 387 current_line_number)
372 388 yield 0, '<td id="hlcode" class="code">' + line + '</td>'
373 389 yield 0, '</tr>'
374 390
375 391 last_shown_line_number = current_line_number
376 392
377 393 current_line_number += 1
378 394
379 395
380 396 yield 0, '</table>'
381 397
382 398
383 399 def extract_phrases(text_query):
384 400 """
385 401 Extracts phrases from search term string making sure phrases
386 402 contained in double quotes are kept together - and discarding empty values
387 403 or fully whitespace values eg.
388 404
389 405 'some text "a phrase" more' => ['some', 'text', 'a phrase', 'more']
390 406
391 407 """
392 408
393 409 in_phrase = False
394 410 buf = ''
395 411 phrases = []
396 412 for char in text_query:
397 413 if in_phrase:
398 414 if char == '"': # end phrase
399 415 phrases.append(buf)
400 416 buf = ''
401 417 in_phrase = False
402 418 continue
403 419 else:
404 420 buf += char
405 421 continue
406 422 else:
407 423 if char == '"': # start phrase
408 424 in_phrase = True
409 425 phrases.append(buf)
410 426 buf = ''
411 427 continue
412 428 elif char == ' ':
413 429 phrases.append(buf)
414 430 buf = ''
415 431 continue
416 432 else:
417 433 buf += char
418 434
419 435 phrases.append(buf)
420 436 phrases = [phrase.strip() for phrase in phrases if phrase.strip()]
421 437 return phrases
422 438
423 439
424 440 def get_matching_offsets(text, phrases):
425 441 """
426 442 Returns a list of string offsets in `text` that the list of `terms` match
427 443
428 444 >>> get_matching_offsets('some text here', ['some', 'here'])
429 445 [(0, 4), (10, 14)]
430 446
431 447 """
432 448 offsets = []
433 449 for phrase in phrases:
434 450 for match in re.finditer(phrase, text):
435 451 offsets.append((match.start(), match.end()))
436 452
437 453 return offsets
438 454
439 455
440 456 def normalize_text_for_matching(x):
441 457 """
442 458 Replaces all non alnum characters to spaces and lower cases the string,
443 459 useful for comparing two text strings without punctuation
444 460 """
445 461 return re.sub(r'[^\w]', ' ', x.lower())
446 462
447 463
448 464 def get_matching_line_offsets(lines, terms):
449 465 """ Return a set of `lines` indices (starting from 1) matching a
450 466 text search query, along with `context` lines above/below matching lines
451 467
452 468 :param lines: list of strings representing lines
453 469 :param terms: search term string to match in lines eg. 'some text'
454 470 :param context: number of lines above/below a matching line to add to result
455 471 :param max_lines: cut off for lines of interest
456 472 eg.
457 473
458 474 text = '''
459 475 words words words
460 476 words words words
461 477 some text some
462 478 words words words
463 479 words words words
464 480 text here what
465 481 '''
466 482 get_matching_line_offsets(text, 'text', context=1)
467 483 {3: [(5, 9)], 6: [(0, 4)]]
468 484
469 485 """
470 486 matching_lines = {}
471 487 phrases = [normalize_text_for_matching(phrase)
472 488 for phrase in extract_phrases(terms)]
473 489
474 490 for line_index, line in enumerate(lines, start=1):
475 491 match_offsets = get_matching_offsets(
476 492 normalize_text_for_matching(line), phrases)
477 493 if match_offsets:
478 494 matching_lines[line_index] = match_offsets
479 495
480 496 return matching_lines
481 497
482 498
483 499 def get_lexer_safe(mimetype=None, filepath=None):
484 500 """
485 501 Tries to return a relevant pygments lexer using mimetype/filepath name,
486 502 defaulting to plain text if none could be found
487 503 """
488 504 lexer = None
489 505 try:
490 506 if mimetype:
491 507 lexer = get_lexer_for_mimetype(mimetype)
492 508 if not lexer:
493 509 lexer = get_lexer_for_filename(filepath)
494 510 except pygments.util.ClassNotFound:
495 511 pass
496 512
497 513 if not lexer:
498 514 lexer = get_lexer_by_name('text')
499 515
500 516 return lexer
501 517
502 518
503 519 def pygmentize(filenode, **kwargs):
504 520 """
505 521 pygmentize function using pygments
506 522
507 523 :param filenode:
508 524 """
509 525 lexer = get_custom_lexer(filenode.extension) or filenode.lexer
510 526 return literal(code_highlight(filenode.content, lexer,
511 527 CodeHtmlFormatter(**kwargs)))
512 528
513 529
514 530 def pygmentize_annotation(repo_name, filenode, **kwargs):
515 531 """
516 532 pygmentize function for annotation
517 533
518 534 :param filenode:
519 535 """
520 536
521 537 color_dict = {}
522 538
523 539 def gen_color(n=10000):
524 540 """generator for getting n of evenly distributed colors using
525 541 hsv color and golden ratio. It always return same order of colors
526 542
527 543 :returns: RGB tuple
528 544 """
529 545
530 546 def hsv_to_rgb(h, s, v):
531 547 if s == 0.0:
532 548 return v, v, v
533 549 i = int(h * 6.0) # XXX assume int() truncates!
534 550 f = (h * 6.0) - i
535 551 p = v * (1.0 - s)
536 552 q = v * (1.0 - s * f)
537 553 t = v * (1.0 - s * (1.0 - f))
538 554 i = i % 6
539 555 if i == 0:
540 556 return v, t, p
541 557 if i == 1:
542 558 return q, v, p
543 559 if i == 2:
544 560 return p, v, t
545 561 if i == 3:
546 562 return p, q, v
547 563 if i == 4:
548 564 return t, p, v
549 565 if i == 5:
550 566 return v, p, q
551 567
552 568 golden_ratio = 0.618033988749895
553 569 h = 0.22717784590367374
554 570
555 571 for _ in xrange(n):
556 572 h += golden_ratio
557 573 h %= 1
558 574 HSV_tuple = [h, 0.95, 0.95]
559 575 RGB_tuple = hsv_to_rgb(*HSV_tuple)
560 576 yield map(lambda x: str(int(x * 256)), RGB_tuple)
561 577
562 578 cgenerator = gen_color()
563 579
564 580 def get_color_string(commit_id):
565 581 if commit_id in color_dict:
566 582 col = color_dict[commit_id]
567 583 else:
568 584 col = color_dict[commit_id] = cgenerator.next()
569 585 return "color: rgb(%s)! important;" % (', '.join(col))
570 586
571 587 def url_func(repo_name):
572 588
573 589 def _url_func(commit):
574 590 author = commit.author
575 591 date = commit.date
576 592 message = tooltip(commit.message)
577 593
578 594 tooltip_html = ("<div style='font-size:0.8em'><b>Author:</b>"
579 595 " %s<br/><b>Date:</b> %s</b><br/><b>Message:"
580 596 "</b> %s<br/></div>")
581 597
582 598 tooltip_html = tooltip_html % (author, date, message)
583 599 lnk_format = '%5s:%s' % ('r%s' % commit.idx, commit.short_id)
584 600 uri = link_to(
585 601 lnk_format,
586 602 url('changeset_home', repo_name=repo_name,
587 603 revision=commit.raw_id),
588 604 style=get_color_string(commit.raw_id),
589 605 class_='tooltip',
590 606 title=tooltip_html
591 607 )
592 608
593 609 uri += '\n'
594 610 return uri
595 611 return _url_func
596 612
597 613 return literal(annotate_highlight(filenode, url_func(repo_name), **kwargs))
598 614
599 615
600 616 def is_following_repo(repo_name, user_id):
601 617 from rhodecode.model.scm import ScmModel
602 618 return ScmModel().is_following_repo(repo_name, user_id)
603 619
604 620
605 621 class _Message(object):
606 622 """A message returned by ``Flash.pop_messages()``.
607 623
608 624 Converting the message to a string returns the message text. Instances
609 625 also have the following attributes:
610 626
611 627 * ``message``: the message text.
612 628 * ``category``: the category specified when the message was created.
613 629 """
614 630
615 631 def __init__(self, category, message):
616 632 self.category = category
617 633 self.message = message
618 634
619 635 def __str__(self):
620 636 return self.message
621 637
622 638 __unicode__ = __str__
623 639
624 640 def __html__(self):
625 641 return escape(safe_unicode(self.message))
626 642
627 643
628 644 class Flash(_Flash):
629 645
630 646 def pop_messages(self):
631 647 """Return all accumulated messages and delete them from the session.
632 648
633 649 The return value is a list of ``Message`` objects.
634 650 """
635 651 from pylons import session
636 652
637 653 messages = []
638 654
639 655 # Pop the 'old' pylons flash messages. They are tuples of the form
640 656 # (category, message)
641 657 for cat, msg in session.pop(self.session_key, []):
642 658 messages.append(_Message(cat, msg))
643 659
644 660 # Pop the 'new' pyramid flash messages for each category as list
645 661 # of strings.
646 662 for cat in self.categories:
647 663 for msg in session.pop_flash(queue=cat):
648 664 messages.append(_Message(cat, msg))
649 665 # Map messages from the default queue to the 'notice' category.
650 666 for msg in session.pop_flash():
651 667 messages.append(_Message('notice', msg))
652 668
653 669 session.save()
654 670 return messages
655 671
656 672 flash = Flash()
657 673
658 674 #==============================================================================
659 675 # SCM FILTERS available via h.
660 676 #==============================================================================
661 677 from rhodecode.lib.vcs.utils import author_name, author_email
662 678 from rhodecode.lib.utils2 import credentials_filter, age as _age
663 679 from rhodecode.model.db import User, ChangesetStatus
664 680
665 681 age = _age
666 682 capitalize = lambda x: x.capitalize()
667 683 email = author_email
668 684 short_id = lambda x: x[:12]
669 685 hide_credentials = lambda x: ''.join(credentials_filter(x))
670 686
671 687
672 688 def age_component(datetime_iso, value=None, time_is_local=False):
673 689 title = value or format_date(datetime_iso)
674 690
675 691 # detect if we have a timezone info, otherwise, add it
676 692 if isinstance(datetime_iso, datetime) and not datetime_iso.tzinfo:
677 693 tzinfo = '+00:00'
678 694
679 695 if time_is_local:
680 696 tzinfo = time.strftime("+%H:%M",
681 697 time.gmtime(
682 698 (datetime.now() - datetime.utcnow()).seconds + 1
683 699 )
684 700 )
685 701
686 702 return literal(
687 703 '<time class="timeago tooltip" '
688 704 'title="{1}" datetime="{0}{2}">{1}</time>'.format(
689 705 datetime_iso, title, tzinfo))
690 706
691 707
692 708 def _shorten_commit_id(commit_id):
693 709 from rhodecode import CONFIG
694 710 def_len = safe_int(CONFIG.get('rhodecode_show_sha_length', 12))
695 711 return commit_id[:def_len]
696 712
697 713
698 714 def show_id(commit):
699 715 """
700 716 Configurable function that shows ID
701 717 by default it's r123:fffeeefffeee
702 718
703 719 :param commit: commit instance
704 720 """
705 721 from rhodecode import CONFIG
706 722 show_idx = str2bool(CONFIG.get('rhodecode_show_revision_number', True))
707 723
708 724 raw_id = _shorten_commit_id(commit.raw_id)
709 725 if show_idx:
710 726 return 'r%s:%s' % (commit.idx, raw_id)
711 727 else:
712 728 return '%s' % (raw_id, )
713 729
714 730
715 731 def format_date(date):
716 732 """
717 733 use a standardized formatting for dates used in RhodeCode
718 734
719 735 :param date: date/datetime object
720 736 :return: formatted date
721 737 """
722 738
723 739 if date:
724 740 _fmt = "%a, %d %b %Y %H:%M:%S"
725 741 return safe_unicode(date.strftime(_fmt))
726 742
727 743 return u""
728 744
729 745
730 746 class _RepoChecker(object):
731 747
732 748 def __init__(self, backend_alias):
733 749 self._backend_alias = backend_alias
734 750
735 751 def __call__(self, repository):
736 752 if hasattr(repository, 'alias'):
737 753 _type = repository.alias
738 754 elif hasattr(repository, 'repo_type'):
739 755 _type = repository.repo_type
740 756 else:
741 757 _type = repository
742 758 return _type == self._backend_alias
743 759
744 760 is_git = _RepoChecker('git')
745 761 is_hg = _RepoChecker('hg')
746 762 is_svn = _RepoChecker('svn')
747 763
748 764
749 765 def get_repo_type_by_name(repo_name):
750 766 repo = Repository.get_by_repo_name(repo_name)
751 767 return repo.repo_type
752 768
753 769
754 770 def is_svn_without_proxy(repository):
755 771 from rhodecode import CONFIG
756 772 if is_svn(repository):
757 773 if not CONFIG.get('rhodecode_proxy_subversion_http_requests', False):
758 774 return True
759 775 return False
760 776
761 777
762 778 def discover_user(author):
763 779 """
764 780 Tries to discover RhodeCode User based on the autho string. Author string
765 781 is typically `FirstName LastName <email@address.com>`
766 782 """
767 783
768 784 # if author is already an instance use it for extraction
769 785 if isinstance(author, User):
770 786 return author
771 787
772 788 # Valid email in the attribute passed, see if they're in the system
773 789 _email = author_email(author)
774 790 if _email != '':
775 791 user = User.get_by_email(_email, case_insensitive=True, cache=True)
776 792 if user is not None:
777 793 return user
778 794
779 795 # Maybe it's a username, we try to extract it and fetch by username ?
780 796 _author = author_name(author)
781 797 user = User.get_by_username(_author, case_insensitive=True, cache=True)
782 798 if user is not None:
783 799 return user
784 800
785 801 return None
786 802
787 803
788 804 def email_or_none(author):
789 805 # extract email from the commit string
790 806 _email = author_email(author)
791 807
792 808 # If we have an email, use it, otherwise
793 809 # see if it contains a username we can get an email from
794 810 if _email != '':
795 811 return _email
796 812 else:
797 813 user = User.get_by_username(
798 814 author_name(author), case_insensitive=True, cache=True)
799 815
800 816 if user is not None:
801 817 return user.email
802 818
803 819 # No valid email, not a valid user in the system, none!
804 820 return None
805 821
806 822
807 823 def link_to_user(author, length=0, **kwargs):
808 824 user = discover_user(author)
809 825 # user can be None, but if we have it already it means we can re-use it
810 826 # in the person() function, so we save 1 intensive-query
811 827 if user:
812 828 author = user
813 829
814 830 display_person = person(author, 'username_or_name_or_email')
815 831 if length:
816 832 display_person = shorter(display_person, length)
817 833
818 834 if user:
819 835 return link_to(
820 836 escape(display_person),
821 837 url('user_profile', username=user.username),
822 838 **kwargs)
823 839 else:
824 840 return escape(display_person)
825 841
826 842
827 843 def person(author, show_attr="username_and_name"):
828 844 user = discover_user(author)
829 845 if user:
830 846 return getattr(user, show_attr)
831 847 else:
832 848 _author = author_name(author)
833 849 _email = email(author)
834 850 return _author or _email
835 851
836 852
837 853 def author_string(email):
838 854 if email:
839 855 user = User.get_by_email(email, case_insensitive=True, cache=True)
840 856 if user:
841 857 if user.firstname or user.lastname:
842 858 return '%s %s &lt;%s&gt;' % (user.firstname, user.lastname, email)
843 859 else:
844 860 return email
845 861 else:
846 862 return email
847 863 else:
848 864 return None
849 865
850 866
851 867 def person_by_id(id_, show_attr="username_and_name"):
852 868 # attr to return from fetched user
853 869 person_getter = lambda usr: getattr(usr, show_attr)
854 870
855 871 #maybe it's an ID ?
856 872 if str(id_).isdigit() or isinstance(id_, int):
857 873 id_ = int(id_)
858 874 user = User.get(id_)
859 875 if user is not None:
860 876 return person_getter(user)
861 877 return id_
862 878
863 879
864 880 def gravatar_with_user(author, show_disabled=False):
865 881 from rhodecode.lib.utils import PartialRenderer
866 882 _render = PartialRenderer('base/base.html')
867 883 return _render('gravatar_with_user', author, show_disabled=show_disabled)
868 884
869 885
870 886 def desc_stylize(value):
871 887 """
872 888 converts tags from value into html equivalent
873 889
874 890 :param value:
875 891 """
876 892 if not value:
877 893 return ''
878 894
879 895 value = re.sub(r'\[see\ \=\>\ *([a-zA-Z0-9\/\=\?\&\ \:\/\.\-]*)\]',
880 896 '<div class="metatag" tag="see">see =&gt; \\1 </div>', value)
881 897 value = re.sub(r'\[license\ \=\>\ *([a-zA-Z0-9\/\=\?\&\ \:\/\.\-]*)\]',
882 898 '<div class="metatag" tag="license"><a href="http:\/\/www.opensource.org/licenses/\\1">\\1</a></div>', value)
883 899 value = re.sub(r'\[(requires|recommends|conflicts|base)\ \=\>\ *([a-zA-Z0-9\-\/]*)\]',
884 900 '<div class="metatag" tag="\\1">\\1 =&gt; <a href="/\\2">\\2</a></div>', value)
885 901 value = re.sub(r'\[(lang|language)\ \=\>\ *([a-zA-Z\-\/\#\+]*)\]',
886 902 '<div class="metatag" tag="lang">\\2</div>', value)
887 903 value = re.sub(r'\[([a-z]+)\]',
888 904 '<div class="metatag" tag="\\1">\\1</div>', value)
889 905
890 906 return value
891 907
892 908
893 909 def escaped_stylize(value):
894 910 """
895 911 converts tags from value into html equivalent, but escaping its value first
896 912 """
897 913 if not value:
898 914 return ''
899 915
900 916 # Using default webhelper escape method, but has to force it as a
901 917 # plain unicode instead of a markup tag to be used in regex expressions
902 918 value = unicode(escape(safe_unicode(value)))
903 919
904 920 value = re.sub(r'\[see\ \=\&gt;\ *([a-zA-Z0-9\/\=\?\&amp;\ \:\/\.\-]*)\]',
905 921 '<div class="metatag" tag="see">see =&gt; \\1 </div>', value)
906 922 value = re.sub(r'\[license\ \=\&gt;\ *([a-zA-Z0-9\/\=\?\&amp;\ \:\/\.\-]*)\]',
907 923 '<div class="metatag" tag="license"><a href="http:\/\/www.opensource.org/licenses/\\1">\\1</a></div>', value)
908 924 value = re.sub(r'\[(requires|recommends|conflicts|base)\ \=\&gt;\ *([a-zA-Z0-9\-\/]*)\]',
909 925 '<div class="metatag" tag="\\1">\\1 =&gt; <a href="/\\2">\\2</a></div>', value)
910 926 value = re.sub(r'\[(lang|language)\ \=\&gt;\ *([a-zA-Z\-\/\#\+]*)\]',
911 927 '<div class="metatag" tag="lang">\\2</div>', value)
912 928 value = re.sub(r'\[([a-z]+)\]',
913 929 '<div class="metatag" tag="\\1">\\1</div>', value)
914 930
915 931 return value
916 932
917 933
918 934 def bool2icon(value):
919 935 """
920 936 Returns boolean value of a given value, represented as html element with
921 937 classes that will represent icons
922 938
923 939 :param value: given value to convert to html node
924 940 """
925 941
926 942 if value: # does bool conversion
927 943 return HTML.tag('i', class_="icon-true")
928 944 else: # not true as bool
929 945 return HTML.tag('i', class_="icon-false")
930 946
931 947
932 948 #==============================================================================
933 949 # PERMS
934 950 #==============================================================================
935 951 from rhodecode.lib.auth import HasPermissionAny, HasPermissionAll, \
936 952 HasRepoPermissionAny, HasRepoPermissionAll, HasRepoGroupPermissionAll, \
937 953 HasRepoGroupPermissionAny, HasRepoPermissionAnyApi, get_csrf_token
938 954
939 955
940 956 #==============================================================================
941 957 # GRAVATAR URL
942 958 #==============================================================================
943 959 class InitialsGravatar(object):
944 960 def __init__(self, email_address, first_name, last_name, size=30,
945 961 background=None, text_color='#fff'):
946 962 self.size = size
947 963 self.first_name = first_name
948 964 self.last_name = last_name
949 965 self.email_address = email_address
950 966 self.background = background or self.str2color(email_address)
951 967 self.text_color = text_color
952 968
953 969 def get_color_bank(self):
954 970 """
955 971 returns a predefined list of colors that gravatars can use.
956 972 Those are randomized distinct colors that guarantee readability and
957 973 uniqueness.
958 974
959 975 generated with: http://phrogz.net/css/distinct-colors.html
960 976 """
961 977 return [
962 978 '#bf3030', '#a67f53', '#00ff00', '#5989b3', '#392040', '#d90000',
963 979 '#402910', '#204020', '#79baf2', '#a700b3', '#bf6060', '#7f5320',
964 980 '#008000', '#003059', '#ee00ff', '#ff0000', '#8c4b00', '#007300',
965 981 '#005fb3', '#de73e6', '#ff4040', '#ffaa00', '#3df255', '#203140',
966 982 '#47004d', '#591616', '#664400', '#59b365', '#0d2133', '#83008c',
967 983 '#592d2d', '#bf9f60', '#73e682', '#1d3f73', '#73006b', '#402020',
968 984 '#b2862d', '#397341', '#597db3', '#e600d6', '#a60000', '#736039',
969 985 '#00b318', '#79aaf2', '#330d30', '#ff8080', '#403010', '#16591f',
970 986 '#002459', '#8c4688', '#e50000', '#ffbf40', '#00732e', '#102340',
971 987 '#bf60ac', '#8c4646', '#cc8800', '#00a642', '#1d3473', '#b32d98',
972 988 '#660e00', '#ffd580', '#80ffb2', '#7391e6', '#733967', '#d97b6c',
973 989 '#8c5e00', '#59b389', '#3967e6', '#590047', '#73281d', '#665200',
974 990 '#00e67a', '#2d50b3', '#8c2377', '#734139', '#b2982d', '#16593a',
975 991 '#001859', '#ff00aa', '#a65e53', '#ffcc00', '#0d3321', '#2d3959',
976 992 '#731d56', '#401610', '#4c3d00', '#468c6c', '#002ca6', '#d936a3',
977 993 '#d94c36', '#403920', '#36d9a3', '#0d1733', '#592d4a', '#993626',
978 994 '#cca300', '#00734d', '#46598c', '#8c005e', '#7f1100', '#8c7000',
979 995 '#00a66f', '#7382e6', '#b32d74', '#d9896c', '#ffe680', '#1d7362',
980 996 '#364cd9', '#73003d', '#d93a00', '#998a4d', '#59b3a1', '#5965b3',
981 997 '#e5007a', '#73341d', '#665f00', '#00b38f', '#0018b3', '#59163a',
982 998 '#b2502d', '#bfb960', '#00ffcc', '#23318c', '#a6537f', '#734939',
983 999 '#b2a700', '#104036', '#3d3df2', '#402031', '#e56739', '#736f39',
984 1000 '#79f2ea', '#000059', '#401029', '#4c1400', '#ffee00', '#005953',
985 1001 '#101040', '#990052', '#402820', '#403d10', '#00ffee', '#0000d9',
986 1002 '#ff80c4', '#a66953', '#eeff00', '#00ccbe', '#8080ff', '#e673a1',
987 1003 '#a62c00', '#474d00', '#1a3331', '#46468c', '#733950', '#662900',
988 1004 '#858c23', '#238c85', '#0f0073', '#b20047', '#d9986c', '#becc00',
989 1005 '#396f73', '#281d73', '#ff0066', '#ff6600', '#dee673', '#59adb3',
990 1006 '#6559b3', '#590024', '#b2622d', '#98b32d', '#36ced9', '#332d59',
991 1007 '#40001a', '#733f1d', '#526600', '#005359', '#242040', '#bf6079',
992 1008 '#735039', '#cef23d', '#007780', '#5630bf', '#66001b', '#b24700',
993 1009 '#acbf60', '#1d6273', '#25008c', '#731d34', '#a67453', '#50592d',
994 1010 '#00ccff', '#6600ff', '#ff0044', '#4c1f00', '#8a994d', '#79daf2',
995 1011 '#a173e6', '#d93662', '#402310', '#aaff00', '#2d98b3', '#8c40ff',
996 1012 '#592d39', '#ff8c40', '#354020', '#103640', '#1a0040', '#331a20',
997 1013 '#331400', '#334d00', '#1d5673', '#583973', '#7f0022', '#4c3626',
998 1014 '#88cc00', '#36a3d9', '#3d0073', '#d9364c', '#33241a', '#698c23',
999 1015 '#5995b3', '#300059', '#e57382', '#7f3300', '#366600', '#00aaff',
1000 1016 '#3a1659', '#733941', '#663600', '#74b32d', '#003c59', '#7f53a6',
1001 1017 '#73000f', '#ff8800', '#baf279', '#79caf2', '#291040', '#a6293a',
1002 1018 '#b2742d', '#587339', '#0077b3', '#632699', '#400009', '#d9a66c',
1003 1019 '#294010', '#2d4a59', '#aa00ff', '#4c131b', '#b25f00', '#5ce600',
1004 1020 '#267399', '#a336d9', '#990014', '#664e33', '#86bf60', '#0088ff',
1005 1021 '#7700b3', '#593a16', '#073300', '#1d4b73', '#ac60bf', '#e59539',
1006 1022 '#4f8c46', '#368dd9', '#5c0073'
1007 1023 ]
1008 1024
1009 1025 def rgb_to_hex_color(self, rgb_tuple):
1010 1026 """
1011 1027 Converts an rgb_tuple passed to an hex color.
1012 1028
1013 1029 :param rgb_tuple: tuple with 3 ints represents rgb color space
1014 1030 """
1015 1031 return '#' + ("".join(map(chr, rgb_tuple)).encode('hex'))
1016 1032
1017 1033 def email_to_int_list(self, email_str):
1018 1034 """
1019 1035 Get every byte of the hex digest value of email and turn it to integer.
1020 1036 It's going to be always between 0-255
1021 1037 """
1022 1038 digest = md5_safe(email_str.lower())
1023 1039 return [int(digest[i * 2:i * 2 + 2], 16) for i in range(16)]
1024 1040
1025 1041 def pick_color_bank_index(self, email_str, color_bank):
1026 1042 return self.email_to_int_list(email_str)[0] % len(color_bank)
1027 1043
1028 1044 def str2color(self, email_str):
1029 1045 """
1030 1046 Tries to map in a stable algorithm an email to color
1031 1047
1032 1048 :param email_str:
1033 1049 """
1034 1050 color_bank = self.get_color_bank()
1035 1051 # pick position (module it's length so we always find it in the
1036 1052 # bank even if it's smaller than 256 values
1037 1053 pos = self.pick_color_bank_index(email_str, color_bank)
1038 1054 return color_bank[pos]
1039 1055
1040 1056 def normalize_email(self, email_address):
1041 1057 import unicodedata
1042 1058 # default host used to fill in the fake/missing email
1043 1059 default_host = u'localhost'
1044 1060
1045 1061 if not email_address:
1046 1062 email_address = u'%s@%s' % (User.DEFAULT_USER, default_host)
1047 1063
1048 1064 email_address = safe_unicode(email_address)
1049 1065
1050 1066 if u'@' not in email_address:
1051 1067 email_address = u'%s@%s' % (email_address, default_host)
1052 1068
1053 1069 if email_address.endswith(u'@'):
1054 1070 email_address = u'%s%s' % (email_address, default_host)
1055 1071
1056 1072 email_address = unicodedata.normalize('NFKD', email_address)\
1057 1073 .encode('ascii', 'ignore')
1058 1074 return email_address
1059 1075
1060 1076 def get_initials(self):
1061 1077 """
1062 1078 Returns 2 letter initials calculated based on the input.
1063 1079 The algorithm picks first given email address, and takes first letter
1064 1080 of part before @, and then the first letter of server name. In case
1065 1081 the part before @ is in a format of `somestring.somestring2` it replaces
1066 1082 the server letter with first letter of somestring2
1067 1083
1068 1084 In case function was initialized with both first and lastname, this
1069 1085 overrides the extraction from email by first letter of the first and
1070 1086 last name. We add special logic to that functionality, In case Full name
1071 1087 is compound, like Guido Von Rossum, we use last part of the last name
1072 1088 (Von Rossum) picking `R`.
1073 1089
1074 1090 Function also normalizes the non-ascii characters to they ascii
1075 1091 representation, eg Δ„ => A
1076 1092 """
1077 1093 import unicodedata
1078 1094 # replace non-ascii to ascii
1079 1095 first_name = unicodedata.normalize(
1080 1096 'NFKD', safe_unicode(self.first_name)).encode('ascii', 'ignore')
1081 1097 last_name = unicodedata.normalize(
1082 1098 'NFKD', safe_unicode(self.last_name)).encode('ascii', 'ignore')
1083 1099
1084 1100 # do NFKD encoding, and also make sure email has proper format
1085 1101 email_address = self.normalize_email(self.email_address)
1086 1102
1087 1103 # first push the email initials
1088 1104 prefix, server = email_address.split('@', 1)
1089 1105
1090 1106 # check if prefix is maybe a 'firstname.lastname' syntax
1091 1107 _dot_split = prefix.rsplit('.', 1)
1092 1108 if len(_dot_split) == 2:
1093 1109 initials = [_dot_split[0][0], _dot_split[1][0]]
1094 1110 else:
1095 1111 initials = [prefix[0], server[0]]
1096 1112
1097 1113 # then try to replace either firtname or lastname
1098 1114 fn_letter = (first_name or " ")[0].strip()
1099 1115 ln_letter = (last_name.split(' ', 1)[-1] or " ")[0].strip()
1100 1116
1101 1117 if fn_letter:
1102 1118 initials[0] = fn_letter
1103 1119
1104 1120 if ln_letter:
1105 1121 initials[1] = ln_letter
1106 1122
1107 1123 return ''.join(initials).upper()
1108 1124
1109 1125 def get_img_data_by_type(self, font_family, img_type):
1110 1126 default_user = """
1111 1127 <svg xmlns="http://www.w3.org/2000/svg"
1112 1128 version="1.1" x="0px" y="0px" width="{size}" height="{size}"
1113 1129 viewBox="-15 -10 439.165 429.164"
1114 1130
1115 1131 xml:space="preserve"
1116 1132 style="background:{background};" >
1117 1133
1118 1134 <path d="M204.583,216.671c50.664,0,91.74-48.075,
1119 1135 91.74-107.378c0-82.237-41.074-107.377-91.74-107.377
1120 1136 c-50.668,0-91.74,25.14-91.74,107.377C112.844,
1121 1137 168.596,153.916,216.671,
1122 1138 204.583,216.671z" fill="{text_color}"/>
1123 1139 <path d="M407.164,374.717L360.88,
1124 1140 270.454c-2.117-4.771-5.836-8.728-10.465-11.138l-71.83-37.392
1125 1141 c-1.584-0.823-3.502-0.663-4.926,0.415c-20.316,
1126 1142 15.366-44.203,23.488-69.076,23.488c-24.877,
1127 1143 0-48.762-8.122-69.078-23.488
1128 1144 c-1.428-1.078-3.346-1.238-4.93-0.415L58.75,
1129 1145 259.316c-4.631,2.41-8.346,6.365-10.465,11.138L2.001,374.717
1130 1146 c-3.191,7.188-2.537,15.412,1.75,22.005c4.285,
1131 1147 6.592,11.537,10.526,19.4,10.526h362.861c7.863,0,15.117-3.936,
1132 1148 19.402-10.527 C409.699,390.129,
1133 1149 410.355,381.902,407.164,374.717z" fill="{text_color}"/>
1134 1150 </svg>""".format(
1135 1151 size=self.size,
1136 1152 background='#979797', # @grey4
1137 1153 text_color=self.text_color,
1138 1154 font_family=font_family)
1139 1155
1140 1156 return {
1141 1157 "default_user": default_user
1142 1158 }[img_type]
1143 1159
1144 1160 def get_img_data(self, svg_type=None):
1145 1161 """
1146 1162 generates the svg metadata for image
1147 1163 """
1148 1164
1149 1165 font_family = ','.join([
1150 1166 'proximanovaregular',
1151 1167 'Proxima Nova Regular',
1152 1168 'Proxima Nova',
1153 1169 'Arial',
1154 1170 'Lucida Grande',
1155 1171 'sans-serif'
1156 1172 ])
1157 1173 if svg_type:
1158 1174 return self.get_img_data_by_type(font_family, svg_type)
1159 1175
1160 1176 initials = self.get_initials()
1161 1177 img_data = """
1162 1178 <svg xmlns="http://www.w3.org/2000/svg" pointer-events="none"
1163 1179 width="{size}" height="{size}"
1164 1180 style="width: 100%; height: 100%; background-color: {background}"
1165 1181 viewBox="0 0 {size} {size}">
1166 1182 <text text-anchor="middle" y="50%" x="50%" dy="0.35em"
1167 1183 pointer-events="auto" fill="{text_color}"
1168 1184 font-family="{font_family}"
1169 1185 style="font-weight: 400; font-size: {f_size}px;">{text}
1170 1186 </text>
1171 1187 </svg>""".format(
1172 1188 size=self.size,
1173 1189 f_size=self.size/1.85, # scale the text inside the box nicely
1174 1190 background=self.background,
1175 1191 text_color=self.text_color,
1176 1192 text=initials.upper(),
1177 1193 font_family=font_family)
1178 1194
1179 1195 return img_data
1180 1196
1181 1197 def generate_svg(self, svg_type=None):
1182 1198 img_data = self.get_img_data(svg_type)
1183 1199 return "data:image/svg+xml;base64,%s" % img_data.encode('base64')
1184 1200
1185 1201
1186 1202 def initials_gravatar(email_address, first_name, last_name, size=30):
1187 1203 svg_type = None
1188 1204 if email_address == User.DEFAULT_USER_EMAIL:
1189 1205 svg_type = 'default_user'
1190 1206 klass = InitialsGravatar(email_address, first_name, last_name, size)
1191 1207 return klass.generate_svg(svg_type=svg_type)
1192 1208
1193 1209
1194 1210 def gravatar_url(email_address, size=30):
1195 1211 # doh, we need to re-import those to mock it later
1196 1212 from pylons import tmpl_context as c
1197 1213
1198 1214 _use_gravatar = c.visual.use_gravatar
1199 1215 _gravatar_url = c.visual.gravatar_url or User.DEFAULT_GRAVATAR_URL
1200 1216
1201 1217 email_address = email_address or User.DEFAULT_USER_EMAIL
1202 1218 if isinstance(email_address, unicode):
1203 1219 # hashlib crashes on unicode items
1204 1220 email_address = safe_str(email_address)
1205 1221
1206 1222 # empty email or default user
1207 1223 if not email_address or email_address == User.DEFAULT_USER_EMAIL:
1208 1224 return initials_gravatar(User.DEFAULT_USER_EMAIL, '', '', size=size)
1209 1225
1210 1226 if _use_gravatar:
1211 1227 # TODO: Disuse pyramid thread locals. Think about another solution to
1212 1228 # get the host and schema here.
1213 1229 request = get_current_request()
1214 1230 tmpl = safe_str(_gravatar_url)
1215 1231 tmpl = tmpl.replace('{email}', email_address)\
1216 1232 .replace('{md5email}', md5_safe(email_address.lower())) \
1217 1233 .replace('{netloc}', request.host)\
1218 1234 .replace('{scheme}', request.scheme)\
1219 1235 .replace('{size}', safe_str(size))
1220 1236 return tmpl
1221 1237 else:
1222 1238 return initials_gravatar(email_address, '', '', size=size)
1223 1239
1224 1240
1225 1241 class Page(_Page):
1226 1242 """
1227 1243 Custom pager to match rendering style with paginator
1228 1244 """
1229 1245
1230 1246 def _get_pos(self, cur_page, max_page, items):
1231 1247 edge = (items / 2) + 1
1232 1248 if (cur_page <= edge):
1233 1249 radius = max(items / 2, items - cur_page)
1234 1250 elif (max_page - cur_page) < edge:
1235 1251 radius = (items - 1) - (max_page - cur_page)
1236 1252 else:
1237 1253 radius = items / 2
1238 1254
1239 1255 left = max(1, (cur_page - (radius)))
1240 1256 right = min(max_page, cur_page + (radius))
1241 1257 return left, cur_page, right
1242 1258
1243 1259 def _range(self, regexp_match):
1244 1260 """
1245 1261 Return range of linked pages (e.g. '1 2 [3] 4 5 6 7 8').
1246 1262
1247 1263 Arguments:
1248 1264
1249 1265 regexp_match
1250 1266 A "re" (regular expressions) match object containing the
1251 1267 radius of linked pages around the current page in
1252 1268 regexp_match.group(1) as a string
1253 1269
1254 1270 This function is supposed to be called as a callable in
1255 1271 re.sub.
1256 1272
1257 1273 """
1258 1274 radius = int(regexp_match.group(1))
1259 1275
1260 1276 # Compute the first and last page number within the radius
1261 1277 # e.g. '1 .. 5 6 [7] 8 9 .. 12'
1262 1278 # -> leftmost_page = 5
1263 1279 # -> rightmost_page = 9
1264 1280 leftmost_page, _cur, rightmost_page = self._get_pos(self.page,
1265 1281 self.last_page,
1266 1282 (radius * 2) + 1)
1267 1283 nav_items = []
1268 1284
1269 1285 # Create a link to the first page (unless we are on the first page
1270 1286 # or there would be no need to insert '..' spacers)
1271 1287 if self.page != self.first_page and self.first_page < leftmost_page:
1272 1288 nav_items.append(self._pagerlink(self.first_page, self.first_page))
1273 1289
1274 1290 # Insert dots if there are pages between the first page
1275 1291 # and the currently displayed page range
1276 1292 if leftmost_page - self.first_page > 1:
1277 1293 # Wrap in a SPAN tag if nolink_attr is set
1278 1294 text = '..'
1279 1295 if self.dotdot_attr:
1280 1296 text = HTML.span(c=text, **self.dotdot_attr)
1281 1297 nav_items.append(text)
1282 1298
1283 1299 for thispage in xrange(leftmost_page, rightmost_page + 1):
1284 1300 # Hilight the current page number and do not use a link
1285 1301 if thispage == self.page:
1286 1302 text = '%s' % (thispage,)
1287 1303 # Wrap in a SPAN tag if nolink_attr is set
1288 1304 if self.curpage_attr:
1289 1305 text = HTML.span(c=text, **self.curpage_attr)
1290 1306 nav_items.append(text)
1291 1307 # Otherwise create just a link to that page
1292 1308 else:
1293 1309 text = '%s' % (thispage,)
1294 1310 nav_items.append(self._pagerlink(thispage, text))
1295 1311
1296 1312 # Insert dots if there are pages between the displayed
1297 1313 # page numbers and the end of the page range
1298 1314 if self.last_page - rightmost_page > 1:
1299 1315 text = '..'
1300 1316 # Wrap in a SPAN tag if nolink_attr is set
1301 1317 if self.dotdot_attr:
1302 1318 text = HTML.span(c=text, **self.dotdot_attr)
1303 1319 nav_items.append(text)
1304 1320
1305 1321 # Create a link to the very last page (unless we are on the last
1306 1322 # page or there would be no need to insert '..' spacers)
1307 1323 if self.page != self.last_page and rightmost_page < self.last_page:
1308 1324 nav_items.append(self._pagerlink(self.last_page, self.last_page))
1309 1325
1310 1326 ## prerender links
1311 1327 #_page_link = url.current()
1312 1328 #nav_items.append(literal('<link rel="prerender" href="%s?page=%s">' % (_page_link, str(int(self.page)+1))))
1313 1329 #nav_items.append(literal('<link rel="prefetch" href="%s?page=%s">' % (_page_link, str(int(self.page)+1))))
1314 1330 return self.separator.join(nav_items)
1315 1331
1316 1332 def pager(self, format='~2~', page_param='page', partial_param='partial',
1317 1333 show_if_single_page=False, separator=' ', onclick=None,
1318 1334 symbol_first='<<', symbol_last='>>',
1319 1335 symbol_previous='<', symbol_next='>',
1320 1336 link_attr={'class': 'pager_link', 'rel': 'prerender'},
1321 1337 curpage_attr={'class': 'pager_curpage'},
1322 1338 dotdot_attr={'class': 'pager_dotdot'}, **kwargs):
1323 1339
1324 1340 self.curpage_attr = curpage_attr
1325 1341 self.separator = separator
1326 1342 self.pager_kwargs = kwargs
1327 1343 self.page_param = page_param
1328 1344 self.partial_param = partial_param
1329 1345 self.onclick = onclick
1330 1346 self.link_attr = link_attr
1331 1347 self.dotdot_attr = dotdot_attr
1332 1348
1333 1349 # Don't show navigator if there is no more than one page
1334 1350 if self.page_count == 0 or (self.page_count == 1 and not show_if_single_page):
1335 1351 return ''
1336 1352
1337 1353 from string import Template
1338 1354 # Replace ~...~ in token format by range of pages
1339 1355 result = re.sub(r'~(\d+)~', self._range, format)
1340 1356
1341 1357 # Interpolate '%' variables
1342 1358 result = Template(result).safe_substitute({
1343 1359 'first_page': self.first_page,
1344 1360 'last_page': self.last_page,
1345 1361 'page': self.page,
1346 1362 'page_count': self.page_count,
1347 1363 'items_per_page': self.items_per_page,
1348 1364 'first_item': self.first_item,
1349 1365 'last_item': self.last_item,
1350 1366 'item_count': self.item_count,
1351 1367 'link_first': self.page > self.first_page and \
1352 1368 self._pagerlink(self.first_page, symbol_first) or '',
1353 1369 'link_last': self.page < self.last_page and \
1354 1370 self._pagerlink(self.last_page, symbol_last) or '',
1355 1371 'link_previous': self.previous_page and \
1356 1372 self._pagerlink(self.previous_page, symbol_previous) \
1357 1373 or HTML.span(symbol_previous, class_="pg-previous disabled"),
1358 1374 'link_next': self.next_page and \
1359 1375 self._pagerlink(self.next_page, symbol_next) \
1360 1376 or HTML.span(symbol_next, class_="pg-next disabled")
1361 1377 })
1362 1378
1363 1379 return literal(result)
1364 1380
1365 1381
1366 1382 #==============================================================================
1367 1383 # REPO PAGER, PAGER FOR REPOSITORY
1368 1384 #==============================================================================
1369 1385 class RepoPage(Page):
1370 1386
1371 1387 def __init__(self, collection, page=1, items_per_page=20,
1372 1388 item_count=None, url=None, **kwargs):
1373 1389
1374 1390 """Create a "RepoPage" instance. special pager for paging
1375 1391 repository
1376 1392 """
1377 1393 self._url_generator = url
1378 1394
1379 1395 # Safe the kwargs class-wide so they can be used in the pager() method
1380 1396 self.kwargs = kwargs
1381 1397
1382 1398 # Save a reference to the collection
1383 1399 self.original_collection = collection
1384 1400
1385 1401 self.collection = collection
1386 1402
1387 1403 # The self.page is the number of the current page.
1388 1404 # The first page has the number 1!
1389 1405 try:
1390 1406 self.page = int(page) # make it int() if we get it as a string
1391 1407 except (ValueError, TypeError):
1392 1408 self.page = 1
1393 1409
1394 1410 self.items_per_page = items_per_page
1395 1411
1396 1412 # Unless the user tells us how many items the collections has
1397 1413 # we calculate that ourselves.
1398 1414 if item_count is not None:
1399 1415 self.item_count = item_count
1400 1416 else:
1401 1417 self.item_count = len(self.collection)
1402 1418
1403 1419 # Compute the number of the first and last available page
1404 1420 if self.item_count > 0:
1405 1421 self.first_page = 1
1406 1422 self.page_count = int(math.ceil(float(self.item_count) /
1407 1423 self.items_per_page))
1408 1424 self.last_page = self.first_page + self.page_count - 1
1409 1425
1410 1426 # Make sure that the requested page number is the range of
1411 1427 # valid pages
1412 1428 if self.page > self.last_page:
1413 1429 self.page = self.last_page
1414 1430 elif self.page < self.first_page:
1415 1431 self.page = self.first_page
1416 1432
1417 1433 # Note: the number of items on this page can be less than
1418 1434 # items_per_page if the last page is not full
1419 1435 self.first_item = max(0, (self.item_count) - (self.page *
1420 1436 items_per_page))
1421 1437 self.last_item = ((self.item_count - 1) - items_per_page *
1422 1438 (self.page - 1))
1423 1439
1424 1440 self.items = list(self.collection[self.first_item:self.last_item + 1])
1425 1441
1426 1442 # Links to previous and next page
1427 1443 if self.page > self.first_page:
1428 1444 self.previous_page = self.page - 1
1429 1445 else:
1430 1446 self.previous_page = None
1431 1447
1432 1448 if self.page < self.last_page:
1433 1449 self.next_page = self.page + 1
1434 1450 else:
1435 1451 self.next_page = None
1436 1452
1437 1453 # No items available
1438 1454 else:
1439 1455 self.first_page = None
1440 1456 self.page_count = 0
1441 1457 self.last_page = None
1442 1458 self.first_item = None
1443 1459 self.last_item = None
1444 1460 self.previous_page = None
1445 1461 self.next_page = None
1446 1462 self.items = []
1447 1463
1448 1464 # This is a subclass of the 'list' type. Initialise the list now.
1449 1465 list.__init__(self, reversed(self.items))
1450 1466
1451 1467
1452 1468 def changed_tooltip(nodes):
1453 1469 """
1454 1470 Generates a html string for changed nodes in commit page.
1455 1471 It limits the output to 30 entries
1456 1472
1457 1473 :param nodes: LazyNodesGenerator
1458 1474 """
1459 1475 if nodes:
1460 1476 pref = ': <br/> '
1461 1477 suf = ''
1462 1478 if len(nodes) > 30:
1463 1479 suf = '<br/>' + _(' and %s more') % (len(nodes) - 30)
1464 1480 return literal(pref + '<br/> '.join([safe_unicode(x.path)
1465 1481 for x in nodes[:30]]) + suf)
1466 1482 else:
1467 1483 return ': ' + _('No Files')
1468 1484
1469 1485
1470 1486 def breadcrumb_repo_link(repo):
1471 1487 """
1472 1488 Makes a breadcrumbs path link to repo
1473 1489
1474 1490 ex::
1475 1491 group >> subgroup >> repo
1476 1492
1477 1493 :param repo: a Repository instance
1478 1494 """
1479 1495
1480 1496 path = [
1481 1497 link_to(group.name, url('repo_group_home', group_name=group.group_name))
1482 1498 for group in repo.groups_with_parents
1483 1499 ] + [
1484 1500 link_to(repo.just_name, url('summary_home', repo_name=repo.repo_name))
1485 1501 ]
1486 1502
1487 1503 return literal(' &raquo; '.join(path))
1488 1504
1489 1505
1490 1506 def format_byte_size_binary(file_size):
1491 1507 """
1492 1508 Formats file/folder sizes to standard.
1493 1509 """
1494 1510 formatted_size = format_byte_size(file_size, binary=True)
1495 1511 return formatted_size
1496 1512
1497 1513
1498 1514 def fancy_file_stats(stats):
1499 1515 """
1500 1516 Displays a fancy two colored bar for number of added/deleted
1501 1517 lines of code on file
1502 1518
1503 1519 :param stats: two element list of added/deleted lines of code
1504 1520 """
1505 1521 from rhodecode.lib.diffs import NEW_FILENODE, DEL_FILENODE, \
1506 1522 MOD_FILENODE, RENAMED_FILENODE, CHMOD_FILENODE, BIN_FILENODE
1507 1523
1508 1524 def cgen(l_type, a_v, d_v):
1509 1525 mapping = {'tr': 'top-right-rounded-corner-mid',
1510 1526 'tl': 'top-left-rounded-corner-mid',
1511 1527 'br': 'bottom-right-rounded-corner-mid',
1512 1528 'bl': 'bottom-left-rounded-corner-mid'}
1513 1529 map_getter = lambda x: mapping[x]
1514 1530
1515 1531 if l_type == 'a' and d_v:
1516 1532 #case when added and deleted are present
1517 1533 return ' '.join(map(map_getter, ['tl', 'bl']))
1518 1534
1519 1535 if l_type == 'a' and not d_v:
1520 1536 return ' '.join(map(map_getter, ['tr', 'br', 'tl', 'bl']))
1521 1537
1522 1538 if l_type == 'd' and a_v:
1523 1539 return ' '.join(map(map_getter, ['tr', 'br']))
1524 1540
1525 1541 if l_type == 'd' and not a_v:
1526 1542 return ' '.join(map(map_getter, ['tr', 'br', 'tl', 'bl']))
1527 1543
1528 1544 a, d = stats['added'], stats['deleted']
1529 1545 width = 100
1530 1546
1531 1547 if stats['binary']: # binary operations like chmod/rename etc
1532 1548 lbl = []
1533 1549 bin_op = 0 # undefined
1534 1550
1535 1551 # prefix with bin for binary files
1536 1552 if BIN_FILENODE in stats['ops']:
1537 1553 lbl += ['bin']
1538 1554
1539 1555 if NEW_FILENODE in stats['ops']:
1540 1556 lbl += [_('new file')]
1541 1557 bin_op = NEW_FILENODE
1542 1558 elif MOD_FILENODE in stats['ops']:
1543 1559 lbl += [_('mod')]
1544 1560 bin_op = MOD_FILENODE
1545 1561 elif DEL_FILENODE in stats['ops']:
1546 1562 lbl += [_('del')]
1547 1563 bin_op = DEL_FILENODE
1548 1564 elif RENAMED_FILENODE in stats['ops']:
1549 1565 lbl += [_('rename')]
1550 1566 bin_op = RENAMED_FILENODE
1551 1567
1552 1568 # chmod can go with other operations, so we add a + to lbl if needed
1553 1569 if CHMOD_FILENODE in stats['ops']:
1554 1570 lbl += [_('chmod')]
1555 1571 if bin_op == 0:
1556 1572 bin_op = CHMOD_FILENODE
1557 1573
1558 1574 lbl = '+'.join(lbl)
1559 1575 b_a = '<div class="bin bin%s %s" style="width:100%%">%s</div>' \
1560 1576 % (bin_op, cgen('a', a_v='', d_v=0), lbl)
1561 1577 b_d = '<div class="bin bin1" style="width:0%%"></div>'
1562 1578 return literal('<div style="width:%spx">%s%s</div>' % (width, b_a, b_d))
1563 1579
1564 1580 t = stats['added'] + stats['deleted']
1565 1581 unit = float(width) / (t or 1)
1566 1582
1567 1583 # needs > 9% of width to be visible or 0 to be hidden
1568 1584 a_p = max(9, unit * a) if a > 0 else 0
1569 1585 d_p = max(9, unit * d) if d > 0 else 0
1570 1586 p_sum = a_p + d_p
1571 1587
1572 1588 if p_sum > width:
1573 1589 #adjust the percentage to be == 100% since we adjusted to 9
1574 1590 if a_p > d_p:
1575 1591 a_p = a_p - (p_sum - width)
1576 1592 else:
1577 1593 d_p = d_p - (p_sum - width)
1578 1594
1579 1595 a_v = a if a > 0 else ''
1580 1596 d_v = d if d > 0 else ''
1581 1597
1582 1598 d_a = '<div class="added %s" style="width:%s%%">%s</div>' % (
1583 1599 cgen('a', a_v, d_v), a_p, a_v
1584 1600 )
1585 1601 d_d = '<div class="deleted %s" style="width:%s%%">%s</div>' % (
1586 1602 cgen('d', a_v, d_v), d_p, d_v
1587 1603 )
1588 1604 return literal('<div style="width:%spx">%s%s</div>' % (width, d_a, d_d))
1589 1605
1590 1606
1591 1607 def urlify_text(text_, safe=True):
1592 1608 """
1593 1609 Extrac urls from text and make html links out of them
1594 1610
1595 1611 :param text_:
1596 1612 """
1597 1613
1598 1614 url_pat = re.compile(r'''(http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@#.&+]'''
1599 1615 '''|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+)''')
1600 1616
1601 1617 def url_func(match_obj):
1602 1618 url_full = match_obj.groups()[0]
1603 1619 return '<a href="%(url)s">%(url)s</a>' % ({'url': url_full})
1604 1620 _newtext = url_pat.sub(url_func, text_)
1605 1621 if safe:
1606 1622 return literal(_newtext)
1607 1623 return _newtext
1608 1624
1609 1625
1610 1626 def urlify_commits(text_, repository):
1611 1627 """
1612 1628 Extract commit ids from text and make link from them
1613 1629
1614 1630 :param text_:
1615 1631 :param repository: repo name to build the URL with
1616 1632 """
1617 1633 from pylons import url # doh, we need to re-import url to mock it later
1618 1634 URL_PAT = re.compile(r'(^|\s)([0-9a-fA-F]{12,40})($|\s)')
1619 1635
1620 1636 def url_func(match_obj):
1621 1637 commit_id = match_obj.groups()[1]
1622 1638 pref = match_obj.groups()[0]
1623 1639 suf = match_obj.groups()[2]
1624 1640
1625 1641 tmpl = (
1626 1642 '%(pref)s<a class="%(cls)s" href="%(url)s">'
1627 1643 '%(commit_id)s</a>%(suf)s'
1628 1644 )
1629 1645 return tmpl % {
1630 1646 'pref': pref,
1631 1647 'cls': 'revision-link',
1632 1648 'url': url('changeset_home', repo_name=repository,
1633 1649 revision=commit_id, qualified=True),
1634 1650 'commit_id': commit_id,
1635 1651 'suf': suf
1636 1652 }
1637 1653
1638 1654 newtext = URL_PAT.sub(url_func, text_)
1639 1655
1640 1656 return newtext
1641 1657
1642 1658
1643 1659 def _process_url_func(match_obj, repo_name, uid, entry,
1644 1660 return_raw_data=False):
1645 1661 pref = ''
1646 1662 if match_obj.group().startswith(' '):
1647 1663 pref = ' '
1648 1664
1649 1665 issue_id = ''.join(match_obj.groups())
1650 1666 tmpl = (
1651 1667 '%(pref)s<a class="%(cls)s" href="%(url)s">'
1652 1668 '%(issue-prefix)s%(id-repr)s'
1653 1669 '</a>')
1654 1670
1655 1671 (repo_name_cleaned,
1656 1672 parent_group_name) = RepoGroupModel().\
1657 1673 _get_group_name_and_parent(repo_name)
1658 1674
1659 1675 # variables replacement
1660 1676 named_vars = {
1661 1677 'id': issue_id,
1662 1678 'repo': repo_name,
1663 1679 'repo_name': repo_name_cleaned,
1664 1680 'group_name': parent_group_name
1665 1681 }
1666 1682 # named regex variables
1667 1683 named_vars.update(match_obj.groupdict())
1668 1684 _url = string.Template(entry['url']).safe_substitute(**named_vars)
1669 1685
1670 1686 data = {
1671 1687 'pref': pref,
1672 1688 'cls': 'issue-tracker-link',
1673 1689 'url': _url,
1674 1690 'id-repr': issue_id,
1675 1691 'issue-prefix': entry['pref'],
1676 1692 'serv': entry['url'],
1677 1693 }
1678 1694 if return_raw_data:
1679 1695 return {
1680 1696 'id': issue_id,
1681 1697 'url': _url
1682 1698 }
1683 1699 return tmpl % data
1684 1700
1685 1701
1686 1702 def process_patterns(text_string, repo_name, config=None):
1687 1703 repo = None
1688 1704 if repo_name:
1689 1705 # Retrieving repo_name to avoid invalid repo_name to explode on
1690 1706 # IssueTrackerSettingsModel but still passing invalid name further down
1691 1707 repo = Repository.get_by_repo_name(repo_name, cache=True)
1692 1708
1693 1709 settings_model = IssueTrackerSettingsModel(repo=repo)
1694 1710 active_entries = settings_model.get_settings(cache=True)
1695 1711
1696 1712 issues_data = []
1697 1713 newtext = text_string
1698 1714 for uid, entry in active_entries.items():
1699 1715 log.debug('found issue tracker entry with uid %s' % (uid,))
1700 1716
1701 1717 if not (entry['pat'] and entry['url']):
1702 1718 log.debug('skipping due to missing data')
1703 1719 continue
1704 1720
1705 1721 log.debug('issue tracker entry: uid: `%s` PAT:%s URL:%s PREFIX:%s'
1706 1722 % (uid, entry['pat'], entry['url'], entry['pref']))
1707 1723
1708 1724 try:
1709 1725 pattern = re.compile(r'%s' % entry['pat'])
1710 1726 except re.error:
1711 1727 log.exception(
1712 1728 'issue tracker pattern: `%s` failed to compile',
1713 1729 entry['pat'])
1714 1730 continue
1715 1731
1716 1732 data_func = partial(
1717 1733 _process_url_func, repo_name=repo_name, entry=entry, uid=uid,
1718 1734 return_raw_data=True)
1719 1735
1720 1736 for match_obj in pattern.finditer(text_string):
1721 1737 issues_data.append(data_func(match_obj))
1722 1738
1723 1739 url_func = partial(
1724 1740 _process_url_func, repo_name=repo_name, entry=entry, uid=uid)
1725 1741
1726 1742 newtext = pattern.sub(url_func, newtext)
1727 1743 log.debug('processed prefix:uid `%s`' % (uid,))
1728 1744
1729 1745 return newtext, issues_data
1730 1746
1731 1747
1732 1748 def urlify_commit_message(commit_text, repository=None):
1733 1749 """
1734 1750 Parses given text message and makes proper links.
1735 1751 issues are linked to given issue-server, and rest is a commit link
1736 1752
1737 1753 :param commit_text:
1738 1754 :param repository:
1739 1755 """
1740 1756 from pylons import url # doh, we need to re-import url to mock it later
1741 1757
1742 1758 def escaper(string):
1743 1759 return string.replace('<', '&lt;').replace('>', '&gt;')
1744 1760
1745 1761 newtext = escaper(commit_text)
1746 1762
1747 1763 # extract http/https links and make them real urls
1748 1764 newtext = urlify_text(newtext, safe=False)
1749 1765
1750 1766 # urlify commits - extract commit ids and make link out of them, if we have
1751 1767 # the scope of repository present.
1752 1768 if repository:
1753 1769 newtext = urlify_commits(newtext, repository)
1754 1770
1755 1771 # process issue tracker patterns
1756 1772 newtext, issues = process_patterns(newtext, repository or '')
1757 1773
1758 1774 return literal(newtext)
1759 1775
1760 1776
1761 1777 def rst(source, mentions=False):
1762 1778 return literal('<div class="rst-block">%s</div>' %
1763 1779 MarkupRenderer.rst(source, mentions=mentions))
1764 1780
1765 1781
1766 1782 def markdown(source, mentions=False):
1767 1783 return literal('<div class="markdown-block">%s</div>' %
1768 1784 MarkupRenderer.markdown(source, flavored=True,
1769 1785 mentions=mentions))
1770 1786
1771 1787 def renderer_from_filename(filename, exclude=None):
1772 1788 return MarkupRenderer.renderer_from_filename(filename, exclude=exclude)
1773 1789
1774 1790
1775 1791 def render(source, renderer='rst', mentions=False):
1776 1792 if renderer == 'rst':
1777 1793 return rst(source, mentions=mentions)
1778 1794 if renderer == 'markdown':
1779 1795 return markdown(source, mentions=mentions)
1780 1796
1781 1797
1782 1798 def commit_status(repo, commit_id):
1783 1799 return ChangesetStatusModel().get_status(repo, commit_id)
1784 1800
1785 1801
1786 1802 def commit_status_lbl(commit_status):
1787 1803 return dict(ChangesetStatus.STATUSES).get(commit_status)
1788 1804
1789 1805
1790 1806 def commit_time(repo_name, commit_id):
1791 1807 repo = Repository.get_by_repo_name(repo_name)
1792 1808 commit = repo.get_commit(commit_id=commit_id)
1793 1809 return commit.date
1794 1810
1795 1811
1796 1812 def get_permission_name(key):
1797 1813 return dict(Permission.PERMS).get(key)
1798 1814
1799 1815
1800 1816 def journal_filter_help():
1801 1817 return _(
1802 1818 'Example filter terms:\n' +
1803 1819 ' repository:vcs\n' +
1804 1820 ' username:marcin\n' +
1805 1821 ' action:*push*\n' +
1806 1822 ' ip:127.0.0.1\n' +
1807 1823 ' date:20120101\n' +
1808 1824 ' date:[20120101100000 TO 20120102]\n' +
1809 1825 '\n' +
1810 1826 'Generate wildcards using \'*\' character:\n' +
1811 1827 ' "repository:vcs*" - search everything starting with \'vcs\'\n' +
1812 1828 ' "repository:*vcs*" - search for repository containing \'vcs\'\n' +
1813 1829 '\n' +
1814 1830 'Optional AND / OR operators in queries\n' +
1815 1831 ' "repository:vcs OR repository:test"\n' +
1816 1832 ' "username:test AND repository:test*"\n'
1817 1833 )
1818 1834
1819 1835
1820 1836 def not_mapped_error(repo_name):
1821 1837 flash(_('%s repository is not mapped to db perhaps'
1822 1838 ' it was created or renamed from the filesystem'
1823 1839 ' please run the application again'
1824 1840 ' in order to rescan repositories') % repo_name, category='error')
1825 1841
1826 1842
1827 1843 def ip_range(ip_addr):
1828 1844 from rhodecode.model.db import UserIpMap
1829 1845 s, e = UserIpMap._get_ip_range(ip_addr)
1830 1846 return '%s - %s' % (s, e)
1831 1847
1832 1848
1833 1849 def form(url, method='post', needs_csrf_token=True, **attrs):
1834 1850 """Wrapper around webhelpers.tags.form to prevent CSRF attacks."""
1835 1851 if method.lower() != 'get' and needs_csrf_token:
1836 1852 raise Exception(
1837 1853 'Forms to POST/PUT/DELETE endpoints should have (in general) a ' +
1838 1854 'CSRF token. If the endpoint does not require such token you can ' +
1839 1855 'explicitly set the parameter needs_csrf_token to false.')
1840 1856
1841 1857 return wh_form(url, method=method, **attrs)
1842 1858
1843 1859
1844 1860 def secure_form(url, method="POST", multipart=False, **attrs):
1845 1861 """Start a form tag that points the action to an url. This
1846 1862 form tag will also include the hidden field containing
1847 1863 the auth token.
1848 1864
1849 1865 The url options should be given either as a string, or as a
1850 1866 ``url()`` function. The method for the form defaults to POST.
1851 1867
1852 1868 Options:
1853 1869
1854 1870 ``multipart``
1855 1871 If set to True, the enctype is set to "multipart/form-data".
1856 1872 ``method``
1857 1873 The method to use when submitting the form, usually either
1858 1874 "GET" or "POST". If "PUT", "DELETE", or another verb is used, a
1859 1875 hidden input with name _method is added to simulate the verb
1860 1876 over POST.
1861 1877
1862 1878 """
1863 1879 from webhelpers.pylonslib.secure_form import insecure_form
1864 1880 from rhodecode.lib.auth import get_csrf_token, csrf_token_key
1865 1881 form = insecure_form(url, method, multipart, **attrs)
1866 1882 token = HTML.div(hidden(csrf_token_key, get_csrf_token()), style="display: none;")
1867 1883 return literal("%s\n%s" % (form, token))
1868 1884
1869 1885 def dropdownmenu(name, selected, options, enable_filter=False, **attrs):
1870 1886 select_html = select(name, selected, options, **attrs)
1871 1887 select2 = """
1872 1888 <script>
1873 1889 $(document).ready(function() {
1874 1890 $('#%s').select2({
1875 1891 containerCssClass: 'drop-menu',
1876 1892 dropdownCssClass: 'drop-menu-dropdown',
1877 1893 dropdownAutoWidth: true%s
1878 1894 });
1879 1895 });
1880 1896 </script>
1881 1897 """
1882 1898 filter_option = """,
1883 1899 minimumResultsForSearch: -1
1884 1900 """
1885 1901 input_id = attrs.get('id') or name
1886 1902 filter_enabled = "" if enable_filter else filter_option
1887 1903 select_script = literal(select2 % (input_id, filter_enabled))
1888 1904
1889 1905 return literal(select_html+select_script)
1890 1906
1891 1907
1892 1908 def get_visual_attr(tmpl_context_var, attr_name):
1893 1909 """
1894 1910 A safe way to get a variable from visual variable of template context
1895 1911
1896 1912 :param tmpl_context_var: instance of tmpl_context, usually present as `c`
1897 1913 :param attr_name: name of the attribute we fetch from the c.visual
1898 1914 """
1899 1915 visual = getattr(tmpl_context_var, 'visual', None)
1900 1916 if not visual:
1901 1917 return
1902 1918 else:
1903 1919 return getattr(visual, attr_name, None)
1904 1920
1905 1921
1906 1922 def get_last_path_part(file_node):
1907 1923 if not file_node.path:
1908 1924 return u''
1909 1925
1910 1926 path = safe_unicode(file_node.path.split('/')[-1])
1911 1927 return u'../' + path
1912 1928
1913 1929
1914 1930 def route_path(*args, **kwds):
1915 1931 """
1916 1932 Wrapper around pyramids `route_path` function. It is used to generate
1917 1933 URLs from within pylons views or templates. This will be removed when
1918 1934 pyramid migration if finished.
1919 1935 """
1920 1936 req = get_current_request()
1921 1937 return req.route_path(*args, **kwds)
1922 1938
1923 1939
1924 1940 def resource_path(*args, **kwds):
1925 1941 """
1926 1942 Wrapper around pyramids `route_path` function. It is used to generate
1927 1943 URLs from within pylons views or templates. This will be removed when
1928 1944 pyramid migration if finished.
1929 1945 """
1930 1946 req = get_current_request()
1931 1947 return req.resource_path(*args, **kwds)
@@ -1,656 +1,656 b''
1 1 ## -*- coding: utf-8 -*-
2 2 <%inherit file="root.html"/>
3 3
4 4 <div class="outerwrapper">
5 5 <!-- HEADER -->
6 6 <div class="header">
7 7 <div id="header-inner" class="wrapper">
8 8 <div id="logo">
9 9 <div class="logo-wrapper">
10 <a href="${h.url('home')}"><img src="${h.url('/images/rhodecode-logo-white-216x60.png')}" alt="RhodeCode"/></a>
10 <a href="${h.url('home')}"><img src="${h.asset('images/rhodecode-logo-white-216x60.png')}" alt="RhodeCode"/></a>
11 11 </div>
12 12 %if c.rhodecode_name:
13 13 <div class="branding">- ${h.branding(c.rhodecode_name)}</div>
14 14 %endif
15 15 </div>
16 16 <!-- MENU BAR NAV -->
17 17 ${self.menu_bar_nav()}
18 18 <!-- END MENU BAR NAV -->
19 19 </div>
20 20 </div>
21 21 ${self.menu_bar_subnav()}
22 22 <!-- END HEADER -->
23 23
24 24 <!-- CONTENT -->
25 25 <div id="content" class="wrapper">
26 26 ${self.flash_msg()}
27 27 <div class="main">
28 28 ${next.main()}
29 29 </div>
30 30 </div>
31 31 <!-- END CONTENT -->
32 32
33 33 </div>
34 34 <!-- FOOTER -->
35 35 <div id="footer">
36 36 <div id="footer-inner" class="title wrapper">
37 37 <div>
38 38 <p class="footer-link-right">
39 39 % if c.visual.show_version:
40 40 RhodeCode Enterprise ${c.rhodecode_version} ${c.rhodecode_edition}
41 41 % endif
42 42 &copy; 2010-${h.datetime.today().year}, <a href="${h.url('rhodecode_official')}" target="_blank">RhodeCode GmbH</a>. All rights reserved.
43 43 % if c.visual.rhodecode_support_url:
44 44 <a href="${c.visual.rhodecode_support_url}" target="_blank">${_('Support')}</a>
45 45 % endif
46 46 </p>
47 47 <% sid = 'block' if request.GET.get('showrcid') else 'none' %>
48 48 <p class="server-instance" style="display:${sid}">
49 49 ## display hidden instance ID if specially defined
50 50 % if c.rhodecode_instanceid:
51 51 ${_('RhodeCode instance id: %s') % c.rhodecode_instanceid}
52 52 % endif
53 53 </p>
54 54 </div>
55 55 </div>
56 56 </div>
57 57
58 58 <!-- END FOOTER -->
59 59
60 60 ### MAKO DEFS ###
61 61
62 62 <%def name="menu_bar_subnav()">
63 63 </%def>
64 64
65 65 <%def name="flash_msg()">
66 66 <%include file="/base/flash_msg.html"/>
67 67 </%def>
68 68
69 69 <%def name="breadcrumbs(class_='breadcrumbs')">
70 70 <div class="${class_}">
71 71 ${self.breadcrumbs_links()}
72 72 </div>
73 73 </%def>
74 74
75 75 <%def name="admin_menu()">
76 76 <ul class="admin_menu submenu">
77 77 <li><a href="${h.url('admin_home')}">${_('Admin journal')}</a></li>
78 78 <li><a href="${h.url('repos')}">${_('Repositories')}</a></li>
79 79 <li><a href="${h.url('repo_groups')}">${_('Repository groups')}</a></li>
80 80 <li><a href="${h.url('users')}">${_('Users')}</a></li>
81 81 <li><a href="${h.url('users_groups')}">${_('User groups')}</a></li>
82 82 <li><a href="${h.url('admin_permissions_application')}">${_('Permissions')}</a></li>
83 83 <li><a href="${h.route_path('auth_home', traverse='')}">${_('Authentication')}</a></li>
84 84 <li><a href="${h.route_path('global_integrations_home')}">${_('Integrations')}</a></li>
85 85 <li><a href="${h.url('admin_defaults_repositories')}">${_('Defaults')}</a></li>
86 86 <li class="last"><a href="${h.url('admin_settings')}">${_('Settings')}</a></li>
87 87 </ul>
88 88 </%def>
89 89
90 90
91 91 <%def name="dt_info_panel(elements)">
92 92 <dl class="dl-horizontal">
93 93 %for dt, dd, title, show_items in elements:
94 94 <dt>${dt}:</dt>
95 95 <dd title="${title}">
96 96 %if callable(dd):
97 97 ## allow lazy evaluation of elements
98 98 ${dd()}
99 99 %else:
100 100 ${dd}
101 101 %endif
102 102 %if show_items:
103 103 <span class="btn-collapse" data-toggle="item-${h.md5(dt)[:6]}-details">${_('Show More')} </span>
104 104 %endif
105 105 </dd>
106 106
107 107 %if show_items:
108 108 <div class="collapsable-content" data-toggle="item-${h.md5(dt)[:6]}-details" style="display: none">
109 109 %for item in show_items:
110 110 <dt></dt>
111 111 <dd>${item}</dd>
112 112 %endfor
113 113 </div>
114 114 %endif
115 115
116 116 %endfor
117 117 </dl>
118 118 </%def>
119 119
120 120
121 121 <%def name="gravatar(email, size=16)">
122 122 <%
123 123 if (size > 16):
124 124 gravatar_class = 'gravatar gravatar-large'
125 125 else:
126 126 gravatar_class = 'gravatar'
127 127 %>
128 128 <%doc>
129 129 TODO: johbo: For now we serve double size images to make it smooth
130 130 for retina. This is how it worked until now. Should be replaced
131 131 with a better solution at some point.
132 132 </%doc>
133 133 <img class="${gravatar_class}" src="${h.gravatar_url(email, size * 2)}" height="${size}" width="${size}">
134 134 </%def>
135 135
136 136
137 137 <%def name="gravatar_with_user(contact, size=16, show_disabled=False)">
138 138 <% email = h.email_or_none(contact) %>
139 139 <div class="rc-user tooltip" title="${h.author_string(email)}">
140 140 ${self.gravatar(email, size)}
141 141 <span class="${'user user-disabled' if show_disabled else 'user'}"> ${h.link_to_user(contact)}</span>
142 142 </div>
143 143 </%def>
144 144
145 145
146 146 ## admin menu used for people that have some admin resources
147 147 <%def name="admin_menu_simple(repositories=None, repository_groups=None, user_groups=None)">
148 148 <ul class="submenu">
149 149 %if repositories:
150 150 <li><a href="${h.url('repos')}">${_('Repositories')}</a></li>
151 151 %endif
152 152 %if repository_groups:
153 153 <li><a href="${h.url('repo_groups')}">${_('Repository groups')}</a></li>
154 154 %endif
155 155 %if user_groups:
156 156 <li><a href="${h.url('users_groups')}">${_('User groups')}</a></li>
157 157 %endif
158 158 </ul>
159 159 </%def>
160 160
161 161 <%def name="repo_page_title(repo_instance)">
162 162 <div class="title-content">
163 163 <div class="title-main">
164 164 ## SVN/HG/GIT icons
165 165 %if h.is_hg(repo_instance):
166 166 <i class="icon-hg"></i>
167 167 %endif
168 168 %if h.is_git(repo_instance):
169 169 <i class="icon-git"></i>
170 170 %endif
171 171 %if h.is_svn(repo_instance):
172 172 <i class="icon-svn"></i>
173 173 %endif
174 174
175 175 ## public/private
176 176 %if repo_instance.private:
177 177 <i class="icon-repo-private"></i>
178 178 %else:
179 179 <i class="icon-repo-public"></i>
180 180 %endif
181 181
182 182 ## repo name with group name
183 183 ${h.breadcrumb_repo_link(c.rhodecode_db_repo)}
184 184
185 185 </div>
186 186
187 187 ## FORKED
188 188 %if repo_instance.fork:
189 189 <p>
190 190 <i class="icon-code-fork"></i> ${_('Fork of')}
191 191 <a href="${h.url('summary_home',repo_name=repo_instance.fork.repo_name)}">${repo_instance.fork.repo_name}</a>
192 192 </p>
193 193 %endif
194 194
195 195 ## IMPORTED FROM REMOTE
196 196 %if repo_instance.clone_uri:
197 197 <p>
198 198 <i class="icon-code-fork"></i> ${_('Clone from')}
199 199 <a href="${h.url(h.safe_str(h.hide_credentials(repo_instance.clone_uri)))}">${h.hide_credentials(repo_instance.clone_uri)}</a>
200 200 </p>
201 201 %endif
202 202
203 203 ## LOCKING STATUS
204 204 %if repo_instance.locked[0]:
205 205 <p class="locking_locked">
206 206 <i class="icon-repo-lock"></i>
207 207 ${_('Repository locked by %(user)s') % {'user': h.person_by_id(repo_instance.locked[0])}}
208 208 </p>
209 209 %elif repo_instance.enable_locking:
210 210 <p class="locking_unlocked">
211 211 <i class="icon-repo-unlock"></i>
212 212 ${_('Repository not locked. Pull repository to lock it.')}
213 213 </p>
214 214 %endif
215 215
216 216 </div>
217 217 </%def>
218 218
219 219 <%def name="repo_menu(active=None)">
220 220 <%
221 221 def is_active(selected):
222 222 if selected == active:
223 223 return "active"
224 224 %>
225 225
226 226 <!--- CONTEXT BAR -->
227 227 <div id="context-bar">
228 228 <div class="wrapper">
229 229 <ul id="context-pages" class="horizontal-list navigation">
230 230 <li class="${is_active('summary')}"><a class="menulink" href="${h.url('summary_home', repo_name=c.repo_name)}"><div class="menulabel">${_('Summary')}</div></a></li>
231 231 <li class="${is_active('changelog')}"><a class="menulink" href="${h.url('changelog_home', repo_name=c.repo_name)}"><div class="menulabel">${_('Changelog')}</div></a></li>
232 232 <li class="${is_active('files')}"><a class="menulink" href="${h.url('files_home', repo_name=c.repo_name, revision=c.rhodecode_db_repo.landing_rev[1])}"><div class="menulabel">${_('Files')}</div></a></li>
233 233 <li class="${is_active('compare')}">
234 234 <a class="menulink" href="${h.url('compare_home',repo_name=c.repo_name)}"><div class="menulabel">${_('Compare')}</div></a>
235 235 </li>
236 236 ## TODO: anderson: ideally it would have a function on the scm_instance "enable_pullrequest() and enable_fork()"
237 237 %if c.rhodecode_db_repo.repo_type in ['git','hg']:
238 238 <li class="${is_active('showpullrequest')}">
239 239 <a class="menulink" href="${h.url('pullrequest_show_all',repo_name=c.repo_name)}" title="${_('Show Pull Requests for %s') % c.repo_name}">
240 240 %if c.repository_pull_requests:
241 241 <span class="pr_notifications">${c.repository_pull_requests}</span>
242 242 %endif
243 243 <div class="menulabel">${_('Pull Requests')}</div>
244 244 </a>
245 245 </li>
246 246 %endif
247 247 <li class="${is_active('options')}">
248 248 <a class="menulink" href="#" class="dropdown"><div class="menulabel">${_('Options')} <div class="show_more"></div></div></a>
249 249 <ul class="submenu">
250 250 %if h.HasRepoPermissionAll('repository.admin')(c.repo_name):
251 251 <li><a href="${h.url('edit_repo',repo_name=c.repo_name)}">${_('Settings')}</a></li>
252 252 %endif
253 253 %if c.rhodecode_db_repo.fork:
254 254 <li><a href="${h.url('compare_url',repo_name=c.rhodecode_db_repo.fork.repo_name,source_ref_type=c.rhodecode_db_repo.landing_rev[0],source_ref=c.rhodecode_db_repo.landing_rev[1], target_repo=c.repo_name,target_ref_type='branch' if request.GET.get('branch') else c.rhodecode_db_repo.landing_rev[0],target_ref=request.GET.get('branch') or c.rhodecode_db_repo.landing_rev[1], merge=1)}">
255 255 ${_('Compare fork')}</a></li>
256 256 %endif
257 257
258 258 <li><a href="${h.url('search_repo_home',repo_name=c.repo_name)}">${_('Search')}</a></li>
259 259
260 260 %if h.HasRepoPermissionAny('repository.write','repository.admin')(c.repo_name) and c.rhodecode_db_repo.enable_locking:
261 261 %if c.rhodecode_db_repo.locked[0]:
262 262 <li><a class="locking_del" href="${h.url('toggle_locking',repo_name=c.repo_name)}">${_('Unlock')}</a></li>
263 263 %else:
264 264 <li><a class="locking_add" href="${h.url('toggle_locking',repo_name=c.repo_name)}">${_('Lock')}</a></li>
265 265 %endif
266 266 %endif
267 267 %if c.rhodecode_user.username != h.DEFAULT_USER:
268 268 %if c.rhodecode_db_repo.repo_type in ['git','hg']:
269 269 <li><a href="${h.url('repo_fork_home',repo_name=c.repo_name)}">${_('Fork')}</a></li>
270 270 <li><a href="${h.url('pullrequest_home',repo_name=c.repo_name)}">${_('Create Pull Request')}</a></li>
271 271 %endif
272 272 %endif
273 273 </ul>
274 274 </li>
275 275 </ul>
276 276 </div>
277 277 <div class="clear"></div>
278 278 </div>
279 279 <!--- END CONTEXT BAR -->
280 280
281 281 </%def>
282 282
283 283 <%def name="usermenu()">
284 284 ## USER MENU
285 285 <li id="quick_login_li">
286 286 <a id="quick_login_link" class="menulink childs">
287 287 ${gravatar(c.rhodecode_user.email, 20)}
288 288 <span class="user">
289 289 %if c.rhodecode_user.username != h.DEFAULT_USER:
290 290 <span class="menu_link_user">${c.rhodecode_user.username}</span><div class="show_more"></div>
291 291 %else:
292 292 <span>${_('Sign in')}</span>
293 293 %endif
294 294 </span>
295 295 </a>
296 296
297 297 <div class="user-menu submenu">
298 298 <div id="quick_login">
299 299 %if c.rhodecode_user.username == h.DEFAULT_USER:
300 300 <h4>${_('Sign in to your account')}</h4>
301 301 ${h.form(h.route_path('login', _query={'came_from': h.url.current()}), needs_csrf_token=False)}
302 302 <div class="form form-vertical">
303 303 <div class="fields">
304 304 <div class="field">
305 305 <div class="label">
306 306 <label for="username">${_('Username')}:</label>
307 307 </div>
308 308 <div class="input">
309 309 ${h.text('username',class_='focus',tabindex=1)}
310 310 </div>
311 311
312 312 </div>
313 313 <div class="field">
314 314 <div class="label">
315 315 <label for="password">${_('Password')}:</label>
316 316 <span class="forgot_password">${h.link_to(_('(Forgot password?)'),h.route_path('reset_password'))}</span>
317 317 </div>
318 318 <div class="input">
319 319 ${h.password('password',class_='focus',tabindex=2)}
320 320 </div>
321 321 </div>
322 322 <div class="buttons">
323 323 <div class="register">
324 324 %if h.HasPermissionAny('hg.admin', 'hg.register.auto_activate', 'hg.register.manual_activate')():
325 325 ${h.link_to(_("Don't have an account ?"),h.route_path('register'))}
326 326 %endif
327 327 </div>
328 328 <div class="submit">
329 329 ${h.submit('sign_in',_('Sign In'),class_="btn btn-small",tabindex=3)}
330 330 </div>
331 331 </div>
332 332 </div>
333 333 </div>
334 334 ${h.end_form()}
335 335 %else:
336 336 <div class="">
337 337 <div class="big_gravatar">${gravatar(c.rhodecode_user.email, 48)}</div>
338 338 <div class="full_name">${c.rhodecode_user.full_name_or_username}</div>
339 339 <div class="email">${c.rhodecode_user.email}</div>
340 340 </div>
341 341 <div class="">
342 342 <ol class="links">
343 343 <li>${h.link_to(_(u'My account'),h.url('my_account'))}</li>
344 344 <li class="logout">
345 345 ${h.secure_form(h.route_path('logout'))}
346 346 ${h.submit('log_out', _(u'Sign Out'),class_="btn btn-primary")}
347 347 ${h.end_form()}
348 348 </li>
349 349 </ol>
350 350 </div>
351 351 %endif
352 352 </div>
353 353 </div>
354 354 %if c.rhodecode_user.username != h.DEFAULT_USER:
355 355 <div class="pill_container">
356 356 % if c.unread_notifications == 0:
357 357 <a class="menu_link_notifications empty" href="${h.url('notifications')}">${c.unread_notifications}</a>
358 358 % else:
359 359 <a class="menu_link_notifications" href="${h.url('notifications')}">${c.unread_notifications}</a>
360 360 % endif
361 361 </div>
362 362 % endif
363 363 </li>
364 364 </%def>
365 365
366 366 <%def name="menu_items(active=None)">
367 367 <%
368 368 def is_active(selected):
369 369 if selected == active:
370 370 return "active"
371 371 return ""
372 372 %>
373 373 <ul id="quick" class="main_nav navigation horizontal-list">
374 374 <!-- repo switcher -->
375 375 <li class="${is_active('repositories')} repo_switcher_li has_select2">
376 376 <input id="repo_switcher" name="repo_switcher" type="hidden">
377 377 </li>
378 378
379 379 ## ROOT MENU
380 380 %if c.rhodecode_user.username != h.DEFAULT_USER:
381 381 <li class="${is_active('journal')}">
382 382 <a class="menulink" title="${_('Show activity journal')}" href="${h.url('journal')}">
383 383 <div class="menulabel">${_('Journal')}</div>
384 384 </a>
385 385 </li>
386 386 %else:
387 387 <li class="${is_active('journal')}">
388 388 <a class="menulink" title="${_('Show Public activity journal')}" href="${h.url('public_journal')}">
389 389 <div class="menulabel">${_('Public journal')}</div>
390 390 </a>
391 391 </li>
392 392 %endif
393 393 <li class="${is_active('gists')}">
394 394 <a class="menulink childs" title="${_('Show Gists')}" href="${h.url('gists')}">
395 395 <div class="menulabel">${_('Gists')}</div>
396 396 </a>
397 397 </li>
398 398 <li class="${is_active('search')}">
399 399 <a class="menulink" title="${_('Search in repositories you have access to')}" href="${h.url('search')}">
400 400 <div class="menulabel">${_('Search')}</div>
401 401 </a>
402 402 </li>
403 403 % if h.HasPermissionAll('hg.admin')('access admin main page'):
404 404 <li class="${is_active('admin')}">
405 405 <a class="menulink childs" title="${_('Admin settings')}" href="#" onclick="return false;">
406 406 <div class="menulabel">${_('Admin')} <div class="show_more"></div></div>
407 407 </a>
408 408 ${admin_menu()}
409 409 </li>
410 410 % elif c.rhodecode_user.repositories_admin or c.rhodecode_user.repository_groups_admin or c.rhodecode_user.user_groups_admin:
411 411 <li class="${is_active('admin')}">
412 412 <a class="menulink childs" title="${_('Delegated Admin settings')}">
413 413 <div class="menulabel">${_('Admin')} <div class="show_more"></div></div>
414 414 </a>
415 415 ${admin_menu_simple(c.rhodecode_user.repositories_admin,
416 416 c.rhodecode_user.repository_groups_admin,
417 417 c.rhodecode_user.user_groups_admin or h.HasPermissionAny('hg.usergroup.create.true')())}
418 418 </li>
419 419 % endif
420 420 % if c.debug_style:
421 421 <li class="${is_active('debug_style')}">
422 422 <a class="menulink" title="${_('Style')}" href="${h.url('debug_style_home')}">
423 423 <div class="menulabel">${_('Style')}</div>
424 424 </a>
425 425 </li>
426 426 % endif
427 427 ## render extra user menu
428 428 ${usermenu()}
429 429 </ul>
430 430
431 431 <script type="text/javascript">
432 432 var visual_show_public_icon = "${c.visual.show_public_icon}" == "True";
433 433
434 434 /*format the look of items in the list*/
435 435 var format = function(state, escapeMarkup){
436 436 if (!state.id){
437 437 return state.text; // optgroup
438 438 }
439 439 var obj_dict = state.obj;
440 440 var tmpl = '';
441 441
442 442 if(obj_dict && state.type == 'repo'){
443 443 if(obj_dict['repo_type'] === 'hg'){
444 444 tmpl += '<i class="icon-hg"></i> ';
445 445 }
446 446 else if(obj_dict['repo_type'] === 'git'){
447 447 tmpl += '<i class="icon-git"></i> ';
448 448 }
449 449 else if(obj_dict['repo_type'] === 'svn'){
450 450 tmpl += '<i class="icon-svn"></i> ';
451 451 }
452 452 if(obj_dict['private']){
453 453 tmpl += '<i class="icon-lock" ></i> ';
454 454 }
455 455 else if(visual_show_public_icon){
456 456 tmpl += '<i class="icon-unlock-alt"></i> ';
457 457 }
458 458 }
459 459 if(obj_dict && state.type == 'commit') {
460 460 tmpl += '<i class="icon-tag"></i>';
461 461 }
462 462 if(obj_dict && state.type == 'group'){
463 463 tmpl += '<i class="icon-folder-close"></i> ';
464 464 }
465 465 tmpl += escapeMarkup(state.text);
466 466 return tmpl;
467 467 };
468 468
469 469 var formatResult = function(result, container, query, escapeMarkup) {
470 470 return format(result, escapeMarkup);
471 471 };
472 472
473 473 var formatSelection = function(data, container, escapeMarkup) {
474 474 return format(data, escapeMarkup);
475 475 };
476 476
477 477 $("#repo_switcher").select2({
478 478 cachedDataSource: {},
479 479 minimumInputLength: 2,
480 480 placeholder: '<div class="menulabel">${_('Go to')} <div class="show_more"></div></div>',
481 481 dropdownAutoWidth: true,
482 482 formatResult: formatResult,
483 483 formatSelection: formatSelection,
484 484 containerCssClass: "repo-switcher",
485 485 dropdownCssClass: "repo-switcher-dropdown",
486 486 escapeMarkup: function(m){
487 487 // don't escape our custom placeholder
488 488 if(m.substr(0,23) == '<div class="menulabel">'){
489 489 return m;
490 490 }
491 491
492 492 return Select2.util.escapeMarkup(m);
493 493 },
494 494 query: $.debounce(250, function(query){
495 495 self = this;
496 496 var cacheKey = query.term;
497 497 var cachedData = self.cachedDataSource[cacheKey];
498 498
499 499 if (cachedData) {
500 500 query.callback({results: cachedData.results});
501 501 } else {
502 502 $.ajax({
503 503 url: "${h.url('goto_switcher_data')}",
504 504 data: {'query': query.term},
505 505 dataType: 'json',
506 506 type: 'GET',
507 507 success: function(data) {
508 508 self.cachedDataSource[cacheKey] = data;
509 509 query.callback({results: data.results});
510 510 },
511 511 error: function(data, textStatus, errorThrown) {
512 512 alert("Error while fetching entries.\nError code {0} ({1}).".format(data.status, data.statusText));
513 513 }
514 514 })
515 515 }
516 516 })
517 517 });
518 518
519 519 $("#repo_switcher").on('select2-selecting', function(e){
520 520 e.preventDefault();
521 521 window.location = e.choice.url;
522 522 });
523 523
524 524 ## Global mouse bindings ##
525 525
526 526 // general help "?"
527 527 Mousetrap.bind(['?'], function(e) {
528 528 $('#help_kb').modal({})
529 529 });
530 530
531 531 // / open the quick filter
532 532 Mousetrap.bind(['/'], function(e) {
533 533 $("#repo_switcher").select2("open");
534 534
535 535 // return false to prevent default browser behavior
536 536 // and stop event from bubbling
537 537 return false;
538 538 });
539 539
540 540 // general nav g + action
541 541 Mousetrap.bind(['g h'], function(e) {
542 542 window.location = pyroutes.url('home');
543 543 });
544 544 Mousetrap.bind(['g g'], function(e) {
545 545 window.location = pyroutes.url('gists', {'private':1});
546 546 });
547 547 Mousetrap.bind(['g G'], function(e) {
548 548 window.location = pyroutes.url('gists', {'public':1});
549 549 });
550 550 Mousetrap.bind(['n g'], function(e) {
551 551 window.location = pyroutes.url('new_gist');
552 552 });
553 553 Mousetrap.bind(['n r'], function(e) {
554 554 window.location = pyroutes.url('new_repo');
555 555 });
556 556
557 557 % if hasattr(c, 'repo_name') and hasattr(c, 'rhodecode_db_repo'):
558 558 // nav in repo context
559 559 Mousetrap.bind(['g s'], function(e) {
560 560 window.location = pyroutes.url('summary_home', {'repo_name': REPO_NAME});
561 561 });
562 562 Mousetrap.bind(['g c'], function(e) {
563 563 window.location = pyroutes.url('changelog_home', {'repo_name': REPO_NAME});
564 564 });
565 565 Mousetrap.bind(['g F'], function(e) {
566 566 window.location = pyroutes.url('files_home', {'repo_name': REPO_NAME, 'revision': '${c.rhodecode_db_repo.landing_rev[1]}', 'f_path': '', 'search': '1'});
567 567 });
568 568 Mousetrap.bind(['g f'], function(e) {
569 569 window.location = pyroutes.url('files_home', {'repo_name': REPO_NAME, 'revision': '${c.rhodecode_db_repo.landing_rev[1]}', 'f_path': ''});
570 570 });
571 571 Mousetrap.bind(['g p'], function(e) {
572 572 window.location = pyroutes.url('pullrequest_show_all', {'repo_name': REPO_NAME});
573 573 });
574 574 Mousetrap.bind(['g o'], function(e) {
575 575 window.location = pyroutes.url('edit_repo', {'repo_name': REPO_NAME});
576 576 });
577 577 Mousetrap.bind(['g O'], function(e) {
578 578 window.location = pyroutes.url('edit_repo_perms', {'repo_name': REPO_NAME});
579 579 });
580 580 % endif
581 581
582 582 </script>
583 <script src="${h.url('/js/rhodecode/base/keyboard-bindings.js', ver=c.rhodecode_version_hash)}"></script>
583 <script src="${h.asset('js/rhodecode/base/keyboard-bindings.js', ver=c.rhodecode_version_hash)}"></script>
584 584 </%def>
585 585
586 586 <div class="modal" id="help_kb" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
587 587 <div class="modal-dialog">
588 588 <div class="modal-content">
589 589 <div class="modal-header">
590 590 <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
591 591 <h4 class="modal-title" id="myModalLabel">${_('Keyboard shortcuts')}</h4>
592 592 </div>
593 593 <div class="modal-body">
594 594 <div class="block-left">
595 595 <table class="keyboard-mappings">
596 596 <tbody>
597 597 <tr>
598 598 <th></th>
599 599 <th>${_('Site-wide shortcuts')}</th>
600 600 </tr>
601 601 <%
602 602 elems = [
603 603 ('/', 'Open quick search box'),
604 604 ('g h', 'Goto home page'),
605 605 ('g g', 'Goto my private gists page'),
606 606 ('g G', 'Goto my public gists page'),
607 607 ('n r', 'New repository page'),
608 608 ('n g', 'New gist page'),
609 609 ]
610 610 %>
611 611 %for key, desc in elems:
612 612 <tr>
613 613 <td class="keys">
614 614 <span class="key tag">${key}</span>
615 615 </td>
616 616 <td>${desc}</td>
617 617 </tr>
618 618 %endfor
619 619 </tbody>
620 620 </table>
621 621 </div>
622 622 <div class="block-left">
623 623 <table class="keyboard-mappings">
624 624 <tbody>
625 625 <tr>
626 626 <th></th>
627 627 <th>${_('Repositories')}</th>
628 628 </tr>
629 629 <%
630 630 elems = [
631 631 ('g s', 'Goto summary page'),
632 632 ('g c', 'Goto changelog page'),
633 633 ('g f', 'Goto files page'),
634 634 ('g F', 'Goto files page with file search activated'),
635 635 ('g p', 'Goto pull requests page'),
636 636 ('g o', 'Goto repository settings'),
637 637 ('g O', 'Goto repository permissions settings'),
638 638 ]
639 639 %>
640 640 %for key, desc in elems:
641 641 <tr>
642 642 <td class="keys">
643 643 <span class="key tag">${key}</span>
644 644 </td>
645 645 <td>${desc}</td>
646 646 </tr>
647 647 %endfor
648 648 </tbody>
649 649 </table>
650 650 </div>
651 651 </div>
652 652 <div class="modal-footer">
653 653 </div>
654 654 </div><!-- /.modal-content -->
655 655 </div><!-- /.modal-dialog -->
656 656 </div><!-- /.modal -->
@@ -1,135 +1,135 b''
1 1 ## -*- coding: utf-8 -*-
2 2 <!DOCTYPE html>
3 3
4 4 <%
5 5 c.template_context['repo_name'] = getattr(c, 'repo_name', '')
6 6
7 7 if hasattr(c, 'rhodecode_db_repo'):
8 8 c.template_context['repo_type'] = c.rhodecode_db_repo.repo_type
9 9 c.template_context['repo_landing_commit'] = c.rhodecode_db_repo.landing_rev[1]
10 10
11 11 if getattr(c, 'rhodecode_user', None) and c.rhodecode_user.user_id:
12 12 c.template_context['rhodecode_user']['username'] = c.rhodecode_user.username
13 13 c.template_context['rhodecode_user']['email'] = c.rhodecode_user.email
14 14
15 15 c.template_context['visual']['default_renderer'] = h.get_visual_attr(c, 'default_renderer')
16 16 %>
17 17
18 18 <html xmlns="http://www.w3.org/1999/xhtml">
19 19 <head>
20 20 <title>${self.title()}</title>
21 21 <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
22 22 <%def name="robots()">
23 23 <meta name="robots" content="index, nofollow"/>
24 24 </%def>
25 25 ${self.robots()}
26 <link rel="icon" href="${h.url('/images/favicon.ico', ver=c.rhodecode_version_hash)}" sizes="16x16 32x32" type="image/png" />
26 <link rel="icon" href="${h.asset('images/favicon.ico', ver=c.rhodecode_version_hash)}" sizes="16x16 32x32" type="image/png" />
27 27
28 28 ## CSS definitions
29 29 <%def name="css()">
30 <link rel="stylesheet" type="text/css" href="${h.url('/css/style.css', ver=c.rhodecode_version_hash)}" media="screen"/>
30 <link rel="stylesheet" type="text/css" href="${h.asset('css/style.css', ver=c.rhodecode_version_hash)}" media="screen"/>
31 31 <!--[if lt IE 9]>
32 <link rel="stylesheet" type="text/css" href="${h.url('/css/ie.css', ver=c.rhodecode_version_hash)}" media="screen"/>
32 <link rel="stylesheet" type="text/css" href="${h.asset('css/ie.css', ver=c.rhodecode_version_hash)}" media="screen"/>
33 33 <![endif]-->
34 34 ## EXTRA FOR CSS
35 35 ${self.css_extra()}
36 36 </%def>
37 37 ## CSS EXTRA - optionally inject some extra CSS stuff needed for specific websites
38 38 <%def name="css_extra()">
39 39 </%def>
40 40
41 41 ${self.css()}
42 42
43 43 ## JAVASCRIPT
44 44 <%def name="js()">
45 <script src="${h.url('/js/rhodecode/i18n/%s.js' % c.language, ver=c.rhodecode_version_hash)}"></script>
45 <script src="${h.asset('js/rhodecode/i18n/%s.js' % c.language, ver=c.rhodecode_version_hash)}"></script>
46 46 <script type="text/javascript">
47 47 // register templateContext to pass template variables to JS
48 48 var templateContext = ${h.json.dumps(c.template_context)|n};
49 49
50 50 var REPO_NAME = "${getattr(c, 'repo_name', '')}";
51 51 %if hasattr(c, 'rhodecode_db_repo'):
52 52 var REPO_LANDING_REV = '${c.rhodecode_db_repo.landing_rev[1]}';
53 53 var REPO_TYPE = '${c.rhodecode_db_repo.repo_type}';
54 54 %else:
55 55 var REPO_LANDING_REV = '';
56 56 var REPO_TYPE = '';
57 57 %endif
58 58 var APPLICATION_URL = "${h.url('home').rstrip('/')}";
59 59 var DEFAULT_RENDERER = "${h.get_visual_attr(c, 'default_renderer')}";
60 60 var CSRF_TOKEN = "${getattr(c, 'csrf_token', '')}";
61 61 % if getattr(c, 'rhodecode_user', None):
62 62 var USER = {name:'${c.rhodecode_user.username}'};
63 63 % else:
64 64 var USER = {name:null};
65 65 % endif
66 66
67 67 var APPENLIGHT = {
68 68 enabled: ${'true' if getattr(c, 'appenlight_enabled', False) else 'false'},
69 69 key: '${getattr(c, "appenlight_api_public_key", "")}',
70 70 serverUrl: '${getattr(c, "appenlight_server_url", "")}',
71 71 requestInfo: {
72 72 % if getattr(c, 'rhodecode_user', None):
73 73 ip: '${c.rhodecode_user.ip_addr}',
74 74 username: '${c.rhodecode_user.username}'
75 75 % endif
76 76 }
77 77 };
78 78 </script>
79 79
80 80 <!--[if lt IE 9]>
81 <script language="javascript" type="text/javascript" src="${h.url('/js/excanvas.min.js')}"></script>
81 <script language="javascript" type="text/javascript" src="${h.asset('js/excanvas.min.js')}"></script>
82 82 <![endif]-->
83 <script language="javascript" type="text/javascript" src="${h.url('/js/rhodecode/routes.js', ver=c.rhodecode_version_hash)}"></script>
84 <script language="javascript" type="text/javascript" src="${h.url('/js/scripts.js', ver=c.rhodecode_version_hash)}"></script>
85 <script>CodeMirror.modeURL = "${h.url('/js/mode/%N/%N.js')}";</script>
83 <script language="javascript" type="text/javascript" src="${h.asset('js/rhodecode/routes.js', ver=c.rhodecode_version_hash)}"></script>
84 <script language="javascript" type="text/javascript" src="${h.asset('js/scripts.js', ver=c.rhodecode_version_hash)}"></script>
85 <script>CodeMirror.modeURL = "${h.asset('js/mode/%N/%N.js')}";</script>
86 86
87 87 ## JAVASCRIPT EXTRA - optionally inject some extra JS for specificed templates
88 88 ${self.js_extra()}
89 89
90 90 <script type="text/javascript">
91 91 $(document).ready(function(){
92 92 show_more_event();
93 93 timeagoActivate();
94 94 })
95 95 </script>
96 96
97 97 </%def>
98 98
99 99 ## JAVASCRIPT EXTRA - optionally inject some extra JS for specificed templates
100 100 <%def name="js_extra()"></%def>
101 101 ${self.js()}
102 102
103 103 <%def name="head_extra()"></%def>
104 104 ${self.head_extra()}
105 105
106 106 <%include file="/base/plugins_base.html"/>
107 107
108 108 ## extra stuff
109 109 %if c.pre_code:
110 110 ${c.pre_code|n}
111 111 %endif
112 112 </head>
113 113 <body id="body">
114 114 <noscript>
115 115 <div class="noscript-error">
116 116 ${_('Please enable JavaScript to use RhodeCode Enterprise')}
117 117 </div>
118 118 </noscript>
119 119 ## IE hacks
120 120 <!--[if IE 7]>
121 121 <script>$(document.body).addClass('ie7')</script>
122 122 <![endif]-->
123 123 <!--[if IE 8]>
124 124 <script>$(document.body).addClass('ie8')</script>
125 125 <![endif]-->
126 126 <!--[if IE 9]>
127 127 <script>$(document.body).addClass('ie9')</script>
128 128 <![endif]-->
129 129
130 130 ${next.body()}
131 131 %if c.post_code:
132 132 ${c.post_code|n}
133 133 %endif
134 134 </body>
135 135 </html>
@@ -1,414 +1,414 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 Changelog') % c.repo_name}
7 7 %if c.changelog_for_path:
8 8 /${c.changelog_for_path}
9 9 %endif
10 10 %if c.rhodecode_name:
11 11 &middot; ${h.branding(c.rhodecode_name)}
12 12 %endif
13 13 </%def>
14 14
15 15 <%def name="breadcrumbs_links()">
16 16 %if c.changelog_for_path:
17 17 /${c.changelog_for_path}
18 18 %endif
19 19 ${ungettext('showing %d out of %d commit', 'showing %d out of %d commits', c.showing_commits) % (c.showing_commits, c.total_cs)}
20 20 </%def>
21 21
22 22 <%def name="menu_bar_nav()">
23 23 ${self.menu_items(active='repositories')}
24 24 </%def>
25 25
26 26 <%def name="menu_bar_subnav()">
27 27 ${self.repo_menu(active='changelog')}
28 28 </%def>
29 29
30 30 <%def name="main()">
31 31
32 32 <div class="box">
33 33 <div class="title">
34 34 ${self.repo_page_title(c.rhodecode_db_repo)}
35 35 <ul class="links">
36 36 <li>
37 37 <a href="#" class="btn btn-small" id="rev_range_container" style="display:none;"></a>
38 38 %if c.rhodecode_db_repo.fork:
39 39 <span>
40 40 <a id="compare_fork_button"
41 41 title="${_('Compare fork with %s' % c.rhodecode_db_repo.fork.repo_name)}"
42 42 class="btn btn-small"
43 43 href="${h.url('compare_url',
44 44 repo_name=c.rhodecode_db_repo.fork.repo_name,
45 45 source_ref_type=c.rhodecode_db_repo.landing_rev[0],
46 46 source_ref=c.rhodecode_db_repo.landing_rev[1],
47 47 target_repo=c.repo_name,
48 48 target_ref_type='branch' if request.GET.get('branch') else c.rhodecode_db_repo.landing_rev[0],
49 49 target_ref=request.GET.get('branch') or c.rhodecode_db_repo.landing_rev[1],
50 50 merge=1)
51 51 }">
52 52 <i class="icon-loop"></i>
53 53 ${_('Compare fork with Parent (%s)' % c.rhodecode_db_repo.fork.repo_name)}
54 54 </a>
55 55 </span>
56 56 %endif
57 57
58 58 ## pr open link
59 59 %if h.is_hg(c.rhodecode_repo) or h.is_git(c.rhodecode_repo):
60 60 <span>
61 61 <a id="open_new_pull_request" class="btn btn-small btn-success" href="${h.url('pullrequest_home',repo_name=c.repo_name)}">
62 62 ${_('Open new pull request')}
63 63 </a>
64 64 </span>
65 65 %endif
66 66
67 67 ## clear selection
68 68 <div title="${_('Clear selection')}" class="btn" id="rev_range_clear" style="display:none">
69 69 ${_('Clear selection')}
70 70 </div>
71 71
72 72 </li>
73 73 </ul>
74 74 </div>
75 75
76 76 % if c.pagination:
77 77
78 78 <div class="graph-header">
79 79 <div id="filter_changelog">
80 80 ${h.hidden('branch_filter')}
81 81 %if c.selected_name:
82 82 <div class="btn btn-default" id="clear_filter" >
83 83 ${_('Clear filter')}
84 84 </div>
85 85 %endif
86 86 </div>
87 87 ${self.breadcrumbs('breadcrumbs_light')}
88 88 </div>
89 89
90 90 <div id="graph">
91 91 <div class="graph-col-wrapper">
92 92 <div id="graph_nodes">
93 93 <div id="graph_canvas" data-graph='${c.jsdata|n}'></div>
94 94 </div>
95 95 <div id="graph_content" class="main-content graph_full_width">
96 96
97 97 <div class="table">
98 98 <table id="changesets" class="rctable">
99 99 <tr>
100 100 <th></th>
101 101 <th></th>
102 102 <th>${_('Author')}</th>
103 103 <th>${_('Age')}</th>
104 104 <th></th>
105 105 <th>${_('Commit Message')}</th>
106 106 <th>${_('Commit')}</th>
107 107 <th></th>
108 108 <th>${_('Refs')}</th>
109 109 </tr>
110 110 <tbody>
111 111 %for cnt,commit in enumerate(c.pagination):
112 112 <tr id="chg_${cnt+1}" class="container ${'tablerow%s' % (cnt%2)}">
113 113
114 114 <td class="td-checkbox">
115 115 ${h.checkbox(commit.raw_id,class_="commit-range")}
116 116 </td>
117 117 <td class="td-status">
118 118
119 119 %if c.statuses.get(commit.raw_id):
120 120 <div class="changeset-status-ico">
121 121 %if c.statuses.get(commit.raw_id)[2]:
122 122 <a class="tooltip" title="${_('Commit status: %s\nClick to open associated pull request #%s') % (h.commit_status_lbl(c.statuses.get(commit.raw_id)[0]), c.statuses.get(commit.raw_id)[2])}" href="${h.url('pullrequest_show',repo_name=c.statuses.get(commit.raw_id)[3],pull_request_id=c.statuses.get(commit.raw_id)[2])}">
123 123 <div class="${'flag_status %s' % c.statuses.get(commit.raw_id)[0]}"></div>
124 124 </a>
125 125 %else:
126 126 <a class="tooltip" title="${_('Commit status: %s') % h.commit_status_lbl(c.statuses.get(commit.raw_id)[0])}" href="${h.url('changeset_home',repo_name=c.repo_name,revision=commit.raw_id,anchor='comment-%s' % c.comments[commit.raw_id][0].comment_id)}">
127 127 <div class="${'flag_status %s' % c.statuses.get(commit.raw_id)[0]}"></div>
128 128 </a>
129 129 %endif
130 130 </div>
131 131 %endif
132 132 </td>
133 133 <td class="td-user">
134 134 ${self.gravatar_with_user(commit.author)}
135 135 </td>
136 136 <td class="td-time">
137 137 ${h.age_component(commit.date)}
138 138 </td>
139 139
140 140 <td class="td-message expand_commit" data-commit-id="${commit.raw_id}" title="${_('Expand commit message')}">
141 141 <div class="show_more_col">
142 142 <i class="show_more"></i>&nbsp;
143 143 </div>
144 144 </td>
145 145 <td class="mid td-description">
146 146 <div class="log-container truncate-wrap">
147 147 <div class="message truncate" id="c-${commit.raw_id}">${h.urlify_commit_message(commit.message, c.repo_name)}</div>
148 148 </div>
149 149 </td>
150 150
151 151 <td class="td-hash">
152 152 <code>
153 153 <a href="${h.url('changeset_home',repo_name=c.repo_name,revision=commit.raw_id)}">
154 154 <span class="commit_hash">${h.show_id(commit)}</span>
155 155 </a>
156 156 </code>
157 157 </td>
158 158
159 159 <td class="td-comments comments-col">
160 160 %if c.comments.get(commit.raw_id):
161 161 <a title="${_('Commit has comments')}" href="${h.url('changeset_home',repo_name=c.repo_name,revision=commit.raw_id,anchor='comment-%s' % c.comments[commit.raw_id][0].comment_id)}">
162 162 ${len(c.comments[commit.raw_id])} <i class="icon-comment icon-comment-colored"></i>
163 163 </a>
164 164 %endif
165 165 </td>
166 166
167 167 <td class="td-tags tags-col truncate-wrap">
168 168 <div class="truncate tags-truncate" id="t-${commit.raw_id}">
169 169 ## branch
170 170 %if commit.branch:
171 171 <span class="branchtag tag" title="${_('Branch %s') % commit.branch}">
172 172 <a href="${h.url('changelog_home',repo_name=c.repo_name,branch=commit.branch)}"><i class="icon-code-fork"></i>${h.shorter(commit.branch)}</a>
173 173 </span>
174 174 %endif
175 175
176 176 ## bookmarks
177 177 %if h.is_hg(c.rhodecode_repo):
178 178 %for book in commit.bookmarks:
179 179 <span class="tag booktag" title="${_('Bookmark %s') % book}">
180 180 <a href="${h.url('files_home',repo_name=c.repo_name,revision=commit.raw_id)}"><i class="icon-bookmark"></i>${h.shorter(book)}</a>
181 181 </span>
182 182 %endfor
183 183 %endif
184 184
185 185 ## tags
186 186 %for tag in commit.tags:
187 187 <span class="tagtag tag" title="${_('Tag %s') % tag}">
188 188 <a href="${h.url('files_home',repo_name=c.repo_name,revision=commit.raw_id)}"><i class="icon-tag"></i>${h.shorter(tag)}</a>
189 189 </span>
190 190 %endfor
191 191
192 192 </div>
193 193 </td>
194 194 </tr>
195 195 %endfor
196 196 </tbody>
197 197 </table>
198 198 </div>
199 199 </div>
200 200 </div>
201 201 <div class="pagination-wh pagination-left">
202 202 ${c.pagination.pager('$link_previous ~2~ $link_next')}
203 203 </div>
204 204
205 <script type="text/javascript" src="${h.url('/js/jquery.commits-graph.js')}"></script>
205 <script type="text/javascript" src="${h.asset('js/jquery.commits-graph.js')}"></script>
206 206 <script type="text/javascript">
207 207 var cache = {};
208 208 $(function(){
209 209
210 210 // Create links to commit ranges when range checkboxes are selected
211 211 var $commitCheckboxes = $('.commit-range');
212 212 // cache elements
213 213 var $commitRangeContainer = $('#rev_range_container');
214 214 var $commitRangeClear = $('#rev_range_clear');
215 215
216 216 var checkboxRangeSelector = function(e){
217 217 var selectedCheckboxes = [];
218 218 for (pos in $commitCheckboxes){
219 219 if($commitCheckboxes[pos].checked){
220 220 selectedCheckboxes.push($commitCheckboxes[pos]);
221 221 }
222 222 }
223 223 var open_new_pull_request = $('#open_new_pull_request');
224 224 if(open_new_pull_request){
225 225 var selected_changes = selectedCheckboxes.length;
226 226 if (selected_changes > 1 || selected_changes == 1 && templateContext.repo_type != 'hg') {
227 227 open_new_pull_request.hide();
228 228 } else {
229 229 if (selected_changes == 1) {
230 230 open_new_pull_request.html(_gettext('Open new pull request for selected commit'));
231 231 } else if (selected_changes == 0) {
232 232 open_new_pull_request.html(_gettext('Open new pull request'));
233 233 }
234 234 open_new_pull_request.show();
235 235 }
236 236 }
237 237
238 238 if (selectedCheckboxes.length>0){
239 239 var revEnd = selectedCheckboxes[0].name;
240 240 var revStart = selectedCheckboxes[selectedCheckboxes.length-1].name;
241 241 var url = pyroutes.url('changeset_home',
242 242 {'repo_name': '${c.repo_name}',
243 243 'revision': revStart+'...'+revEnd});
244 244
245 245 var link = (revStart == revEnd)
246 246 ? _gettext('Show selected commit __S')
247 247 : _gettext('Show selected commits __S ... __E');
248 248
249 249 link = link.replace('__S', revStart.substr(0,6));
250 250 link = link.replace('__E', revEnd.substr(0,6));
251 251
252 252 $commitRangeContainer
253 253 .attr('href',url)
254 254 .html(link)
255 255 .show();
256 256
257 257 $commitRangeClear.show();
258 258 var _url = pyroutes.url('pullrequest_home',
259 259 {'repo_name': '${c.repo_name}',
260 260 'commit': revEnd});
261 261 open_new_pull_request.attr('href', _url);
262 262 $('#compare_fork_button').hide();
263 263 } else {
264 264 $commitRangeContainer.hide();
265 265 $commitRangeClear.hide();
266 266
267 267 %if c.branch_name:
268 268 var _url = pyroutes.url('pullrequest_home',
269 269 {'repo_name': '${c.repo_name}',
270 270 'branch':'${c.branch_name}'});
271 271 open_new_pull_request.attr('href', _url);
272 272 %else:
273 273 var _url = pyroutes.url('pullrequest_home',
274 274 {'repo_name': '${c.repo_name}'});
275 275 open_new_pull_request.attr('href', _url);
276 276 %endif
277 277 $('#compare_fork_button').show();
278 278 }
279 279 };
280 280
281 281 $commitCheckboxes.on('click', checkboxRangeSelector);
282 282
283 283 $commitRangeClear.on('click',function(e) {
284 284 $commitCheckboxes.attr('checked', false)
285 285 checkboxRangeSelector();
286 286 e.preventDefault();
287 287 });
288 288
289 289 // make sure the buttons are consistent when navigate back and forth
290 290 checkboxRangeSelector();
291 291
292 292
293 293 var msgs = $('.message');
294 294 // get first element height
295 295 var el = $('#graph_content .container')[0];
296 296 var row_h = el.clientHeight;
297 297 for (var i=0; i < msgs.length; i++) {
298 298 var m = msgs[i];
299 299
300 300 var h = m.clientHeight;
301 301 var pad = $(m).css('padding');
302 302 if (h > row_h) {
303 303 var offset = row_h - (h+12);
304 304 $(m.nextElementSibling).css('display','block');
305 305 $(m.nextElementSibling).css('margin-top',offset+'px');
306 306 }
307 307 }
308 308
309 309 $('.expand_commit').on('click',function(e){
310 310 var target_expand = $(this);
311 311 var cid = target_expand.data('commitId');
312 312
313 313 if (target_expand.hasClass('open')){
314 314 $('#c-'+cid).css({'height': '1.5em', 'white-space': 'nowrap', 'text-overflow': 'ellipsis', 'overflow':'hidden'});
315 315 $('#t-'+cid).css({'height': 'auto', 'line-height': '.9em', 'text-overflow': 'ellipsis', 'overflow':'hidden', 'white-space':'nowrap'});
316 316 target_expand.removeClass('open');
317 317 }
318 318 else {
319 319 $('#c-'+cid).css({'height': 'auto', 'white-space': 'pre-line', 'text-overflow': 'initial', 'overflow':'visible'});
320 320 $('#t-'+cid).css({'height': 'auto', 'max-height': 'none', 'text-overflow': 'initial', 'overflow':'visible', 'white-space':'normal'});
321 321 target_expand.addClass('open');
322 322 }
323 323 // redraw the graph
324 324 graph_options.height = $("#changesets").height();
325 325 $("canvas").remove();
326 326 $("[data-graph]").commits(graph_options);
327 327 });
328 328
329 329 $("#clear_filter").on("click", function() {
330 330 var filter = {'repo_name': '${c.repo_name}'};
331 331 window.location = pyroutes.url('changelog_home', filter);
332 332 });
333 333
334 334 $("#branch_filter").select2({
335 335 'dropdownAutoWidth': true,
336 336 'width': 'resolve',
337 337 'placeholder': "${c.selected_name or _('Filter changelog')}",
338 338 containerCssClass: "drop-menu",
339 339 dropdownCssClass: "drop-menu-dropdown",
340 340 query: function(query){
341 341 var key = 'cache';
342 342 var cached = cache[key] ;
343 343 if(cached) {
344 344 var data = {results: []};
345 345 //filter results
346 346 $.each(cached.results, function(){
347 347 var section = this.text;
348 348 var children = [];
349 349 $.each(this.children, function(){
350 350 if(query.term.length == 0 || this.text.toUpperCase().indexOf(query.term.toUpperCase()) >= 0 ){
351 351 children.push({'id': this.id, 'text': this.text, 'type': this.type})
352 352 }
353 353 });
354 354 data.results.push({'text': section, 'children': children});
355 355 query.callback({results: data.results});
356 356 });
357 357 }else{
358 358 $.ajax({
359 359 url: pyroutes.url('repo_refs_changelog_data', {'repo_name': '${c.repo_name}'}),
360 360 data: {},
361 361 dataType: 'json',
362 362 type: 'GET',
363 363 success: function(data) {
364 364 cache[key] = data;
365 365 query.callback({results: data.results});
366 366 }
367 367 })
368 368 }
369 369 }
370 370 });
371 371
372 372 $('#branch_filter').on('change', function(e){
373 373 var data = $('#branch_filter').select2('data');
374 374 var selected = data.text;
375 375 var filter = {'repo_name': '${c.repo_name}'};
376 376 if(data.type == 'branch' || data.type == 'branch_closed'){
377 377 filter["branch"] = selected;
378 378 }
379 379 else if (data.type == 'book'){
380 380 filter["bookmark"] = selected;
381 381 }
382 382 window.location = pyroutes.url('changelog_home', filter);
383 383 });
384 384
385 385 // Determine max number of edges per row in graph
386 386 var jsdata = $.parseJSON($("[data-graph]").attr('data-graph'));
387 387 var edgeCount = 1;
388 388 $.each(jsdata, function(i, item){
389 389 $.each(item[2], function(key, value) {
390 390 if (value[1] > edgeCount){
391 391 edgeCount = value[1];
392 392 }
393 393 });
394 394 });
395 395 var x_step = Math.min(18, Math.floor(86 / edgeCount));
396 396 var graph_options = {
397 397 width: 100,
398 398 height: $("#changesets").height(),
399 399 x_step: x_step,
400 400 y_step: 42,
401 401 dotRadius: 3.5,
402 402 lineWidth: 2.5
403 403 };
404 404 $("[data-graph]").commits(graph_options);
405 405
406 406 });
407 407
408 408 </script>
409 409 %else:
410 410 ${_('There are no changes yet')}
411 411 %endif
412 412 </div>
413 413 </div>
414 414 </%def>
@@ -1,1162 +1,1162 b''
1 1 ## -*- coding: utf-8 -*-
2 2 <%namespace name="base" file="/base/base.html"/>
3 3 <%inherit file="/debug_style/index.html"/>
4 4
5 5 <%def name="breadcrumbs_links()">
6 6 ${h.link_to(_('Style'), h.url('debug_style_home'))}
7 7 &raquo;
8 8 ${c.active}
9 9 </%def>
10 10
11 11 <%def name="js_extra()">
12 <script type="text/javascript" src="${h.url('/js/mergerly.js')}"></script>
12 <script type="text/javascript" src="${h.asset('js/mergerly.js')}"></script>
13 13 </%def>
14 14
15 15 <%def name="css_extra()">
16 <link rel="stylesheet" type="text/css" href="${h.url('/css/mergerly.css')}"/>
16 <link rel="stylesheet" type="text/css" href="${h.asset('css/mergerly.css')}"/>
17 17 </%def>
18 18
19 19
20 20 <%def name="real_main()">
21 21 <div class="box">
22 22 <div class="title">
23 23 ${self.breadcrumbs()}
24 24 </div>
25 25
26 26 ##main
27 27 <div class='sidebar-col-wrapper'>
28 28 ${self.sidebar()}
29 29
30 30 <div class="main-content">
31 31
32 32
33 33
34 34 <h2>Code Blocks</h2>
35 35
36 36 <dl class="dl-horizontal">
37 37 <dt><code>.codeblock</code></dt>
38 38 <dd>Used as a wrapping element around <code>.code-header</code> and
39 39 <code>.code-body</code>. Used to show the content of a file or a
40 40 Gist.</dd>
41 41
42 42 <dt><code>.diffblock</code></dt>
43 43 <dd>Used as a wrapping element to show a diff in a Commit or Pull
44 44 Request page. Contains usually <code>.code-header</code>,
45 45 <code>.code-body</code> and in the edit case a <code>.message</code>.
46 46 </dd>
47 47 </dl>
48 48
49 49
50 50 <p>Code Blocks are used in the following areas:</p>
51 51
52 52 <ul>
53 53 <li>Commit: Showing the Diff (still called Changeset in a few
54 54 places).</li>
55 55 <li>File: Display a file, annotations, and edit a file.</li>
56 56 <li>Gist: Show the Gist and edit it.</li>
57 57 <li>Pull Request: Display the Diff of a Pull Request.</li>
58 58 </ul>
59 59
60 60
61 61
62 62 <!--
63 63 Compare Commits
64 64 -->
65 65 <h2>Compare Commits</h2>
66 66
67 67 <div id="c-e589e34d6be8-5ab783e6d81b" class="diffblock margined comm">
68 68 <div class="code-header">
69 69 <div title="Go back to changed files overview">
70 70 <a href="#changes_box">
71 71 <i class="icon-circle-arrow-up"></i>
72 72 </a>
73 73 </div>
74 74 <div class="changeset_header">
75 75 <div class="changeset_file">
76 76 <i class="icon-file"></i>
77 77 <a href="/example/files/e589e34d6be8ec2b44017f6c2e0bbe782f1aba6d/rhodecode/public/css/code-block.less">rhodecode/public/css/code-block.less</a>
78 78 </div>
79 79 <div class="diff-actions">
80 80 <a href="/example/diff/rhodecode/public/css/code-block.less?fulldiff=1&amp;diff1=d12301bafcc0aea15c9283d3af018daee2b04cd9&amp;diff=diff&amp;diff2=e589e34d6be8ec2b44017f6c2e0bbe782f1aba6d" class="tooltip" title="Show full diff for this file">
81 81 <img class="icon" src="/images/icons/page_white_go.png">
82 82 </a>
83 83 <a href="/example/diff-2way/rhodecode/public/css/code-block.less?fulldiff=1&amp;diff1=d12301bafcc0aea15c9283d3af018daee2b04cd9&amp;diff=diff&amp;diff2=e589e34d6be8ec2b44017f6c2e0bbe782f1aba6d" class="tooltip" title="Show full side-by-side diff for this file">
84 84 <img class="icon" src="/images/icons/application_double.png">
85 85 </a>
86 86 <a href="/example/diff/rhodecode/public/css/code-block.less?diff1=d12301bafcc0aea15c9283d3af018daee2b04cd9&amp;diff=raw&amp;diff2=e589e34d6be8ec2b44017f6c2e0bbe782f1aba6d" class="tooltip" title="Raw diff" tt_title="Raw diff">
87 87 <img class="icon" src="/images/icons/page_white.png">
88 88 </a>
89 89 <a href="/example/diff/rhodecode/public/css/code-block.less?diff1=d12301bafcc0aea15c9283d3af018daee2b04cd9&amp;diff=download&amp;diff2=e589e34d6be8ec2b44017f6c2e0bbe782f1aba6d" class="tooltip" title="Download diff">
90 90 <img class="icon" src="/images/icons/page_save.png">
91 91 </a>
92 92 <a class="tooltip" href="/example/changeset/d12301bafcc0aea15c9283d3af018daee2b04cd9...80ead1899f50a894889e19ffeb49c9cebf5bf045?c-e589e34d6be8-5ab783e6d81b=WS%3A1&amp;c-e589e34d6be8-5ab783e6d81b=C%3A3#c-e589e34d6be8-5ab783e6d81b" title="Ignore white space"><img alt="Ignore white space" class="icon" src="/images/icons/text_strikethrough.png"></a>
93 93 <a class="tooltip" href="/example/changeset/d12301bafcc0aea15c9283d3af018daee2b04cd9...80ead1899f50a894889e19ffeb49c9cebf5bf045?c-e589e34d6be8-5ab783e6d81b=C%3A6#c-e589e34d6be8-5ab783e6d81b" title="increase diff context to 6 lines"><img alt="increase diff context to 6 lines" class="icon" src="/images/icons/table_add.png"></a>
94 94 </div>
95 95 <span>
96 96 <label>
97 97 Show inline comments
98 98 <input checked="checked" class="show-inline-comments" id="" id_for="c-e589e34d6be8-5ab783e6d81b" name="" type="checkbox" value="1">
99 99 </label>
100 100 </span>
101 101 </div>
102 102 </div>
103 103 <div class="code-body">
104 104 <div class="full_f_path" path="rhodecode/public/css/code-block.less"></div>
105 105 <table class="code-difftable">
106 106 <tbody><tr class="line context">
107 107 <td class="lineno old"><a href="#rhodecodepubliccsscode-blockless_o...">...</a></td>
108 108 <td class="lineno new"><a href="#rhodecodepubliccsscode-blockless_n...">...</a></td>
109 109 <td class="code no-comment">
110 110 <pre>@@ -391,7 +391,7 @@
111 111 </pre>
112 112 </td>
113 113 </tr>
114 114 <tr class="line unmod">
115 115 <td id="rhodecodepubliccsscode-blockless_o391" class="lineno old"><a href="#rhodecodepubliccsscode-blockless_o391">391</a></td>
116 116 <td id="rhodecodepubliccsscode-blockless_n391" class="lineno new"><a href="#rhodecodepubliccsscode-blockless_n391">391</a></td>
117 117 <td class="code no-comment">
118 118 <pre>} /* Existing line, it might have a quite long content actually and in this case we might need some horizontal scrolling. The remaining text here is just used to make this line very long.
119 119 </pre>
120 120 </td>
121 121 </tr>
122 122 <tr class="line unmod">
123 123 <td id="rhodecodepubliccsscode-blockless_o392" class="lineno old"><a href="#rhodecodepubliccsscode-blockless_o392">392</a></td>
124 124 <td id="rhodecodepubliccsscode-blockless_n392" class="lineno new"><a href="#rhodecodepubliccsscode-blockless_n392">392</a></td>
125 125 <td class="code no-comment">
126 126 <pre></pre>
127 127 </td>
128 128 </tr>
129 129 <tr class="line unmod">
130 130 <td id="rhodecodepubliccsscode-blockless_o393" class="lineno old"><a href="#rhodecodepubliccsscode-blockless_o393">393</a></td>
131 131 <td id="rhodecodepubliccsscode-blockless_n393" class="lineno new"><a href="#rhodecodepubliccsscode-blockless_n393">393</a></td>
132 132 <td class="code no-comment">
133 133 <pre>.code-body.textarea.editor,
134 134 </pre>
135 135 </td>
136 136 </tr>
137 137 <tr class="line del">
138 138 <td id="rhodecodepubliccsscode-blockless_o394" class="lineno old"><a href="#rhodecodepubliccsscode-blockless_o394">394</a></td>
139 139 <td class="lineno new"><a href="#rhodecodepubliccsscode-blockless_n"></a></td>
140 140 <td class="code no-comment">
141 141 <pre>div.code-body{
142 142 </pre>
143 143 </td>
144 144 </tr>
145 145 <tr class="line add">
146 146 <td class="lineno old"><a href="#rhodecodepubliccsscode-blockless_o"></a></td>
147 147 <td id="rhodecodepubliccsscode-blockless_n394" class="lineno new"><a href="#rhodecodepubliccsscode-blockless_n394">394</a></td>
148 148 <td class="code no-comment">
149 149 <pre>div.code-body<ins> </ins>{
150 150 </pre>
151 151 </td>
152 152 </tr>
153 153 <tr class="line unmod">
154 154 <td id="rhodecodepubliccsscode-blockless_o395" class="lineno old"><a href="#rhodecodepubliccsscode-blockless_o395">395</a></td>
155 155 <td id="rhodecodepubliccsscode-blockless_n395" class="lineno new"><a href="#rhodecodepubliccsscode-blockless_n395">395</a></td>
156 156 <td class="code no-comment">
157 157 <pre> float: left;
158 158 </pre>
159 159 </td>
160 160 </tr>
161 161 <tr class="line unmod">
162 162 <td id="rhodecodepubliccsscode-blockless_o396" class="lineno old"><a href="#rhodecodepubliccsscode-blockless_o396">396</a></td>
163 163 <td id="rhodecodepubliccsscode-blockless_n396" class="lineno new"><a href="#rhodecodepubliccsscode-blockless_n396">396</a></td>
164 164 <td class="code no-comment">
165 165 <pre> position: relative;
166 166 </pre>
167 167 </td>
168 168 </tr>
169 169 <tr class="line unmod">
170 170 <td id="rhodecodepubliccsscode-blockless_o397" class="lineno old"><a href="#rhodecodepubliccsscode-blockless_o397">397</a></td>
171 171 <td id="rhodecodepubliccsscode-blockless_n397" class="lineno new"><a href="#rhodecodepubliccsscode-blockless_n397">397</a></td>
172 172 <td class="code no-comment">
173 173 <pre> max-width: none;
174 174 </pre>
175 175 </td>
176 176 </tr>
177 177 <tr class="line context">
178 178 <td class="lineno old"><a href="#rhodecodepubliccsscode-blockless_o...">...</a></td>
179 179 <td class="lineno new"><a href="#rhodecodepubliccsscode-blockless_n...">...</a></td>
180 180 <td class="code no-comment">
181 181 <pre>@@ -399,3 +399,6 @@
182 182 </pre>
183 183 </td>
184 184 </tr>
185 185 <tr class="line unmod">
186 186 <td id="rhodecodepubliccsscode-blockless_o399" class="lineno old"><a href="#rhodecodepubliccsscode-blockless_o399">399</a></td>
187 187 <td id="rhodecodepubliccsscode-blockless_n399" class="lineno new"><a href="#rhodecodepubliccsscode-blockless_n399">399</a></td>
188 188 <td class="code no-comment">
189 189 <pre> box-sizing: border-box;
190 190 </pre>
191 191 </td>
192 192 </tr>
193 193 <tr class="line unmod">
194 194 <td id="rhodecodepubliccsscode-blockless_o400" class="lineno old"><a href="#rhodecodepubliccsscode-blockless_o400">400</a></td>
195 195 <td id="rhodecodepubliccsscode-blockless_n400" class="lineno new"><a href="#rhodecodepubliccsscode-blockless_n400">400</a></td>
196 196 <td class="code no-comment">
197 197 <pre>}
198 198 </pre>
199 199 </td>
200 200 </tr>
201 201 <tr class="line unmod">
202 202 <td id="rhodecodepubliccsscode-blockless_o401" class="lineno old"><a href="#rhodecodepubliccsscode-blockless_o401">401</a></td>
203 203 <td id="rhodecodepubliccsscode-blockless_n401" class="lineno new"><a href="#rhodecodepubliccsscode-blockless_n401">401</a></td>
204 204 <td class="code no-comment">
205 205 <pre></pre>
206 206 </td>
207 207 </tr>
208 208 <tr class="line add">
209 209 <td class="lineno old"><a href="#rhodecodepubliccsscode-blockless_o"></a></td>
210 210 <td id="rhodecodepubliccsscode-blockless_n402" class="lineno new"><a href="#rhodecodepubliccsscode-blockless_n402">402</a></td>
211 211 <td class="code no-comment">
212 212 <pre>.code-body td{
213 213 </pre>
214 214 </td>
215 215 </tr>
216 216 <tr class="line add">
217 217 <td class="lineno old"><a href="#rhodecodepubliccsscode-blockless_o"></a></td>
218 218 <td id="rhodecodepubliccsscode-blockless_n403" class="lineno new"><a href="#rhodecodepubliccsscode-blockless_n403">403</a></td>
219 219 <td class="code no-comment">
220 220 <pre> line-height: 1.2em;
221 221 </pre>
222 222 </td>
223 223 </tr>
224 224 <tr class="line add">
225 225 <td class="lineno old"><a href="#rhodecodepubliccsscode-blockless_o"></a></td>
226 226 <td id="rhodecodepubliccsscode-blockless_n404" class="lineno new"><a href="#rhodecodepubliccsscode-blockless_n404">404</a></td>
227 227 <td class="code no-comment">
228 228 <pre>}
229 229 </pre>
230 230 </td>
231 231 </tr>
232 232 <tr class="line context">
233 233 <td class="lineno old"><a href="#rhodecodepubliccsscode-blockless_o...">...</a></td>
234 234 <td class="lineno new"><a href="#rhodecodepubliccsscode-blockless_n...">...</a></td>
235 235 <td class="code no-comment">
236 236 <pre> No newline at end of file
237 237 </pre>
238 238 </td>
239 239 </tr>
240 240 </tbody></table>
241 241 </div>
242 242 </div>
243 243
244 244
245 245
246 246
247 247
248 248
249 249 <!--
250 250 Pull Request
251 251 -->
252 252
253 253 <h2>Pull Request</h2>
254 254
255 255 <div class="cs_files">
256 256 <table class="compare_view_files">
257 257
258 258 <tbody><tr class="cs_M collapse_file" fid="c--5f1d017cf13b">
259 259 <td class="cs_icon_td">
260 260 <span class="collapse_file_icon" fid="c--5f1d017cf13b"></span>
261 261 </td>
262 262 <td class="cs_icon_td">
263 263 <div class="flag_status not_reviewed hidden"></div>
264 264 </td>
265 265 <td id="a_c--5f1d017cf13b">
266 266 <a class="compare_view_filepath" href="#a_c--5f1d017cf13b">
267 267 rhodecode/public/css/main.less
268 268 </a>
269 269 <span id="diff_c--5f1d017cf13b" class="diff_links" style="">
270 270 <a href="/example/diff/rhodecode/public/css/main.less?fulldiff=1&amp;diff1=f73e9946825c8a7ef2c1178cd1e67986d5831f8f&amp;diff=diff&amp;diff2=27eb56cf467ca849112536d62decb2ed020b3ebc">
271 271 Unified Diff
272 272 </a>
273 273 |
274 274 <a href="/example/diff-2way/rhodecode/public/css/main.less?fulldiff=1&amp;diff1=f73e9946825c8a7ef2c1178cd1e67986d5831f8f&amp;diff=diff&amp;diff2=27eb56cf467ca849112536d62decb2ed020b3ebc">
275 275 Side-by-side Diff
276 276 </a>
277 277 </span>
278 278 </td>
279 279 <td>
280 280 <div class="changes pull-right"><div style="width:100px"><div class="added top-left-rounded-corner-mid bottom-left-rounded-corner-mid" style="width:33.3333333333%">1</div><div class="deleted top-right-rounded-corner-mid bottom-right-rounded-corner-mid" style="width:66.6666666667%">2</div></div></div>
281 281 <div class="comment-bubble pull-right" data-path="rhodecode/public/css/main.less">
282 282 <i class="icon-comment"></i>
283 283 </div>
284 284 </td>
285 285 </tr>
286 286 <tr id="tr_c--5f1d017cf13b">
287 287 <td></td>
288 288 <td></td>
289 289 <td class="injected_diff" colspan="2">
290 290
291 291 <div class="diff-container" id="diff-container-140360026534904">
292 292 <div id="c--5f1d017cf13b_target"></div>
293 293 <div id="c--5f1d017cf13b" class="diffblock margined comm">
294 294 <div class="code-body">
295 295 <div class="full_f_path" path="rhodecode/public/css/main.less" style="display: none;"></div>
296 296 <table class="code-difftable">
297 297 <tbody><tr class="line context">
298 298 <td class="lineno old"><a href="#rhodecodepubliccssmainless_o...">...</a></td>
299 299 <td class="lineno new"><a href="#rhodecodepubliccssmainless_n...">...</a></td>
300 300 <td class="code ">
301 301 <pre>@@ -2110,7 +2110,6 @@
302 302 </pre>
303 303 </td>
304 304 </tr>
305 305 <tr class="line unmod">
306 306 <td id="rhodecodepubliccssmainless_o2110" class="lineno old"><a href="#rhodecodepubliccssmainless_o2110">2110</a></td>
307 307 <td id="rhodecodepubliccssmainless_n2110" class="lineno new"><a href="#rhodecodepubliccssmainless_n2110">2110</a></td>
308 308 <td class="code ">
309 309 <pre><span class="tab-escape"> </span>width: auto !important;
310 310 </pre>
311 311 </td>
312 312 </tr>
313 313 <tr class="line unmod">
314 314 <td id="rhodecodepubliccssmainless_o2111" class="lineno old"><a href="#rhodecodepubliccssmainless_o2111">2111</a></td>
315 315 <td id="rhodecodepubliccssmainless_n2111" class="lineno new"><a href="#rhodecodepubliccssmainless_n2111">2111</a></td>
316 316 <td class="code ">
317 317 <pre><span class="tab-escape"> </span>min-width: 160px;
318 318 </pre>
319 319 </td>
320 320 </tr>
321 321 <tr class="line unmod">
322 322 <td id="rhodecodepubliccssmainless_o2112" class="lineno old"><a href="#rhodecodepubliccssmainless_o2112">2112</a></td>
323 323 <td id="rhodecodepubliccssmainless_n2112" class="lineno new"><a href="#rhodecodepubliccssmainless_n2112">2112</a></td>
324 324 <td class="code ">
325 325 <pre><span class="tab-escape"> </span>margin: @padding @padding @padding 0;
326 326 </pre>
327 327 </td>
328 328 </tr>
329 329 <tr class="line del">
330 330 <td id="rhodecodepubliccssmainless_o2113" class="lineno old"><a href="#rhodecodepubliccssmainless_o2113">2113</a></td>
331 331 <td class="lineno new"><a href="#rhodecodepubliccssmainless_n"></a></td>
332 332 <td class="code ">
333 333 <pre><span class="tab-escape"> </span>padding: .9em; /* Old comment which was making this line a very long line so that we might have to deal with it by either adding horizontal scrolling or some smart way of breaking this line. */
334 334 </pre>
335 335 </td>
336 336 </tr>
337 337 <tr class="line unmod">
338 338 <td id="rhodecodepubliccssmainless_o2114" class="lineno old"><a href="#rhodecodepubliccssmainless_o2114">2114</a></td>
339 339 <td id="rhodecodepubliccssmainless_n2113" class="lineno new"><a href="#rhodecodepubliccssmainless_n2113">2113</a></td>
340 340 <td class="code ">
341 341 <pre> line-height: 1em;
342 342 </pre>
343 343 </td>
344 344 </tr>
345 345 <tr class="line unmod">
346 346 <td id="rhodecodepubliccssmainless_o2115" class="lineno old"><a href="#rhodecodepubliccssmainless_o2115">2115</a></td>
347 347 <td id="rhodecodepubliccssmainless_n2114" class="lineno new"><a href="#rhodecodepubliccssmainless_n2114">2114</a></td>
348 348 <td class="code ">
349 349 <pre><span class="tab-escape"> </span>z-index: 100;//js sets the menu below it to 9999
350 350 </pre>
351 351 </td>
352 352 </tr>
353 353 <tr class="line unmod">
354 354 <td id="rhodecodepubliccssmainless_o2116" class="lineno old"><a href="#rhodecodepubliccssmainless_o2116">2116</a></td>
355 355 <td id="rhodecodepubliccssmainless_n2115" class="lineno new"><a href="#rhodecodepubliccssmainless_n2115">2115</a></td>
356 356 <td class="code ">
357 357 <pre><span class="tab-escape"> </span>background-color: white;
358 358 </pre>
359 359 </td>
360 360 </tr>
361 361 <tr class="line context">
362 362 <td class="lineno old"><a href="#rhodecodepubliccssmainless_o...">...</a></td>
363 363 <td class="lineno new"><a href="#rhodecodepubliccssmainless_n...">...</a></td>
364 364 <td class="code ">
365 365 <pre>@@ -2118,7 +2117,7 @@
366 366 </pre>
367 367 </td>
368 368 </tr>
369 369 <tr class="line unmod">
370 370 <td id="rhodecodepubliccssmainless_o2118" class="lineno old"><a href="#rhodecodepubliccssmainless_o2118">2118</a></td>
371 371 <td id="rhodecodepubliccssmainless_n2117" class="lineno new"><a href="#rhodecodepubliccssmainless_n2117">2117</a></td>
372 372 <td class="code ">
373 373 <pre></pre>
374 374 </td>
375 375 </tr>
376 376 <tr class="line unmod">
377 377 <td id="rhodecodepubliccssmainless_o2119" class="lineno old"><a href="#rhodecodepubliccssmainless_o2119">2119</a></td>
378 378 <td id="rhodecodepubliccssmainless_n2118" class="lineno new"><a href="#rhodecodepubliccssmainless_n2118">2118</a></td>
379 379 <td class="code ">
380 380 <pre><span class="tab-escape"> </span>a {
381 381 </pre>
382 382 </td>
383 383 </tr>
384 384 <tr class="line unmod">
385 385 <td id="rhodecodepubliccssmainless_o2120" class="lineno old"><a href="#rhodecodepubliccssmainless_o2120">2120</a></td>
386 386 <td id="rhodecodepubliccssmainless_n2119" class="lineno new"><a href="#rhodecodepubliccssmainless_n2119">2119</a></td>
387 387 <td class="code ">
388 388 <pre><span class="tab-escape"> </span><span class="tab-escape"> </span>display:block;
389 389 </pre>
390 390 </td>
391 391 </tr>
392 392 <tr class="line del">
393 393 <td id="rhodecodepubliccssmainless_o2121" class="lineno old"><a href="#rhodecodepubliccssmainless_o2121">2121</a></td>
394 394 <td class="lineno new"><a href="#rhodecodepubliccssmainless_n"></a></td>
395 395 <td class="code ">
396 396 <pre><span class="tab-escape"> </span><del><span< del=""> <del>class=</del><del>"tab-escape"</del><del>&gt; </del>padding: <del>0</del>;
397 397 </span<></del></pre>
398 398 </td>
399 399 </tr>
400 400 <tr class="line add">
401 401 <td class="lineno old"><a href="#rhodecodepubliccssmainless_o"></a></td>
402 402 <td id="rhodecodepubliccssmainless_n2120" class="lineno new"><a href="#rhodecodepubliccssmainless_n2120">2120</a></td>
403 403 <td class="code ">
404 404 <pre><span class="tab-escape"> </span><ins> </ins> <ins> </ins><ins> </ins>padding: <ins>.9em</ins>;
405 405 </pre>
406 406 </td>
407 407 </tr>
408 408 <tr class="line unmod">
409 409 <td id="rhodecodepubliccssmainless_o2122" class="lineno old"><a href="#rhodecodepubliccssmainless_o2122">2122</a></td>
410 410 <td id="rhodecodepubliccssmainless_n2121" class="lineno new"><a href="#rhodecodepubliccssmainless_n2121">2121</a></td>
411 411 <td class="code ">
412 412 <pre></pre>
413 413 </td>
414 414 </tr>
415 415 <tr class="line unmod">
416 416 <td id="rhodecodepubliccssmainless_o2123" class="lineno old"><a href="#rhodecodepubliccssmainless_o2123">2123</a></td>
417 417 <td id="rhodecodepubliccssmainless_n2122" class="lineno new"><a href="#rhodecodepubliccssmainless_n2122">2122</a></td>
418 418 <td class="code ">
419 419 <pre><span class="tab-escape"> </span><span class="tab-escape"> </span>&amp;:after {
420 420 </pre>
421 421 </td>
422 422 </tr>
423 423 <tr class="line unmod">
424 424 <td id="rhodecodepubliccssmainless_o2124" class="lineno old"><a href="#rhodecodepubliccssmainless_o2124">2124</a></td>
425 425 <td id="rhodecodepubliccssmainless_n2123" class="lineno new"><a href="#rhodecodepubliccssmainless_n2123">2123</a></td>
426 426 <td class="code ">
427 427 <pre><span class="tab-escape"> </span><span class="tab-escape"> </span><span class="tab-escape"> </span>content: "\00A0\25BE";
428 428 </pre>
429 429 </td>
430 430 </tr>
431 431 </tbody></table>
432 432 </div>
433 433 </div>
434 434 </div>
435 435
436 436 </td>
437 437 </tr>
438 438 </tbody></table>
439 439 </div>
440 440
441 441
442 442
443 443
444 444
445 445
446 446
447 447
448 448
449 449 <!--
450 450 File View
451 451 -->
452 452
453 453 ##TODO: lisa: I believe this needs to be updated as the layout has changed.
454 454 <h2>File View</h2>
455 455
456 456 <div class="codeblock">
457 457 <div class="code-header">
458 458 <div class="stats">
459 459 <div class="img">
460 460 <i class="icon-file"></i>
461 461 <span class="revision_id item"><a href="/example/changeset/fc252256eb0fcb4f2613e66f0126ea27967ae28c">r5487:fc252256eb0f</a></span>
462 462 <span>1.2 KiB</span>
463 463 <span class="item last">text/x-python</span>
464 464 <div class="buttons">
465 465
466 466 <a id="file_history_overview" class="btn btn-mini" href="#">
467 467 <i class="icon-time"></i> history
468 468 </a>
469 469 <a id="file_history_overview_full" class="btn btn-mini" style="display: none" href="/example/changelog/fc252256eb0fcb4f2613e66f0126ea27967ae28c/rhodecode/websetup.py">
470 470 <i class="icon-time"></i> show full history
471 471 </a>
472 472 <a class="btn btn-mini" href="/example/annotate/fc252256eb0fcb4f2613e66f0126ea27967ae28c/rhodecode/websetup.py">annotation</a>
473 473 <a class="btn btn-mini" href="/example/raw/fc252256eb0fcb4f2613e66f0126ea27967ae28c/rhodecode/websetup.py">raw</a>
474 474 <a class="btn btn-mini" href="/example/rawfile/fc252256eb0fcb4f2613e66f0126ea27967ae28c/rhodecode/websetup.py">
475 475 <i class="icon-archive"></i> download
476 476 </a>
477 477
478 478 <a class="btn btn-mini disabled tooltip" href="#" title="Editing files allowed only when on branch head commit">edit</a>
479 479 <a class="btn btn-mini btn-danger disabled tooltip" href="#" title="Deleting files allowed only when on branch head commit">delete</a>
480 480 </div>
481 481 </div>
482 482 </div>
483 483 <div id="file_history_container"></div>
484 484 <div class="author">
485 485 <div class="gravatar">
486 486 <img alt="gravatar" src="https://secure.gravatar.com/avatar/99e27b99c64003ca8c9875c9e3843495?d=identicon&amp;s=32" height="16" width="16">
487 487 </div>
488 488 <div title="Marcin Kuzminski <marcin@python-works.com>" class="user">Marcin Kuzminski - <span class="tooltip" title="Wed, 02 Jul 2014 08:48:15">6m and 12d ago</span></div>
489 489 </div>
490 490 <div id="trimmed_message_box" class="commit">License changes</div>
491 491 <div id="message_expand" style="display: none;">
492 492 <i class="icon-resize-vertical"></i>
493 493 expand
494 494 <i class="icon-resize-vertical"></i>
495 495 </div>
496 496 </div>
497 497 <div class="code-body">
498 498 <table class="code-highlighttable"><tbody><tr><td class="linenos"><div class="linenodiv"><pre><a href="#L1"> 1</a>
499 499 <a href="#L2"> 2</a>
500 500 <a href="#L3"> 3</a>
501 501 <a href="#L4"> 4</a>
502 502 <a href="#L5"> 5</a>
503 503 <a href="#L6"> 6</a>
504 504 <a href="#L7"> 7</a>
505 505 <a href="#L8"> 8</a>
506 506 <a href="#L9"> 9</a>
507 507 <a href="#L10">10</a>
508 508 <a href="#L11">11</a>
509 509 <a href="#L12">12</a>
510 510 <a href="#L13">13</a>
511 511 <a href="#L14">14</a>
512 512 <a href="#L15">15</a>
513 513 <a href="#L16">16</a>
514 514 <a href="#L17">17</a>
515 515 <a href="#L18">18</a>
516 516 <a href="#L19">19</a>
517 517 <a href="#L20">20</a>
518 518 <a href="#L21">21</a>
519 519 <a href="#L22">22</a>
520 520 <a href="#L23">23</a>
521 521 <a href="#L24">24</a>
522 522 <a href="#L25">25</a>
523 523 <a href="#L26">26</a>
524 524 <a href="#L27">27</a>
525 525 <a href="#L28">28</a>
526 526 <a href="#L29">29</a>
527 527 <a href="#L30">30</a>
528 528 <a href="#L31">31</a>
529 529 <a href="#L32">32</a>
530 530 <a href="#L33">33</a>
531 531 <a href="#L34">34</a>
532 532 <a href="#L35">35</a>
533 533 <a href="#L36">36</a>
534 534 <a href="#L37">37</a>
535 535 <a href="#L38">38</a>
536 536 <a href="#L39">39</a>
537 537 <a href="#L40">40</a>
538 538 <a href="#L41">41</a>
539 539 <a href="#L42">42</a></pre></div></td><td id="hlcode" class="code"><div class="code-highlight"><pre><div id="L1"><a name="L-1"></a><span class="c"># -*- coding: utf-8 -*-</span>
540 540 </div><div id="L2"><a name="L-2"></a>
541 541 </div><div id="L3"><a name="L-3"></a><span class="c"># Published under Business Source License.</span>
542 542 </div><div id="L4"><a name="L-4"></a><span class="c"># Read the full license text at https://rhodecode.com/licenses.</span>
543 543 </div><div id="L5"><a name="L-5"></a><span class="sd">"""</span>
544 544 </div><div id="L6"><a name="L-6"></a><span class="sd">rhodecode.websetup</span>
545 545 </div><div id="L7"><a name="L-7"></a><span class="sd">~~~~~~~~~~~~~~~~~~</span>
546 546 </div><div id="L8"><a name="L-8"></a>
547 547 </div><div id="L9"><a name="L-9"></a><span class="sd">Weboperations and setup for rhodecode. Intentionally long line to show what will happen if this line does not fit onto the screen. It might have some horizontal scrolling applied or some other fancy mechanism to deal with it.</span>
548 548 </div><div id="L10"><a name="L-10"></a>
549 549 </div><div id="L11"><a name="L-11"></a><span class="sd">:created_on: Dec 11, 2010</span>
550 550 </div><div id="L12"><a name="L-12"></a><span class="sd">:author: marcink</span>
551 551 </div><div id="L13"><a name="L-13"></a><span class="sd">:copyright: (c) 2013-2015 RhodeCode GmbH.</span>
552 552 </div><div id="L14"><a name="L-14"></a><span class="sd">:license: Business Source License, see LICENSE for more details.</span>
553 553 </div><div id="L15"><a name="L-15"></a><span class="sd">"""</span>
554 554 </div><div id="L16"><a name="L-16"></a>
555 555 </div><div id="L17"><a name="L-17"></a><span class="kn">import</span> <span class="nn">logging</span>
556 556 </div><div id="L18"><a name="L-18"></a>
557 557 </div><div id="L19"><a name="L-19"></a><span class="kn">from</span> <span class="nn">rhodecode.config.environment</span> <span class="kn">import</span> <span class="n">load_environment</span>
558 558 </div><div id="L20"><a name="L-20"></a><span class="kn">from</span> <span class="nn">rhodecode.lib.db_manage</span> <span class="kn">import</span> <span class="n">DbManage</span>
559 559 </div><div id="L21"><a name="L-21"></a><span class="kn">from</span> <span class="nn">rhodecode.model.meta</span> <span class="kn">import</span> <span class="n">Session</span>
560 560 </div><div id="L22"><a name="L-22"></a>
561 561 </div><div id="L23"><a name="L-23"></a>
562 562 </div><div id="L24"><a name="L-24"></a><span class="n">log</span> <span class="o">=</span> <span class="n">logging</span><span class="o">.</span><span class="n">getLogger</span><span class="p">(</span><span class="n">__name__</span><span class="p">)</span>
563 563 </div><div id="L25"><a name="L-25"></a>
564 564 </div><div id="L26"><a name="L-26"></a>
565 565 </div><div id="L27"><a name="L-27"></a><span class="k">def</span> <span class="nf">setup_app</span><span class="p">(</span><span class="n">command</span><span class="p">,</span> <span class="n">conf</span><span class="p">,</span> <span class="nb">vars</span><span class="p">):</span>
566 566 </div><div id="L28"><a name="L-28"></a> <span class="sd">"""Place any commands to setup rhodecode here"""</span>
567 567 </div><div id="L29"><a name="L-29"></a> <span class="n">dbconf</span> <span class="o">=</span> <span class="n">conf</span><span class="p">[</span><span class="s">'sqlalchemy.db1.url'</span><span class="p">]</span>
568 568 </div><div id="L30"><a name="L-30"></a> <span class="n">dbmanage</span> <span class="o">=</span> <span class="n">DbManage</span><span class="p">(</span><span class="n">log_sql</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span> <span class="n">dbconf</span><span class="o">=</span><span class="n">dbconf</span><span class="p">,</span> <span class="n">root</span><span class="o">=</span><span class="n">conf</span><span class="p">[</span><span class="s">'here'</span><span class="p">],</span>
569 569 </div><div id="L31"><a name="L-31"></a> <span class="n">tests</span><span class="o">=</span><span class="bp">False</span><span class="p">,</span> <span class="n">cli_args</span><span class="o">=</span><span class="n">command</span><span class="o">.</span><span class="n">options</span><span class="o">.</span><span class="n">__dict__</span><span class="p">)</span>
570 570 </div><div id="L32"><a name="L-32"></a> <span class="n">dbmanage</span><span class="o">.</span><span class="n">create_tables</span><span class="p">(</span><span class="n">override</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
571 571 </div><div id="L33"><a name="L-33"></a> <span class="n">dbmanage</span><span class="o">.</span><span class="n">set_db_version</span><span class="p">()</span>
572 572 </div><div id="L34"><a name="L-34"></a> <span class="n">opts</span> <span class="o">=</span> <span class="n">dbmanage</span><span class="o">.</span><span class="n">config_prompt</span><span class="p">(</span><span class="bp">None</span><span class="p">)</span>
573 573 </div><div id="L35"><a name="L-35"></a> <span class="n">dbmanage</span><span class="o">.</span><span class="n">create_settings</span><span class="p">(</span><span class="n">opts</span><span class="p">)</span>
574 574 </div><div id="L36"><a name="L-36"></a> <span class="n">dbmanage</span><span class="o">.</span><span class="n">create_default_user</span><span class="p">()</span>
575 575 </div><div id="L37"><a name="L-37"></a> <span class="n">dbmanage</span><span class="o">.</span><span class="n">admin_prompt</span><span class="p">()</span>
576 576 </div><div id="L38"><a name="L-38"></a> <span class="n">dbmanage</span><span class="o">.</span><span class="n">create_permissions</span><span class="p">()</span>
577 577 </div><div id="L39"><a name="L-39"></a> <span class="n">dbmanage</span><span class="o">.</span><span class="n">populate_default_permissions</span><span class="p">()</span>
578 578 </div><div id="L40"><a name="L-40"></a> <span class="n">Session</span><span class="p">()</span><span class="o">.</span><span class="n">commit</span><span class="p">()</span>
579 579 </div><div id="L41"><a name="L-41"></a> <span class="n">load_environment</span><span class="p">(</span><span class="n">conf</span><span class="o">.</span><span class="n">global_conf</span><span class="p">,</span> <span class="n">conf</span><span class="o">.</span><span class="n">local_conf</span><span class="p">,</span> <span class="n">initial</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
580 580 </div><div id="L42"><a name="L-42"></a> <span class="n">DbManage</span><span class="o">.</span><span class="n">check_waitress</span><span class="p">()</span>
581 581 </div></pre></div>
582 582 </td></tr></tbody></table>
583 583 </div>
584 584 </div>
585 585
586 586
587 587
588 588
589 589
590 590
591 591
592 592
593 593
594 594 <!--
595 595 Gist Edit
596 596 -->
597 597
598 598
599 599 <h2>Gist Edit</h2>
600 600
601 601 <div class="codeblock">
602 602 <div class="code-header">
603 603 <div class="form">
604 604 <div class="fields">
605 605 <input id="filename" name="filename" placeholder="name this file..." size="30" type="text">
606 606 <div class="select2-container drop-menu" id="s2id_mimetype"><a href="javascript:void(0)" class="select2-choice" tabindex="-1"> <span class="select2-chosen" id="select2-chosen-3">Python</span><abbr class="select2-search-choice-close"></abbr> <span class="select2-arrow" role="presentation"><b role="presentation"></b></span></a><label for="s2id_autogen3" class="select2-offscreen"></label><input class="select2-focusser select2-offscreen" type="text" aria-haspopup="true" role="button" aria-labelledby="select2-chosen-3" id="s2id_autogen3"><div class="select2-drop select2-display-none drop-menu-dropdown select2-with-searchbox"> <div class="select2-search"> <label for="s2id_autogen3_search" class="select2-offscreen"></label> <input type="text" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" class="select2-input" role="combobox" aria-expanded="true" aria-autocomplete="list" aria-owns="select2-results-3" id="s2id_autogen3_search" placeholder=""> </div> <ul class="select2-results" role="listbox" id="select2-results-3"> </ul></div></div><select id="mimetype" name="mimetype" tabindex="-1" title="" style="display: none;">
607 607 <option selected="selected" value="plain">plain</option>
608 608 <option value="text/apl" mode="apl">APL</option><option value="text/x-asterisk" mode="asterisk">Asterisk</option><option value="text/x-csrc" mode="clike">C</option><option value="text/x-c++src" mode="clike">C++</option><option value="text/x-cobol" mode="cobol">Cobol</option><option value="text/x-java" mode="clike">Java</option><option value="text/x-csharp" mode="clike">C#</option><option value="text/x-scala" mode="clike">Scala</option><option value="text/x-clojure" mode="clojure">Clojure</option><option value="text/x-coffeescript" mode="coffeescript">CoffeeScript</option><option value="text/x-common-lisp" mode="commonlisp">Common Lisp</option><option value="text/css" mode="css">CSS</option><option value="text/x-d" mode="d">D</option><option value="text/x-diff" mode="diff">diff</option><option value="application/xml-dtd" mode="dtd">DTD</option><option value="text/x-dylan" mode="dylan">Dylan</option><option value="text/x-ecl" mode="ecl">ECL</option><option value="text/x-eiffel" mode="eiffel">Eiffel</option><option value="text/x-erlang" mode="erlang">Erlang</option><option value="text/x-fortran" mode="fortran">Fortran</option><option value="text/x-fsharp" mode="mllike">F#</option><option value="text/x-gas" mode="gas">Gas</option><option value="text/x-go" mode="go">GO</option><option value="text/x-feature" mode="gherkin">Gherkin</option><option value="text/x-go" mode="go">Go</option><option value="text/x-groovy" mode="groovy">Groovy</option><option value="text/x-haml" mode="haml">HAML</option><option value="text/x-haskell" mode="haskell">Haskell</option><option value="text/x-haxe" mode="haxe">Haxe</option><option value="application/x-aspx" mode="htmlembedded">ASP.NET</option><option value="application/x-ejs" mode="htmlembedded">Embedded Javascript</option><option value="application/x-jsp" mode="htmlembedded">JavaServer Pages</option><option value="text/html" mode="htmlmixed">HTML</option><option value="message/http" mode="http">HTTP</option><option value="text/x-jade" mode="jade">Jade</option><option value="text/javascript" mode="javascript">JavaScript</option><option value="application/json" mode="javascript">JSON</option><option value="application/typescript" mode="javascript">TypeScript</option><option value="jinja2" mode="jinja2">Jinja2</option><option value="text/x-julia" mode="julia">Julia</option><option value="text/x-less" mode="less">LESS</option><option value="text/x-livescript" mode="livescript">LiveScript</option><option value="text/x-lua" mode="lua">Lua</option><option value="text/x-markdown" mode="markdown">Markdown (GitHub-flavour)</option><option value="text/mirc" mode="mirc">mIRC</option><option value="text/x-nginx-conf" mode="nginx">Nginx</option><option value="text/n-triples" mode="ntriples">NTriples</option><option value="text/x-ocaml" mode="ocaml">OCaml</option><option value="text/x-ocaml" mode="mllike">OCaml</option><option value="text/x-octave" mode="octave">Octave</option><option value="text/x-pascal" mode="pascal">Pascal</option><option value="null" mode="pegjs">PEG.js</option><option value="text/x-perl" mode="perl">Perl</option><option value="text/x-php" mode="php">PHP</option><option value="text/x-pig" mode="pig">Pig</option><option value="text/plain" mode="null">Plain Text</option><option value="text/x-properties" mode="properties">Properties files</option><option value="text/x-python" mode="python">Python</option><option value="text/x-puppet" mode="puppet">Puppet</option><option value="text/x-rsrc" mode="r">R</option><option value="text/x-rst" mode="rst">reStructuredText</option><option value="text/x-ruby" mode="ruby">Ruby</option><option value="text/x-rustsrc" mode="rust">Rust</option><option value="text/x-sass" mode="sass">Sass</option><option value="text/x-scheme" mode="scheme">Scheme</option><option value="text/x-scss" mode="css">SCSS</option><option value="text/x-sh" mode="shell">Shell</option><option value="application/sieve" mode="sieve">Sieve</option><option value="text/x-stsrc" mode="smalltalk">Smalltalk</option><option value="text/x-smarty" mode="smarty">Smarty</option><option value="text/x-smarty" mode="smartymixed">SmartyMixed</option><option value="text/x-solr" mode="solr">Solr</option><option value="application/x-sparql-query" mode="sparql">SPARQL</option><option value="text/x-sql" mode="sql">SQL</option><option value="text/x-mariadb" mode="sql">MariaDB</option><option value="text/x-stex" mode="stex">sTeX</option><option value="text/x-latex" mode="stex">LaTeX</option><option value="text/x-systemverilog" mode="verilog">SystemVerilog</option><option value="text/x-tcl" mode="tcl">Tcl</option><option value="text/x-tiddlywiki" mode="tiddlywiki">TiddlyWiki </option><option value="text/tiki" mode="tiki">Tiki wiki</option><option value="text/x-toml" mode="toml">TOML</option><option value="text/turtle" mode="turtle">Turtle</option><option value="text/x-vb" mode="vb">VB.NET</option><option value="text/vbscript" mode="vbscript">VBScript</option><option value="text/velocity" mode="velocity">Velocity</option><option value="text/x-verilog" mode="verilog">Verilog</option><option value="application/xml" mode="xml">XML</option><option value="text/html" mode="xml">HTML</option><option value="application/xquery" mode="xquery">XQuery</option><option value="text/x-yaml" mode="yaml">YAML</option><option value="text/x-z80" mode="z80">Z80</option></select>
609 609 <script>
610 610 $(document).ready(function() {
611 611 $('#mimetype').select2({
612 612 containerCssClass: 'drop-menu',
613 613 dropdownCssClass: 'drop-menu-dropdown',
614 614 dropdownAutoWidth: true
615 615 });
616 616 });
617 617 </script>
618 618
619 619 </div>
620 620 </div>
621 621 </div>
622 622 <div id="editor_container">
623 623 <div id="editor_pre"></div>
624 624 <textarea id="editor" name="content" style="display: none;"></textarea><div class="CodeMirror cm-s-default"><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 484px; left: 219.4091796875px;"><textarea autocorrect="off" autocapitalize="off" spellcheck="false" style="position: absolute; padding: 0px; width: 1000px; height: 1em; outline: none;" tabindex="0"></textarea></div><div class="CodeMirror-hscrollbar" style="left: 29px; min-height: 18px;"><div style="height: 100%; min-height: 1px; width: 0px;"></div></div><div class="CodeMirror-vscrollbar" style="min-width: 18px; display: block; bottom: 0px;"><div style="min-width: 1px; height: 619px;"></div></div><div class="CodeMirror-scrollbar-filler"></div><div class="CodeMirror-gutter-filler"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="min-width: 700.269653320313px; margin-left: 29px; min-height: 619px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines"><div style="position: relative; outline: none;"><div class="CodeMirror-measure"><div class="CodeMirror-linenumber CodeMirror-gutter-elt"><div>47</div></div></div><div style="position: relative; z-index: 1; display: none;"></div><div class="CodeMirror-code"><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">1</div></div><pre><span class="cm-keyword">import</span> <span class="cm-variable">re</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">2</div></div><pre>&nbsp;</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">3</div></div><pre><span class="cm-keyword">from</span> <span class="cm-variable">django</span>.<span class="cm-variable">utils</span>.<span class="cm-variable">text</span> <span class="cm-keyword">import</span> <span class="cm-variable">compress_sequence</span>, <span class="cm-variable">compress_string</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">4</div></div><pre><span class="cm-keyword">from</span> <span class="cm-variable">django</span>.<span class="cm-variable">utils</span>.<span class="cm-variable">cache</span> <span class="cm-keyword">import</span> <span class="cm-variable">patch_vary_headers</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">5</div></div><pre>&nbsp;</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">6</div></div><pre><span class="cm-variable">re_accepts_gzip</span> = <span class="cm-variable">re</span>.<span class="cm-builtin">compile</span>(<span class="cm-string">r'\bgzip\b'</span>)</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">7</div></div><pre>&nbsp;</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">8</div></div><pre>&nbsp;</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">9</div></div><pre><span class="cm-keyword">class</span> <span class="cm-def">GZipMiddleware</span>(<span class="cm-builtin">object</span>): # Intentionally long line to show what will happen if this line does not fit onto the screen. It might have some horizontal scrolling applied or some other fancy mechanism to deal with it.</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">10</div></div><pre> <span class="cm-string">"""</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">11</div></div><pre><span class="cm-string"> This middleware compresses content if the browser allows gzip compression.</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">12</div></div><pre><span class="cm-string"> It sets the Vary header accordingly, so that caches will base their storage</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">13</div></div><pre><span class="cm-string"> on the Accept-Encoding header.</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">14</div></div><pre><span class="cm-string"> """</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">15</div></div><pre> <span class="cm-keyword">def</span> <span class="cm-def">process_response</span>(<span class="cm-variable-2">self</span>, <span class="cm-variable">request</span>, <span class="cm-variable">response</span>):</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">16</div></div><pre> <span class="cm-comment"># It's not worth attempting to compress really short responses.</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">17</div></div><pre> <span class="cm-keyword">if</span> <span class="cm-operator">not</span> <span class="cm-variable">response</span>.<span class="cm-variable">streaming</span> <span class="cm-operator">and</span> <span class="cm-builtin">len</span>(<span class="cm-variable">response</span>.<span class="cm-variable">content</span>) <span class="cm-operator">&lt;</span> <span class="cm-number">200</span>:</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">18</div></div><pre> <span class="cm-keyword">return</span> <span class="cm-variable">response</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">19</div></div><pre>&nbsp;</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">20</div></div><pre> <span class="cm-comment"># Avoid gzipping if we've already got a content-encoding.</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">21</div></div><pre> <span class="cm-keyword">if</span> <span class="cm-variable">response</span>.<span class="cm-variable">has_header</span>(<span class="cm-string">'Content-Encoding'</span>):</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">22</div></div><pre> <span class="cm-keyword">return</span> <span class="cm-variable">response</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">23</div></div><pre>&nbsp;</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">24</div></div><pre> <span class="cm-variable">patch_vary_headers</span>(<span class="cm-variable">response</span>, (<span class="cm-string">'Accept-Encoding'</span>,))</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">25</div></div><pre>&nbsp;</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">26</div></div><pre> <span class="cm-variable">ae</span> = <span class="cm-variable">request</span>.<span class="cm-variable">META</span>.<span class="cm-variable">get</span>(<span class="cm-string">'HTTP_ACCEPT_ENCODING'</span>, <span class="cm-string">''</span>)</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">27</div></div><pre> <span class="cm-keyword">if</span> <span class="cm-operator">not</span> <span class="cm-variable">re_accepts_gzip</span>.<span class="cm-variable">search</span>(<span class="cm-variable">ae</span>):</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">28</div></div><pre> <span class="cm-keyword">return</span> <span class="cm-variable">response</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">29</div></div><pre>&nbsp;</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">30</div></div><pre> <span class="cm-keyword">if</span> <span class="cm-variable">response</span>.<span class="cm-variable">streaming</span>:</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">31</div></div><pre> <span class="cm-comment"># Delete the `Content-Length` header for streaming content, because</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">32</div></div><pre> <span class="cm-comment"># we won't know the compressed size until we stream it.</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">33</div></div><pre> <span class="cm-variable">response</span>.<span class="cm-variable">streaming_content</span> = <span class="cm-variable">compress_sequence</span>(<span class="cm-variable">response</span>.<span class="cm-variable">streaming_content</span>)</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">34</div></div><pre> <span class="cm-keyword">del</span> <span class="cm-variable">response</span>[<span class="cm-string">'Content-Length'</span>]</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">35</div></div><pre> <span class="cm-keyword">else</span>:</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">36</div></div><pre> <span class="cm-comment"># Return the compressed content only if it's actually shorter.</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">37</div></div><pre> <span class="cm-variable">compressed_content</span> = <span class="cm-variable">compress_string</span>(<span class="cm-variable">response</span>.<span class="cm-variable">content</span>)</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">38</div></div><pre> <span class="cm-keyword">if</span> <span class="cm-builtin">len</span>(<span class="cm-variable">compressed_content</span>) <span class="cm-operator">&gt;=</span> <span class="cm-builtin">len</span>(<span class="cm-variable">response</span>.<span class="cm-variable">content</span>):</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">39</div></div><pre> <span class="cm-keyword">return</span> <span class="cm-variable">response</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">40</div></div><pre> <span class="cm-variable">response</span>.<span class="cm-variable">content</span> = <span class="cm-variable">compressed_content</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">41</div></div><pre> <span class="cm-variable">response</span>[<span class="cm-string">'Content-Length'</span>] = <span class="cm-builtin">str</span>(<span class="cm-builtin">len</span>(<span class="cm-variable">response</span>.<span class="cm-variable">content</span>))</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">42</div></div><pre>&nbsp;</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">43</div></div><pre> <span class="cm-keyword">if</span> <span class="cm-variable">response</span>.<span class="cm-variable">has_header</span>(<span class="cm-string">'ETag'</span>):</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">44</div></div><pre> <span class="cm-variable">response</span>[<span class="cm-string">'ETag'</span>] = <span class="cm-variable">re</span>.<span class="cm-variable">sub</span>(<span class="cm-string">'"$'</span>, <span class="cm-string">';gzip"'</span>, <span class="cm-variable">response</span>[<span class="cm-string">'ETag'</span>])</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">45</div></div><pre> <span class="cm-variable">response</span>[<span class="cm-string">'Content-Encoding'</span>] = <span class="cm-string">'gzip'</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">46</div></div><pre>&nbsp;</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">47</div></div><pre> <span class="cm-keyword">return</span> <span class="cm-variable">response</span></pre></div></div><div class="CodeMirror-cursor" style="left: 189.4091796875px; top: 598px; height: 13px;">&nbsp;</div><div class="CodeMirror-cursor CodeMirror-secondarycursor" style="display: none;">&nbsp;</div></div></div></div></div><div style="position: absolute; height: 30px; width: 1px; top: 619px;"></div><div class="CodeMirror-gutters" style="height: 619px;"><div class="CodeMirror-gutter CodeMirror-linenumbers" style="width: 28px;"></div></div></div></div>
625 625 </div>
626 626 </div>
627 627
628 628
629 629
630 630
631 631
632 632 <!--
633 633 File Edit
634 634 -->
635 635
636 636 <h2>File Edit</h2>
637 637
638 638 <div class="codeblock">
639 639 <div class="code-header">
640 640 <div class="stats">
641 641 <i class="icon-file"></i>
642 642 <span class="item"><a href="/example/changeset/80ead1899f50a894889e19ffeb49c9cebf5bf045">r8248:80ead1899f50</a></span>
643 643 <span class="item">1.2 KiB</span>
644 644 <span class="item last">text/x-python</span>
645 645 <div class="buttons">
646 646 <a class="btn btn-mini" href="/example/changelog/80ead1899f50a894889e19ffeb49c9cebf5bf045/rhodecode/websetup.py">
647 647 <i class="icon-time"></i> history
648 648 </a>
649 649
650 650 <a class="btn btn-mini" href="/example/files/80ead1899f50a894889e19ffeb49c9cebf5bf045/rhodecode/websetup.py">source</a>
651 651 <a class="btn btn-mini" href="/example/raw/80ead1899f50a894889e19ffeb49c9cebf5bf045/rhodecode/websetup.py">raw</a>
652 652 <a class="btn btn-mini" href="/example/rawfile/80ead1899f50a894889e19ffeb49c9cebf5bf045/rhodecode/websetup.py">
653 653 <i class="icon-archive"></i> download
654 654 </a>
655 655 </div>
656 656 </div>
657 657 <div class="form">
658 658 <label for="set_mode">Editing file:</label>
659 659 rhodecode /
660 660 <input type="text" name="filename" value="websetup.py">
661 661
662 662 <div class="select2-container drop-menu" id="s2id_set_mode"><a href="javascript:void(0)" class="select2-choice" tabindex="-1"> <span class="select2-chosen" id="select2-chosen-2">plain</span><abbr class="select2-search-choice-close"></abbr> <span class="select2-arrow" role="presentation"><b role="presentation"></b></span></a><label for="s2id_autogen2" class="select2-offscreen">Editing file:</label><input class="select2-focusser select2-offscreen" type="text" aria-haspopup="true" role="button" aria-labelledby="select2-chosen-2" id="s2id_autogen2"><div class="select2-drop select2-display-none drop-menu-dropdown select2-with-searchbox"> <div class="select2-search"> <label for="s2id_autogen2_search" class="select2-offscreen">Editing file:</label> <input type="text" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" class="select2-input" role="combobox" aria-expanded="true" aria-autocomplete="list" aria-owns="select2-results-2" id="s2id_autogen2_search" placeholder=""> </div> <ul class="select2-results" role="listbox" id="select2-results-2"> </ul></div></div><select id="set_mode" name="set_mode" tabindex="-1" title="Editing file:" style="display: none;">
663 663 <option selected="selected" value="plain">plain</option>
664 664 <option value="apl">APL</option><option value="asterisk">Asterisk</option><option value="clike">C</option><option value="clike">C++</option><option value="cobol">Cobol</option><option value="clike">Java</option><option value="clike">C#</option><option value="clike">Scala</option><option value="clojure">Clojure</option><option value="coffeescript">CoffeeScript</option><option value="commonlisp">Common Lisp</option><option value="css">CSS</option><option value="d">D</option><option value="diff">diff</option><option value="dtd">DTD</option><option value="dylan">Dylan</option><option value="ecl">ECL</option><option value="eiffel">Eiffel</option><option value="erlang">Erlang</option><option value="fortran">Fortran</option><option value="mllike">F#</option><option value="gas">Gas</option><option value="go">GO</option><option value="gherkin">Gherkin</option><option value="go">Go</option><option value="groovy">Groovy</option><option value="haml">HAML</option><option value="haskell">Haskell</option><option value="haxe">Haxe</option><option value="htmlembedded">ASP.NET</option><option value="htmlembedded">Embedded Javascript</option><option value="htmlembedded">JavaServer Pages</option><option value="htmlmixed">HTML</option><option value="http">HTTP</option><option value="jade">Jade</option><option value="javascript">JavaScript</option><option value="javascript">JSON</option><option value="javascript">TypeScript</option><option value="jinja2">Jinja2</option><option value="julia">Julia</option><option value="less">LESS</option><option value="livescript">LiveScript</option><option value="lua">Lua</option><option value="markdown">Markdown (GitHub-flavour)</option><option value="mirc">mIRC</option><option value="nginx">Nginx</option><option value="ntriples">NTriples</option><option value="ocaml">OCaml</option><option value="mllike">OCaml</option><option value="octave">Octave</option><option value="pascal">Pascal</option><option value="pegjs">PEG.js</option><option value="perl">Perl</option><option value="php">PHP</option><option value="pig">Pig</option><option value="null">Plain Text</option><option value="properties">Properties files</option><option value="python" selected="selected">Python</option><option value="puppet">Puppet</option><option value="r">R</option><option value="rst">reStructuredText</option><option value="ruby">Ruby</option><option value="rust">Rust</option><option value="sass">Sass</option><option value="scheme">Scheme</option><option value="css">SCSS</option><option value="shell">Shell</option><option value="sieve">Sieve</option><option value="smalltalk">Smalltalk</option><option value="smarty">Smarty</option><option value="smartymixed">SmartyMixed</option><option value="solr">Solr</option><option value="sparql">SPARQL</option><option value="sql">SQL</option><option value="sql">MariaDB</option><option value="stex">sTeX</option><option value="stex">LaTeX</option><option value="verilog">SystemVerilog</option><option value="tcl">Tcl</option><option value="tiddlywiki">TiddlyWiki </option><option value="tiki">Tiki wiki</option><option value="toml">TOML</option><option value="turtle">Turtle</option><option value="vb">VB.NET</option><option value="vbscript">VBScript</option><option value="velocity">Velocity</option><option value="verilog">Verilog</option><option value="xml">XML</option><option value="xml">HTML</option><option value="xquery">XQuery</option><option value="yaml">YAML</option><option value="z80">Z80</option></select>
665 665 <script>
666 666 $(document).ready(function() {
667 667 $('#set_mode').select2({
668 668 containerCssClass: 'drop-menu',
669 669 dropdownCssClass: 'drop-menu-dropdown',
670 670 dropdownAutoWidth: true
671 671 });
672 672 });
673 673 </script>
674 674
675 675 <label for="line_wrap">line wraps</label>
676 676 <div class="select2-container drop-menu" id="s2id_line_wrap"><a href="javascript:void(0)" class="select2-choice" tabindex="-1"> <span class="select2-chosen" id="select2-chosen-3">off</span><abbr class="select2-search-choice-close"></abbr> <span class="select2-arrow" role="presentation"><b role="presentation"></b></span></a><label for="s2id_autogen3" class="select2-offscreen">line wraps</label><input class="select2-focusser select2-offscreen" type="text" aria-haspopup="true" role="button" aria-labelledby="select2-chosen-3" id="s2id_autogen3"><div class="select2-drop select2-display-none drop-menu-dropdown"> <div class="select2-search select2-search-hidden select2-offscreen"> <label for="s2id_autogen3_search" class="select2-offscreen">line wraps</label> <input type="text" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" class="select2-input" role="combobox" aria-expanded="true" aria-autocomplete="list" aria-owns="select2-results-3" id="s2id_autogen3_search" placeholder=""> </div> <ul class="select2-results" role="listbox" id="select2-results-3"> </ul></div></div><select id="line_wrap" name="line_wrap" tabindex="-1" title="line wraps" style="display: none;">
677 677 <option value="on">on</option>
678 678 <option selected="selected" value="off">off</option>
679 679 </select>
680 680 <script>
681 681 $(document).ready(function() {
682 682 $('#line_wrap').select2({
683 683 containerCssClass: 'drop-menu',
684 684 dropdownCssClass: 'drop-menu-dropdown',
685 685 dropdownAutoWidth: true,
686 686 minimumResultsForSearch: -1
687 687
688 688 });
689 689 });
690 690 </script>
691 691
692 692 <div id="render_preview" class="btn btn-mini hidden disabled">Preview</div>
693 693 </div>
694 694 </div>
695 695 <div id="editor_container">
696 696 <pre id="editor_pre"></pre>
697 697 <textarea id="editor" name="content" style="display: none;"># -*- coding: utf-8 -*-
698 698
699 699 # Published under Commercial License.
700 700 # Read the full license text at https://rhodecode.com/licenses.
701 701 """
702 702 rhodecode.websetup
703 703 ~~~~~~~~~~~~~~~~~~
704 704
705 705 Weboperations and setup for rhodecode
706 706
707 707 :created_on: Dec 11, 2010
708 708 :author: marcink
709 709 :copyright: (c) 2013-2015 RhodeCode GmbH.
710 710 :license: Commercial License, see LICENSE for more details.
711 711 """
712 712
713 713 import logging
714 714
715 715 from rhodecode.config.environment import load_environment
716 716 from rhodecode.lib.db_manage import DbManage
717 717 from rhodecode.model.meta import Session
718 718
719 719
720 720 log = logging.getLogger(__name__)
721 721
722 722
723 723 def setup_app(command, conf, vars):
724 724 """Place any commands to setup rhodecode here"""
725 725 dbconf = conf['sqlalchemy.db1.url']
726 726 dbmanage = DbManage(log_sql=True, dbconf=dbconf, root=conf['here'],
727 727 tests=False, cli_args=command.options.__dict__)
728 728 dbmanage.create_tables(override=True)
729 729 dbmanage.set_db_version()
730 730 opts = dbmanage.config_prompt(None)
731 731 dbmanage.create_settings(opts)
732 732 dbmanage.create_default_user()
733 733 dbmanage.admin_prompt()
734 734 dbmanage.create_permissions()
735 735 dbmanage.populate_default_permissions()
736 736 Session().commit()
737 737 load_environment(conf.global_conf, conf.local_conf, initial=True)
738 738 </textarea><div class="CodeMirror cm-s-default CodeMirror-focused"><div style="overflow: hidden; position: relative; width: 3px; height: 0px; top: 5px; left: 34px;"><textarea autocorrect="off" autocapitalize="off" spellcheck="false" style="position: absolute; padding: 0px; width: 1000px; height: 1em; outline: none;" tabindex="0"></textarea></div><div class="CodeMirror-hscrollbar" style="left: 29px; min-height: 18px;"><div style="height: 100%; min-height: 1px; width: 0px;"></div></div><div class="CodeMirror-vscrollbar" style="display: block; bottom: 0px; min-width: 18px;"><div style="min-width: 1px; height: 554px;"></div></div><div class="CodeMirror-scrollbar-filler"></div><div class="CodeMirror-gutter-filler"></div><div class="CodeMirror-scroll" tabindex="-1"><div class="CodeMirror-sizer" style="min-width: 579.350463867188px; margin-left: 29px; min-height: 554px;"><div style="position: relative; top: 0px;"><div class="CodeMirror-lines"><div style="position: relative; outline: none;"><div class="CodeMirror-measure"><div style="width: 50px; height: 50px; overflow-x: scroll;"></div></div><div style="position: relative; z-index: 1; display: none;"></div><div class="CodeMirror-code"><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">1</div></div><pre><span class="cm-comment"># -*- coding: utf-8 -*-</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">2</div></div><pre>&nbsp;</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">3</div></div><pre><span class="cm-comment"># Published under Commercial License.</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">4</div></div><pre><span class="cm-comment"># Read the full license text at https://rhodecode.com/licenses.</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">5</div></div><pre><span class="cm-string">"""</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">6</div></div><pre><span class="cm-string">rhodecode.websetup</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">7</div></div><pre><span class="cm-string">~~~~~~~~~~~~~~~~~~</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">8</div></div><pre>&nbsp;</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">9</div></div><pre><span class="cm-string">Weboperations and setup for rhodecode</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">10</div></div><pre>&nbsp;</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">11</div></div><pre><span class="cm-string">:created_on: Dec 11, 2010</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">12</div></div><pre><span class="cm-string">:author: marcink</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">13</div></div><pre><span class="cm-string">:copyright: (c) 2013-2015 RhodeCode GmbH.</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">14</div></div><pre><span class="cm-string">:license: Commercial License, see LICENSE for more details.</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">15</div></div><pre><span class="cm-string">"""</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">16</div></div><pre>&nbsp;</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">17</div></div><pre><span class="cm-keyword">import</span> <span class="cm-variable">logging</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">18</div></div><pre>&nbsp;</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">19</div></div><pre><span class="cm-keyword">from</span> <span class="cm-variable">rhodecode</span>.<span class="cm-variable">config</span>.<span class="cm-variable">environment</span> <span class="cm-keyword">import</span> <span class="cm-variable">load_environment</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">20</div></div><pre><span class="cm-keyword">from</span> <span class="cm-variable">rhodecode</span>.<span class="cm-variable">lib</span>.<span class="cm-variable">db_manage</span> <span class="cm-keyword">import</span> <span class="cm-variable">DbManage</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">21</div></div><pre><span class="cm-keyword">from</span> <span class="cm-variable">rhodecode</span>.<span class="cm-variable">model</span>.<span class="cm-variable">meta</span> <span class="cm-keyword">import</span> <span class="cm-variable">Session</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">22</div></div><pre>&nbsp;</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">23</div></div><pre>&nbsp;</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">24</div></div><pre><span class="cm-variable">log</span> = <span class="cm-variable">logging</span>.<span class="cm-variable">getLogger</span>(<span class="cm-variable">__name__</span>) # Intentionally long line to show what will happen if this line does not fit onto the screen. It might have some horizontal scrolling applied or some other fancy mechanism to deal with it.</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">25</div></div><pre>&nbsp;</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">26</div></div><pre>&nbsp;</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">27</div></div><pre><span class="cm-keyword">def</span> <span class="cm-def">setup_app</span>(<span class="cm-variable">command</span>, <span class="cm-variable">conf</span>, <span class="cm-builtin">vars</span>):</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">28</div></div><pre> <span class="cm-string">"""Place any commands to setup rhodecode here"""</span></pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">29</div></div><pre> <span class="cm-variable">dbconf</span> = <span class="cm-variable">conf</span>[<span class="cm-string">'sqlalchemy.db1.url'</span>]</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">30</div></div><pre> <span class="cm-variable">dbmanage</span> = <span class="cm-variable">DbManage</span>(<span class="cm-variable">log_sql</span>=<span class="cm-builtin">True</span>, <span class="cm-variable">dbconf</span>=<span class="cm-variable">dbconf</span>, <span class="cm-variable">root</span>=<span class="cm-variable">conf</span>[<span class="cm-string">'here'</span>],</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">31</div></div><pre> <span class="cm-variable">tests</span>=<span class="cm-builtin">False</span>, <span class="cm-variable">cli_args</span>=<span class="cm-variable">command</span>.<span class="cm-variable">options</span>.<span class="cm-variable">__dict__</span>)</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">32</div></div><pre> <span class="cm-variable">dbmanage</span>.<span class="cm-variable">create_tables</span>(<span class="cm-variable">override</span>=<span class="cm-builtin">True</span>)</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">33</div></div><pre> <span class="cm-variable">dbmanage</span>.<span class="cm-variable">set_db_version</span>()</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">34</div></div><pre> <span class="cm-variable">opts</span> = <span class="cm-variable">dbmanage</span>.<span class="cm-variable">config_prompt</span>(<span class="cm-builtin">None</span>)</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">35</div></div><pre> <span class="cm-variable">dbmanage</span>.<span class="cm-variable">create_settings</span>(<span class="cm-variable">opts</span>)</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">36</div></div><pre> <span class="cm-variable">dbmanage</span>.<span class="cm-variable">create_default_user</span>()</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">37</div></div><pre> <span class="cm-variable">dbmanage</span>.<span class="cm-variable">admin_prompt</span>()</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">38</div></div><pre> <span class="cm-variable">dbmanage</span>.<span class="cm-variable">create_permissions</span>()</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">39</div></div><pre> <span class="cm-variable">dbmanage</span>.<span class="cm-variable">populate_default_permissions</span>()</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">40</div></div><pre> <span class="cm-variable">Session</span>().<span class="cm-variable">commit</span>()</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">41</div></div><pre> <span class="cm-variable">load_environment</span>(<span class="cm-variable">conf</span>.<span class="cm-variable">global_conf</span>, <span class="cm-variable">conf</span>.<span class="cm-variable">local_conf</span>, <span class="cm-variable">initial</span>=<span class="cm-builtin">True</span>)</pre></div><div style="position: relative;"><div class="CodeMirror-gutter-wrapper" style="position: absolute; left: -29px;"><div class="CodeMirror-linenumber CodeMirror-gutter-elt" style="left: 0px; width: 20px;">42</div></div><pre>&nbsp;</pre></div></div><div class="CodeMirror-cursor" style="left: 4px; top: 0px; height: 13px;">&nbsp;</div><div class="CodeMirror-cursor CodeMirror-secondarycursor" style="display: none;">&nbsp;</div></div></div></div></div><div style="position: absolute; height: 30px; width: 1px; top: 554px;"></div><div class="CodeMirror-gutters" style="height: 554px;"><div class="CodeMirror-gutter CodeMirror-linenumbers" style="width: 28px;"></div></div></div></div>
739 739 <div id="editor_preview"></div>
740 740 </div>
741 741 <div class="message">
742 742 <label class="codeblock-label">Commit Message</label>
743 743 <textarea id="commit" name="message" placeholder="Edited file rhodecode/websetup.py via RhodeCode"></textarea>
744 744 </div>
745 745 </div>
746 746
747 747
748 748
749 749
750 750
751 751
752 752 <!--
753 753 Commit with comments
754 754 -->
755 755
756 756 <h2>Commit with comments</h2>
757 757
758 758 <div class="diff-container" id="diff-container-140360037209920">
759 759 <div id="c-4e5ee86997c6-7046e4320b26_target"></div>
760 760 <div id="c-4e5ee86997c6-7046e4320b26" class="diffblock margined comm">
761 761 <div class="code-header">
762 762 <div title="Go back to changed files overview">
763 763 <a href="#changes_box">
764 764 <i class="icon-circle-arrow-up"></i>
765 765 </a>
766 766 </div>
767 767 <div class="changeset_header">
768 768 <div class="changeset_file">
769 769 <i class="icon-file"></i>
770 770 <a href="/andersonsantos/rhodecode-dev-fork/files/4e5ee86997c64981d85cf62283af448624e26929/rhodecode/tests/functional/test_compare_local.py">rhodecode/tests/functional/test_compare_local.py</a>
771 771 </div>
772 772 <div class="diff-actions">
773 773 <a href="/andersonsantos/rhodecode-dev-fork/diff/rhodecode/tests/functional/test_compare_local.py?fulldiff=1&amp;diff1=682135c2e3958d7c84db06d716efe482bd3ce7c6&amp;diff=diff&amp;diff2=4e5ee86997c64981d85cf62283af448624e26929" class="tooltip" title="Show full diff for this file">
774 774 <img class="icon" src="/images/icons/page_white_go.png">
775 775 </a>
776 776 <a href="/andersonsantos/rhodecode-dev-fork/diff-2way/rhodecode/tests/functional/test_compare_local.py?fulldiff=1&amp;diff1=682135c2e3958d7c84db06d716efe482bd3ce7c6&amp;diff=diff&amp;diff2=4e5ee86997c64981d85cf62283af448624e26929" class="tooltip" title="Show full side-by-side diff for this file">
777 777 <img class="icon" src="/images/icons/application_double.png">
778 778 </a>
779 779 <a href="/andersonsantos/rhodecode-dev-fork/diff/rhodecode/tests/functional/test_compare_local.py?diff1=682135c2e3958d7c84db06d716efe482bd3ce7c6&amp;diff=raw&amp;diff2=4e5ee86997c64981d85cf62283af448624e26929" class="tooltip" title="Raw diff">
780 780 <img class="icon" src="/images/icons/page_white.png">
781 781 </a>
782 782 <a href="/andersonsantos/rhodecode-dev-fork/diff/rhodecode/tests/functional/test_compare_local.py?diff1=682135c2e3958d7c84db06d716efe482bd3ce7c6&amp;diff=download&amp;diff2=4e5ee86997c64981d85cf62283af448624e26929" class="tooltip" title="Download diff">
783 783 <img class="icon" src="/images/icons/page_save.png">
784 784 </a>
785 785 <a class="tooltip" href="/andersonsantos/rhodecode-dev-fork/changeset/4e5ee86997c64981d85cf62283af448624e26929?c-4e5ee86997c6-7046e4320b26=WS%3A1&amp;c-4e5ee86997c6-7046e4320b26=C%3A3#c-4e5ee86997c6-7046e4320b26" title="Ignore white space"><img alt="Ignore white space" class="icon" src="/images/icons/text_strikethrough.png"></a>
786 786 <a class="tooltip" href="/andersonsantos/rhodecode-dev-fork/changeset/4e5ee86997c64981d85cf62283af448624e26929?c-4e5ee86997c6-7046e4320b26=C%3A6#c-4e5ee86997c6-7046e4320b26" title="increase diff context to 6 lines"><img alt="increase diff context to 6 lines" class="icon" src="/images/icons/table_add.png"></a>
787 787 </div>
788 788 <span>
789 789 <label>
790 790 Show inline comments
791 791 <input checked="checked" class="show-inline-comments" id="" id_for="c-4e5ee86997c6-7046e4320b26" name="" type="checkbox" value="1">
792 792 </label>
793 793 </span>
794 794 </div>
795 795 </div>
796 796 <div class="code-body">
797 797 <div class="full_f_path" path="rhodecode/tests/functional/test_compare_local.py"></div>
798 798 <table class="code-difftable">
799 799 <tbody><tr class="line context">
800 800 <td class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o...">...</a></td>
801 801 <td class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n...">...</a></td>
802 802 <td class="code ">
803 803 <pre>@@ -59,7 +59,7 @@
804 804 </pre>
805 805 </td>
806 806 </tr>
807 807 <tr class="line unmod">
808 808 <td id="rhodecodetestsfunctionaltest_compare_localpy_o59" class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o59">59</a></td>
809 809 <td id="rhodecodetestsfunctionaltest_compare_localpy_n59" class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n59">59</a></td>
810 810 <td class="code ">
811 811 <pre> 'tag': 'v0.2.0',
812 812 </pre>
813 813 </td>
814 814 </tr>
815 815 <tr class="line unmod">
816 816 <td id="rhodecodetestsfunctionaltest_compare_localpy_o60" class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o60">60</a></td>
817 817 <td id="rhodecodetestsfunctionaltest_compare_localpy_n60" class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n60">60</a></td>
818 818 <td class="code ">
819 819 <pre> 'branch': 'default',
820 820 </pre>
821 821 </td>
822 822 </tr>
823 823 <tr class="line unmod">
824 824 <td id="rhodecodetestsfunctionaltest_compare_localpy_o61" class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o61">61</a></td>
825 825 <td id="rhodecodetestsfunctionaltest_compare_localpy_n61" class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n61">61</a></td>
826 826 <td class="code ">
827 827 <pre> 'response': # Intentionally long line to show what will happen if this line does not fit onto the screen. It might have some horizontal scrolling applied or some other fancy mechanism to deal with it.
828 828 </pre>
829 829 </td>
830 830 </tr>
831 831 <tr class="line del">
832 832 <td id="rhodecodetestsfunctionaltest_compare_localpy_o62" class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o62">62</a></td>
833 833 <td class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n"></a></td>
834 834 <td class="code ">
835 835 <pre> '147 files changed: 5700 inserted, 10176 deleted'
836 836 </pre>
837 837 </td>
838 838 </tr>
839 839 <tr class="line add">
840 840 <td class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o"></a></td>
841 841 <td id="rhodecodetestsfunctionaltest_compare_localpy_n62" class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n62">62</a></td>
842 842 <td class="code ">
843 843 <pre><ins> </ins> '147 files changed: 5700 inserted, 10176 deleted'
844 844 </pre>
845 845 </td>
846 846 </tr>
847 847 <tr class="line unmod">
848 848 <td id="rhodecodetestsfunctionaltest_compare_localpy_o63" class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o63">63</a></td>
849 849 <td id="rhodecodetestsfunctionaltest_compare_localpy_n63" class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n63">63</a></td>
850 850 <td class="code ">
851 851 <pre> },
852 852 </pre>
853 853 </td>
854 854 </tr>
855 855 <tr class="line unmod">
856 856 <td id="rhodecodetestsfunctionaltest_compare_localpy_o64" class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o64">64</a></td>
857 857 <td id="rhodecodetestsfunctionaltest_compare_localpy_n64" class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n64">64</a></td>
858 858 <td class="code ">
859 859 <pre> 'git': {
860 860 </pre>
861 861 </td>
862 862 </tr>
863 863 <tr class="line unmod">
864 864 <td id="rhodecodetestsfunctionaltest_compare_localpy_o65" class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o65">65</a></td>
865 865 <td id="rhodecodetestsfunctionaltest_compare_localpy_n65" class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n65">65</a></td>
866 866 <td class="code ">
867 867 <pre> 'tag': 'v0.2.2',
868 868 </pre>
869 869 </td>
870 870 </tr>
871 871 <tr class="line context">
872 872 <td class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o...">...</a></td>
873 873 <td class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n...">...</a></td>
874 874 <td class="code ">
875 875 <pre>@@ -77,9 +77,11 @@
876 876 </pre>
877 877 </td>
878 878 </tr>
879 879 <tr class="line unmod">
880 880 <td id="rhodecodetestsfunctionaltest_compare_localpy_o77" class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o77">77</a></td>
881 881 <td id="rhodecodetestsfunctionaltest_compare_localpy_n77" class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n77">77</a></td>
882 882 <td class="code ">
883 883 <pre> target_ref=revisions[backend.alias]['tag'],
884 884 </pre>
885 885 </td>
886 886 </tr>
887 887 <tr class="line unmod">
888 888 <td id="rhodecodetestsfunctionaltest_compare_localpy_o78" class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o78">78</a></td>
889 889 <td id="rhodecodetestsfunctionaltest_compare_localpy_n78" class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n78">78</a></td>
890 890 <td class="code ">
891 891 <pre> ))
892 892 </pre>
893 893 </td>
894 894 </tr><tr id="comment-tr-3754" class="inline-comments"><td></td><td></td><td>
895 895
896 896 <div class="comment" id="comment-3754" line="n78">
897 897 <div class="comment-wrapp">
898 898 <div class="meta">
899 899 <span class="gravatar">
900 900 <img src="https://secure.gravatar.com/avatar/72706ebd30734451af9ff3fb59f05ff1?d=identicon&amp;s=40" height="20" width="20">
901 901 </span>
902 902 <span class="user">
903 903 anderson
904 904 </span>
905 905 <span class="date">
906 906 just now |
907 907 </span>
908 908 <span class="status-change">
909 909 Comment on commit
910 910 </span>
911 911 <a class="permalink" href="#comment-3754">ΒΆ</a>
912 912 </div>
913 913 <div class="text">
914 914 <div class="rst-block"><p>commented line
915 915 with multiple lines</p>
916 916 </div>
917 917 </div>
918 918 </div>
919 919 </div><div class="add-comment"><span class="btn btn-default">Add another comment</span></div>
920 920
921 921 </td></tr>
922 922 <tr class="line unmod">
923 923 <td id="rhodecodetestsfunctionaltest_compare_localpy_o79" class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o79">79</a></td>
924 924 <td id="rhodecodetestsfunctionaltest_compare_localpy_n79" class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n79">79</a></td>
925 925 <td class="code ">
926 926 <pre></pre>
927 927 </td>
928 928 </tr>
929 929 <tr class="line del form-open hl-comment">
930 930 <td id="rhodecodetestsfunctionaltest_compare_localpy_o80" class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o80">80</a></td>
931 931 <td class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n"></a></td>
932 932 <td class="code ">
933 933 <pre> response.mustcontain('%s@%s' % (<del>backend.repo_name,</del>
934 934 </pre>
935 935 </td>
936 936 </tr><tr id="comment-tr-undefined" class="comment-form-inline"><td></td><td></td><td>
937 937 <div class="comment-inline-form ac">
938 938 <div class="overlay"><div class="overlay-text">Submitting...</div></div>
939 939 <form action="#" class="inline-form" method="get">
940 940 <div id="edit-container_o80" class="clearfix">
941 941 <div class="comment-title pull-left">
942 942 Commenting on line o80.
943 943 </div>
944 944 <div class="comment-help pull-right">
945 945 Comments parsed using <a href="http://docutils.sourceforge.net/docs/user/rst/quickref.html">RST</a> syntax with <span class="tooltip" title="Use @username inside this text to send notification to this RhodeCode user">@mention</span> support.
946 946 </div>
947 947 <div style="clear: both"></div>
948 948 <textarea id="text_o80" name="text" class="comment-block-ta ac-input" autocomplete="off"></textarea>
949 949 </div>
950 950 <div id="preview-container_o80" class="clearfix" style="display: none;">
951 951 <div class="comment-help">
952 952 Comment preview
953 953 </div>
954 954 <div id="preview-box_o80" class="preview-box"></div>
955 955 </div>
956 956 <div class="comment-button pull-right">
957 957 <input type="hidden" name="f_path" value="rhodecode/tests/functional/test_compare_local.py">
958 958 <input type="hidden" name="line" value="o80">
959 959 <div id="preview-btn_o80" class="btn btn-default">Preview</div>
960 960 <div id="edit-btn_o80" class="btn" style="display: none;">Edit</div>
961 961 <input class="btn btn-success save-inline-form" id="save" name="save" type="submit" value="Comment">
962 962 </div>
963 963 <div class="comment-button hide-inline-form-button">
964 964 <input class="btn hide-inline-form" id="hide-inline-form" name="hide-inline-form" type="reset" value="Cancel">
965 965 </div>
966 966 </form>
967 967 </div>
968 968 </td></tr>
969 969 <tr class="line add">
970 970 <td class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o"></a></td>
971 971 <td id="rhodecodetestsfunctionaltest_compare_localpy_n80" class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n80">80</a></td>
972 972 <td class="code ">
973 973 <pre> response.mustcontain('%s@%s' % (
974 974 </pre>
975 975 </td>
976 976 </tr>
977 977 <tr class="line add">
978 978 <td class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o"></a></td>
979 979 <td id="rhodecodetestsfunctionaltest_compare_localpy_n81" class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n81">81</a></td>
980 980 <td class="code ">
981 981 <pre> backend.repo_name,
982 982 </pre>
983 983 </td>
984 984 </tr>
985 985 <tr class="line unmod">
986 986 <td id="rhodecodetestsfunctionaltest_compare_localpy_o81" class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o81">81</a></td>
987 987 <td id="rhodecodetestsfunctionaltest_compare_localpy_n82" class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n82">82</a></td>
988 988 <td class="code ">
989 989 <pre> revisions[backend.alias]['branch']))
990 990 </pre>
991 991 </td>
992 992 </tr>
993 993 <tr class="line del">
994 994 <td id="rhodecodetestsfunctionaltest_compare_localpy_o82" class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o82">82</a></td>
995 995 <td class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n"></a></td>
996 996 <td class="code ">
997 997 <pre> response.mustcontain('%s@%s' % (<del>backend.repo_name,</del>
998 998 </pre>
999 999 </td>
1000 1000 </tr>
1001 1001 <tr class="line add">
1002 1002 <td class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o"></a></td>
1003 1003 <td id="rhodecodetestsfunctionaltest_compare_localpy_n83" class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n83">83</a></td>
1004 1004 <td class="code ">
1005 1005 <pre> response.mustcontain('%s@%s' % (
1006 1006 </pre>
1007 1007 </td>
1008 1008 </tr>
1009 1009 <tr class="line add">
1010 1010 <td class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o"></a></td>
1011 1011 <td id="rhodecodetestsfunctionaltest_compare_localpy_n84" class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n84">84</a></td>
1012 1012 <td class="code ">
1013 1013 <pre> backend.repo_name,
1014 1014 </pre>
1015 1015 </td>
1016 1016 </tr>
1017 1017 <tr class="line unmod">
1018 1018 <td id="rhodecodetestsfunctionaltest_compare_localpy_o83" class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o83">83</a></td>
1019 1019 <td id="rhodecodetestsfunctionaltest_compare_localpy_n85" class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n85">85</a></td>
1020 1020 <td class="code ">
1021 1021 <pre> revisions[backend.alias]['tag']))
1022 1022 </pre>
1023 1023 </td>
1024 1024 </tr>
1025 1025 <tr class="line unmod">
1026 1026 <td id="rhodecodetestsfunctionaltest_compare_localpy_o84" class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o84">84</a></td>
1027 1027 <td id="rhodecodetestsfunctionaltest_compare_localpy_n86" class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n86">86</a></td>
1028 1028 <td class="code ">
1029 1029 <pre> response.mustcontain(revisions[backend.alias]['response'])
1030 1030 </pre>
1031 1031 </td>
1032 1032 </tr>
1033 1033 <tr class="line unmod">
1034 1034 <td id="rhodecodetestsfunctionaltest_compare_localpy_o85" class="lineno old"><a href="#rhodecodetestsfunctionaltest_compare_localpy_o85">85</a></td>
1035 1035 <td id="rhodecodetestsfunctionaltest_compare_localpy_n87" class="lineno new"><a href="#rhodecodetestsfunctionaltest_compare_localpy_n87">87</a></td>
1036 1036 <td class="code ">
1037 1037 <pre></pre>
1038 1038 </td>
1039 1039 </tr>
1040 1040 </tbody></table>
1041 1041 </div>
1042 1042 </div>
1043 1043 </div>
1044 1044
1045 1045
1046 1046
1047 1047 <!--
1048 1048 Side-by-side diff
1049 1049 -->
1050 1050
1051 1051 <h2>Side-by-side diff</h2>
1052 1052
1053 1053 <div class="box">
1054 1054 <div class="diff-container" style="overflow-x: hidden">
1055 1055 <div class="diffblock comm" style="margin:3px; padding:1px">
1056 1056 <div class="code-header">
1057 1057 <div class="changeset_header">
1058 1058 <div class="changeset_file">
1059 1059 <i class="icon-file"></i>
1060 1060 <a href="/pygments/files/ea295cfb622620f5ba13e226ec531e3fe5296399/tests/test_basic_api.py">tests/test_basic_api.py</a>
1061 1061 [mode: <span id="selected_mode">python</span>]
1062 1062 </div>
1063 1063 <div class="diff-actions">
1064 1064 <a href="/pygments/diff/tests/test_basic_api.py?diff2=ea295cfb622620f5ba13e226ec531e3fe5296399&amp;diff=diff&amp;diff1=de45f950b669e2d991c4ba512fa6fe450c6616db&amp;fulldiff=1" class="tooltip" title="Show full diff for this file">
1065 1065 <img class="icon" src="/images/icons/page_white_go.png">
1066 1066 </a>
1067 1067 <a href="/pygments/diff-2way/tests/test_basic_api.py?diff2=ea295cfb622620f5ba13e226ec531e3fe5296399&amp;diff=diff&amp;diff1=de45f950b669e2d991c4ba512fa6fe450c6616db&amp;fulldiff=1" class="tooltip" title="Show full side-by-side diff for this file" tt_title="Show full side-by-side diff for this file">
1068 1068 <img class="icon" src="/images/icons/application_double.png">
1069 1069 </a>
1070 1070 <a href="/pygments/diff/tests/test_basic_api.py?diff2=ea295cfb622620f5ba13e226ec531e3fe5296399&amp;diff1=de45f950b669e2d991c4ba512fa6fe450c6616db&amp;diff=raw" class="tooltip" title="Raw diff">
1071 1071 <img class="icon" src="/images/icons/page_white.png">
1072 1072 </a>
1073 1073 <a href="/pygments/diff/tests/test_basic_api.py?diff2=ea295cfb622620f5ba13e226ec531e3fe5296399&amp;diff1=de45f950b669e2d991c4ba512fa6fe450c6616db&amp;diff=download" class="tooltip" title="Download diff">
1074 1074 <img class="icon" src="/images/icons/page_save.png">
1075 1075 </a>
1076 1076 <label><input id="ignorews" name="ignorews" type="checkbox" value="1">ignore white space</label>
1077 1077 <label><input id="edit_mode" name="edit_mode" type="checkbox" value="1">turn on edit mode</label>
1078 1078
1079 1079 </div>
1080 1080 <div style="float: right; padding: 0px 10px 0px 0px">
1081 1081 r1538:de45f950b669 ... r1539:ea295cfb6226
1082 1082 </div>
1083 1083 </div>
1084 1084 </div>
1085 1085 <div id="compare"></div>
1086 1086 </div>
1087 1087 </div>
1088 1088
1089 1089 <script>
1090 1090 $(document).ready(function () {
1091 1091 var example_lines = '1\n2\n3\n4\n5\n6\n7\n8\n9\n \n';
1092 1092
1093 1093 $('#compare').mergely({
1094 1094 width: 'auto',
1095 1095 height: '600',
1096 1096 fgcolor: {a:'#ddffdd',c:'#cccccc',d:'#ffdddd'},
1097 1097 bgcolor: '#fff',
1098 1098 viewport: true,
1099 1099 cmsettings: {mode: 'text/plain', readOnly: true, lineWrapping: false, lineNumbers: true},
1100 1100 lhs: function(setValue) {
1101 1101 if("False" == "True"){
1102 1102 setValue('Binary file')
1103 1103 }
1104 1104 else if("MercurialCommit" == "EmptyCommit"){
1105 1105 setValue('');
1106 1106 }
1107 1107 else{
1108 1108 var left_value = example_lines.slice(0, 10) +
1109 1109 '123456789 '.repeat(10) +
1110 1110 '\n'+
1111 1111 example_lines.slice(10, 20);
1112 1112 setValue(left_value + example_lines.repeat(9));
1113 1113 }
1114 1114
1115 1115 },
1116 1116 rhs: function(setValue) {
1117 1117 if("False" == "True"){
1118 1118 setValue('Binary file')
1119 1119 }
1120 1120 else if("MercurialCommit" == "EmptyCommit"){
1121 1121 setValue('');
1122 1122 }
1123 1123 else{
1124 1124 var right_value = example_lines +
1125 1125 example_lines.slice(0, 8) +
1126 1126 'abcdefghi '.repeat(10) +
1127 1127 '\n'+
1128 1128 example_lines.slice(8, 20);
1129 1129 setValue(right_value + example_lines.repeat(9));
1130 1130 }
1131 1131 },
1132 1132 });
1133 1133
1134 1134 var detected_mode = detectCodeMirrorModeFromExt('test_basic_api.py', true);
1135 1135 if(detected_mode){
1136 1136 setCodeMirrorMode($('#compare').mergely('cm', 'lhs'), detected_mode);
1137 1137 setCodeMirrorMode($('#compare').mergely('cm', 'rhs'), detected_mode);
1138 1138 $('#selected_mode').html(detected_mode);
1139 1139 }
1140 1140
1141 1141 $('#ignorews').change(function(e){
1142 1142 var val = e.currentTarget.checked;
1143 1143 $('#compare').mergely('options', {ignorews: val});
1144 1144 $('#compare').mergely('update');
1145 1145 })
1146 1146 $('#edit_mode').change(function(e){
1147 1147 var val = !e.currentTarget.checked;
1148 1148 $('#compare').mergely('cm', 'lhs').setOption('readOnly', val);
1149 1149 $('#compare').mergely('cm', 'rhs').setOption('readOnly', val);
1150 1150 $('#compare').mergely('update');
1151 1151 })
1152 1152 });
1153 1153 </script>
1154 1154
1155 1155 </div>
1156 1156
1157 1157 <!-- end examples -->
1158 1158
1159 1159 </div>
1160 1160 </div>
1161 1161 </div>
1162 1162 </%def>
@@ -1,545 +1,545 b''
1 1 ## -*- coding: utf-8 -*-
2 2 <%inherit file="/debug_style/index.html"/>
3 3
4 4 <%def name="breadcrumbs_links()">
5 5 ${h.link_to(_('Style'), h.url('debug_style_home'))}
6 6 &raquo;
7 7 ${c.active}
8 8 </%def>
9 9
10 10
11 11 <%def name="real_main()">
12 12 <div class="box">
13 13 <div class="title">
14 14 ${self.breadcrumbs()}
15 15 </div>
16 16
17 17 <div class='sidebar-col-wrapper'>
18 18 ##main
19 19 ${self.sidebar()}
20 20
21 21 <div class="main-content">
22 22
23 23 <div style="opacity:.5">
24 24
25 25 <h2>Simple tables</h2>
26 26
27 27 <p>These styles will be adjusted later to provide a baseline style
28 28 for all tables without classes added, whether part of the
29 29 application or not. Currently, some of the
30 30 application-specific styles are applied to this table.</p>
31 31 <p>This is a baseline style for all tables, whether part of the
32 32 application or not. It has no class applied for styling. Use
33 33 the "rctable" class as outlined before for tables which are
34 34 part of the RhodeCode application.</p>
35 35 <table>
36 36 <tbody>
37 37 <tr>
38 38 <th>Header A</th>
39 39 <th>Header B</th>
40 40 <th>Header C</th>
41 41 <th>Header D</th>
42 42 </tr>
43 43 <tr>
44 44 <td>Content of col A</td>
45 45 <td>Content of col B</td>
46 46 <td>Content of col C</td>
47 47 <td>Content of col D</td>
48 48 </tr>
49 49 <tr>
50 50 <td>Content of col A</td>
51 51 <td>Content of col B</td>
52 52 <td>Content of col C</td>
53 53 <td>Content of col D</td>
54 54 </tr>
55 55 <tr>
56 56 <td>Content of col A</td>
57 57 <td>Content of col B</td>
58 58 <td>Content of col C</td>
59 59 <td>Content of col D</td>
60 60 </tr>
61 61 <tr>
62 62 <td>Content of col A</td>
63 63 <td>Content of col B</td>
64 64 <td>Content of col C</td>
65 65 <td>Content of col D</td>
66 66 </tr>
67 67 </tbody>
68 68 </table>
69 69 </div>
70 70
71 71
72 72
73 73
74 74 <h2>RC application table with examples</h2>
75 75
76 76 <p>This is a standard table which applies the rhodecode-specific styling to be used
77 77 throughout the application; it has <code>&lt;table class="rctable"&gt;</code>.
78 78 <br/>
79 79 By default, table data is not truncated, and wraps inside of the <code>&lt;td&gt
80 80 ;</code>. To prevent wrapping and contain data on one line, use the <code>&lt;
81 81 class="truncate-wrap"&gt;</code> on the <code>&lt;td&gt;</code>, and <code>span
82 82 class="truncate"</code> around the specific data to be truncated.
83 83 </p>
84 84 <p>
85 85 Ellipsis is added via CSS. Please always add a row of headers using <code>&lt;th
86 86 &gt;</code> to the top of a table.
87 87 </p>
88 88
89 89 ## TODO: johbo: in case we have more tables with examples, we should
90 90 ## create a generic class here.
91 91 <table class="rctable issuetracker">
92 92 <thead>
93 93 <tr>
94 94 <th>Header A</th>
95 95 <th>Header B</th>
96 96 <th>Header C</th>
97 97 <th>Header D</th>
98 98 </tr>
99 99 </thead>
100 100 <tbody>
101 101 <tr>
102 102 <td class="issue-tracker-example">
103 103 Example of col A
104 104 </td>
105 105 <td class="issue-tracker-example">
106 106 Example of col B
107 107 </td>
108 108 <td class="issue-tracker-example">
109 109 Example of col C
110 110 </td>
111 111 <td class="issue-tracker-example">
112 112 Example of col D
113 113 </td>
114 114 </tr>
115 115 <tr>
116 116 <td>Content of col A</td>
117 117 <td>Content of col B</td>
118 118 <td>Content of col C which is very long and will not be
119 119 truncated because sometimes people just want to write
120 120 really, really long commit messages which explain what
121 121 they did in excruciating detail and you really, really
122 122 want to read them.</td>
123 123 <td>Content of col D</td>
124 124 </tr>
125 125 <tr>
126 126 <td>Content of col A</td>
127 127 <td>Content of col B</td>
128 128 <td>Content of col C</td>
129 129 <td class="truncate-wrap"><span class="truncate">Truncated
130 130 content of column D truncate truncate truncatetruncate
131 131 truncate truncate</span></td>
132 132 </tr>
133 133 </tbody>
134 134 </table>
135 135
136 136 <h2>RC application table data classes</h2>
137 137
138 138 <p>The following tables contain documentation of all existing table data classes.
139 139 Please update when new classes are made.
140 140 </p>
141 141 <table class="rctable examples">
142 142 <thead>
143 143 <tr>
144 144 <th>Class</th>
145 145 <th>Description</th>
146 146 <th>Example</th>
147 147 </tr>
148 148 </thead>
149 149 <tbody>
150 150 <td>td-user</td>
151 151 <td>Any username/gravatar combination (see also Icons style).</td>
152 152 <td class="td-user author">
153 153 <img class="gravatar" alt="gravatar" src="https://secure.gravatar.com/avatar/0c9a7e6674b6f0b35d98dbe073e3f0ab?d=identicon&amp;s=32" height="16" width="16">
154 154 <span title="Oliver Strobel <oliver@rhodecode.com>" class="user">ostrobel (Oliver Strobel)</span>
155 155 </td>
156 156 </tr>
157 157 <tr>
158 158 <td>td-hash</td>
159 159 <td>Any hash; a commit, revision, etc. Use <code>&lt;pre&gt;</code> and header 'Commit'</td>
160 160 <td class="td-commit">
161 161 <pre><a href="/anothercpythonforkkkk/files/8d6b27837c6979983b037693fe975cdbb761b500/">r93699:8d6b27837c69</a></pre>
162 162 </td>
163 163 </tr>
164 164 <tr>
165 165 <td>td-rss</td>
166 166 <td>RSS feed link icon</td>
167 167 <td class="td-rss">
168 168 <a title="Subscribe to rss feed" href="/feed/rss"><i class="icon-rss-sign"></i></a>
169 169 </td>
170 170 </tr>
171 171 <tr>
172 172 <td>td-componentname</td>
173 173 <td>Any group, file, gist, or directory name.</td>
174 174 <td class="td-componentname">
175 175 <a href="/cpythonfork">
176 176 <span title="Mercurial repository"><i class="icon-hg"></i></span>
177 177 <i class="icon-unlock-alt" title="Public repository"></i>
178 178 rhodecode-dev-restyle-fork
179 179 </a>
180 180 </td>
181 181 </tr>
182 182 <tr>
183 183 <td>td-tags</td>
184 184 <td>Any cell containing tags, including branches and bookmarks.</td>
185 185 <td class="td-tags">
186 186 <span class="branchtag tag" title="Branch default">
187 187 <a href="/rhodecode-dev-restyle- fork/changelog?branch=default"><i class="icon-code-fork"></i>default</a>
188 188 </span>
189 189 </td>
190 190 </tr>
191 191 <tr>
192 192 <td>tags-truncate</td>
193 193 <td>Used to truncate a cell containing tags; avoid if possible.</td>
194 194 <td class="td-tags truncate-wrap">
195 195 <div class="truncate tags-truncate">
196 196 <div class="autoexpand">
197 197 <span class="tagtag tag" title="Tag tip">
198 198 <a href="/rhodecode-dev-restyle-fork/files/e519d5a0e71466d27257ddff921c4a13c540408e/"><i class="icon-tag"></i>tip</a>
199 199 </span>
200 200 <span class="branchtag tag" title="Branch default">
201 201 <a href="/rhodecode-dev-restyle-fork/changelog?branch=default"><i class="icon-code-fork"></i>default</a>
202 202 </span>
203 203 <span class="branchtag tag" title="Branch default">
204 204 <a href="/rhodecode-dev-restyle-fork/changelog?branch=default"><i class="icon-code-fork"></i>default</a>
205 205 </span>
206 206 </div>
207 207 </div>
208 208 </td>
209 209 </tr>
210 210 <tr>
211 211 <td>td-ip</td>
212 212 <td>Any ip address.</td>
213 213 <td class="td-ip">
214 214 172.16.115.168
215 215 </td>
216 216 </tr>
217 217 <tr>
218 218 <td>td-type</td>
219 219 <td>A state or an auth type.</td>
220 220 <td class="td-type">
221 221 rhodecode
222 222 </td>
223 223 </tr>
224 224 <tr>
225 225 <td>td-authtoken</td>
226 226 <td>For auth tokens. Use truncate classes for hover expand; see html.</td>
227 227 <td class="truncate-wrap td-authtoken">
228 228 <div class="truncate autoexpand">
229 229 <code>688df65b87d3ad16ae9f8fc6338a551d40f41c7a</code>
230 230 </div>
231 231 </td>
232 232 </tr>
233 233 <tr>
234 234 <td>td-action</td>
235 235 <td>Buttons which perform an action.</td>
236 236 <td class="td-action">
237 237 <div class="grid_edit">
238 238 <a href="/_admin/users/2/edit" title="edit">
239 239 <i class="icon-pencil"></i>Edit</a>
240 240 </div>
241 241 <div class="grid_delete">
242 242 <form action="/_admin/users/2" method="post">
243 243 <i class="icon-remove-sign"></i>
244 244 <input class="btn btn-danger btn-link" id="remove_user_2" name="remove_" type="submit" value="delete">
245 245 </form>
246 246 </div>
247 247 </td>
248 248 </tr>
249 249 <tr>
250 250 <td>td-radio</td>
251 251 <td>Radio buttons for a form. Centers element.</td>
252 252 <td class="td-radio">
253 253 <input type="radio" checked="checked" value="" name="1" id="read"></td>
254 254 </tr>
255 255 <tr>
256 256 <td>td-checkbox</td>
257 257 <td>Checkbox for a form. Centers element.</td>
258 258 <td class="td-checkbox">
259 259 <input type="checkbox" checked="checked" value="" name="1" id="read"></td>
260 260 </tr>
261 261 <tr>
262 262 <tr>
263 263 <td>td-buttons</td>
264 264 <td>Buttons.</td>
265 265 <td class="td-buttons">
266 266 <span class="btn btn-mini btn-primary">feed access</span>
267 267 </td>
268 268 </tr>
269 269 <tr>
270 270 <td>td-compare</td>
271 271 <td>Radio buttons to compare commits.</td>
272 272 <td class=" td-compare">
273 273 <input class="compare-radio-button" type="radio" name="compare_source" value="2.0">
274 274 <input class="compare-radio-button" type="radio" name="compare_target" value="2.0">
275 275 </td>
276 276 </tr>
277 277 <tr>
278 278 <td>td-comments</td>
279 279 <td>Comments indicator icon.</td>
280 280 <td>
281 281 <i class="icon-comment icon-comment-colored"></i> 0
282 282 </td>
283 283 </tr>
284 284 <tr>
285 285 <td>td-status</td>
286 286 <td>Status indicator icon.</td>
287 287 <td class="td-description">
288 288 <div class="flag_status under_review pull-left"></div>
289 289 </td>
290 290 </tr>
291 291 </tbody>
292 292 </table>
293 293 <table class="dataTable rctable examples">
294 294 <tbody>
295 295 <tr>
296 296 <td>quick_repo_menu</td>
297 297 <td>Hidden menu generated by dataTable.</td>
298 298 <td class="quick_repo_menu">
299 299 <i class="pointer icon-more"></i>
300 300 <div class="menu_items_container" style="display: none;">
301 301 <ul class="menu_items">
302 302 <li>
303 303 <a title="Summary" href="/anothercpythonforkkkk-fork">
304 304 <span>Summary</span>
305 305 </a>
306 306 </li>
307 307 <li>
308 308 <a title="Changelog" href="/anothercpythonforkkkk-fork/changelog">
309 309 <span>Changelog</span>
310 310 </a>
311 311 </li>
312 312 <li>
313 313 <a title="Files" href="/anothercpythonforkkkk-fork/files/tip/">
314 314 <span>Files</span>
315 315 </a>
316 316 </li>
317 317 <li>
318 318 <a title="Fork" href="/anothercpythonforkkkk-fork/fork">
319 319 <span>Fork</span>
320 320 </a>
321 321 </li>
322 322 </ul>
323 323 </div>
324 324 </td>
325 325 <td></td>
326 326 </tr>
327 327 </tbody>
328 328 </table>
329 329 <script>quick_repo_menu();</script>
330 330 <table class="rctable examples">
331 331 <tbody>
332 332 <tr>
333 333 <td>td-description</td>
334 334 <td>Any description. They may be rather long, and using the expand_commit outlined below is recommended.</td>
335 335 <td class="td-description">
336 336 Ultrices mattis! Enim pellentesque lacus, sit magna natoque risus turpis ut, auctor ultrices facilisis dapibus odio? Parturient! Porta egestas nascetur, quis, elementum dolor, in magna ac dis sit etiam turpis, scelerisque! Integer tristique aliquam.
337 337 </td>
338 338 </tr>
339 339 </tbody>
340 340 </table>
341 341 <table id="changesets" class="rctable examples end">
342 342 <tbody>
343 343 <tr>
344 344 <td>expand_commit</td>
345 345 <td>Expands a long message; see html+js.</td>
346 346 <td class="expand_commit" data-commit-id="2ffc6faabc7a9c790b1b452943a3f0c047b8b436" title="Expand commit message">
347 347 <div class="show_more_col">
348 348 <i class="show_more"></i>
349 349 </div>
350 350 </td>
351 351 <td class="mid td-description">
352 352 <div class="log-container truncate-wrap">
353 353 <div id="c-2ffc6faabc7a9c790b1b452943a3f0c047b8b436" class="message truncate" data-message-raw="tests: Test echo method on the server object
354 354
355 355 This only works for Pyro4 so far, have to extend it still for HTTP to work.">tests: Test echo method on the server object
356 356
357 357 This only works for Pyro4 so far, have to extend it still for HTTP to work.</div>
358 358 </div>
359 359 </td>
360 360 </tr>
361 361 </tbody>
362 362 </table>
363 363 <script type="text/javascript">
364 364 var cache = {}
365 365 $('.expand_commit').on('click',function(e){
366 366 var target_expand = $(this);
367 367 var cid = target_expand.data('commitId');
368 368
369 369 if (target_expand.hasClass('open')){
370 370 $('#c-'+cid).css({'height': '1.5em', 'white-space': 'nowrap', 'text-overflow': 'ellipsis', 'overflow':'hidden'});
371 371 $('#t-'+cid).css({'height': '1.5em', 'max-height': '1.5em', 'text-overflow': 'ellipsis', 'overflow':'hidden', 'white-space':'nowrap'});
372 372 target_expand.removeClass('open');
373 373 }
374 374 else {
375 375 $('#c-'+cid).css({'height': 'auto', 'white-space': 'pre-line', 'text-overflow': 'initial', 'overflow':'visible'});
376 376 $('#t-'+cid).css({'height': 'auto', 'max-height': 'none', 'text-overflow': 'initial', 'overflow':'visible', 'white-space':'normal'});
377 377 target_expand.addClass('open');
378 378 }
379 379 });
380 380
381 381 </script>
382 382 <p>The following classes currently do not have unique styles applied.</p>
383 383 <table class="rctable examples end">
384 384 <tbody>
385 385 <tr>
386 386 <td>td-regex</td>
387 387 <td>Regex patterns</td>
388 388 <td class="td-regex">(?:#)(?P<issue_id>\d+)</td>
389 389 </tr>
390 390 <tr>
391 391 <td>td-url</td>
392 392 <td>Any URL.</td>
393 393 <td class="td-url">https://rhodecode.com</td>
394 394 </tr>
395 395 <tr>
396 396 <td>td-journalaction</td>
397 397 <td>Action listed in a journal</td>
398 398 <td class="td-journalaction">started following repository supervisor-fork-4</td>
399 399 </tr>
400 400 <tr>
401 401 <td>td-iprange</td>
402 402 <td>Any ip address.</td>
403 403 <td class="td-ip">127.0.0.1-127.0.0.10</td>
404 404 </tr>
405 405 <tr>
406 406 <td>td-exp</td>
407 407 <td>Expiration time.</td>
408 408 <td class="td-exp">never</td>
409 409 </tr>
410 410 <tr>
411 411 <td>td-prefix</td>
412 412 <td>Prefixes outlined in settings.</td>
413 413 <td class="td-prefix">ubuntu-92539</td>
414 414 </tr>
415 415 <tr>
416 416 <td>td-cachekey</td>
417 417 <td>Cache key value.</td>
418 418 <td class="td-cachekey">ubuntu-92539supervisor</td>
419 419 </tr>
420 420 <tr>
421 421 <td>td-email</td>
422 422 <td>Any email address.</td>
423 423 <td class="td-email">example@rhodecode.com</td>
424 424 </tr>
425 425 <tr>
426 426 <td>td-active</td>
427 427 <td>Shows active state with icon-true/icon-false.</td>
428 428 <td class="td-active"><i class="icon-false"></i></td>
429 429 </tr>
430 430 <tr>
431 431 <td>td-size</td>
432 432 <td>File, repo, or directory size.</td>
433 433 <td class="td-size">89 MB</td>
434 434 </tr>
435 435 <tr>
436 436 <td>td-number</td>
437 437 <td>Any numerical data.</td>
438 438 <td class="td-number">42</td>
439 439 </tr>
440 440 <tr>
441 441 <td>td-message</td>
442 442 <td>Any commit message. Often treated with the truncate class used for descriptions as well.</td>
443 443 <td class="td-message">Updated the files</td>
444 444 </tr>
445 445 </tbody>
446 446 </table>
447 447
448 448
449 449 <h2>Permissions table</h2>
450 450
451 451 <p>
452 452 This is a special-case table; it has
453 453 <code>table class="rctable permissions"</code>
454 454 where "rctable" applies the rhodecode styling as above, and
455 455 "permissions" adds an extra layer of customization specific to
456 456 permissions tables. Other special-case tables may exist or be
457 457 created if necessary.
458 458 </p>
459 459
460 460 <table class="rctable permissions">
461 461 <tr>
462 462 <th class="td-radio">none</th>
463 463 <th class="td-radio">read</th>
464 464 <th class="td-radio">write</th>
465 465 <th class="td-radio">admin</th>
466 466 <th>user/user group</th>
467 467 <th></th>
468 468 </tr>
469 469 <tr class="perm_admin_row">
470 470 <td class="td-radio"><input type="radio" value="repository.none"
471 471 name="admin_perm_2" id="admin_perm_2_repositorynone"
472 472 disabled="disabled"></td>
473 473 <td class="td-radio"><input type="radio" value="repository.read"
474 474 name="admin_perm_2" id="admin_perm_2_repositoryread"
475 475 disabled="disabled"></td>
476 476 <td class="td-radio"><input type="radio" value="repository.write"
477 477 name="admin_perm_2" id="admin_perm_2_repositorywrite"
478 478 disabled="disabled"></td>
479 479 <td class="td-radio"><input type="radio" value="repository.admin"
480 480 name="admin_perm_2" id="admin_perm_2_repositoryadmin"
481 481 disabled="disabled" checked="checked"></td>
482 482 <td>
483 483 <img class="gravatar" src="https://secure.gravatar.com/avatar/be9d18f611892a738e54f2a3a171e2f9?d=identicon&amp;s=32" height="16" width="16">
484 484 <span class="user">dev (super admin) (owner)</span>
485 485 </td>
486 486 <td></td>
487 487 </tr>
488 488 <tr>
489 489 <td colspan="4">
490 490 <span class="private_repo_msg">
491 491 private repository
492 492 </span>
493 493 </td>
494 494 <td class="private_repo_msg">
495 495 <i class="icon-user"></i>
496 496 default - only people explicitly added here will have access</td>
497 497 <td></td>
498 498 </tr>
499 499 <tr>
500 500 <td class="td-radio"><input type="radio" value="repository.none"
501 501 name="u_perm_1" id="u_perm_1_repositorynone"></td>
502 502 <td class="td-radio"><input type="radio" checked="checked"
503 503 value="repository.read" name="u_perm_1"
504 504 id="u_perm_1_repositoryread"></td>
505 505 <td class="td-radio"><input type="radio" value="repository.write"
506 506 name="u_perm_1" id="u_perm_1_repositorywrite"></td>
507 507 <td class="td-radio"><input type="radio" value="repository.admin"
508 508 name="u_perm_1" id="u_perm_1_repositoryadmin"></td>
509 509 <td>
510 <img class="gravatar" src="/images/user30.png" height="16" width="16">
510 <img class="gravatar" src="/_static/images/user30.png" height="16" width="16">
511 511 <span class="user">default</span>
512 512 </td>
513 513 <td></td>
514 514 </tr>
515 515 <tr>
516 516 <td class="td-radio"><input type="radio" value="repository.none"
517 517 name="u_perm_2" id="u_perm_2_repositorynone"></td>
518 518 <td class="td-radio"><input type="radio" checked="checked"
519 519 value="repository.read" name="u_perm_2"
520 520 id="u_perm_2_repositoryread"></td>
521 521 <td class="td-radio"><input type="radio" value="repository.write"
522 522 name="u_perm_2" id="u_perm_2_repositorywrite"></td>
523 523 <td class="td-radio"><input type="radio" value="repository.admin"
524 524 name="u_perm_2" id="u_perm_2_repositoryadmin"></td>
525 525 <td>
526 526 <img class="gravatar" src="https://secure.gravatar.com/avatar/be9d18f611892a738e54f2a3a171e2f9?d=identicon&amp;s=32" height="16" width="16">
527 527 <a class="user" href="/_admin/users/2/edit">dev</a>
528 528 </td>
529 529 <td>
530 530 <span member_type="user" member="2"
531 531 class="btn action_button btn-link btn-danger">revoke</span>
532 532 </td>
533 533 </tr>
534 534 </tbody>
535 535 </table>
536 536 <div class="link" id="add_perm">
537 537 Add new
538 538 </div>
539 539
540 540
541 541
542 542 </div>
543 543 </div>
544 544 </div>
545 545 </%def>
@@ -1,64 +1,64 b''
1 1 ## -*- coding: utf-8 -*-
2 2 <!DOCTYPE html>
3 3 <html xmlns="http://www.w3.org/1999/xhtml">
4 4 <head>
5 5 <title>Error - ${c.error_message}</title>
6 6 <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
7 7 <meta name="robots" content="index, nofollow"/>
8 <link rel="icon" href="${h.url('/images/favicon.ico')}" sizes="16x16 32x32" type="image/png" />
8 <link rel="icon" href="${h.asset('images/favicon.ico')}" sizes="16x16 32x32" type="image/png" />
9 9
10 10
11 11 <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
12 12 %if c.redirect_time:
13 13 <meta http-equiv="refresh" content="${c.redirect_time}; url=${c.url_redirect}"/>
14 14 %endif
15 15
16 <link rel="stylesheet" type="text/css" href="${h.url('/css/style.css')}" media="screen"/>
16 <link rel="stylesheet" type="text/css" href="${h.asset('css/style.css')}" media="screen"/>
17 17 <!--[if IE]>
18 <link rel="stylesheet" type="text/css" href="${h.url('/css/ie.css')}" media="screen"/>
18 <link rel="stylesheet" type="text/css" href="${h.asset('css/ie.css')}" media="screen"/>
19 19 <![endif]-->
20 20 <style>body { background:#eeeeee; }</style>
21 21
22 <script type="text/javascript" src="${h.url('/js/scripts.js')}"></script>
22 <script type="text/javascript" src="${h.asset('js/scripts.js')}"></script>
23 23 </head>
24 24 <body>
25 25 <%include file="/base/flash_msg.html"/>
26 26
27 27 <div class="wrapper error_page">
28 28 <div class="sidebar">
29 <a href="${h.url('home')}"><img class="error-page-logo" src="${h.url('/images/RhodeCode_Logo_Black.png')}" alt="RhodeCode"/></a>
29 <a href="${h.url('home')}"><img class="error-page-logo" src="${h.asset('images/RhodeCode_Logo_Black.png')}" alt="RhodeCode"/></a>
30 30 </div>
31 31 <div class="main-content">
32 32 <h1>
33 33 <span class="error-branding">
34 34 ${h.branding(c.rhodecode_name)}
35 35 </span><br/>
36 36 ${c.error_message} | <span class="error_message">${c.error_explanation}</span>
37 37 </h1>
38 38 %if c.redirect_time:
39 39 <p>${_('You will be redirected to %s in %s seconds') % (c.redirect_module,c.redirect_time)}</p>
40 40 %endif
41 41 <div class="inner-column">
42 42 <h4>Possible Cause</h4>
43 43 <ul>
44 44 <li>The resource may have been deleted.</li>
45 45 <li>You may not have access to this repository.</li>
46 46 <li>The link may be incorrect.</li>
47 47 </ul>
48 48 </div>
49 49 <div class="inner-column">
50 50 <h4>Support</h4>
51 51 <p>For support, go to <a href="${c.visual.rhodecode_support_url}" target="_blank">${_('Support')}</a>.
52 52 It may be useful to include your log file; see the log file locations <a href="${h.url('enterprise_log_file_locations')}">here</a>.
53 53 </p>
54 54 </div>
55 55 <div class="inner-column">
56 56 <h4>Documentation</h4>
57 57 <p>For more information, see <a href="${h.url('enterprise_docs')}">docs.rhodecode.com</a>.</p>
58 58 </div>
59 59 </div>
60 60 </div>
61 61
62 62 </body>
63 63
64 64 </html>
@@ -1,225 +1,225 b''
1 1 ## -*- coding: utf-8 -*-
2 2
3 3 <%inherit file="/base/base.html"/>
4 4 <%namespace name="diff_block" file="/changeset/diff_block.html"/>
5 5
6 6 <%def name="js_extra()">
7 <script type="text/javascript" src="${h.url('/js/mergerly.js')}"></script>
7 <script type="text/javascript" src="${h.asset('js/mergerly.js')}"></script>
8 8 </%def>
9 9
10 10 <%def name="css_extra()">
11 <link rel="stylesheet" type="text/css" href="${h.url('/css/mergerly.css')}"/>
11 <link rel="stylesheet" type="text/css" href="${h.asset('css/mergerly.css')}"/>
12 12 </%def>
13 13
14 14 <%def name="title()">
15 15 ${_('%s File side-by-side diff') % c.repo_name}
16 16 %if c.rhodecode_name:
17 17 &middot; ${h.branding(c.rhodecode_name)}
18 18 %endif
19 19 </%def>
20 20
21 21 <%def name="breadcrumbs_links()">
22 22 r${c.commit_1.revision}:${h.short_id(c.commit_1.raw_id)} ... r${c.commit_2.revision}:${h.short_id(c.commit_2.raw_id)}
23 23 </%def>
24 24
25 25 <%def name="menu_bar_nav()">
26 26 ${self.menu_items(active='repositories')}
27 27 </%def>
28 28
29 29 <%def name="menu_bar_subnav()">
30 30 ${self.repo_menu(active='changelog')}
31 31 </%def>
32 32
33 33 <%def name="main()">
34 34 <div class="box">
35 35 <div class="title">
36 36 ${self.repo_page_title(c.rhodecode_db_repo)}
37 37 </div>
38 38
39 39 <div class="breadcrumbs">
40 40 ${_('Side-by-side Diff')} r${c.commit_1.revision}:${h.short_id(c.commit_1.raw_id)} ... r${c.commit_2.revision}:${h.short_id(c.commit_2.raw_id)}
41 41 </div>
42 42 <div class="cs_files">
43 43 <table class="compare_view_files commit_diff">
44 44 <tr class="cs_${c.diff_data['operation']} collapse_file" fid="${c.FID}">
45 45 <td class="cs_icon_td">
46 46 <span class="collapse_file_icon" fid="${c.FID}"></span>
47 47 </td>
48 48 <td class="cs_icon_td">
49 49 <div class="flag_status not_reviewed hidden"></div>
50 50 </td>
51 51 <td class="cs_${c.diff_data['operation']}" id="a_${c.FID}">
52 52 <div class="node">
53 53 <a href="#a_${c.FID}">
54 54 <i class="icon-file-${c.diff_data['operation'].lower()}"></i>
55 55 ${h.safe_unicode(c.node1.path)}
56 56 </a>
57 57 </div>
58 58 </td>
59 59 <td>
60 60 <div class="changes pull-right">${h.fancy_file_stats(c.diff_data['stats'])}</div>
61 61 <div class="comment-bubble pull-right" data-path="${h.safe_unicode(c.node1.path)}">
62 62 <i class="icon-comment"></i>
63 63 </div>
64 64 </td>
65 65 </tr>
66 66 <tr fid="${c.FID}" id="diff_${c.FID}" class="diff_links">
67 67 <td></td>
68 68 <td></td>
69 69 <td class="cs_${c.diff_data['operation']}">
70 70 ${diff_block.diff_menu(c.repo_name, h.safe_unicode(c.node1.path), c.commit_1.raw_id, c.commit_2.raw_id, c.diff_data['operation'])}
71 71 </td>
72 72 <td class="td-actions rc-form">
73 73 <div id="ignorews" class="btn-link show-inline-comments">
74 74 <span data-enabled=false class="toggle">${_('Ignore whitespace')}</span>
75 75 <span data-enabled=true class="toggle" style="display: none">${_('Show whitespace')}</span>
76 76 </div> |
77 77
78 78 <div id="edit_mode" class="btn-link show-inline-comments">
79 79 <span data-enabled=true class="toggle">${_('Enable editor mode')}</span>
80 80 <span data-enabled=false class="toggle" style="display: none">${_('Disable editor mode')}</span>
81 81 </div> |
82 82
83 83 <div class="btn-link show-inline-comments">
84 84 <span id="prev_change" title="${_('Previous change')}"><i class="icon-left"></i></span>
85 85 <span id="next_change" title="${_('Next change')}"><i class="icon-right"></i></span>
86 86 </div>
87 87
88 88 </td>
89 89 </tr>
90 90 <tr id="tr_${c.FID}">
91 91 <td></td>
92 92 <td></td>
93 93 <td class="injected_diff" colspan="2">
94 94 <div class="diff-container" id="${'diff-container-%s' % (id(c.diff_data['operation']))}">
95 95 <div id="${c.FID}" class="diffblock margined comm">
96 96 <div class="diff-container" >
97 97 <div class="diffblock comm sidebyside">
98 98 <div class="code-header">
99 99 <div class="changeset_header">
100 100 ${_('mode')}: <span id="selected_mode">plain</span> |
101 101 </div>
102 102 </div>
103 103 <div id="compare"></div>
104 104 </div>
105 105 </div>
106 106 </div>
107 107 </div>
108 108 </td>
109 109 </tr>
110 110 </table>
111 111 </div>
112 112
113 113
114 114 <script>
115 115 var orig1_url = '${h.url('files_raw_home',repo_name=c.repo_name,f_path=h.safe_unicode(c.node1.path),revision=c.commit_1.raw_id)}';
116 116 var orig2_url = '${h.url('files_raw_home',repo_name=c.repo_name,f_path=h.safe_unicode(c.node2.path),revision=c.commit_2.raw_id)}';
117 117 $(document).ready(function () {
118 118
119 119
120 120 var editor = $('#compare');
121 121 editor.mergely({
122 122 autoupdate: true,
123 123 width: 'auto',
124 124 height: '600',
125 125 fgcolor: {a: '#ddffdd', c: '#cccccc', d: '#ffdddd'},
126 126 bgcolor: '#fff',
127 127 viewport: false,
128 128 cmsettings: {
129 129 mode: 'text/plain',
130 130 readOnly: true,
131 131 lineWrapping: false,
132 132 lineNumbers: true
133 133 }
134 134 });
135 135
136 136
137 137 var lhs = function(deferred) {
138 138 if ("${c.node1.is_binary}" == "True") {
139 139 deferred.resolve('Binary file');
140 140 }
141 141 else if ("${c.node1.commit.__class__.__name__}" == "EmptyCommit") {
142 142 deferred.resolve('');
143 143 }
144 144 else {
145 145 editor.mergely('lhs', 'loading diff...');
146 146 $.ajax(orig1_url, {
147 147 dataType: 'text',
148 148 success: function(data) {
149 149 // call the complete function to let CodeMirror know
150 150 deferred.resolve(data);
151 151 }
152 152 });
153 153 }
154 154 };
155 155
156 156 var rhs = function(deferred) {
157 157 if ("${c.node2.is_binary}" == "True") {
158 158 deferred.resolve('Binary file');
159 159 }
160 160 else if ("${c.node2.commit.__class__.__name__}" == "EmptyCommit") {
161 161 deferred.resolve('');
162 162 }
163 163 else {
164 164 editor.mergely('rhs', 'loading diff...');
165 165 $.ajax(orig2_url, {
166 166 dataType: 'text',
167 167 success: function(data) {
168 168 // call the complete function to let CodeMirror know
169 169 deferred.resolve(data);
170 170 }
171 171 });
172 172 }
173 173 };
174 174
175 175 var deferred_lhs = $.Deferred();
176 176 var deferred_rhs = $.Deferred();
177 177 $.when(
178 178 deferred_lhs, deferred_rhs
179 179 ).done(function(lhs_response, rhs_response) {
180 180 editor.mergely('lhs', lhs_response);
181 181 editor.mergely('rhs', rhs_response);
182 182
183 183 var detected_mode = detectCodeMirrorModeFromExt(
184 184 '${h.safe_unicode(c.node1.path.split("/")[-1])}', true);
185 185 if (detected_mode) {
186 186 setCodeMirrorMode(editor.mergely('cm', 'lhs'), detected_mode);
187 187 setCodeMirrorMode(editor.mergely('cm', 'rhs'), detected_mode);
188 188 $('#selected_mode').html(detected_mode);
189 189 }
190 190 });
191 191 // load via ajax, and use deferred signals to notify when finished.
192 192 lhs(deferred_lhs);
193 193 rhs(deferred_rhs);
194 194
195 195 $("#ignorews").click(function() {
196 196 $("#ignorews .toggle").toggle();
197 197 var val = $('#ignorews .toggle:visible').data()['enabled'];
198 198 editor.mergely('options', {ignorews: val});
199 199 editor.mergely('update');
200 200 });
201 201
202 202 $("#edit_mode").click(function() {
203 203 $("#edit_mode .toggle").toggle();
204 204 var val = $('#edit_mode .toggle:visible').data()['enabled'];
205 205 editor.mergely('cm', 'lhs').setOption('readOnly', val);
206 206 editor.mergely('cm', 'rhs').setOption('readOnly', val);
207 207 editor.mergely('update');
208 208 });
209 209
210 210 $('#prev_change').on('click', function() {
211 211 editor.mergely('scrollToDiff', 'prev');
212 212 });
213 213 $('#next_change').on('click', function() {
214 214 editor.mergely('scrollToDiff', 'next');
215 215 });
216 216
217 217 // extend content dynamically on this component for readability
218 218 $('#content').css({'max-width': '2000px'});
219 219 editor.mergely('resize');
220 220
221 221 });
222 222 </script>
223 223
224 224 </div>
225 225 </%def>
@@ -1,77 +1,77 b''
1 1 ## -*- coding: utf-8 -*-
2 2 <%inherit file="base/root.html"/>
3 3
4 4 <%def name="title()">
5 5 ${_('Sign In')}
6 6 %if c.rhodecode_name:
7 7 &middot; ${h.branding(c.rhodecode_name)}
8 8 %endif
9 9 </%def>
10 10
11 11 <style>body{background-color:#eeeeee;}</style>
12 12 <div class="loginbox">
13 13 <div class="header">
14 14 <div id="header-inner" class="title">
15 15 <div id="logo">
16 16 <div class="logo-wrapper">
17 <a href="${h.url('home')}"><img src="${h.url('/images/rhodecode-logo-white-216x60.png')}" alt="RhodeCode"/></a>
17 <a href="${h.url('home')}"><img src="${h.asset('images/rhodecode-logo-white-216x60.png')}" alt="RhodeCode"/></a>
18 18 </div>
19 19 %if c.rhodecode_name:
20 20 <div class="branding"> ${h.branding(c.rhodecode_name)}</div>
21 21 %endif
22 22 </div>
23 23 </div>
24 24 </div>
25 25
26 26 <div class="loginwrapper">
27 27 <div class="left-column">
28 <img class="sign-in-image" src="${h.url('/images/sign-in.png')}" alt="RhodeCode"/>
28 <img class="sign-in-image" src="${h.asset('images/sign-in.png')}" alt="RhodeCode"/>
29 29 </div>
30 30 <%block name="above_login_button" />
31 31 <div id="login" class="right-column">
32 32 <%include file="/base/flash_msg.html"/>
33 33 <!-- login -->
34 34 <div class="sign-in-title">
35 35 <h1>${_('Sign In')}</h1>
36 36 %if h.HasPermissionAny('hg.admin', 'hg.register.auto_activate', 'hg.register.manual_activate')():
37 37 <h4>${h.link_to(_("Go to the registration page to create a new account."), request.route_path('register'))}</h4>
38 38 %endif
39 39 </div>
40 40 <div class="inner form">
41 41 ${h.form(request.route_path('login', _query={'came_from': came_from}), needs_csrf_token=False)}
42 42
43 43 <label for="username">${_('Username')}:</label>
44 44 ${h.text('username', class_='focus', value=defaults.get('username'))}
45 45 %if 'username' in errors:
46 46 <span class="error-message">${errors.get('username')}</span>
47 47 <br />
48 48 %endif
49 49
50 50 <label for="password">${_('Password')}:</label>
51 51 ${h.password('password', class_='focus')}
52 52 %if 'password' in errors:
53 53 <span class="error-message">${errors.get('password')}</span>
54 54 <br />
55 55 %endif
56 56
57 57 ${h.checkbox('remember', value=True, checked=defaults.get('remember'))}
58 58 <label class="checkbox" for="remember">${_('Remember me')}</label>
59 59
60 60 <p class="links">
61 61 ${h.link_to(_('Forgot your password?'), h.route_path('reset_password'))}
62 62 </p>
63 63
64 64 ${h.submit('sign_in', _('Sign In'), class_="btn sign-in")}
65 65
66 66 ${h.end_form()}
67 67 <script type="text/javascript">
68 68 $(document).ready(function(){
69 69 $('#username').focus();
70 70 })
71 71 </script>
72 72 </div>
73 73 <!-- end login -->
74 74 <%block name="below_login_button" />
75 75 </div>
76 76 </div>
77 77 </div>
@@ -1,78 +1,78 b''
1 1 ## -*- coding: utf-8 -*-
2 2 <%inherit file="base/root.html"/>
3 3
4 4 <%def name="title()">
5 5 ${_('Create an Account')}
6 6 %if c.rhodecode_name:
7 7 &middot; ${h.branding(c.rhodecode_name)}
8 8 %endif
9 9 </%def>
10 10 <style>body{background-color:#eeeeee;}</style>
11 11
12 12 <div class="loginbox">
13 13 <div class="header">
14 14 <div id="header-inner" class="title">
15 15 <div id="logo">
16 16 <div class="logo-wrapper">
17 <a href="${h.url('home')}"><img src="${h.url('/images/rhodecode-logo-white-216x60.png')}" alt="RhodeCode"/></a>
17 <a href="${h.url('home')}"><img src="${h.asset('images/rhodecode-logo-white-216x60.png')}" alt="RhodeCode"/></a>
18 18 </div>
19 19 %if c.rhodecode_name:
20 20 <div class="branding"> ${h.branding(c.rhodecode_name)}</div>
21 21 %endif
22 22 </div>
23 23 </div>
24 24 </div>
25 25
26 26 <div class="loginwrapper">
27 27 <div class="left-column">
28 <img class="sign-in-image" src="${h.url('/images/sign-in.png')}" alt="RhodeCode"/>
28 <img class="sign-in-image" src="${h.asset('images/sign-in.png')}" alt="RhodeCode"/>
29 29 </div>
30 30
31 31 <div id="register" class="right-column">
32 32 <%include file="/base/flash_msg.html"/>
33 33 <!-- login -->
34 34 <div class="sign-in-title">
35 35 <h1>${_('Reset your Password')}</h1>
36 36 <h4>${h.link_to(_("Go to the login page to sign in."), request.route_path('login'))}</h4>
37 37 </div>
38 38 <div class="inner form">
39 39 ${h.form(request.route_path('reset_password'), needs_csrf_token=False)}
40 40 <label for="email">${_('Email Address')}:</label>
41 41 ${h.text('email', defaults.get('email'))}
42 42 %if 'email' in errors:
43 43 <span class="error-message">${errors.get('email')}</span>
44 44 <br />
45 45 %endif
46 46
47 47 %if captcha_active:
48 48 <div class="login-captcha"
49 49 <label for="email">${_('Captcha')}:</label>
50 50 ${h.hidden('recaptcha_field')}
51 51 <div id="recaptcha"></div>
52 52 %if 'recaptcha_field' in errors:
53 53 <span class="error-message">${errors.get('recaptcha_field')}</span>
54 54 <br />
55 55 %endif
56 56 </div>
57 57 %endif
58 58
59 59 ${h.submit('send', _('Send password reset email'), class_="btn sign-in")}
60 60 <div class="activation_msg">${_('Password reset link will be send to matching email address')}</div>
61 61
62 62 ${h.end_form()}
63 63 </div>
64 64 </div>
65 65 </div>
66 66 </div>
67 67
68 68 %if captcha_active:
69 69 <script type="text/javascript" src="https://www.google.com/recaptcha/api/js/recaptcha_ajax.js"></script>
70 70 %endif
71 71 <script type="text/javascript">
72 72 $(document).ready(function(){
73 73 $('#email').focus();
74 74 %if captcha_active:
75 75 Recaptcha.create("${captcha_public_key}", "recaptcha", {theme: "white"});
76 76 %endif
77 77 });
78 78 </script>
@@ -1,123 +1,123 b''
1 1 ## -*- coding: utf-8 -*-
2 2 <%inherit file="base/root.html"/>
3 3
4 4 <%def name="title()">
5 5 ${_('Create an Account')}
6 6 %if c.rhodecode_name:
7 7 &middot; ${h.branding(c.rhodecode_name)}
8 8 %endif
9 9 </%def>
10 10 <style>body{background-color:#eeeeee;}</style>
11 11
12 12 <div class="loginbox">
13 13 <div class="header">
14 14 <div id="header-inner" class="title">
15 15 <div id="logo">
16 16 <div class="logo-wrapper">
17 <a href="${h.url('home')}"><img src="${h.url('/images/rhodecode-logo-white-216x60.png')}" alt="RhodeCode"/></a>
17 <a href="${h.url('home')}"><img src="${h.asset('images/rhodecode-logo-white-216x60.png')}" alt="RhodeCode"/></a>
18 18 </div>
19 19 %if c.rhodecode_name:
20 20 <div class="branding"> ${h.branding(c.rhodecode_name)}</div>
21 21 %endif
22 22 </div>
23 23 </div>
24 24 </div>
25 25
26 26 <div class="loginwrapper">
27 27 <div class="left-column">
28 <img class="sign-in-image" src="${h.url('/images/sign-in.png')}" alt="RhodeCode"/>
28 <img class="sign-in-image" src="${h.asset('images/sign-in.png')}" alt="RhodeCode"/>
29 29 </div>
30 30 <%block name="above_register_button" />
31 31 <div id="register" class="right-column">
32 32 <%include file="/base/flash_msg.html"/>
33 33 <!-- login -->
34 34 <div class="sign-in-title">
35 35 <h1>${_('Create an account')}</h1>
36 36 <h4>${h.link_to(_("Go to the login page to sign in with an existing account."), request.route_path('login'))}</h4>
37 37 </div>
38 38 <div class="inner form">
39 39 ${h.form(request.route_path('register'), needs_csrf_token=False)}
40 40
41 41 <label for="username">${_('Username')}:</label>
42 42 ${h.text('username', defaults.get('username'))}
43 43 %if 'username' in errors:
44 44 <span class="error-message">${errors.get('username')}</span>
45 45 <br />
46 46 %endif
47 47
48 48 <label for="password">${_('Password')}:</label>
49 49 ${h.password('password', defaults.get('password'))}
50 50 %if 'password' in errors:
51 51 <span class="error-message">${errors.get('password')}</span>
52 52 <br />
53 53 %endif
54 54
55 55 <label for="password_confirmation">${_('Re-enter password')}:</label>
56 56 ${h.password('password_confirmation', defaults.get('password_confirmation'))}
57 57 %if 'password_confirmation' in errors:
58 58 <span class="error-message">${errors.get('password_confirmation')}</span>
59 59 <br />
60 60 %endif
61 61
62 62 <label for="firstname">${_('First Name')}:</label>
63 63 ${h.text('firstname', defaults.get('firstname'))}
64 64 %if 'firstname' in errors:
65 65 <span class="error-message">${errors.get('firstname')}</span>
66 66 <br />
67 67 %endif
68 68
69 69 <label for="lastname">${_('Last Name')}:</label>
70 70 ${h.text('lastname', defaults.get('lastname'))}
71 71 %if 'lastname' in errors:
72 72 <span class="error-message">${errors.get('lastname')}</span>
73 73 <br />
74 74 %endif
75 75
76 76 <label for="email">${_('Email')}:</label>
77 77 ${h.text('email', defaults.get('email'))}
78 78 %if 'email' in errors:
79 79 <span class="error-message">${errors.get('email')}</span>
80 80 <br />
81 81 %endif
82 82
83 83 %if captcha_active:
84 84 <div>
85 85 <label for="recaptcha">${_('Captcha')}:</label>
86 86 ${h.hidden('recaptcha_field')}
87 87 <div id="recaptcha"></div>
88 88 %if 'recaptcha_field' in errors:
89 89 <span class="error-message">${errors.get('recaptcha_field')}</span>
90 90 <br />
91 91 %endif
92 92 </div>
93 93 %endif
94 94
95 95 %if not auto_active:
96 96 <p class="activation_msg">
97 97 ${_('Account activation requires admin approval.')}
98 98 </p>
99 99 %endif
100 100 <p class="register_message">
101 101 ${register_message|n}
102 102 </p>
103 103
104 104 ${h.submit('sign_up',_('Create Account'),class_="btn sign-in")}
105 105
106 106 ${h.end_form()}
107 107 </div>
108 108 <%block name="below_register_button" />
109 109 </div>
110 110 </div>
111 111 </div>
112 112
113 113 %if captcha_active:
114 114 <script type="text/javascript" src="https://www.google.com/recaptcha/api/js/recaptcha_ajax.js"></script>
115 115 %endif
116 116 <script type="text/javascript">
117 117 $(document).ready(function(){
118 118 $('#username').focus();
119 119 %if captcha_active:
120 120 Recaptcha.create("${captcha_public_key}", "recaptcha", {theme: "white"});
121 121 %endif
122 122 });
123 123 </script>
General Comments 0
You need to be logged in to leave comments. Login now