##// END OF EJS Templates
fixed #597 commits in future get negative age.
marcink -
r2902:e2b2791d beta
parent child Browse files
Show More
@@ -1,820 +1,821 b''
1 1 .. _changelog:
2 2
3 3 =========
4 4 Changelog
5 5 =========
6 6
7 7 1.4.4 (**2012-XX-XX**)
8 8 ----------------------
9 9
10 10 :status: in-progress
11 11 :branch: beta
12 12
13 13 news
14 14 ++++
15 15
16 16 - obfuscate db password in logs for engine connection string
17 17 - #574 Show pull request status also in shortlog (if any)
18 18 - remember selected tab in my account page
19 19 - Bumped mercurial version to 2.3.2
20 20
21 21 fixes
22 22 +++++
23 23
24 24 - Add git version detection to warn users that Git used in system is to
25 25 old. Ref #588 - also show git version in system details in settings page
26 26 - fixed files quick filter links
27 27 - #590 Add GET flag that controls the way the diff are generated, for pull
28 28 requests we want to use non-bundle based diffs, That are far better for
29 29 doing code reviews. The /compare url still uses bundle compare for full
30 30 comparison including the incoming changesets
31 31 - Fixed #585, checks for status of revision where to strict, and made
32 32 opening pull request with those revision impossible due to previously set
33 33 status. Checks now are made also for the repository.
34 34 - fixes #591 git backend was causing encoding errors when handling binary
35 35 files - added a test case for VCS lib tests
36 - fixed #597 commits in future get negative age.
36 37
37 38 1.4.3 (**2012-09-28**)
38 39 ----------------------
39 40
40 41 news
41 42 ++++
42 43
43 44 - #558 Added config file to hooks extra data
44 45 - bumped mercurial version to 2.3.1
45 46 - #518 added possibility of specifying multiple patterns for issues
46 47 - update codemirror to latest version
47 48
48 49 fixes
49 50 +++++
50 51
51 52 - fixed #570 explicit users group permissions can overwrite owner permissions
52 53 - fixed #578 set proper PATH with current Python for Git
53 54 hooks to execute within same Python as RhodeCode
54 55 - fixed issue with Git bare repos that ends with .git in name
55 56
56 57 1.4.2 (**2012-09-12**)
57 58 ----------------------
58 59
59 60 news
60 61 ++++
61 62
62 63 - added option to menu to quick lock/unlock repository for users that have
63 64 write access to
64 65 - Implemented permissions for writing to repo
65 66 groups. Now only write access to group allows to create a repostiory
66 67 within that group
67 68 - #565 Add support for {netloc} and {scheme} to alternative_gravatar_url
68 69 - updated translation for zh_CN
69 70
70 71 fixes
71 72 +++++
72 73
73 74 - fixed visual permissions check on repos groups inside groups
74 75 - fixed issues with non-ascii search terms in search, and indexers
75 76 - fixed parsing of page number in GET parameters
76 77 - fixed issues with generating pull-request overview for repos with
77 78 bookmarks and tags, also preview doesn't loose chosen revision from
78 79 select dropdown
79 80
80 81 1.4.1 (**2012-09-07**)
81 82 ----------------------
82 83
83 84 news
84 85 ++++
85 86
86 87 - always put a comment about code-review status change even if user send
87 88 empty data
88 89 - modified_on column saves repository update and it's going to be used
89 90 later for light version of main page ref #500
90 91 - pull request notifications send much nicer emails with details about pull
91 92 request
92 93 - #551 show breadcrumbs in summary view for repositories inside a group
93 94
94 95 fixes
95 96 +++++
96 97
97 98 - fixed migrations of permissions that can lead to inconsistency.
98 99 Some users sent feedback that after upgrading from older versions issues
99 100 with updating default permissions occurred. RhodeCode detects that now and
100 101 resets default user permission to initial state if there is a need for that.
101 102 Also forces users to set the default value for new forking permission.
102 103 - #535 improved apache wsgi example configuration in docs
103 104 - fixes #550 mercurial repositories comparision failed when origin repo had
104 105 additional not-common changesets
105 106 - fixed status of code-review in preview windows of pull request
106 107 - git forks were not initialized at bare repos
107 108 - fixes #555 fixes issues with comparing non-related repositories
108 109 - fixes #557 follower counter always counts up
109 110 - fixed issue #560 require push ssl checkbox wasn't shown when option was
110 111 enabled
111 112 - fixed #559
112 113 - fixed issue #559 fixed bug in routing that mapped repo names with <name>_<num> in name as
113 114 if it was a request to url by repository ID
114 115
115 116 1.4.0 (**2012-09-03**)
116 117 ----------------------
117 118
118 119 news
119 120 ++++
120 121
121 122 - new codereview system
122 123 - email map, allowing users to have multiple email addresses mapped into
123 124 their accounts
124 125 - improved git-hook system. Now all actions for git are logged into journal
125 126 including pushed revisions, user and IP address
126 127 - changed setup-app into setup-rhodecode and added default options to it.
127 128 - new git repos are created as bare now by default
128 129 - #464 added links to groups in permission box
129 130 - #465 mentions autocomplete inside comments boxes
130 131 - #469 added --update-only option to whoosh to re-index only given list
131 132 of repos in index
132 133 - rhodecode-api CLI client
133 134 - new git http protocol replaced buggy dulwich implementation.
134 135 Now based on pygrack & gitweb
135 136 - Improved RSS/ATOM feeds. Discoverable by browsers using proper headers, and
136 137 reformated based on user suggestions. Additional rss/atom feeds for user
137 138 journal
138 139 - various i18n improvements
139 140 - #478 permissions overview for admin in user edit view
140 141 - File view now displays small gravatars off all authors of given file
141 142 - Implemented landing revisions. Each repository will get landing_rev attribute
142 143 that defines 'default' revision/branch for generating readme files
143 144 - Implemented #509, RhodeCode enforces SSL for push/pulling if requested at
144 145 earliest possible call.
145 146 - Import remote svn repositories to mercurial using hgsubversion.
146 147 - Fixed #508 RhodeCode now has a option to explicitly set forking permissions
147 148 - RhodeCode can use alternative server for generating avatar icons
148 149 - implemented repositories locking. Pull locks, push unlocks. Also can be done
149 150 via API calls
150 151 - #538 form for permissions can handle multiple users at once
151 152
152 153 fixes
153 154 +++++
154 155
155 156 - improved translations
156 157 - fixes issue #455 Creating an archive generates an exception on Windows
157 158 - fixes #448 Download ZIP archive keeps file in /tmp open and results
158 159 in out of disk space
159 160 - fixes issue #454 Search results under Windows include proceeding
160 161 backslash
161 162 - fixed issue #450. Rhodecode no longer will crash when bad revision is
162 163 present in journal data.
163 164 - fix for issue #417, git execution was broken on windows for certain
164 165 commands.
165 166 - fixed #413. Don't disable .git directory for bare repos on deleting
166 167 - fixed issue #459. Changed the way of obtaining logger in reindex task.
167 168 - fixed #453 added ID field in whoosh SCHEMA that solves the issue of
168 169 reindexing modified files
169 170 - fixed #481 rhodecode emails are sent without Date header
170 171 - fixed #458 wrong count when no repos are present
171 172 - fixed issue #492 missing `\ No newline at end of file` test at the end of
172 173 new chunk in html diff
173 174 - full text search now works also for commit messages
174 175
175 176 1.3.6 (**2012-05-17**)
176 177 ----------------------
177 178
178 179 news
179 180 ++++
180 181
181 182 - chinese traditional translation
182 183 - changed setup-app into setup-rhodecode and added arguments for auto-setup
183 184 mode that doesn't need user interaction
184 185
185 186 fixes
186 187 +++++
187 188
188 189 - fixed no scm found warning
189 190 - fixed __future__ import error on rcextensions
190 191 - made simplejson required lib for speedup on JSON encoding
191 192 - fixes #449 bad regex could get more than revisions from parsing history
192 193 - don't clear DB session when CELERY_EAGER is turned ON
193 194
194 195 1.3.5 (**2012-05-10**)
195 196 ----------------------
196 197
197 198 news
198 199 ++++
199 200
200 201 - use ext_json for json module
201 202 - unified annotation view with file source view
202 203 - notification improvements, better inbox + css
203 204 - #419 don't strip passwords for login forms, make rhodecode
204 205 more compatible with LDAP servers
205 206 - Added HTTP_X_FORWARDED_FOR as another method of extracting
206 207 IP for pull/push logs. - moved all to base controller
207 208 - #415: Adding comment to changeset causes reload.
208 209 Comments are now added via ajax and doesn't reload the page
209 210 - #374 LDAP config is discarded when LDAP can't be activated
210 211 - limited push/pull operations are now logged for git in the journal
211 212 - bumped mercurial to 2.2.X series
212 213 - added support for displaying submodules in file-browser
213 214 - #421 added bookmarks in changelog view
214 215
215 216 fixes
216 217 +++++
217 218
218 219 - fixed dev-version marker for stable when served from source codes
219 220 - fixed missing permission checks on show forks page
220 221 - #418 cast to unicode fixes in notification objects
221 222 - #426 fixed mention extracting regex
222 223 - fixed remote-pulling for git remotes remopositories
223 224 - fixed #434: Error when accessing files or changesets of a git repository
224 225 with submodules
225 226 - fixed issue with empty APIKEYS for users after registration ref. #438
226 227 - fixed issue with getting README files from git repositories
227 228
228 229 1.3.4 (**2012-03-28**)
229 230 ----------------------
230 231
231 232 news
232 233 ++++
233 234
234 235 - Whoosh logging is now controlled by the .ini files logging setup
235 236 - added clone-url into edit form on /settings page
236 237 - added help text into repo add/edit forms
237 238 - created rcextensions module with additional mappings (ref #322) and
238 239 post push/pull/create repo hooks callbacks
239 240 - implemented #377 Users view for his own permissions on account page
240 241 - #399 added inheritance of permissions for users group on repos groups
241 242 - #401 repository group is automatically pre-selected when adding repos
242 243 inside a repository group
243 244 - added alternative HTTP 403 response when client failed to authenticate. Helps
244 245 solving issues with Mercurial and LDAP
245 246 - #402 removed group prefix from repository name when listing repositories
246 247 inside a group
247 248 - added gravatars into permission view and permissions autocomplete
248 249 - #347 when running multiple RhodeCode instances, properly invalidates cache
249 250 for all registered servers
250 251
251 252 fixes
252 253 +++++
253 254
254 255 - fixed #390 cache invalidation problems on repos inside group
255 256 - fixed #385 clone by ID url was loosing proxy prefix in URL
256 257 - fixed some unicode problems with waitress
257 258 - fixed issue with escaping < and > in changeset commits
258 259 - fixed error occurring during recursive group creation in API
259 260 create_repo function
260 261 - fixed #393 py2.5 fixes for routes url generator
261 262 - fixed #397 Private repository groups shows up before login
262 263 - fixed #396 fixed problems with revoking users in nested groups
263 264 - fixed mysql unicode issues + specified InnoDB as default engine with
264 265 utf8 charset
265 266 - #406 trim long branch/tag names in changelog to not break UI
266 267
267 268 1.3.3 (**2012-03-02**)
268 269 ----------------------
269 270
270 271 news
271 272 ++++
272 273
273 274
274 275 fixes
275 276 +++++
276 277
277 278 - fixed some python2.5 compatibility issues
278 279 - fixed issues with removed repos was accidentally added as groups, after
279 280 full rescan of paths
280 281 - fixes #376 Cannot edit user (using container auth)
281 282 - fixes #378 Invalid image urls on changeset screen with proxy-prefix
282 283 configuration
283 284 - fixed initial sorting of repos inside repo group
284 285 - fixes issue when user tried to resubmit same permission into user/user_groups
285 286 - bumped beaker version that fixes #375 leap error bug
286 287 - fixed raw_changeset for git. It was generated with hg patch headers
287 288 - fixed vcs issue with last_changeset for filenodes
288 289 - fixed missing commit after hook delete
289 290 - fixed #372 issues with git operation detection that caused a security issue
290 291 for git repos
291 292
292 293 1.3.2 (**2012-02-28**)
293 294 ----------------------
294 295
295 296 news
296 297 ++++
297 298
298 299
299 300 fixes
300 301 +++++
301 302
302 303 - fixed git protocol issues with repos-groups
303 304 - fixed git remote repos validator that prevented from cloning remote git repos
304 305 - fixes #370 ending slashes fixes for repo and groups
305 306 - fixes #368 improved git-protocol detection to handle other clients
306 307 - fixes #366 When Setting Repository Group To Blank Repo Group Wont Be
307 308 Moved To Root
308 309 - fixes #371 fixed issues with beaker/sqlalchemy and non-ascii cache keys
309 310 - fixed #373 missing cascade drop on user_group_to_perm table
310 311
311 312 1.3.1 (**2012-02-27**)
312 313 ----------------------
313 314
314 315 news
315 316 ++++
316 317
317 318
318 319 fixes
319 320 +++++
320 321
321 322 - redirection loop occurs when remember-me wasn't checked during login
322 323 - fixes issues with git blob history generation
323 324 - don't fetch branch for git in file history dropdown. Causes unneeded slowness
324 325
325 326 1.3.0 (**2012-02-26**)
326 327 ----------------------
327 328
328 329 news
329 330 ++++
330 331
331 332 - code review, inspired by github code-comments
332 333 - #215 rst and markdown README files support
333 334 - #252 Container-based and proxy pass-through authentication support
334 335 - #44 branch browser. Filtering of changelog by branches
335 336 - mercurial bookmarks support
336 337 - new hover top menu, optimized to add maximum size for important views
337 338 - configurable clone url template with possibility to specify protocol like
338 339 ssh:// or http:// and also manually alter other parts of clone_url.
339 340 - enabled largefiles extension by default
340 341 - optimized summary file pages and saved a lot of unused space in them
341 342 - #239 option to manually mark repository as fork
342 343 - #320 mapping of commit authors to RhodeCode users
343 344 - #304 hashes are displayed using monospace font
344 345 - diff configuration, toggle white lines and context lines
345 346 - #307 configurable diffs, whitespace toggle, increasing context lines
346 347 - sorting on branches, tags and bookmarks using YUI datatable
347 348 - improved file filter on files page
348 349 - implements #330 api method for listing nodes ar particular revision
349 350 - #73 added linking issues in commit messages to chosen issue tracker url
350 351 based on user defined regular expression
351 352 - added linking of changesets in commit messages
352 353 - new compact changelog with expandable commit messages
353 354 - firstname and lastname are optional in user creation
354 355 - #348 added post-create repository hook
355 356 - #212 global encoding settings is now configurable from .ini files
356 357 - #227 added repository groups permissions
357 358 - markdown gets codehilite extensions
358 359 - new API methods, delete_repositories, grante/revoke permissions for groups
359 360 and repos
360 361
361 362
362 363 fixes
363 364 +++++
364 365
365 366 - rewrote dbsession management for atomic operations, and better error handling
366 367 - fixed sorting of repo tables
367 368 - #326 escape of special html entities in diffs
368 369 - normalized user_name => username in api attributes
369 370 - fixes #298 ldap created users with mixed case emails created conflicts
370 371 on saving a form
371 372 - fixes issue when owner of a repo couldn't revoke permissions for users
372 373 and groups
373 374 - fixes #271 rare JSON serialization problem with statistics
374 375 - fixes #337 missing validation check for conflicting names of a group with a
375 376 repositories group
376 377 - #340 fixed session problem for mysql and celery tasks
377 378 - fixed #331 RhodeCode mangles repository names if the a repository group
378 379 contains the "full path" to the repositories
379 380 - #355 RhodeCode doesn't store encrypted LDAP passwords
380 381
381 382 1.2.5 (**2012-01-28**)
382 383 ----------------------
383 384
384 385 news
385 386 ++++
386 387
387 388 fixes
388 389 +++++
389 390
390 391 - #340 Celery complains about MySQL server gone away, added session cleanup
391 392 for celery tasks
392 393 - #341 "scanning for repositories in None" log message during Rescan was missing
393 394 a parameter
394 395 - fixed creating archives with subrepos. Some hooks were triggered during that
395 396 operation leading to crash.
396 397 - fixed missing email in account page.
397 398 - Reverted Mercurial to 2.0.1 for windows due to bug in Mercurial that makes
398 399 forking on windows impossible
399 400
400 401 1.2.4 (**2012-01-19**)
401 402 ----------------------
402 403
403 404 news
404 405 ++++
405 406
406 407 - RhodeCode is bundled with mercurial series 2.0.X by default, with
407 408 full support to largefiles extension. Enabled by default in new installations
408 409 - #329 Ability to Add/Remove Groups to/from a Repository via AP
409 410 - added requires.txt file with requirements
410 411
411 412 fixes
412 413 +++++
413 414
414 415 - fixes db session issues with celery when emailing admins
415 416 - #331 RhodeCode mangles repository names if the a repository group
416 417 contains the "full path" to the repositories
417 418 - #298 Conflicting e-mail addresses for LDAP and RhodeCode users
418 419 - DB session cleanup after hg protocol operations, fixes issues with
419 420 `mysql has gone away` errors
420 421 - #333 doc fixes for get_repo api function
421 422 - #271 rare JSON serialization problem with statistics enabled
422 423 - #337 Fixes issues with validation of repository name conflicting with
423 424 a group name. A proper message is now displayed.
424 425 - #292 made ldap_dn in user edit readonly, to get rid of confusion that field
425 426 doesn't work
426 427 - #316 fixes issues with web description in hgrc files
427 428
428 429 1.2.3 (**2011-11-02**)
429 430 ----------------------
430 431
431 432 news
432 433 ++++
433 434
434 435 - added option to manage repos group for non admin users
435 436 - added following API methods for get_users, create_user, get_users_groups,
436 437 get_users_group, create_users_group, add_user_to_users_groups, get_repos,
437 438 get_repo, create_repo, add_user_to_repo
438 439 - implements #237 added password confirmation for my account
439 440 and admin edit user.
440 441 - implements #291 email notification for global events are now sent to all
441 442 administrator users, and global config email.
442 443
443 444 fixes
444 445 +++++
445 446
446 447 - added option for passing auth method for smtp mailer
447 448 - #276 issue with adding a single user with id>10 to usergroups
448 449 - #277 fixes windows LDAP settings in which missing values breaks the ldap auth
449 450 - #288 fixes managing of repos in a group for non admin user
450 451
451 452 1.2.2 (**2011-10-17**)
452 453 ----------------------
453 454
454 455 news
455 456 ++++
456 457
457 458 - #226 repo groups are available by path instead of numerical id
458 459
459 460 fixes
460 461 +++++
461 462
462 463 - #259 Groups with the same name but with different parent group
463 464 - #260 Put repo in group, then move group to another group -> repo becomes unavailable
464 465 - #258 RhodeCode 1.2 assumes egg folder is writable (lockfiles problems)
465 466 - #265 ldap save fails sometimes on converting attributes to booleans,
466 467 added getter and setter into model that will prevent from this on db model level
467 468 - fixed problems with timestamps issues #251 and #213
468 469 - fixes #266 RhodeCode allows to create repo with the same name and in
469 470 the same parent as group
470 471 - fixes #245 Rescan of the repositories on Windows
471 472 - fixes #248 cannot edit repos inside a group on windows
472 473 - fixes #219 forking problems on windows
473 474
474 475 1.2.1 (**2011-10-08**)
475 476 ----------------------
476 477
477 478 news
478 479 ++++
479 480
480 481
481 482 fixes
482 483 +++++
483 484
484 485 - fixed problems with basic auth and push problems
485 486 - gui fixes
486 487 - fixed logger
487 488
488 489 1.2.0 (**2011-10-07**)
489 490 ----------------------
490 491
491 492 news
492 493 ++++
493 494
494 495 - implemented #47 repository groups
495 496 - implemented #89 Can setup google analytics code from settings menu
496 497 - implemented #91 added nicer looking archive urls with more download options
497 498 like tags, branches
498 499 - implemented #44 into file browsing, and added follow branch option
499 500 - implemented #84 downloads can be enabled/disabled for each repository
500 501 - anonymous repository can be cloned without having to pass default:default
501 502 into clone url
502 503 - fixed #90 whoosh indexer can index chooses repositories passed in command
503 504 line
504 505 - extended journal with day aggregates and paging
505 506 - implemented #107 source code lines highlight ranges
506 507 - implemented #93 customizable changelog on combined revision ranges -
507 508 equivalent of githubs compare view
508 509 - implemented #108 extended and more powerful LDAP configuration
509 510 - implemented #56 users groups
510 511 - major code rewrites optimized codes for speed and memory usage
511 512 - raw and diff downloads are now in git format
512 513 - setup command checks for write access to given path
513 514 - fixed many issues with international characters and unicode. It uses utf8
514 515 decode with replace to provide less errors even with non utf8 encoded strings
515 516 - #125 added API KEY access to feeds
516 517 - #109 Repository can be created from external Mercurial link (aka. remote
517 518 repository, and manually updated (via pull) from admin panel
518 519 - beta git support - push/pull server + basic view for git repos
519 520 - added followers page and forks page
520 521 - server side file creation (with binary file upload interface)
521 522 and edition with commits powered by codemirror
522 523 - #111 file browser file finder, quick lookup files on whole file tree
523 524 - added quick login sliding menu into main page
524 525 - changelog uses lazy loading of affected files details, in some scenarios
525 526 this can improve speed of changelog page dramatically especially for
526 527 larger repositories.
527 528 - implements #214 added support for downloading subrepos in download menu.
528 529 - Added basic API for direct operations on rhodecode via JSON
529 530 - Implemented advanced hook management
530 531
531 532 fixes
532 533 +++++
533 534
534 535 - fixed file browser bug, when switching into given form revision the url was
535 536 not changing
536 537 - fixed propagation to error controller on simplehg and simplegit middlewares
537 538 - fixed error when trying to make a download on empty repository
538 539 - fixed problem with '[' chars in commit messages in journal
539 540 - fixed #99 Unicode errors, on file node paths with non utf-8 characters
540 541 - journal fork fixes
541 542 - removed issue with space inside renamed repository after deletion
542 543 - fixed strange issue on formencode imports
543 544 - fixed #126 Deleting repository on Windows, rename used incompatible chars.
544 545 - #150 fixes for errors on repositories mapped in db but corrupted in
545 546 filesystem
546 547 - fixed problem with ascendant characters in realm #181
547 548 - fixed problem with sqlite file based database connection pool
548 549 - whoosh indexer and code stats share the same dynamic extensions map
549 550 - fixes #188 - relationship delete of repo_to_perm entry on user removal
550 551 - fixes issue #189 Trending source files shows "show more" when no more exist
551 552 - fixes issue #197 Relative paths for pidlocks
552 553 - fixes issue #198 password will require only 3 chars now for login form
553 554 - fixes issue #199 wrong redirection for non admin users after creating a repository
554 555 - fixes issues #202, bad db constraint made impossible to attach same group
555 556 more than one time. Affects only mysql/postgres
556 557 - fixes #218 os.kill patch for windows was missing sig param
557 558 - improved rendering of dag (they are not trimmed anymore when number of
558 559 heads exceeds 5)
559 560
560 561 1.1.8 (**2011-04-12**)
561 562 ----------------------
562 563
563 564 news
564 565 ++++
565 566
566 567 - improved windows support
567 568
568 569 fixes
569 570 +++++
570 571
571 572 - fixed #140 freeze of python dateutil library, since new version is python2.x
572 573 incompatible
573 574 - setup-app will check for write permission in given path
574 575 - cleaned up license info issue #149
575 576 - fixes for issues #137,#116 and problems with unicode and accented characters.
576 577 - fixes crashes on gravatar, when passed in email as unicode
577 578 - fixed tooltip flickering problems
578 579 - fixed came_from redirection on windows
579 580 - fixed logging modules, and sql formatters
580 581 - windows fixes for os.kill issue #133
581 582 - fixes path splitting for windows issues #148
582 583 - fixed issue #143 wrong import on migration to 1.1.X
583 584 - fixed problems with displaying binary files, thanks to Thomas Waldmann
584 585 - removed name from archive files since it's breaking ui for long repo names
585 586 - fixed issue with archive headers sent to browser, thanks to Thomas Waldmann
586 587 - fixed compatibility for 1024px displays, and larger dpi settings, thanks to
587 588 Thomas Waldmann
588 589 - fixed issue #166 summary pager was skipping 10 revisions on second page
589 590
590 591
591 592 1.1.7 (**2011-03-23**)
592 593 ----------------------
593 594
594 595 news
595 596 ++++
596 597
597 598 fixes
598 599 +++++
599 600
600 601 - fixed (again) #136 installation support for FreeBSD
601 602
602 603
603 604 1.1.6 (**2011-03-21**)
604 605 ----------------------
605 606
606 607 news
607 608 ++++
608 609
609 610 fixes
610 611 +++++
611 612
612 613 - fixed #136 installation support for FreeBSD
613 614 - RhodeCode will check for python version during installation
614 615
615 616 1.1.5 (**2011-03-17**)
616 617 ----------------------
617 618
618 619 news
619 620 ++++
620 621
621 622 - basic windows support, by exchanging pybcrypt into sha256 for windows only
622 623 highly inspired by idea of mantis406
623 624
624 625 fixes
625 626 +++++
626 627
627 628 - fixed sorting by author in main page
628 629 - fixed crashes with diffs on binary files
629 630 - fixed #131 problem with boolean values for LDAP
630 631 - fixed #122 mysql problems thanks to striker69
631 632 - fixed problem with errors on calling raw/raw_files/annotate functions
632 633 with unknown revisions
633 634 - fixed returned rawfiles attachment names with international character
634 635 - cleaned out docs, big thanks to Jason Harris
635 636
636 637 1.1.4 (**2011-02-19**)
637 638 ----------------------
638 639
639 640 news
640 641 ++++
641 642
642 643 fixes
643 644 +++++
644 645
645 646 - fixed formencode import problem on settings page, that caused server crash
646 647 when that page was accessed as first after server start
647 648 - journal fixes
648 649 - fixed option to access repository just by entering http://server/<repo_name>
649 650
650 651 1.1.3 (**2011-02-16**)
651 652 ----------------------
652 653
653 654 news
654 655 ++++
655 656
656 657 - implemented #102 allowing the '.' character in username
657 658 - added option to access repository just by entering http://server/<repo_name>
658 659 - celery task ignores result for better performance
659 660
660 661 fixes
661 662 +++++
662 663
663 664 - fixed ehlo command and non auth mail servers on smtp_lib. Thanks to
664 665 apollo13 and Johan Walles
665 666 - small fixes in journal
666 667 - fixed problems with getting setting for celery from .ini files
667 668 - registration, password reset and login boxes share the same title as main
668 669 application now
669 670 - fixed #113: to high permissions to fork repository
670 671 - fixed problem with '[' chars in commit messages in journal
671 672 - removed issue with space inside renamed repository after deletion
672 673 - db transaction fixes when filesystem repository creation failed
673 674 - fixed #106 relation issues on databases different than sqlite
674 675 - fixed static files paths links to use of url() method
675 676
676 677 1.1.2 (**2011-01-12**)
677 678 ----------------------
678 679
679 680 news
680 681 ++++
681 682
682 683
683 684 fixes
684 685 +++++
685 686
686 687 - fixes #98 protection against float division of percentage stats
687 688 - fixed graph bug
688 689 - forced webhelpers version since it was making troubles during installation
689 690
690 691 1.1.1 (**2011-01-06**)
691 692 ----------------------
692 693
693 694 news
694 695 ++++
695 696
696 697 - added force https option into ini files for easier https usage (no need to
697 698 set server headers with this options)
698 699 - small css updates
699 700
700 701 fixes
701 702 +++++
702 703
703 704 - fixed #96 redirect loop on files view on repositories without changesets
704 705 - fixed #97 unicode string passed into server header in special cases (mod_wsgi)
705 706 and server crashed with errors
706 707 - fixed large tooltips problems on main page
707 708 - fixed #92 whoosh indexer is more error proof
708 709
709 710 1.1.0 (**2010-12-18**)
710 711 ----------------------
711 712
712 713 news
713 714 ++++
714 715
715 716 - rewrite of internals for vcs >=0.1.10
716 717 - uses mercurial 1.7 with dotencode disabled for maintaining compatibility
717 718 with older clients
718 719 - anonymous access, authentication via ldap
719 720 - performance upgrade for cached repos list - each repository has its own
720 721 cache that's invalidated when needed.
721 722 - performance upgrades on repositories with large amount of commits (20K+)
722 723 - main page quick filter for filtering repositories
723 724 - user dashboards with ability to follow chosen repositories actions
724 725 - sends email to admin on new user registration
725 726 - added cache/statistics reset options into repository settings
726 727 - more detailed action logger (based on hooks) with pushed changesets lists
727 728 and options to disable those hooks from admin panel
728 729 - introduced new enhanced changelog for merges that shows more accurate results
729 730 - new improved and faster code stats (based on pygments lexers mapping tables,
730 731 showing up to 10 trending sources for each repository. Additionally stats
731 732 can be disabled in repository settings.
732 733 - gui optimizations, fixed application width to 1024px
733 734 - added cut off (for large files/changesets) limit into config files
734 735 - whoosh, celeryd, upgrade moved to paster command
735 736 - other than sqlite database backends can be used
736 737
737 738 fixes
738 739 +++++
739 740
740 741 - fixes #61 forked repo was showing only after cache expired
741 742 - fixes #76 no confirmation on user deletes
742 743 - fixes #66 Name field misspelled
743 744 - fixes #72 block user removal when he owns repositories
744 745 - fixes #69 added password confirmation fields
745 746 - fixes #87 RhodeCode crashes occasionally on updating repository owner
746 747 - fixes #82 broken annotations on files with more than 1 blank line at the end
747 748 - a lot of fixes and tweaks for file browser
748 749 - fixed detached session issues
749 750 - fixed when user had no repos he would see all repos listed in my account
750 751 - fixed ui() instance bug when global hgrc settings was loaded for server
751 752 instance and all hgrc options were merged with our db ui() object
752 753 - numerous small bugfixes
753 754
754 755 (special thanks for TkSoh for detailed feedback)
755 756
756 757
757 758 1.0.2 (**2010-11-12**)
758 759 ----------------------
759 760
760 761 news
761 762 ++++
762 763
763 764 - tested under python2.7
764 765 - bumped sqlalchemy and celery versions
765 766
766 767 fixes
767 768 +++++
768 769
769 770 - fixed #59 missing graph.js
770 771 - fixed repo_size crash when repository had broken symlinks
771 772 - fixed python2.5 crashes.
772 773
773 774
774 775 1.0.1 (**2010-11-10**)
775 776 ----------------------
776 777
777 778 news
778 779 ++++
779 780
780 781 - small css updated
781 782
782 783 fixes
783 784 +++++
784 785
785 786 - fixed #53 python2.5 incompatible enumerate calls
786 787 - fixed #52 disable mercurial extension for web
787 788 - fixed #51 deleting repositories don't delete it's dependent objects
788 789
789 790
790 791 1.0.0 (**2010-11-02**)
791 792 ----------------------
792 793
793 794 - security bugfix simplehg wasn't checking for permissions on commands
794 795 other than pull or push.
795 796 - fixed doubled messages after push or pull in admin journal
796 797 - templating and css corrections, fixed repo switcher on chrome, updated titles
797 798 - admin menu accessible from options menu on repository view
798 799 - permissions cached queries
799 800
800 801 1.0.0rc4 (**2010-10-12**)
801 802 --------------------------
802 803
803 804 - fixed python2.5 missing simplejson imports (thanks to Jens BΓ€ckman)
804 805 - removed cache_manager settings from sqlalchemy meta
805 806 - added sqlalchemy cache settings to ini files
806 807 - validated password length and added second try of failure on paster setup-app
807 808 - fixed setup database destroy prompt even when there was no db
808 809
809 810
810 811 1.0.0rc3 (**2010-10-11**)
811 812 -------------------------
812 813
813 814 - fixed i18n during installation.
814 815
815 816 1.0.0rc2 (**2010-10-11**)
816 817 -------------------------
817 818
818 819 - Disabled dirsize in file browser, it's causing nasty bug when dir renames
819 820 occure. After vcs is fixed it'll be put back again.
820 821 - templating/css rewrites, optimized css. No newline at end of file
@@ -1,507 +1,518 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.lib.utils
4 4 ~~~~~~~~~~~~~~~~~~~
5 5
6 6 Some simple helper functions
7 7
8 8 :created_on: Jan 5, 2011
9 9 :author: marcink
10 10 :copyright: (C) 2011-2012 Marcin Kuzminski <marcin@python-works.com>
11 11 :license: GPLv3, see COPYING for more details.
12 12 """
13 13 # This program is free software: you can redistribute it and/or modify
14 14 # it under the terms of the GNU General Public License as published by
15 15 # the Free Software Foundation, either version 3 of the License, or
16 16 # (at your option) any later version.
17 17 #
18 18 # This program is distributed in the hope that it will be useful,
19 19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 21 # GNU General Public License for more details.
22 22 #
23 23 # You should have received a copy of the GNU General Public License
24 24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25 25
26 26 import re
27 27 import time
28 28 import datetime
29 29 from pylons.i18n.translation import _, ungettext
30 30 from rhodecode.lib.vcs.utils.lazy import LazyProperty
31 31
32 32
33 33 def __get_lem():
34 34 """
35 35 Get language extension map based on what's inside pygments lexers
36 36 """
37 37 from pygments import lexers
38 38 from string import lower
39 39 from collections import defaultdict
40 40
41 41 d = defaultdict(lambda: [])
42 42
43 43 def __clean(s):
44 44 s = s.lstrip('*')
45 45 s = s.lstrip('.')
46 46
47 47 if s.find('[') != -1:
48 48 exts = []
49 49 start, stop = s.find('['), s.find(']')
50 50
51 51 for suffix in s[start + 1:stop]:
52 52 exts.append(s[:s.find('[')] + suffix)
53 53 return map(lower, exts)
54 54 else:
55 55 return map(lower, [s])
56 56
57 57 for lx, t in sorted(lexers.LEXERS.items()):
58 58 m = map(__clean, t[-2])
59 59 if m:
60 60 m = reduce(lambda x, y: x + y, m)
61 61 for ext in m:
62 62 desc = lx.replace('Lexer', '')
63 63 d[ext].append(desc)
64 64
65 65 return dict(d)
66 66
67 67 def str2bool(_str):
68 68 """
69 69 returs True/False value from given string, it tries to translate the
70 70 string into boolean
71 71
72 72 :param _str: string value to translate into boolean
73 73 :rtype: boolean
74 74 :returns: boolean from given string
75 75 """
76 76 if _str is None:
77 77 return False
78 78 if _str in (True, False):
79 79 return _str
80 80 _str = str(_str).strip().lower()
81 81 return _str in ('t', 'true', 'y', 'yes', 'on', '1')
82 82
83 83
84 84 def convert_line_endings(line, mode):
85 85 """
86 86 Converts a given line "line end" accordingly to given mode
87 87
88 88 Available modes are::
89 89 0 - Unix
90 90 1 - Mac
91 91 2 - DOS
92 92
93 93 :param line: given line to convert
94 94 :param mode: mode to convert to
95 95 :rtype: str
96 96 :return: converted line according to mode
97 97 """
98 98 from string import replace
99 99
100 100 if mode == 0:
101 101 line = replace(line, '\r\n', '\n')
102 102 line = replace(line, '\r', '\n')
103 103 elif mode == 1:
104 104 line = replace(line, '\r\n', '\r')
105 105 line = replace(line, '\n', '\r')
106 106 elif mode == 2:
107 107 line = re.sub("\r(?!\n)|(?<!\r)\n", "\r\n", line)
108 108 return line
109 109
110 110
111 111 def detect_mode(line, default):
112 112 """
113 113 Detects line break for given line, if line break couldn't be found
114 114 given default value is returned
115 115
116 116 :param line: str line
117 117 :param default: default
118 118 :rtype: int
119 119 :return: value of line end on of 0 - Unix, 1 - Mac, 2 - DOS
120 120 """
121 121 if line.endswith('\r\n'):
122 122 return 2
123 123 elif line.endswith('\n'):
124 124 return 0
125 125 elif line.endswith('\r'):
126 126 return 1
127 127 else:
128 128 return default
129 129
130 130
131 131 def generate_api_key(username, salt=None):
132 132 """
133 133 Generates unique API key for given username, if salt is not given
134 134 it'll be generated from some random string
135 135
136 136 :param username: username as string
137 137 :param salt: salt to hash generate KEY
138 138 :rtype: str
139 139 :returns: sha1 hash from username+salt
140 140 """
141 141 from tempfile import _RandomNameSequence
142 142 import hashlib
143 143
144 144 if salt is None:
145 145 salt = _RandomNameSequence().next()
146 146
147 147 return hashlib.sha1(username + salt).hexdigest()
148 148
149 149
150 150 def safe_int(val, default=None):
151 151 """
152 152 Returns int() of val if val is not convertable to int use default
153 153 instead
154 154
155 155 :param val:
156 156 :param default:
157 157 """
158 158
159 159 try:
160 160 val = int(val)
161 161 except ValueError:
162 162 val = default
163 163
164 164 return val
165 165
166 166
167 167 def safe_unicode(str_, from_encoding=None):
168 168 """
169 169 safe unicode function. Does few trick to turn str_ into unicode
170 170
171 171 In case of UnicodeDecode error we try to return it with encoding detected
172 172 by chardet library if it fails fallback to unicode with errors replaced
173 173
174 174 :param str_: string to decode
175 175 :rtype: unicode
176 176 :returns: unicode object
177 177 """
178 178 if isinstance(str_, unicode):
179 179 return str_
180 180
181 181 if not from_encoding:
182 182 import rhodecode
183 183 DEFAULT_ENCODING = rhodecode.CONFIG.get('default_encoding','utf8')
184 184 from_encoding = DEFAULT_ENCODING
185 185
186 186 try:
187 187 return unicode(str_)
188 188 except UnicodeDecodeError:
189 189 pass
190 190
191 191 try:
192 192 return unicode(str_, from_encoding)
193 193 except UnicodeDecodeError:
194 194 pass
195 195
196 196 try:
197 197 import chardet
198 198 encoding = chardet.detect(str_)['encoding']
199 199 if encoding is None:
200 200 raise Exception()
201 201 return str_.decode(encoding)
202 202 except (ImportError, UnicodeDecodeError, Exception):
203 203 return unicode(str_, from_encoding, 'replace')
204 204
205 205
206 206 def safe_str(unicode_, to_encoding=None):
207 207 """
208 208 safe str function. Does few trick to turn unicode_ into string
209 209
210 210 In case of UnicodeEncodeError we try to return it with encoding detected
211 211 by chardet library if it fails fallback to string with errors replaced
212 212
213 213 :param unicode_: unicode to encode
214 214 :rtype: str
215 215 :returns: str object
216 216 """
217 217
218 218 # if it's not basestr cast to str
219 219 if not isinstance(unicode_, basestring):
220 220 return str(unicode_)
221 221
222 222 if isinstance(unicode_, str):
223 223 return unicode_
224 224
225 225 if not to_encoding:
226 226 import rhodecode
227 227 DEFAULT_ENCODING = rhodecode.CONFIG.get('default_encoding','utf8')
228 228 to_encoding = DEFAULT_ENCODING
229 229
230 230 try:
231 231 return unicode_.encode(to_encoding)
232 232 except UnicodeEncodeError:
233 233 pass
234 234
235 235 try:
236 236 import chardet
237 237 encoding = chardet.detect(unicode_)['encoding']
238 238 if encoding is None:
239 239 raise UnicodeEncodeError()
240 240
241 241 return unicode_.encode(encoding)
242 242 except (ImportError, UnicodeEncodeError):
243 243 return unicode_.encode(to_encoding, 'replace')
244 244
245 245 return safe_str
246 246
247 247
248 248 def engine_from_config(configuration, prefix='sqlalchemy.', **kwargs):
249 249 """
250 250 Custom engine_from_config functions that makes sure we use NullPool for
251 251 file based sqlite databases. This prevents errors on sqlite. This only
252 252 applies to sqlalchemy versions < 0.7.0
253 253
254 254 """
255 255 import sqlalchemy
256 256 from sqlalchemy import engine_from_config as efc
257 257 import logging
258 258
259 259 if int(sqlalchemy.__version__.split('.')[1]) < 7:
260 260
261 261 # This solution should work for sqlalchemy < 0.7.0, and should use
262 262 # proxy=TimerProxy() for execution time profiling
263 263
264 264 from sqlalchemy.pool import NullPool
265 265 url = configuration[prefix + 'url']
266 266
267 267 if url.startswith('sqlite'):
268 268 kwargs.update({'poolclass': NullPool})
269 269 return efc(configuration, prefix, **kwargs)
270 270 else:
271 271 import time
272 272 from sqlalchemy import event
273 273 from sqlalchemy.engine import Engine
274 274
275 275 log = logging.getLogger('sqlalchemy.engine')
276 276 BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE = xrange(30, 38)
277 277 engine = efc(configuration, prefix, **kwargs)
278 278
279 279 def color_sql(sql):
280 280 COLOR_SEQ = "\033[1;%dm"
281 281 COLOR_SQL = YELLOW
282 282 normal = '\x1b[0m'
283 283 return ''.join([COLOR_SEQ % COLOR_SQL, sql, normal])
284 284
285 285 if configuration['debug']:
286 286 #attach events only for debug configuration
287 287
288 288 def before_cursor_execute(conn, cursor, statement,
289 289 parameters, context, executemany):
290 290 context._query_start_time = time.time()
291 291 log.info(color_sql(">>>>> STARTING QUERY >>>>>"))
292 292
293 293 def after_cursor_execute(conn, cursor, statement,
294 294 parameters, context, executemany):
295 295 total = time.time() - context._query_start_time
296 296 log.info(color_sql("<<<<< TOTAL TIME: %f <<<<<" % total))
297 297
298 298 event.listen(engine, "before_cursor_execute",
299 299 before_cursor_execute)
300 300 event.listen(engine, "after_cursor_execute",
301 301 after_cursor_execute)
302 302
303 303 return engine
304 304
305 305
306 306 def age(prevdate):
307 307 """
308 308 turns a datetime into an age string.
309 309
310 310 :param prevdate: datetime object
311 311 :rtype: unicode
312 312 :returns: unicode words describing age
313 313 """
314 314
315 315 order = ['year', 'month', 'day', 'hour', 'minute', 'second']
316 316 deltas = {}
317 future = False
317 318
318 319 # Get date parts deltas
319 320 now = datetime.datetime.now()
321 if prevdate > now:
322 now, prevdate = prevdate, now
323 future = True
324
320 325 for part in order:
321 326 deltas[part] = getattr(now, part) - getattr(prevdate, part)
322 327
323 328 # Fix negative offsets (there is 1 second between 10:59:59 and 11:00:00,
324 329 # not 1 hour, -59 minutes and -59 seconds)
325 330
326 331 for num, length in [(5, 60), (4, 60), (3, 24)]: # seconds, minutes, hours
327 332 part = order[num]
328 333 carry_part = order[num - 1]
329 334
330 335 if deltas[part] < 0:
331 336 deltas[part] += length
332 337 deltas[carry_part] -= 1
333 338
334 339 # Same thing for days except that the increment depends on the (variable)
335 340 # number of days in the month
336 341 month_lengths = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
337 342 if deltas['day'] < 0:
338 343 if prevdate.month == 2 and (prevdate.year % 4 == 0 and
339 344 (prevdate.year % 100 != 0 or prevdate.year % 400 == 0)):
340 345 deltas['day'] += 29
341 346 else:
342 347 deltas['day'] += month_lengths[prevdate.month - 1]
343 348
344 349 deltas['month'] -= 1
345 350
346 351 if deltas['month'] < 0:
347 352 deltas['month'] += 12
348 353 deltas['year'] -= 1
349 354
350 355 # Format the result
351 356 fmt_funcs = {
352 357 'year': lambda d: ungettext(u'%d year', '%d years', d) % d,
353 358 'month': lambda d: ungettext(u'%d month', '%d months', d) % d,
354 359 'day': lambda d: ungettext(u'%d day', '%d days', d) % d,
355 360 'hour': lambda d: ungettext(u'%d hour', '%d hours', d) % d,
356 361 'minute': lambda d: ungettext(u'%d minute', '%d minutes', d) % d,
357 362 'second': lambda d: ungettext(u'%d second', '%d seconds', d) % d,
358 363 }
359 364
360 365 for i, part in enumerate(order):
361 366 value = deltas[part]
362 367 if value == 0:
363 368 continue
364 369
365 370 if i < 5:
366 371 sub_part = order[i + 1]
367 372 sub_value = deltas[sub_part]
368 373 else:
369 374 sub_value = 0
370 375
371 376 if sub_value == 0:
372 return _(u'%s ago') % fmt_funcs[part](value)
373
374 return _(u'%s and %s ago') % (fmt_funcs[part](value),
375 fmt_funcs[sub_part](sub_value))
377 if future:
378 return _(u'in %s') % fmt_funcs[part](value)
379 else:
380 return _(u'%s ago') % fmt_funcs[part](value)
381 if future:
382 return _(u'in %s and %s') % (fmt_funcs[part](value),
383 fmt_funcs[sub_part](sub_value))
384 else:
385 return _(u'%s and %s ago') % (fmt_funcs[part](value),
386 fmt_funcs[sub_part](sub_value))
376 387
377 388 return _(u'just now')
378 389
379 390
380 391 def uri_filter(uri):
381 392 """
382 393 Removes user:password from given url string
383 394
384 395 :param uri:
385 396 :rtype: unicode
386 397 :returns: filtered list of strings
387 398 """
388 399 if not uri:
389 400 return ''
390 401
391 402 proto = ''
392 403
393 404 for pat in ('https://', 'http://'):
394 405 if uri.startswith(pat):
395 406 uri = uri[len(pat):]
396 407 proto = pat
397 408 break
398 409
399 410 # remove passwords and username
400 411 uri = uri[uri.find('@') + 1:]
401 412
402 413 # get the port
403 414 cred_pos = uri.find(':')
404 415 if cred_pos == -1:
405 416 host, port = uri, None
406 417 else:
407 418 host, port = uri[:cred_pos], uri[cred_pos + 1:]
408 419
409 420 return filter(None, [proto, host, port])
410 421
411 422
412 423 def credentials_filter(uri):
413 424 """
414 425 Returns a url with removed credentials
415 426
416 427 :param uri:
417 428 """
418 429
419 430 uri = uri_filter(uri)
420 431 #check if we have port
421 432 if len(uri) > 2 and uri[2]:
422 433 uri[2] = ':' + uri[2]
423 434
424 435 return ''.join(uri)
425 436
426 437
427 438 def get_changeset_safe(repo, rev):
428 439 """
429 440 Safe version of get_changeset if this changeset doesn't exists for a
430 441 repo it returns a Dummy one instead
431 442
432 443 :param repo:
433 444 :param rev:
434 445 """
435 446 from rhodecode.lib.vcs.backends.base import BaseRepository
436 447 from rhodecode.lib.vcs.exceptions import RepositoryError
437 448 from rhodecode.lib.vcs.backends.base import EmptyChangeset
438 449 if not isinstance(repo, BaseRepository):
439 450 raise Exception('You must pass an Repository '
440 451 'object as first argument got %s', type(repo))
441 452
442 453 try:
443 454 cs = repo.get_changeset(rev)
444 455 except RepositoryError:
445 456 cs = EmptyChangeset(requested_revision=rev)
446 457 return cs
447 458
448 459
449 460 def datetime_to_time(dt):
450 461 if dt:
451 462 return time.mktime(dt.timetuple())
452 463
453 464
454 465 def time_to_datetime(tm):
455 466 if tm:
456 467 if isinstance(tm, basestring):
457 468 try:
458 469 tm = float(tm)
459 470 except ValueError:
460 471 return
461 472 return datetime.datetime.fromtimestamp(tm)
462 473
463 474 MENTIONS_REGEX = r'(?:^@|\s@)([a-zA-Z0-9]{1}[a-zA-Z0-9\-\_\.]+)(?:\s{1})'
464 475
465 476
466 477 def extract_mentioned_users(s):
467 478 """
468 479 Returns unique usernames from given string s that have @mention
469 480
470 481 :param s: string to get mentions
471 482 """
472 483 usrs = set()
473 484 for username in re.findall(MENTIONS_REGEX, s):
474 485 usrs.add(username)
475 486
476 487 return sorted(list(usrs), key=lambda k: k.lower())
477 488
478 489
479 490 class AttributeDict(dict):
480 491 def __getattr__(self, attr):
481 492 return self.get(attr, None)
482 493 __setattr__ = dict.__setitem__
483 494 __delattr__ = dict.__delitem__
484 495
485 496
486 497 def fix_PATH(os_=None):
487 498 """
488 499 Get current active python path, and append it to PATH variable to fix issues
489 500 of subprocess calls and different python versions
490 501 """
491 502 import sys
492 503 if os_ is None:
493 504 import os
494 505 else:
495 506 os = os_
496 507
497 508 cur_path = os.path.split(sys.executable)[0]
498 509 if not os.environ['PATH'].startswith(cur_path):
499 510 os.environ['PATH'] = '%s:%s' % (cur_path, os.environ['PATH'])
500 511
501 512
502 513 def obfuscate_url_pw(engine):
503 514 from sqlalchemy.engine import url
504 515 url = url.make_url(engine)
505 516 if url.password:
506 517 url.password = 'XXXXX'
507 return str(url) No newline at end of file
518 return str(url)
@@ -1,198 +1,213 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.tests.test_libs
4 4 ~~~~~~~~~~~~~~~~~~~~~~~~~
5 5
6 6
7 7 Package for testing various lib/helper functions in rhodecode
8 8
9 9 :created_on: Jun 9, 2011
10 10 :copyright: (C) 2011-2012 Marcin Kuzminski <marcin@python-works.com>
11 11 :license: GPLv3, see COPYING for more details.
12 12 """
13 13 # This program is free software: you can redistribute it and/or modify
14 14 # it under the terms of the GNU General Public License as published by
15 15 # the Free Software Foundation, either version 3 of the License, or
16 16 # (at your option) any later version.
17 17 #
18 18 # This program is distributed in the hope that it will be useful,
19 19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 21 # GNU General Public License for more details.
22 22 #
23 23 # You should have received a copy of the GNU General Public License
24 24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25 25 from __future__ import with_statement
26 26 import unittest
27 27 import datetime
28 28 import hashlib
29 29 import mock
30 30 from rhodecode.tests import *
31 31
32 32 proto = 'http'
33 33 TEST_URLS = [
34 34 ('%s://127.0.0.1' % proto, ['%s://' % proto, '127.0.0.1'],
35 35 '%s://127.0.0.1' % proto),
36 36 ('%s://marcink@127.0.0.1' % proto, ['%s://' % proto, '127.0.0.1'],
37 37 '%s://127.0.0.1' % proto),
38 38 ('%s://marcink:pass@127.0.0.1' % proto, ['%s://' % proto, '127.0.0.1'],
39 39 '%s://127.0.0.1' % proto),
40 40 ('%s://127.0.0.1:8080' % proto, ['%s://' % proto, '127.0.0.1', '8080'],
41 41 '%s://127.0.0.1:8080' % proto),
42 42 ('%s://domain.org' % proto, ['%s://' % proto, 'domain.org'],
43 43 '%s://domain.org' % proto),
44 44 ('%s://user:pass@domain.org:8080' % proto, ['%s://' % proto, 'domain.org',
45 45 '8080'],
46 46 '%s://domain.org:8080' % proto),
47 47 ]
48 48
49 49 proto = 'https'
50 50 TEST_URLS += [
51 51 ('%s://127.0.0.1' % proto, ['%s://' % proto, '127.0.0.1'],
52 52 '%s://127.0.0.1' % proto),
53 53 ('%s://marcink@127.0.0.1' % proto, ['%s://' % proto, '127.0.0.1'],
54 54 '%s://127.0.0.1' % proto),
55 55 ('%s://marcink:pass@127.0.0.1' % proto, ['%s://' % proto, '127.0.0.1'],
56 56 '%s://127.0.0.1' % proto),
57 57 ('%s://127.0.0.1:8080' % proto, ['%s://' % proto, '127.0.0.1', '8080'],
58 58 '%s://127.0.0.1:8080' % proto),
59 59 ('%s://domain.org' % proto, ['%s://' % proto, 'domain.org'],
60 60 '%s://domain.org' % proto),
61 61 ('%s://user:pass@domain.org:8080' % proto, ['%s://' % proto, 'domain.org',
62 62 '8080'],
63 63 '%s://domain.org:8080' % proto),
64 64 ]
65 65
66 66
67 67 class TestLibs(unittest.TestCase):
68 68
69 69 def test_uri_filter(self):
70 70 from rhodecode.lib.utils2 import uri_filter
71 71
72 72 for url in TEST_URLS:
73 73 self.assertEqual(uri_filter(url[0]), url[1])
74 74
75 75 def test_credentials_filter(self):
76 76 from rhodecode.lib.utils2 import credentials_filter
77 77
78 78 for url in TEST_URLS:
79 79 self.assertEqual(credentials_filter(url[0]), url[2])
80 80
81 81 def test_str2bool(self):
82 82 from rhodecode.lib.utils2 import str2bool
83 83 test_cases = [
84 84 ('t', True),
85 85 ('true', True),
86 86 ('y', True),
87 87 ('yes', True),
88 88 ('on', True),
89 89 ('1', True),
90 90 ('Y', True),
91 91 ('yeS', True),
92 92 ('Y', True),
93 93 ('TRUE', True),
94 94 ('T', True),
95 95 ('False', False),
96 96 ('F', False),
97 97 ('FALSE', False),
98 98 ('0', False),
99 99 ('-1', False),
100 100 ('', False), ]
101 101
102 102 for case in test_cases:
103 103 self.assertEqual(str2bool(case[0]), case[1])
104 104
105 105 def test_mention_extractor(self):
106 106 from rhodecode.lib.utils2 import extract_mentioned_users
107 107 sample = (
108 108 "@first hi there @marcink here's my email marcin@email.com "
109 109 "@lukaszb check @one_more22 it pls @ ttwelve @D[] @one@two@three "
110 110 "@MARCIN @maRCiN @2one_more22 @john please see this http://org.pl "
111 111 "@marian.user just do it @marco-polo and next extract @marco_polo "
112 112 "user.dot hej ! not-needed maril@domain.org"
113 113 )
114 114
115 115 s = sorted([
116 116 'first', 'marcink', 'lukaszb', 'one_more22', 'MARCIN', 'maRCiN', 'john',
117 117 'marian.user', 'marco-polo', 'marco_polo'
118 118 ], key=lambda k: k.lower())
119 119 self.assertEqual(s, extract_mentioned_users(sample))
120 120
121 121 def test_age(self):
122 122 import calendar
123 123 from rhodecode.lib.utils2 import age
124 124 n = datetime.datetime.now()
125 125 delt = lambda *args, **kwargs: datetime.timedelta(*args, **kwargs)
126 126 self.assertEqual(age(n), u'just now')
127 127 self.assertEqual(age(n - delt(seconds=1)), u'1 second ago')
128 128 self.assertEqual(age(n - delt(seconds=60 * 2)), u'2 minutes ago')
129 129 self.assertEqual(age(n - delt(hours=1)), u'1 hour ago')
130 130 self.assertEqual(age(n - delt(hours=24)), u'1 day ago')
131 131 self.assertEqual(age(n - delt(hours=24 * 5)), u'5 days ago')
132 self.assertEqual(age(n - delt(hours=24 * (calendar.mdays[n.month-1] + 2))),
132 self.assertEqual(age(n - delt(hours=24 * (calendar.mdays[n.month - 1] + 2))),
133 133 u'1 month and 2 days ago')
134 134 self.assertEqual(age(n - delt(hours=24 * 400)), u'1 year and 1 month ago')
135 135
136 def test_age_in_future(self):
137 import calendar
138 from rhodecode.lib.utils2 import age
139 n = datetime.datetime.now()
140 delt = lambda *args, **kwargs: datetime.timedelta(*args, **kwargs)
141 self.assertEqual(age(n), u'just now')
142 self.assertEqual(age(n + delt(seconds=1)), u'in 1 second')
143 self.assertEqual(age(n + delt(seconds=60 * 2)), u'in 2 minutes')
144 self.assertEqual(age(n + delt(hours=1)), u'in 1 hour')
145 self.assertEqual(age(n + delt(hours=24)), u'in 1 day')
146 self.assertEqual(age(n + delt(hours=24 * 5)), u'in 5 days')
147 self.assertEqual(age(n + delt(hours=24 * (calendar.mdays[n.month - 1] + 2))),
148 u'in 1 month and 1 days')
149 self.assertEqual(age(n + delt(hours=24 * 400)), u'in 1 year and 1 month')
150
136 151 def test_tag_exctrator(self):
137 152 sample = (
138 153 "hello pta[tag] gog [[]] [[] sda ero[or]d [me =>>< sa]"
139 154 "[requires] [stale] [see<>=>] [see => http://url.com]"
140 155 "[requires => url] [lang => python] [just a tag]"
141 156 "[,d] [ => ULR ] [obsolete] [desc]]"
142 157 )
143 158 from rhodecode.lib.helpers import desc_stylize
144 159 res = desc_stylize(sample)
145 160 self.assertTrue('<div class="metatag" tag="tag">tag</div>' in res)
146 161 self.assertTrue('<div class="metatag" tag="obsolete">obsolete</div>' in res)
147 162 self.assertTrue('<div class="metatag" tag="stale">stale</div>' in res)
148 163 self.assertTrue('<div class="metatag" tag="lang">python</div>' in res)
149 164 self.assertTrue('<div class="metatag" tag="requires">requires =&gt; <a href="/url">url</a></div>' in res)
150 165 self.assertTrue('<div class="metatag" tag="tag">tag</div>' in res)
151 166
152 167 def test_alternative_gravatar(self):
153 168 from rhodecode.lib.helpers import gravatar_url
154 169 _md5 = lambda s: hashlib.md5(s).hexdigest()
155 170
156 171 def fake_conf(**kwargs):
157 172 from pylons import config
158 173 config['app_conf'] = {}
159 174 config['app_conf']['use_gravatar'] = True
160 175 config['app_conf'].update(kwargs)
161 176 return config
162 177
163 178 class fake_url():
164 179 @classmethod
165 180 def current(cls, *args, **kwargs):
166 181 return 'https://server.com'
167 182
168 183 with mock.patch('pylons.url', fake_url):
169 184 fake = fake_conf(alternative_gravatar_url='http://test.com/{email}')
170 185 with mock.patch('pylons.config', fake):
171 186 from pylons import url
172 187 assert url.current() == 'https://server.com'
173 188 grav = gravatar_url(email_address='test@foo.com', size=24)
174 189 assert grav == 'http://test.com/test@foo.com'
175 190
176 191 fake = fake_conf(alternative_gravatar_url='http://test.com/{email}')
177 192 with mock.patch('pylons.config', fake):
178 193 grav = gravatar_url(email_address='test@foo.com', size=24)
179 194 assert grav == 'http://test.com/test@foo.com'
180 195
181 196 fake = fake_conf(alternative_gravatar_url='http://test.com/{md5email}')
182 197 with mock.patch('pylons.config', fake):
183 198 em = 'test@foo.com'
184 199 grav = gravatar_url(email_address=em, size=24)
185 200 assert grav == 'http://test.com/%s' % (_md5(em))
186 201
187 202 fake = fake_conf(alternative_gravatar_url='http://test.com/{md5email}/{size}')
188 203 with mock.patch('pylons.config', fake):
189 204 em = 'test@foo.com'
190 205 grav = gravatar_url(email_address=em, size=24)
191 206 assert grav == 'http://test.com/%s/%s' % (_md5(em), 24)
192 207
193 208 fake = fake_conf(alternative_gravatar_url='{scheme}://{netloc}/{md5email}/{size}')
194 209 with mock.patch('pylons.config', fake):
195 210 em = 'test@foo.com'
196 211 grav = gravatar_url(email_address=em, size=24)
197 212 assert grav == 'https://server.com/%s/%s' % (_md5(em), 24)
198 213
General Comments 0
You need to be logged in to leave comments. Login now