##// END OF EJS Templates
fixed mising scm key for remote-pulls execution
marcink -
r2208:954d8952 beta
parent child Browse files
Show More
@@ -1,461 +1,466 b''
1 # -*- coding: utf-8 -*-
1 # -*- coding: utf-8 -*-
2 """
2 """
3 rhodecode.model.scm
3 rhodecode.model.scm
4 ~~~~~~~~~~~~~~~~~~~
4 ~~~~~~~~~~~~~~~~~~~
5
5
6 Scm model for RhodeCode
6 Scm model for RhodeCode
7
7
8 :created_on: Apr 9, 2010
8 :created_on: Apr 9, 2010
9 :author: marcink
9 :author: marcink
10 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
10 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
11 :license: GPLv3, see COPYING for more details.
11 :license: GPLv3, see COPYING for more details.
12 """
12 """
13 # This program is free software: you can redistribute it and/or modify
13 # This program is free software: you can redistribute it and/or modify
14 # it under the terms of the GNU General Public License as published by
14 # it under the terms of the GNU General Public License as published by
15 # the Free Software Foundation, either version 3 of the License, or
15 # the Free Software Foundation, either version 3 of the License, or
16 # (at your option) any later version.
16 # (at your option) any later version.
17 #
17 #
18 # This program is distributed in the hope that it will be useful,
18 # This program is distributed in the hope that it will be useful,
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # but WITHOUT ANY WARRANTY; without even the implied warranty of
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 # GNU General Public License for more details.
21 # GNU General Public License for more details.
22 #
22 #
23 # You should have received a copy of the GNU General Public License
23 # You should have received a copy of the GNU General Public License
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
24 # along with this program. If not, see <http://www.gnu.org/licenses/>.
25 import os
25 import os
26 import time
26 import time
27 import traceback
27 import traceback
28 import logging
28 import logging
29 import cStringIO
29 import cStringIO
30
30
31 from rhodecode.lib.vcs import get_backend
31 from rhodecode.lib.vcs import get_backend
32 from rhodecode.lib.vcs.exceptions import RepositoryError
32 from rhodecode.lib.vcs.exceptions import RepositoryError
33 from rhodecode.lib.vcs.utils.lazy import LazyProperty
33 from rhodecode.lib.vcs.utils.lazy import LazyProperty
34 from rhodecode.lib.vcs.nodes import FileNode
34 from rhodecode.lib.vcs.nodes import FileNode
35
35
36 from rhodecode import BACKENDS
36 from rhodecode import BACKENDS
37 from rhodecode.lib import helpers as h
37 from rhodecode.lib import helpers as h
38 from rhodecode.lib.utils2 import safe_str, safe_unicode
38 from rhodecode.lib.utils2 import safe_str, safe_unicode
39 from rhodecode.lib.auth import HasRepoPermissionAny, HasReposGroupPermissionAny
39 from rhodecode.lib.auth import HasRepoPermissionAny, HasReposGroupPermissionAny
40 from rhodecode.lib.utils import get_repos as get_filesystem_repos, make_ui, \
40 from rhodecode.lib.utils import get_repos as get_filesystem_repos, make_ui, \
41 action_logger, EmptyChangeset, REMOVED_REPO_PAT
41 action_logger, EmptyChangeset, REMOVED_REPO_PAT
42 from rhodecode.model import BaseModel
42 from rhodecode.model import BaseModel
43 from rhodecode.model.db import Repository, RhodeCodeUi, CacheInvalidation, \
43 from rhodecode.model.db import Repository, RhodeCodeUi, CacheInvalidation, \
44 UserFollowing, UserLog, User, RepoGroup
44 UserFollowing, UserLog, User, RepoGroup
45
45
46 log = logging.getLogger(__name__)
46 log = logging.getLogger(__name__)
47
47
48
48
49 class UserTemp(object):
49 class UserTemp(object):
50 def __init__(self, user_id):
50 def __init__(self, user_id):
51 self.user_id = user_id
51 self.user_id = user_id
52
52
53 def __repr__(self):
53 def __repr__(self):
54 return "<%s('id:%s')>" % (self.__class__.__name__, self.user_id)
54 return "<%s('id:%s')>" % (self.__class__.__name__, self.user_id)
55
55
56
56
57 class RepoTemp(object):
57 class RepoTemp(object):
58 def __init__(self, repo_id):
58 def __init__(self, repo_id):
59 self.repo_id = repo_id
59 self.repo_id = repo_id
60
60
61 def __repr__(self):
61 def __repr__(self):
62 return "<%s('id:%s')>" % (self.__class__.__name__, self.repo_id)
62 return "<%s('id:%s')>" % (self.__class__.__name__, self.repo_id)
63
63
64
64
65 class CachedRepoList(object):
65 class CachedRepoList(object):
66
66
67 def __init__(self, db_repo_list, repos_path, order_by=None):
67 def __init__(self, db_repo_list, repos_path, order_by=None):
68 self.db_repo_list = db_repo_list
68 self.db_repo_list = db_repo_list
69 self.repos_path = repos_path
69 self.repos_path = repos_path
70 self.order_by = order_by
70 self.order_by = order_by
71 self.reversed = (order_by or '').startswith('-')
71 self.reversed = (order_by or '').startswith('-')
72
72
73 def __len__(self):
73 def __len__(self):
74 return len(self.db_repo_list)
74 return len(self.db_repo_list)
75
75
76 def __repr__(self):
76 def __repr__(self):
77 return '<%s (%s)>' % (self.__class__.__name__, self.__len__())
77 return '<%s (%s)>' % (self.__class__.__name__, self.__len__())
78
78
79 def __iter__(self):
79 def __iter__(self):
80 for dbr in self.db_repo_list:
80 for dbr in self.db_repo_list:
81 scmr = dbr.scm_instance_cached
81 scmr = dbr.scm_instance_cached
82 # check permission at this level
82 # check permission at this level
83 if not HasRepoPermissionAny(
83 if not HasRepoPermissionAny(
84 'repository.read', 'repository.write', 'repository.admin'
84 'repository.read', 'repository.write', 'repository.admin'
85 )(dbr.repo_name, 'get repo check'):
85 )(dbr.repo_name, 'get repo check'):
86 continue
86 continue
87
87
88 if scmr is None:
88 if scmr is None:
89 log.error(
89 log.error(
90 '%s this repository is present in database but it '
90 '%s this repository is present in database but it '
91 'cannot be created as an scm instance' % dbr.repo_name
91 'cannot be created as an scm instance' % dbr.repo_name
92 )
92 )
93 continue
93 continue
94
94
95 last_change = scmr.last_change
95 last_change = scmr.last_change
96 tip = h.get_changeset_safe(scmr, 'tip')
96 tip = h.get_changeset_safe(scmr, 'tip')
97
97
98 tmp_d = {}
98 tmp_d = {}
99 tmp_d['name'] = dbr.repo_name
99 tmp_d['name'] = dbr.repo_name
100 tmp_d['name_sort'] = tmp_d['name'].lower()
100 tmp_d['name_sort'] = tmp_d['name'].lower()
101 tmp_d['description'] = dbr.description
101 tmp_d['description'] = dbr.description
102 tmp_d['description_sort'] = tmp_d['description']
102 tmp_d['description_sort'] = tmp_d['description']
103 tmp_d['last_change'] = last_change
103 tmp_d['last_change'] = last_change
104 tmp_d['last_change_sort'] = time.mktime(last_change.timetuple())
104 tmp_d['last_change_sort'] = time.mktime(last_change.timetuple())
105 tmp_d['tip'] = tip.raw_id
105 tmp_d['tip'] = tip.raw_id
106 tmp_d['tip_sort'] = tip.revision
106 tmp_d['tip_sort'] = tip.revision
107 tmp_d['rev'] = tip.revision
107 tmp_d['rev'] = tip.revision
108 tmp_d['contact'] = dbr.user.full_contact
108 tmp_d['contact'] = dbr.user.full_contact
109 tmp_d['contact_sort'] = tmp_d['contact']
109 tmp_d['contact_sort'] = tmp_d['contact']
110 tmp_d['owner_sort'] = tmp_d['contact']
110 tmp_d['owner_sort'] = tmp_d['contact']
111 tmp_d['repo_archives'] = list(scmr._get_archives())
111 tmp_d['repo_archives'] = list(scmr._get_archives())
112 tmp_d['last_msg'] = tip.message
112 tmp_d['last_msg'] = tip.message
113 tmp_d['author'] = tip.author
113 tmp_d['author'] = tip.author
114 tmp_d['dbrepo'] = dbr.get_dict()
114 tmp_d['dbrepo'] = dbr.get_dict()
115 tmp_d['dbrepo_fork'] = dbr.fork.get_dict() if dbr.fork else {}
115 tmp_d['dbrepo_fork'] = dbr.fork.get_dict() if dbr.fork else {}
116 yield tmp_d
116 yield tmp_d
117
117
118
118
119 class GroupList(object):
119 class GroupList(object):
120
120
121 def __init__(self, db_repo_group_list):
121 def __init__(self, db_repo_group_list):
122 self.db_repo_group_list = db_repo_group_list
122 self.db_repo_group_list = db_repo_group_list
123
123
124 def __len__(self):
124 def __len__(self):
125 return len(self.db_repo_group_list)
125 return len(self.db_repo_group_list)
126
126
127 def __repr__(self):
127 def __repr__(self):
128 return '<%s (%s)>' % (self.__class__.__name__, self.__len__())
128 return '<%s (%s)>' % (self.__class__.__name__, self.__len__())
129
129
130 def __iter__(self):
130 def __iter__(self):
131 for dbgr in self.db_repo_group_list:
131 for dbgr in self.db_repo_group_list:
132 # check permission at this level
132 # check permission at this level
133 if not HasReposGroupPermissionAny(
133 if not HasReposGroupPermissionAny(
134 'group.read', 'group.write', 'group.admin'
134 'group.read', 'group.write', 'group.admin'
135 )(dbgr.group_name, 'get group repo check'):
135 )(dbgr.group_name, 'get group repo check'):
136 continue
136 continue
137
137
138 yield dbgr
138 yield dbgr
139
139
140
140
141 class ScmModel(BaseModel):
141 class ScmModel(BaseModel):
142 """
142 """
143 Generic Scm Model
143 Generic Scm Model
144 """
144 """
145
145
146 def __get_repo(self, instance):
146 def __get_repo(self, instance):
147 cls = Repository
147 cls = Repository
148 if isinstance(instance, cls):
148 if isinstance(instance, cls):
149 return instance
149 return instance
150 elif isinstance(instance, int) or str(instance).isdigit():
150 elif isinstance(instance, int) or str(instance).isdigit():
151 return cls.get(instance)
151 return cls.get(instance)
152 elif isinstance(instance, basestring):
152 elif isinstance(instance, basestring):
153 return cls.get_by_repo_name(instance)
153 return cls.get_by_repo_name(instance)
154 elif instance:
154 elif instance:
155 raise Exception('given object must be int, basestr or Instance'
155 raise Exception('given object must be int, basestr or Instance'
156 ' of %s got %s' % (type(cls), type(instance)))
156 ' of %s got %s' % (type(cls), type(instance)))
157
157
158 @LazyProperty
158 @LazyProperty
159 def repos_path(self):
159 def repos_path(self):
160 """
160 """
161 Get's the repositories root path from database
161 Get's the repositories root path from database
162 """
162 """
163
163
164 q = self.sa.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == '/').one()
164 q = self.sa.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == '/').one()
165
165
166 return q.ui_value
166 return q.ui_value
167
167
168 def repo_scan(self, repos_path=None):
168 def repo_scan(self, repos_path=None):
169 """
169 """
170 Listing of repositories in given path. This path should not be a
170 Listing of repositories in given path. This path should not be a
171 repository itself. Return a dictionary of repository objects
171 repository itself. Return a dictionary of repository objects
172
172
173 :param repos_path: path to directory containing repositories
173 :param repos_path: path to directory containing repositories
174 """
174 """
175
175
176 if repos_path is None:
176 if repos_path is None:
177 repos_path = self.repos_path
177 repos_path = self.repos_path
178
178
179 log.info('scanning for repositories in %s' % repos_path)
179 log.info('scanning for repositories in %s' % repos_path)
180
180
181 baseui = make_ui('db')
181 baseui = make_ui('db')
182 repos = {}
182 repos = {}
183
183
184 for name, path in get_filesystem_repos(repos_path, recursive=True):
184 for name, path in get_filesystem_repos(repos_path, recursive=True):
185 # skip removed repos
185 # skip removed repos
186 if REMOVED_REPO_PAT.match(name):
186 if REMOVED_REPO_PAT.match(name):
187 continue
187 continue
188
188
189 # name need to be decomposed and put back together using the /
189 # name need to be decomposed and put back together using the /
190 # since this is internal storage separator for rhodecode
190 # since this is internal storage separator for rhodecode
191 name = Repository.url_sep().join(name.split(os.sep))
191 name = Repository.url_sep().join(name.split(os.sep))
192
192
193 try:
193 try:
194 if name in repos:
194 if name in repos:
195 raise RepositoryError('Duplicate repository name %s '
195 raise RepositoryError('Duplicate repository name %s '
196 'found in %s' % (name, path))
196 'found in %s' % (name, path))
197 else:
197 else:
198
198
199 klass = get_backend(path[0])
199 klass = get_backend(path[0])
200
200
201 if path[0] == 'hg' and path[0] in BACKENDS.keys():
201 if path[0] == 'hg' and path[0] in BACKENDS.keys():
202 repos[name] = klass(safe_str(path[1]), baseui=baseui)
202 repos[name] = klass(safe_str(path[1]), baseui=baseui)
203
203
204 if path[0] == 'git' and path[0] in BACKENDS.keys():
204 if path[0] == 'git' and path[0] in BACKENDS.keys():
205 repos[name] = klass(path[1])
205 repos[name] = klass(path[1])
206 except OSError:
206 except OSError:
207 continue
207 continue
208
208
209 return repos
209 return repos
210
210
211 def get_repos(self, all_repos=None, sort_key=None):
211 def get_repos(self, all_repos=None, sort_key=None):
212 """
212 """
213 Get all repos from db and for each repo create it's
213 Get all repos from db and for each repo create it's
214 backend instance and fill that backed with information from database
214 backend instance and fill that backed with information from database
215
215
216 :param all_repos: list of repository names as strings
216 :param all_repos: list of repository names as strings
217 give specific repositories list, good for filtering
217 give specific repositories list, good for filtering
218 """
218 """
219 if all_repos is None:
219 if all_repos is None:
220 all_repos = self.sa.query(Repository)\
220 all_repos = self.sa.query(Repository)\
221 .filter(Repository.group_id == None)\
221 .filter(Repository.group_id == None)\
222 .order_by(Repository.repo_name).all()
222 .order_by(Repository.repo_name).all()
223
223
224 repo_iter = CachedRepoList(all_repos, repos_path=self.repos_path,
224 repo_iter = CachedRepoList(all_repos, repos_path=self.repos_path,
225 order_by=sort_key)
225 order_by=sort_key)
226
226
227 return repo_iter
227 return repo_iter
228
228
229 def get_repos_groups(self, all_groups=None):
229 def get_repos_groups(self, all_groups=None):
230 if all_groups is None:
230 if all_groups is None:
231 all_groups = RepoGroup.query()\
231 all_groups = RepoGroup.query()\
232 .filter(RepoGroup.group_parent_id == None).all()
232 .filter(RepoGroup.group_parent_id == None).all()
233 group_iter = GroupList(all_groups)
233 group_iter = GroupList(all_groups)
234
234
235 return group_iter
235 return group_iter
236
236
237 def mark_for_invalidation(self, repo_name):
237 def mark_for_invalidation(self, repo_name):
238 """
238 """
239 Puts cache invalidation task into db for
239 Puts cache invalidation task into db for
240 further global cache invalidation
240 further global cache invalidation
241
241
242 :param repo_name: this repo that should invalidation take place
242 :param repo_name: this repo that should invalidation take place
243 """
243 """
244 CacheInvalidation.set_invalidate(repo_name)
244 CacheInvalidation.set_invalidate(repo_name)
245
245
246 def toggle_following_repo(self, follow_repo_id, user_id):
246 def toggle_following_repo(self, follow_repo_id, user_id):
247
247
248 f = self.sa.query(UserFollowing)\
248 f = self.sa.query(UserFollowing)\
249 .filter(UserFollowing.follows_repo_id == follow_repo_id)\
249 .filter(UserFollowing.follows_repo_id == follow_repo_id)\
250 .filter(UserFollowing.user_id == user_id).scalar()
250 .filter(UserFollowing.user_id == user_id).scalar()
251
251
252 if f is not None:
252 if f is not None:
253 try:
253 try:
254 self.sa.delete(f)
254 self.sa.delete(f)
255 action_logger(UserTemp(user_id),
255 action_logger(UserTemp(user_id),
256 'stopped_following_repo',
256 'stopped_following_repo',
257 RepoTemp(follow_repo_id))
257 RepoTemp(follow_repo_id))
258 return
258 return
259 except:
259 except:
260 log.error(traceback.format_exc())
260 log.error(traceback.format_exc())
261 raise
261 raise
262
262
263 try:
263 try:
264 f = UserFollowing()
264 f = UserFollowing()
265 f.user_id = user_id
265 f.user_id = user_id
266 f.follows_repo_id = follow_repo_id
266 f.follows_repo_id = follow_repo_id
267 self.sa.add(f)
267 self.sa.add(f)
268
268
269 action_logger(UserTemp(user_id),
269 action_logger(UserTemp(user_id),
270 'started_following_repo',
270 'started_following_repo',
271 RepoTemp(follow_repo_id))
271 RepoTemp(follow_repo_id))
272 except:
272 except:
273 log.error(traceback.format_exc())
273 log.error(traceback.format_exc())
274 raise
274 raise
275
275
276 def toggle_following_user(self, follow_user_id, user_id):
276 def toggle_following_user(self, follow_user_id, user_id):
277 f = self.sa.query(UserFollowing)\
277 f = self.sa.query(UserFollowing)\
278 .filter(UserFollowing.follows_user_id == follow_user_id)\
278 .filter(UserFollowing.follows_user_id == follow_user_id)\
279 .filter(UserFollowing.user_id == user_id).scalar()
279 .filter(UserFollowing.user_id == user_id).scalar()
280
280
281 if f is not None:
281 if f is not None:
282 try:
282 try:
283 self.sa.delete(f)
283 self.sa.delete(f)
284 return
284 return
285 except:
285 except:
286 log.error(traceback.format_exc())
286 log.error(traceback.format_exc())
287 raise
287 raise
288
288
289 try:
289 try:
290 f = UserFollowing()
290 f = UserFollowing()
291 f.user_id = user_id
291 f.user_id = user_id
292 f.follows_user_id = follow_user_id
292 f.follows_user_id = follow_user_id
293 self.sa.add(f)
293 self.sa.add(f)
294 except:
294 except:
295 log.error(traceback.format_exc())
295 log.error(traceback.format_exc())
296 raise
296 raise
297
297
298 def is_following_repo(self, repo_name, user_id, cache=False):
298 def is_following_repo(self, repo_name, user_id, cache=False):
299 r = self.sa.query(Repository)\
299 r = self.sa.query(Repository)\
300 .filter(Repository.repo_name == repo_name).scalar()
300 .filter(Repository.repo_name == repo_name).scalar()
301
301
302 f = self.sa.query(UserFollowing)\
302 f = self.sa.query(UserFollowing)\
303 .filter(UserFollowing.follows_repository == r)\
303 .filter(UserFollowing.follows_repository == r)\
304 .filter(UserFollowing.user_id == user_id).scalar()
304 .filter(UserFollowing.user_id == user_id).scalar()
305
305
306 return f is not None
306 return f is not None
307
307
308 def is_following_user(self, username, user_id, cache=False):
308 def is_following_user(self, username, user_id, cache=False):
309 u = User.get_by_username(username)
309 u = User.get_by_username(username)
310
310
311 f = self.sa.query(UserFollowing)\
311 f = self.sa.query(UserFollowing)\
312 .filter(UserFollowing.follows_user == u)\
312 .filter(UserFollowing.follows_user == u)\
313 .filter(UserFollowing.user_id == user_id).scalar()
313 .filter(UserFollowing.user_id == user_id).scalar()
314
314
315 return f is not None
315 return f is not None
316
316
317 def get_followers(self, repo_id):
317 def get_followers(self, repo_id):
318 if not isinstance(repo_id, int):
318 if not isinstance(repo_id, int):
319 repo_id = getattr(Repository.get_by_repo_name(repo_id), 'repo_id')
319 repo_id = getattr(Repository.get_by_repo_name(repo_id), 'repo_id')
320
320
321 return self.sa.query(UserFollowing)\
321 return self.sa.query(UserFollowing)\
322 .filter(UserFollowing.follows_repo_id == repo_id).count()
322 .filter(UserFollowing.follows_repo_id == repo_id).count()
323
323
324 def get_forks(self, repo_id):
324 def get_forks(self, repo_id):
325 if not isinstance(repo_id, int):
325 if not isinstance(repo_id, int):
326 repo_id = getattr(Repository.get_by_repo_name(repo_id), 'repo_id')
326 repo_id = getattr(Repository.get_by_repo_name(repo_id), 'repo_id')
327
327
328 return self.sa.query(Repository)\
328 return self.sa.query(Repository)\
329 .filter(Repository.fork_id == repo_id).count()
329 .filter(Repository.fork_id == repo_id).count()
330
330
331 def mark_as_fork(self, repo, fork, user):
331 def mark_as_fork(self, repo, fork, user):
332 repo = self.__get_repo(repo)
332 repo = self.__get_repo(repo)
333 fork = self.__get_repo(fork)
333 fork = self.__get_repo(fork)
334 repo.fork = fork
334 repo.fork = fork
335 self.sa.add(repo)
335 self.sa.add(repo)
336 return repo
336 return repo
337
337
338 def pull_changes(self, repo_name, username):
338 def pull_changes(self, repo_name, username):
339 dbrepo = Repository.get_by_repo_name(repo_name)
339 dbrepo = Repository.get_by_repo_name(repo_name)
340 clone_uri = dbrepo.clone_uri
340 clone_uri = dbrepo.clone_uri
341 if not clone_uri:
341 if not clone_uri:
342 raise Exception("This repository doesn't have a clone uri")
342 raise Exception("This repository doesn't have a clone uri")
343
343
344 repo = dbrepo.scm_instance
344 repo = dbrepo.scm_instance
345 try:
345 try:
346 extras = {'ip': '',
346 extras = {
347 'username': username,
347 'ip': '',
348 'action': 'push_remote',
348 'username': username,
349 'repository': repo_name}
349 'action': 'push_remote',
350 'repository': repo_name,
351 'scm': repo.alias,
352 }
350
353
351 #inject ui extra param to log this action via push logger
354 #inject ui extra param to log this action via push logger
352 for k, v in extras.items():
355 for k, v in extras.items():
353 repo._repo.ui.setconfig('rhodecode_extras', k, v)
356 repo._repo.ui.setconfig('rhodecode_extras', k, v)
354
357
355 repo.pull(clone_uri)
358 repo.pull(clone_uri)
356 self.mark_for_invalidation(repo_name)
359 self.mark_for_invalidation(repo_name)
357 except:
360 except:
358 log.error(traceback.format_exc())
361 log.error(traceback.format_exc())
359 raise
362 raise
360
363
361 def commit_change(self, repo, repo_name, cs, user, author, message,
364 def commit_change(self, repo, repo_name, cs, user, author, message,
362 content, f_path):
365 content, f_path):
363
366
364 if repo.alias == 'hg':
367 if repo.alias == 'hg':
365 from rhodecode.lib.vcs.backends.hg import MercurialInMemoryChangeset as IMC
368 from rhodecode.lib.vcs.backends.hg import \
369 MercurialInMemoryChangeset as IMC
366 elif repo.alias == 'git':
370 elif repo.alias == 'git':
367 from rhodecode.lib.vcs.backends.git import GitInMemoryChangeset as IMC
371 from rhodecode.lib.vcs.backends.git import \
372 GitInMemoryChangeset as IMC
368
373
369 # decoding here will force that we have proper encoded values
374 # decoding here will force that we have proper encoded values
370 # in any other case this will throw exceptions and deny commit
375 # in any other case this will throw exceptions and deny commit
371 content = safe_str(content)
376 content = safe_str(content)
372 path = safe_str(f_path)
377 path = safe_str(f_path)
373 # message and author needs to be unicode
378 # message and author needs to be unicode
374 # proper backend should then translate that into required type
379 # proper backend should then translate that into required type
375 message = safe_unicode(message)
380 message = safe_unicode(message)
376 author = safe_unicode(author)
381 author = safe_unicode(author)
377 m = IMC(repo)
382 m = IMC(repo)
378 m.change(FileNode(path, content))
383 m.change(FileNode(path, content))
379 tip = m.commit(message=message,
384 tip = m.commit(message=message,
380 author=author,
385 author=author,
381 parents=[cs], branch=cs.branch)
386 parents=[cs], branch=cs.branch)
382
387
383 new_cs = tip.short_id
388 new_cs = tip.short_id
384 action = 'push_local:%s' % new_cs
389 action = 'push_local:%s' % new_cs
385
390
386 action_logger(user, action, repo_name)
391 action_logger(user, action, repo_name)
387
392
388 self.mark_for_invalidation(repo_name)
393 self.mark_for_invalidation(repo_name)
389
394
390 def create_node(self, repo, repo_name, cs, user, author, message, content,
395 def create_node(self, repo, repo_name, cs, user, author, message, content,
391 f_path):
396 f_path):
392 if repo.alias == 'hg':
397 if repo.alias == 'hg':
393 from rhodecode.lib.vcs.backends.hg import MercurialInMemoryChangeset as IMC
398 from rhodecode.lib.vcs.backends.hg import MercurialInMemoryChangeset as IMC
394 elif repo.alias == 'git':
399 elif repo.alias == 'git':
395 from rhodecode.lib.vcs.backends.git import GitInMemoryChangeset as IMC
400 from rhodecode.lib.vcs.backends.git import GitInMemoryChangeset as IMC
396 # decoding here will force that we have proper encoded values
401 # decoding here will force that we have proper encoded values
397 # in any other case this will throw exceptions and deny commit
402 # in any other case this will throw exceptions and deny commit
398
403
399 if isinstance(content, (basestring,)):
404 if isinstance(content, (basestring,)):
400 content = safe_str(content)
405 content = safe_str(content)
401 elif isinstance(content, (file, cStringIO.OutputType,)):
406 elif isinstance(content, (file, cStringIO.OutputType,)):
402 content = content.read()
407 content = content.read()
403 else:
408 else:
404 raise Exception('Content is of unrecognized type %s' % (
409 raise Exception('Content is of unrecognized type %s' % (
405 type(content)
410 type(content)
406 ))
411 ))
407
412
408 message = safe_unicode(message)
413 message = safe_unicode(message)
409 author = safe_unicode(author)
414 author = safe_unicode(author)
410 path = safe_str(f_path)
415 path = safe_str(f_path)
411 m = IMC(repo)
416 m = IMC(repo)
412
417
413 if isinstance(cs, EmptyChangeset):
418 if isinstance(cs, EmptyChangeset):
414 # EmptyChangeset means we we're editing empty repository
419 # EmptyChangeset means we we're editing empty repository
415 parents = None
420 parents = None
416 else:
421 else:
417 parents = [cs]
422 parents = [cs]
418
423
419 m.add(FileNode(path, content=content))
424 m.add(FileNode(path, content=content))
420 tip = m.commit(message=message,
425 tip = m.commit(message=message,
421 author=author,
426 author=author,
422 parents=parents, branch=cs.branch)
427 parents=parents, branch=cs.branch)
423 new_cs = tip.short_id
428 new_cs = tip.short_id
424 action = 'push_local:%s' % new_cs
429 action = 'push_local:%s' % new_cs
425
430
426 action_logger(user, action, repo_name)
431 action_logger(user, action, repo_name)
427
432
428 self.mark_for_invalidation(repo_name)
433 self.mark_for_invalidation(repo_name)
429
434
430 def get_nodes(self, repo_name, revision, root_path='/', flat=True):
435 def get_nodes(self, repo_name, revision, root_path='/', flat=True):
431 """
436 """
432 recursive walk in root dir and return a set of all path in that dir
437 recursive walk in root dir and return a set of all path in that dir
433 based on repository walk function
438 based on repository walk function
434
439
435 :param repo_name: name of repository
440 :param repo_name: name of repository
436 :param revision: revision for which to list nodes
441 :param revision: revision for which to list nodes
437 :param root_path: root path to list
442 :param root_path: root path to list
438 :param flat: return as a list, if False returns a dict with decription
443 :param flat: return as a list, if False returns a dict with decription
439
444
440 """
445 """
441 _files = list()
446 _files = list()
442 _dirs = list()
447 _dirs = list()
443 try:
448 try:
444 _repo = self.__get_repo(repo_name)
449 _repo = self.__get_repo(repo_name)
445 changeset = _repo.scm_instance.get_changeset(revision)
450 changeset = _repo.scm_instance.get_changeset(revision)
446 root_path = root_path.lstrip('/')
451 root_path = root_path.lstrip('/')
447 for topnode, dirs, files in changeset.walk(root_path):
452 for topnode, dirs, files in changeset.walk(root_path):
448 for f in files:
453 for f in files:
449 _files.append(f.path if flat else {"name": f.path,
454 _files.append(f.path if flat else {"name": f.path,
450 "type": "file"})
455 "type": "file"})
451 for d in dirs:
456 for d in dirs:
452 _dirs.append(d.path if flat else {"name": d.path,
457 _dirs.append(d.path if flat else {"name": d.path,
453 "type": "dir"})
458 "type": "dir"})
454 except RepositoryError:
459 except RepositoryError:
455 log.debug(traceback.format_exc())
460 log.debug(traceback.format_exc())
456 raise
461 raise
457
462
458 return _dirs, _files
463 return _dirs, _files
459
464
460 def get_unread_journal(self):
465 def get_unread_journal(self):
461 return self.sa.query(UserLog).count()
466 return self.sa.query(UserLog).count()
General Comments 0
You need to be logged in to leave comments. Login now