##// END OF EJS Templates
merge upstream
Aras Pranckevicius -
r1861:3f5be4db merge beta
parent child Browse files
Show More
@@ -1,6 +1,6 b''
1 =================================================
2 Welcome to RhodeCode (RhodiumCode) documentation!
3 =================================================
1 ========================
2 RhodeCode documentation!
3 ========================
4 4
5 5 ``RhodeCode`` is a fast and powerful management tool for Mercurial_ and GIT_
6 6 with a built in push/pull server and full text search.
@@ -102,7 +102,6 b' Incoming / Plans'
102 102 - pull requests and web based merges
103 103 - per line file history
104 104 - SSH based authentication with server side key management
105 - Redmine and other bugtrackers integration
106 105 - Commit based built in wiki system
107 106 - More statistics and graph (global annotation + some more statistics)
108 107 - Other advancements as development continues (or you can of course make
@@ -58,13 +58,34 b' container_auth_enabled = false'
58 58 proxypass_auth_enabled = false
59 59
60 60 ## overwrite schema of clone url
61 # available vars:
62 # scheme - http/https
63 # user - current user
64 # pass - password
65 # netloc - network location
66 # path - usually repo_name
67 # clone_uri = {scheme}://{user}{pass}{netloc}{path}
61 ## available vars:
62 ## scheme - http/https
63 ## user - current user
64 ## pass - password
65 ## netloc - network location
66 ## path - usually repo_name
67
68 #clone_uri = {scheme}://{user}{pass}{netloc}{path}
69
70 ## issue tracking mapping for commits messages
71 ## uncomment url_pat, issue_server, issue_prefix to enable
72
73
74 ## pattern to get the issues from commit messages
75 ## default one used here is #1234
76
77 #url_pat = (?:^#|\s#)(\w+)
78
79 ## server url to the issue, each {id} will be replaced with id
80 ## fetched from the regex
81
82 #issue_server = https://myissueserver.com/issue/{id}
83
84 ## prefix to add to link to indicate it's an url
85 ## #314 will be replaced by <issue_prefix><id>
86
87 #issue_prefix = #
88
68 89
69 90 ####################################
70 91 ### CELERY CONFIG ####
@@ -10,6 +10,8 b" There's a single schema for calling all "
10 10 with JSON protocol both ways. An url to send API request in RhodeCode is
11 11 <your_server>/_admin/api
12 12
13 API ACCESS FOR WEB VIEWS
14 ++++++++++++++++++++++++
13 15
14 16 API access can also be turned on for each view decorated with `@LoginRequired`
15 17 decorator. To enable API access simple change standard login decorator into
@@ -18,6 +20,9 b' by adding a GET parameter to url `?api_k'
18 20 enabled on RSS/ATOM feed views.
19 21
20 22
23 API ACCESS
24 ++++++++++
25
21 26 All clients are required to send JSON-RPC spec JSON data::
22 27
23 28 {
@@ -69,15 +74,47 b' INPUT::'
69 74 api_key : "<api_key>"
70 75 method : "pull"
71 76 args : {
72 "repo" : "<repo_name>"
77 "repo_name" : "<reponame>"
73 78 }
74 79
75 80 OUTPUT::
76 81
77 result : "Pulled from <repo_name>"
82 result : "Pulled from <reponame>"
78 83 error : null
79 84
80 85
86 get_user
87 --------
88
89 Get's an user by username, Returns empty result if user is not found.
90 This command can be executed only using api_key belonging to user with admin
91 rights.
92
93 INPUT::
94
95 api_key : "<api_key>"
96 method : "get_user"
97 args : {
98 "username" : "<username>"
99 }
100
101 OUTPUT::
102
103 result: None if user does not exist or
104 {
105 "id" : "<id>",
106 "username" : "<username>",
107 "firstname": "<firstname>",
108 "lastname" : "<lastname>",
109 "email" : "<email>",
110 "active" : "<bool>",
111 "admin" :  "<bool>",
112 "ldap" : "<ldap_dn>"
113 }
114
115 error: null
116
117
81 118 get_users
82 119 ---------
83 120
@@ -131,46 +168,11 b' INPUT::'
131 168 OUTPUT::
132 169
133 170 result: {
171 "id" : "<new_user_id>",
134 172 "msg" : "created new user <username>"
135 173 }
136 174 error: null
137 175
138 get_users_groups
139 ----------------
140
141 Lists all existing users groups. This command can be executed only using api_key
142 belonging to user with admin rights.
143
144 INPUT::
145
146 api_key : "<api_key>"
147 method : "get_users_groups"
148 args : { }
149
150 OUTPUT::
151
152 result : [
153 {
154 "id" : "<id>",
155 "name" : "<name>",
156 "active": "<bool>",
157 "members" : [
158 {
159 "id" : "<userid>",
160 "username" : "<username>",
161 "firstname": "<firstname>",
162 "lastname" : "<lastname>",
163 "email" : "<email>",
164 "active" : "<bool>",
165 "admin" :  "<bool>",
166 "ldap" : "<ldap_dn>"
167 },
168
169 ]
170 }
171 ]
172 error : null
173
174 176 get_users_group
175 177 ---------------
176 178
@@ -189,24 +191,61 b' OUTPUT::'
189 191
190 192 result : None if group not exist
191 193 {
192 "id" : "<id>",
193 "name" : "<name>",
194 "active": "<bool>",
194 "id" : "<id>",
195 "group_name" : "<groupname>",
196 "active": "<bool>",
195 197 "members" : [
196 { "id" : "<userid>",
197 "username" : "<username>",
198 "firstname": "<firstname>",
199 "lastname" : "<lastname>",
200 "email" : "<email>",
201 "active" : "<bool>",
202 "admin" :  "<bool>",
203 "ldap" : "<ldap_dn>"
204 },
205
206 ]
198 { "id" : "<userid>",
199 "username" : "<username>",
200 "firstname": "<firstname>",
201 "lastname" : "<lastname>",
202 "email" : "<email>",
203 "active" : "<bool>",
204 "admin" :  "<bool>",
205 "ldap" : "<ldap_dn>"
206 },
207
208 ]
207 209 }
208 210 error : null
209 211
212 get_users_groups
213 ----------------
214
215 Lists all existing users groups. This command can be executed only using
216 api_key belonging to user with admin rights.
217
218 INPUT::
219
220 api_key : "<api_key>"
221 method : "get_users_groups"
222 args : { }
223
224 OUTPUT::
225
226 result : [
227 {
228 "id" : "<id>",
229 "group_name" : "<groupname>",
230 "active": "<bool>",
231 "members" : [
232 {
233 "id" : "<userid>",
234 "username" : "<username>",
235 "firstname": "<firstname>",
236 "lastname" : "<lastname>",
237 "email" : "<email>",
238 "active" : "<bool>",
239 "admin" :  "<bool>",
240 "ldap" : "<ldap_dn>"
241 },
242
243 ]
244 }
245 ]
246 error : null
247
248
210 249 create_users_group
211 250 ------------------
212 251
@@ -218,7 +257,7 b' INPUT::'
218 257 api_key : "<api_key>"
219 258 method : "create_users_group"
220 259 args: {
221 "name": "<name>",
260 "group_name": "<groupname>",
222 261 "active":"<bool> = True"
223 262 }
224 263
@@ -226,7 +265,7 b' OUTPUT::'
226 265
227 266 result: {
228 267 "id": "<newusersgroupid>",
229 "msg": "created new users group <name>"
268 "msg": "created new users group <groupname>"
230 269 }
231 270 error: null
232 271
@@ -253,6 +292,51 b' OUTPUT::'
253 292 }
254 293 error: null
255 294
295 get_repo
296 --------
297
298 Gets an existing repository. This command can be executed only using api_key
299 belonging to user with admin rights
300
301 INPUT::
302
303 api_key : "<api_key>"
304 method : "get_repo"
305 args: {
306 "repo_name" : "<reponame>"
307 }
308
309 OUTPUT::
310
311 result: None if repository does not exist or
312 {
313 "id" : "<id>",
314 "repo_name" : "<reponame>"
315 "type" : "<type>",
316 "description" : "<description>",
317 "members" : [
318 { "id" : "<userid>",
319 "username" : "<username>",
320 "firstname": "<firstname>",
321 "lastname" : "<lastname>",
322 "email" : "<email>",
323 "active" : "<bool>",
324 "admin" :  "<bool>",
325 "ldap" : "<ldap_dn>",
326 "permission" : "repository.(read|write|admin)"
327 },
328
329 {
330 "id" : "<usersgroupid>",
331 "name" : "<usersgroupname>",
332 "active": "<bool>",
333 "permission" : "repository.(read|write|admin)"
334 },
335
336 ]
337 }
338 error: null
339
256 340 get_repos
257 341 ---------
258 342
@@ -270,7 +354,7 b' OUTPUT::'
270 354 result: [
271 355 {
272 356 "id" : "<id>",
273 "name" : "<name>"
357 "repo_name" : "<reponame>"
274 358 "type" : "<type>",
275 359 "description" : "<description>"
276 360 },
@@ -278,57 +362,13 b' OUTPUT::'
278 362 ]
279 363 error: null
280 364
281 get_repo
282 --------
283
284 Gets an existing repository. This command can be executed only using api_key
285 belonging to user with admin rights
286
287 INPUT::
288
289 api_key : "<api_key>"
290 method : "get_repo"
291 args: {
292 "name" : "<name>"
293 }
294
295 OUTPUT::
296
297 result: None if repository not exist
298 {
299 "id" : "<id>",
300 "name" : "<name>"
301 "type" : "<type>",
302 "description" : "<description>",
303 "members" : [
304 { "id" : "<userid>",
305 "username" : "<username>",
306 "firstname": "<firstname>",
307 "lastname" : "<lastname>",
308 "email" : "<email>",
309 "active" : "<bool>",
310 "admin" :  "<bool>",
311 "ldap" : "<ldap_dn>",
312 "permission" : "repository.(read|write|admin)"
313 },
314
315 {
316 "id" : "<usersgroupid>",
317 "name" : "<usersgroupname>",
318 "active": "<bool>",
319 "permission" : "repository.(read|write|admin)"
320 },
321
322 ]
323 }
324 error: null
325 365
326 366 get_repo_nodes
327 367 --------------
328 368
329 369 returns a list of nodes and it's children in a flat list for a given path
330 at given revision. It's possible to specify ret_type to show only files or
331 dirs. This command can be executed only using api_key belonging to user
370 at given revision. It's possible to specify ret_type to show only `files` or
371 `dirs`. This command can be executed only using api_key belonging to user
332 372 with admin rights
333 373
334 374 INPUT::
@@ -336,7 +376,7 b' INPUT::'
336 376 api_key : "<api_key>"
337 377 method : "get_repo_nodes"
338 378 args: {
339 "repo_name" : "<name>",
379 "repo_name" : "<reponame>",
340 380 "revision" : "<revision>",
341 381 "root_path" : "<root_path>",
342 382 "ret_type" : "<ret_type>" = 'all'
@@ -369,7 +409,7 b' INPUT::'
369 409 api_key : "<api_key>"
370 410 method : "create_repo"
371 411 args: {
372 "name" : "<name>",
412 "repo_name" : "<reponame>",
373 413 "owner_name" : "<ownername>",
374 414 "description" : "<description> = ''",
375 415 "repo_type" : "<type> = 'hg'",
@@ -378,7 +418,10 b' INPUT::'
378 418
379 419 OUTPUT::
380 420
381 result: None
421 result: {
422 "id": "<newrepoid>",
423 "msg": "Created new repository <reponame>",
424 }
382 425 error: null
383 426
384 427 add_user_to_repo
@@ -394,13 +437,15 b' INPUT::'
394 437 method : "add_user_to_repo"
395 438 args: {
396 439 "repo_name" : "<reponame>",
397 "username" : "<username>",
440 "username" : "<username>",
398 441 "perm" : "(None|repository.(read|write|admin))",
399 442 }
400 443
401 444 OUTPUT::
402 445
403 result: None
446 result: {
447 "msg" : "Added perm: <perm> for <username> in repo: <reponame>"
448 }
404 449 error: null
405 450
406 451 add_users_group_to_repo
@@ -416,6 +461,12 b' INPUT::'
416 461 method : "add_users_group_to_repo"
417 462 args: {
418 463 "repo_name" : "<reponame>",
419 "group_name" : "<groupname>",
464 "group_name" : "<groupname>",
420 465 "perm" : "(None|repository.(read|write|admin))",
421 } No newline at end of file
466 }
467 OUTPUT::
468
469 result: {
470 "msg" : Added perm: <perm> for <groupname> in repo: <reponame>"
471 }
472
@@ -1,4 +1,4 b''
1 .. _api:
1 .. _indexapi:
2 2
3 3 API Reference
4 4 =============
@@ -6,14 +6,29 b' The :mod:`models` Module'
6 6 .. automodule:: rhodecode.model
7 7 :members:
8 8
9 .. automodule:: rhodecode.model.comment
10 :members:
11
12 .. automodule:: rhodecode.model.notification
13 :members:
14
9 15 .. automodule:: rhodecode.model.permission
10 16 :members:
11
17
18 .. automodule:: rhodecode.model.repo_permission
19 :members:
20
12 21 .. automodule:: rhodecode.model.repo
13 22 :members:
14 23
24 .. automodule:: rhodecode.model.repos_group
25 :members:
26
15 27 .. automodule:: rhodecode.model.scm
16 28 :members:
17
29
18 30 .. automodule:: rhodecode.model.user
19 31 :members:
32
33 .. automodule:: rhodecode.model.users_group
34 :members: No newline at end of file
@@ -33,7 +33,9 b' news'
33 33 - implements #330 api method for listing nodes ar particular revision
34 34 - fixed #331 RhodeCode mangles repository names if the a repository group
35 35 contains the "full path" to the repositories
36
36 - #73 added linking issues in commit messages to choosen issue tracker url
37 based on user defined regular expression
38
37 39 fixes
38 40 -----
39 41
@@ -2,8 +2,8 b''
2 2
3 3 .. include:: ./../README.rst
4 4
5 Documentation
6 -------------
5 Users Guide
6 -----------
7 7
8 8 **Installation:**
9 9
@@ -23,7 +23,6 b' Documentation'
23 23 usage/enable_git
24 24 usage/statistics
25 25 usage/backup
26 usage/api_key_access
27 26
28 27 **Develop**
29 28
@@ -36,7 +35,7 b' Documentation'
36 35 **API**
37 36
38 37 .. toctree::
39 :maxdepth: 2
38 :maxdepth: 1
40 39
41 40 api/index
42 41
@@ -425,7 +425,25 b' the following in the [app:main] section '
425 425 forge the authentication header and could effectively become authenticated
426 426 using any account of their liking.
427 427
428 Integration with Issue trackers
429 -------------------------------
428 430
431 RhodeCode provides a simple integration with issue trackers. It's possible
432 to define a regular expression that will fetch issue id stored in commit
433 messages and replace that with an url to this issue. To enable this simply
434 uncomment following variables in the ini file::
435
436 url_pat = (?:^#|\s#)(\w+)
437 issue_server = https://myissueserver.com/issue/{id}
438 issue_prefix = #
439
440 `url_pat` is the regular expression that will match issues, default given regex
441 will match issues in format of #<number> eg. #300.
442 Matched issues will be replace with the `issue_server` url replacing {id} with
443 id fetched from regex. Since the # is striped `issue_prefix` is added as a
444 prefix to url. `issue_prefix` can be something different than # if you pass
445 ISSUE- as issue prefix this will generate an url in format
446 `<a href="https://myissueserver.com/issue/300">ISSUE-300</a>`
429 447
430 448 Hook management
431 449 ---------------
@@ -58,13 +58,34 b' container_auth_enabled = false'
58 58 proxypass_auth_enabled = false
59 59
60 60 ## overwrite schema of clone url
61 # available vars:
62 # scheme - http/https
63 # user - current user
64 # pass - password
65 # netloc - network location
66 # path - usually repo_name
67 # clone_uri = {scheme}://{user}{pass}{netloc}{path}
61 ## available vars:
62 ## scheme - http/https
63 ## user - current user
64 ## pass - password
65 ## netloc - network location
66 ## path - usually repo_name
67
68 #clone_uri = {scheme}://{user}{pass}{netloc}{path}
69
70 ## issue tracking mapping for commits messages
71 ## uncomment url_pat, issue_server, issue_prefix to enable
72
73
74 ## pattern to get the issues from commit messages
75 ## default one used here is #1234
76
77 #url_pat = (?:^#|\s#)(\w+)
78
79 ## server url to the issue, each {id} will be replaced with id
80 ## fetched from the regex
81
82 #issue_server = https://myissueserver.com/issue/{id}
83
84 ## prefix to add to link to indicate it's an url
85 ## #314 will be replaced by <issue_prefix><id>
86
87 #issue_prefix = #
88
68 89
69 90 ####################################
70 91 ### CELERY CONFIG ####
@@ -58,14 +58,35 b' container_auth_enabled = false'
58 58 proxypass_auth_enabled = false
59 59
60 60 ## overwrite schema of clone url
61 # available vars:
62 # scheme - http/https
63 # user - current user
64 # pass - password
65 # netloc - network location
66 # path - usually repo_name
61 ## available vars:
62 ## scheme - http/https
63 ## user - current user
64 ## pass - password
65 ## netloc - network location
66 ## path - usually repo_name
67
67 68 # clone_uri = {scheme}://{user}{pass}{netloc}{path}
68 69
70 ## issue tracking mapping for commits messages
71 ## uncomment url_pat, issue_server, issue_prefix to enable
72
73
74 ## pattern to get the issues from commit messages
75 ## default one used here is #1234
76
77 #url_pat = (?:^#|\s#)(\w+)
78
79 ## server url to the issue, each {id} will be replaced with id
80 ## fetched from the regex
81
82 #issue_server = https://myissueserver.com/issue/{id}
83
84 ## prefix to add to link to indicate it's an url
85 ## #314 will be replaced by <issue_prefix><id>
86
87 #issue_prefix = #
88
89
69 90 ####################################
70 91 ### CELERY CONFIG ####
71 92 ####################################
@@ -64,23 +64,23 b' class ApiController(JSONRPCController):'
64 64 """
65 65
66 66 @HasPermissionAllDecorator('hg.admin')
67 def pull(self, apiuser, repo):
67 def pull(self, apiuser, repo_name):
68 68 """
69 69 Dispatch pull action on given repo
70 70
71 71
72 72 :param user:
73 :param repo:
73 :param repo_name:
74 74 """
75 75
76 if Repository.is_valid(repo) is False:
77 raise JSONRPCError('Unknown repo "%s"' % repo)
76 if Repository.is_valid(repo_name) is False:
77 raise JSONRPCError('Unknown repo "%s"' % repo_name)
78 78
79 79 try:
80 ScmModel().pull_changes(repo, self.rhodecode_user.username)
81 return 'Pulled from %s' % repo
80 ScmModel().pull_changes(repo_name, self.rhodecode_user.username)
81 return 'Pulled from %s' % repo_name
82 82 except Exception:
83 raise JSONRPCError('Unable to pull changes from "%s"' % repo)
83 raise JSONRPCError('Unable to pull changes from "%s"' % repo_name)
84 84
85 85 @HasPermissionAllDecorator('hg.admin')
86 86 def get_user(self, apiuser, username):
@@ -151,10 +151,15 b' class ApiController(JSONRPCController):'
151 151 raise JSONRPCError("user %s already exist" % username)
152 152
153 153 try:
154 UserModel().create_or_update(username, password, email, firstname,
155 lastname, active, admin, ldap_dn)
154 usr = UserModel().create_or_update(
155 username, password, email, firstname,
156 lastname, active, admin, ldap_dn
157 )
156 158 Session.commit()
157 return dict(msg='created new user %s' % username)
159 return dict(
160 id=usr.user_id,
161 msg='created new user %s' % username
162 )
158 163 except Exception:
159 164 log.error(traceback.format_exc())
160 165 raise JSONRPCError('failed to create user %s' % username)
@@ -185,7 +190,7 b' class ApiController(JSONRPCController):'
185 190 ldap=user.ldap_dn))
186 191
187 192 return dict(id=users_group.users_group_id,
188 name=users_group.users_group_name,
193 group_name=users_group.users_group_name,
189 194 active=users_group.users_group_active,
190 195 members=members)
191 196
@@ -212,31 +217,31 b' class ApiController(JSONRPCController):'
212 217 ldap=user.ldap_dn))
213 218
214 219 result.append(dict(id=users_group.users_group_id,
215 name=users_group.users_group_name,
220 group_name=users_group.users_group_name,
216 221 active=users_group.users_group_active,
217 222 members=members))
218 223 return result
219 224
220 225 @HasPermissionAllDecorator('hg.admin')
221 def create_users_group(self, apiuser, name, active=True):
226 def create_users_group(self, apiuser, group_name, active=True):
222 227 """
223 228 Creates an new usergroup
224 229
225 :param name:
230 :param group_name:
226 231 :param active:
227 232 """
228 233
229 if self.get_users_group(apiuser, name):
230 raise JSONRPCError("users group %s already exist" % name)
234 if self.get_users_group(apiuser, group_name):
235 raise JSONRPCError("users group %s already exist" % group_name)
231 236
232 237 try:
233 ug = UsersGroupModel().create(name=name, active=active)
238 ug = UsersGroupModel().create(name=group_name, active=active)
234 239 Session.commit()
235 240 return dict(id=ug.users_group_id,
236 msg='created new users group %s' % name)
241 msg='created new users group %s' % group_name)
237 242 except Exception:
238 243 log.error(traceback.format_exc())
239 raise JSONRPCError('failed to create group %s' % name)
244 raise JSONRPCError('failed to create group %s' % group_name)
240 245
241 246 @HasPermissionAllDecorator('hg.admin')
242 247 def add_user_to_users_group(self, apiuser, group_name, username):
@@ -312,7 +317,7 b' class ApiController(JSONRPCController):'
312 317
313 318 return dict(
314 319 id=repo.repo_id,
315 name=repo.repo_name,
320 repo_name=repo.repo_name,
316 321 type=repo.repo_type,
317 322 description=repo.description,
318 323 members=members
@@ -331,7 +336,7 b' class ApiController(JSONRPCController):'
331 336 result.append(
332 337 dict(
333 338 id=repository.repo_id,
334 name=repository.repo_name,
339 repo_name=repository.repo_name,
335 340 type=repository.repo_type,
336 341 description=repository.description
337 342 )
@@ -367,13 +372,13 b' class ApiController(JSONRPCController):'
367 372 raise JSONRPCError(e)
368 373
369 374 @HasPermissionAnyDecorator('hg.admin', 'hg.create.repository')
370 def create_repo(self, apiuser, name, owner_name, description='',
375 def create_repo(self, apiuser, repo_name, owner_name, description='',
371 376 repo_type='hg', private=False):
372 377 """
373 378 Create a repository
374 379
375 380 :param apiuser:
376 :param name:
381 :param repo_name:
377 382 :param description:
378 383 :param type:
379 384 :param private:
@@ -386,10 +391,10 b' class ApiController(JSONRPCController):'
386 391 except NoResultFound:
387 392 raise JSONRPCError('unknown user %s' % owner)
388 393
389 if self.get_repo(apiuser, name):
390 raise JSONRPCError("repo %s already exist" % name)
394 if Repository.get_by_repo_name(repo_name):
395 raise JSONRPCError("repo %s already exist" % repo_name)
391 396
392 groups = name.split('/')
397 groups = repo_name.split('/')
393 398 real_name = groups[-1]
394 399 groups = groups[:-1]
395 400 parent_id = None
@@ -405,10 +410,10 b' class ApiController(JSONRPCController):'
405 410 )
406 411 parent_id = group.group_id
407 412
408 RepoModel().create(
413 repo = RepoModel().create(
409 414 dict(
410 415 repo_name=real_name,
411 repo_name_full=name,
416 repo_name_full=repo_name,
412 417 description=description,
413 418 private=private,
414 419 repo_type=repo_type,
@@ -418,9 +423,15 b' class ApiController(JSONRPCController):'
418 423 owner
419 424 )
420 425 Session.commit()
426
427 return dict(
428 id=repo.repo_id,
429 msg="Created new repository %s" % repo.repo_name
430 )
431
421 432 except Exception:
422 433 log.error(traceback.format_exc())
423 raise JSONRPCError('failed to create repository %s' % name)
434 raise JSONRPCError('failed to create repository %s' % repo_name)
424 435
425 436 @HasPermissionAnyDecorator('hg.admin')
426 437 def add_user_to_repo(self, apiuser, repo_name, username, perm):
@@ -97,6 +97,13 b' class DbManage(object):'
97 97 from rhodecode.lib.dbmigrate.migrate.exceptions import \
98 98 DatabaseNotControlledError
99 99
100 if 'sqlite' in self.dburi:
101 print (
102 '********************** WARNING **********************\n'
103 'Make sure your version of sqlite is at least 3.7.X. \n'
104 'Earlier versions are known to fail on some migrations\n'
105 '*****************************************************\n'
106 )
100 107 upgrade = ask_ok('You are about to perform database upgrade, make '
101 108 'sure You backed up your database before. '
102 109 'Continue ? [y/n]')
@@ -161,6 +168,9 b' class DbManage(object):'
161 168 print ('Adding ldap defaults')
162 169 self.klass.create_ldap_options(skip_existing=True)
163 170
171 def step_4(self):
172 print ('TODO:')
173
164 174 upgrade_steps = [0] + range(curr_version + 1, __dbversion__ + 1)
165 175
166 176 # CALL THE PROPER ORDER OF STEPS TO PERFORM FULL UPGRADE
@@ -8,6 +8,7 b' import hashlib'
8 8 import StringIO
9 9 import urllib
10 10 import math
11 import logging
11 12
12 13 from datetime import datetime
13 14 from pygments.formatters.html import HtmlFormatter
@@ -41,6 +42,8 b' from rhodecode.lib.utils import repo_nam'
41 42 from rhodecode.lib import str2bool, safe_unicode, safe_str, get_changeset_safe
42 43 from rhodecode.lib.markup_renderer import MarkupRenderer
43 44
45 log = logging.getLogger(__name__)
46
44 47
45 48 def _reset(name, value=None, id=NotGiven, type="reset", **attrs):
46 49 """
@@ -728,7 +731,7 b' def fancy_file_stats(stats):'
728 731 return literal('<div style="width:%spx">%s%s</div>' % (width, d_a, d_d))
729 732
730 733
731 def urlify_text(text):
734 def urlify_text(text_):
732 735 import re
733 736
734 737 url_pat = re.compile(r'''(http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]'''
@@ -738,8 +741,42 b' def urlify_text(text):'
738 741 url_full = match_obj.groups()[0]
739 742 return '<a href="%(url)s">%(url)s</a>' % ({'url':url_full})
740 743
741 return literal(url_pat.sub(url_func, text))
744 return literal(url_pat.sub(url_func, text_))
742 745
746 def urlify_commit(text_):
747 import re
748 import traceback
749
750 try:
751 conf = config['app_conf']
752
753 URL_PAT = re.compile(r'%s' % conf.get('url_pat'))
754
755 if URL_PAT:
756 ISSUE_SERVER = conf.get('issue_server')
757 ISSUE_PREFIX = conf.get('issue_prefix')
758 def url_func(match_obj):
759 issue_id = match_obj.groups()[0]
760 tmpl = (
761 '<a class="%(cls)s" href="%(url)s">'
762 ' %(issue-prefix)s%(id-repr)s'
763 '</a>'
764 )
765 return tmpl % (
766 {
767 'cls':'issue-tracker-link',
768 'url':ISSUE_SERVER.replace('{id}',issue_id),
769 'id-repr':issue_id,
770 'issue-prefix':ISSUE_PREFIX,
771 'serv':ISSUE_SERVER,
772 }
773 )
774 return literal(URL_PAT.sub(url_func, text_))
775 except:
776 log.error(traceback.format_exc())
777 pass
778
779 return text_
743 780
744 781 def rst(source):
745 782 return literal('<div class="rst-block">%s</div>' %
@@ -1,3 +1,4 b''
1
1 2
2 3 class InvalidMessage(RuntimeError):
3 4 """
@@ -5,6 +6,7 b' class InvalidMessage(RuntimeError):'
5 6 as recipients or sender address.
6 7 """
7 8
9
8 10 class BadHeaders(RuntimeError):
9 11 """
10 12 Raised if message contains newlines in headers.
@@ -45,6 +45,8 b' class Message(object):'
45 45 :param bcc: BCC list
46 46 :param extra_headers: dict of extra email headers
47 47 :param attachments: list of Attachment instances
48 :param recipients_separator: alternative separator for any of
49 'From', 'To', 'Delivered-To', 'Cc', 'Bcc' fields
48 50 """
49 51
50 52 def __init__(self,
@@ -56,8 +58,8 b' class Message(object):'
56 58 cc=None,
57 59 bcc=None,
58 60 extra_headers=None,
59 attachments=None):
60
61 attachments=None,
62 recipients_separator="; "):
61 63
62 64 self.subject = subject or ''
63 65 self.sender = sender
@@ -70,6 +72,8 b' class Message(object):'
70 72 self.bcc = bcc or []
71 73 self.extra_headers = extra_headers or {}
72 74
75 self.recipients_separator = recipients_separator
76
73 77 @property
74 78 def send_to(self):
75 79 return set(self.recipients) | set(self.bcc or ()) | set(self.cc or ())
@@ -92,7 +96,8 b' class Message(object):'
92 96 To=self.recipients,
93 97 From=self.sender,
94 98 Body=self.body,
95 Html=self.html)
99 Html=self.html,
100 separator=self.recipients_separator)
96 101
97 102 if self.bcc:
98 103 response.base['Bcc'] = self.bcc
@@ -141,12 +141,14 b' class MailResponse(object):'
141 141 MailResponse.to_message. This lets you change it and work with it, then
142 142 send it out when it's ready.
143 143 """
144 def __init__(self, To=None, From=None, Subject=None, Body=None, Html=None):
144 def __init__(self, To=None, From=None, Subject=None, Body=None, Html=None,
145 separator="; "):
145 146 self.Body = Body
146 147 self.Html = Html
147 148 self.base = MailBase([('To', To), ('From', From), ('Subject', Subject)])
148 149 self.multipart = self.Body and self.Html
149 150 self.attachments = []
151 self.separator = separator
150 152
151 153 def __contains__(self, key):
152 154 return self.base.__contains__(key)
@@ -298,7 +300,7 b' class MailResponse(object):'
298 300 self.base.body = self.Html
299 301 self.base.content_encoding['Content-Type'] = ('text/html', {})
300 302
301 return to_message(self.base)
303 return to_message(self.base, separator=self.separator)
302 304
303 305 def all_parts(self):
304 306 """
@@ -310,7 +312,7 b' class MailResponse(object):'
310 312 def keys(self):
311 313 return self.base.keys()
312 314
313 def to_message(mail):
315 def to_message(mail, separator="; "):
314 316 """
315 317 Given a MailBase message, this will construct a MIMEPart
316 318 that is canonicalized for use with the Python email API.
@@ -339,10 +341,16 b' def to_message(mail):'
339 341
340 342 for k in mail.keys():
341 343 if k in ADDRESS_HEADERS_WHITELIST:
342 out[k.encode('ascii')] = header_to_mime_encoding(mail[k])
344 out[k.encode('ascii')] = header_to_mime_encoding(
345 mail[k],
346 not_email=False,
347 separator=separator
348 )
343 349 else:
344 out[k.encode('ascii')] = header_to_mime_encoding(mail[k],
345 not_email=True)
350 out[k.encode('ascii')] = header_to_mime_encoding(
351 mail[k],
352 not_email=True
353 )
346 354
347 355 out.extract_payload(mail)
348 356
@@ -403,12 +411,12 b' class MIMEPart(MIMEBase):'
403 411 self.is_multipart())
404 412
405 413
406 def header_to_mime_encoding(value, not_email=False):
414 def header_to_mime_encoding(value, not_email=False, separator=", "):
407 415 if not value: return ""
408 416
409 417 encoder = Charset(DEFAULT_ENCODING)
410 418 if type(value) == list:
411 return "; ".join(properly_encode_header(
419 return separator.join(properly_encode_header(
412 420 v, encoder, not_email) for v in value)
413 421 else:
414 422 return properly_encode_header(value, encoder, not_email)
@@ -59,7 +59,8 b' class SmtpMailer(object):'
59 59
60 60 if isinstance(recipients, basestring):
61 61 recipients = [recipients]
62 msg = Message(subject, recipients, body, html, self.mail_from)
62 msg = Message(subject, recipients, body, html, self.mail_from,
63 recipients_separator=", ")
63 64 raw_msg = msg.to_message()
64 65
65 66 if self.ssl:
@@ -152,12 +152,12 b' def get_repos(path, recursive=False):'
152 152 """
153 153 Scans given path for repos and return (name,(type,path)) tuple
154 154
155 :param path: path to scann for repositories
155 :param path: path to scan for repositories
156 156 :param recursive: recursive search and return names with subdirs in front
157 157 """
158 158
159 159 # remove ending slash for better results
160 path = path.rstrip('/')
160 path = path.rstrip(os.sep)
161 161
162 162 def _get_repos(p):
163 163 if not os.access(p, os.W_OK):
@@ -1,7 +1,7 b''
1 1 # -*- coding: utf-8 -*-
2 2 """
3 3 rhodecode.model.notification
4 ~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
5 5
6 6 Model for notifications
7 7
@@ -48,7 +48,7 b''
48 48 <div class="left">
49 49 <div>
50 50 ${h.checkbox(cs.short_id,class_="changeset_range")}
51 <span class="changeset_id">${cs.revision}:<span class="changeset_hash">${h.short_id(cs.raw_id)}</span></span>
51 <span class="tooltip" title="${cs.date}"><a href="${h.url('changeset_home',repo_name=c.repo_name,revision=cs.raw_id)}"><span class="changeset_id">${cs.revision}:<span class="changeset_hash">${h.short_id(cs.raw_id)}</span></span></a></span>
52 52 </div>
53 53 <div class="author">
54 54 <div class="gravatar">
@@ -49,7 +49,7 b''
49 49 <span>${h.person(c.changeset.author)}</span><br/>
50 50 <span><a href="mailto:${h.email_or_none(c.changeset.author)}">${h.email_or_none(c.changeset.author)}</a></span><br/>
51 51 </div>
52 <div class="message">${h.wrap_paragraphs(c.changeset.message)}</div>
52 <div class="message">${h.urlify_commit(h.wrap_paragraphs(c.changeset.message))}</div>
53 53 </div>
54 54 <div class="right">
55 55 <div class="changes">
@@ -95,7 +95,7 b''
95 95 <div class="cs_${change}">
96 96 <div class="node">
97 97 %if change != 'removed':
98 ${h.link_to(h.safe_unicode(filenode.path),c.anchor_url(filenode.changeset.raw_id,filenode.path))}
98 ${h.link_to(h.safe_unicode(filenode.path),c.anchor_url(filenode.changeset.raw_id,filenode.path)+"_target")}
99 99 %else:
100 100 ${h.link_to(h.safe_unicode(filenode.path),h.url.current(anchor=h.FID('',filenode.path)))}
101 101 %endif
@@ -138,11 +138,15 b''
138 138 YUE.on(YUQ('.show-inline-comments'),'change',function(e){
139 139 var show = 'none';
140 140 var target = e.currentTarget;
141 console.log(target);
141 142 if(target.checked){
142 143 var show = ''
143 144 }
145 console.log('aa')
144 146 var boxid = YUD.getAttribute(target,'id_for');
147 console.log(boxid);
145 148 var comments = YUQ('#{0} .inline-comments'.format(boxid));
149 console.log(comments)
146 150 for(c in comments){
147 151 YUD.setStyle(comments[c],'display',show);
148 152 }
@@ -41,7 +41,7 b''
41 41 <td>${h.link_to('r%s:%s' % (cs.revision,h.short_id(cs.raw_id)),h.url('changeset_home',repo_name=c.repo_name,revision=cs.raw_id))}</td>
42 42 <td><div class="author">${h.person(cs.author)}</div></td>
43 43 <td><span class="tooltip" title="${h.age(cs.date)}">${cs.date}</span></td>
44 <td><div class="message">${h.link_to(h.wrap_paragraphs(cs.message),h.url('changeset_home',repo_name=c.repo_name,revision=cs.raw_id))}</div></td>
44 <td><div class="message">${h.urlify_commit(h.wrap_paragraphs(cs.message))}</div></td>
45 45 </tr>
46 46 %endfor
47 47 </table>
@@ -7,8 +7,8 b''
7 7
8 8 %for change,filenode,diff,cs1,cs2,stat in changes:
9 9 %if change !='removed':
10 <div id="${h.FID(filenode.changeset.raw_id,filenode.path)}" style="clear:both;height:90px;margin-top:-60px"></div>
11 <div class="diffblock margined comm">
10 <div id="${h.FID(filenode.changeset.raw_id,filenode.path)}_target" style="clear:both;height:90px;margin-top:-60px"></div>
11 <div id="${h.FID(filenode.changeset.raw_id,filenode.path)}" class="diffblock margined comm">
12 12 <div class="code-header">
13 13 <div class="changeset_header">
14 14 <div class="changeset_file">
@@ -2,16 +2,19 b''
2 2 %if c.repo_changesets:
3 3 <table class="table_disp">
4 4 <tr>
5 <th class="left">${_('commit message')}</th>
5 <th class="left">${_('revision')}</th>
6 <th class="left">${_('commit message')}</th>
6 7 <th class="left">${_('age')}</th>
7 8 <th class="left">${_('author')}</th>
8 <th class="left">${_('revision')}</th>
9 9 <th class="left">${_('branch')}</th>
10 10 <th class="left">${_('tags')}</th>
11 11 </tr>
12 12 %for cnt,cs in enumerate(c.repo_changesets):
13 13 <tr class="parity${cnt%2}">
14 14 <td>
15 <div><pre><a href="${h.url('files_home',repo_name=c.repo_name,revision=cs.raw_id)}">r${cs.revision}:${h.short_id(cs.raw_id)}</a></pre></div>
16 </td>
17 <td>
15 18 ${h.link_to(h.truncate(cs.message,50),
16 19 h.url('changeset_home',repo_name=c.repo_name,revision=cs.raw_id),
17 20 title=cs.message)}
@@ -20,7 +23,6 b''
20 23 ${h.age(cs.date)}</span>
21 24 </td>
22 25 <td title="${cs.author}">${h.person(cs.author)}</td>
23 <td><div><pre><a href="${h.url('files_home',repo_name=c.repo_name,revision=cs.raw_id)}">r${cs.revision}:${h.short_id(cs.raw_id)}</a></pre></div></td>
24 26 <td>
25 27 <span class="logtags">
26 28 <span class="branchtag">${cs.branch}</span>
1 NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now