##// END OF EJS Templates
accept that repos are read-only - very convenient for testing....
accept that repos are read-only - very convenient for testing. Users are prompt to confirm they want to use read only paths. org author: Mads Kiilerich

File last commit:

r3980:3648a2b2 default
r3980:3648a2b2 default
Show More
scm.py
755 lines | 26.9 KiB | text/x-python | PythonLexer
rolled back to make transient since got some exceptions on expunge...
r757 # -*- coding: utf-8 -*-
"""
docs updates
r811 rhodecode.model.scm
~~~~~~~~~~~~~~~~~~~
rolled back to make transient since got some exceptions on expunge...
r757
docs updates
r811 Scm model for RhodeCode
rolled back to make transient since got some exceptions on expunge...
r757 :created_on: Apr 9, 2010
:author: marcink
2012 copyrights
r1824 :copyright: (C) 2010-2012 Marcin Kuzminski <marcin@python-works.com>
rolled back to make transient since got some exceptions on expunge...
r757 :license: GPLv3, see COPYING for more details.
"""
fixed license issue #149
r1206 # This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
source code cleanup: remove trailing white space, normalize file endings
r1203 #
Refactor codes for scm model...
r691 # This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
source code cleanup: remove trailing white space, normalize file endings
r1203 #
Refactor codes for scm model...
r691 # You should have received a copy of the GNU General Public License
fixed license issue #149
r1206 # along with this program. If not, see <http://www.gnu.org/licenses/>.
fixed python2.5 compat and repo mapper issue
r2620 from __future__ import with_statement
fixes #245 Rescan of the repositories on Windows
r1554 import os
Created install_git_hook more verbose version of previos code....
r2618 import re
rolled back to make transient since got some exceptions on expunge...
r757 import time
import traceback
import logging
fixed problem with uploading files into rhodecode that wasn't detected as streams
r1801 import cStringIO
Created install_git_hook more verbose version of previos code....
r2618 import pkg_resources
Cleanup code
r3952 from os.path import join as jn
rolled back to make transient since got some exceptions on expunge...
r757
fixed default sorting on main page with sorting using wrapped lower() call on database level
r2354 from sqlalchemy import func
Initial version of landing revisions ref #483...
r2459 from pylons.i18n.translation import _
fixed default sorting on main page with sorting using wrapped lower() call on database level
r2354
Created install_git_hook more verbose version of previos code....
r2618 import rhodecode
Added VCS into rhodecode core for faster and easier deployments of new versions
r2007 from rhodecode.lib.vcs import get_backend
from rhodecode.lib.vcs.exceptions import RepositoryError
from rhodecode.lib.vcs.utils.lazy import LazyProperty
from rhodecode.lib.vcs.nodes import FileNode
Bumped mercurial version to 2.3...
r2684 from rhodecode.lib.vcs.backends.base import EmptyChangeset
rolled back to make transient since got some exceptions on expunge...
r757
Disable git support due to large problems with dulwich....
r710 from rhodecode import BACKENDS
Refactor codes for scm model...
r691 from rhodecode.lib import helpers as h
Switched handling of RhodeCode extra params in consistent way...
r3577 from rhodecode.lib.utils2 import safe_str, safe_unicode, get_server_url,\
_set_extras
- Manage User’s Groups: create, delete, rename, add/remove users inside....
r3714 from rhodecode.lib.auth import HasRepoPermissionAny, HasReposGroupPermissionAny,\
Cleanup code
r3952 HasUserGroupPermissionAny
reposcann should skip directories with starting with '.'...
r3228 from rhodecode.lib.utils import get_filesystem_repos, make_ui, \
Cleanup code
r3952 action_logger
fixed Example celery config to ampq,...
r752 from rhodecode.model import BaseModel
code cleanups
r758 from rhodecode.model.db import Repository, RhodeCodeUi, CacheInvalidation, \
- pull request generates overview based on it's params...
r2440 UserFollowing, UserLog, User, RepoGroup, PullRequest
webinterface file commiting executes push hooks ref #594
r3478 from rhodecode.lib.hooks import log_push_action
Implemented simple gist functionality ref #530....
r3840 from rhodecode.lib.exceptions import NonRelativePathError
rolled back to make transient since got some exceptions on expunge...
r757
Refactor codes for scm model...
r691 log = logging.getLogger(__name__)
rolled back to make transient since got some exceptions on expunge...
r757
added action loggers to following repositories,...
r735 class UserTemp(object):
def __init__(self, user_id):
self.user_id = user_id
Fixed repo of Temp user and repo for better logging
r901
def __repr__(self):
return "<%s('id:%s')>" % (self.__class__.__name__, self.user_id)
#150 fixes for errors on repositories mapped in db but corrupted in filesystem
r1213
added action loggers to following repositories,...
r735 class RepoTemp(object):
def __init__(self, repo_id):
self.repo_id = repo_id
Added icons with numbers of followers and number of forks
r747
Fixed repo of Temp user and repo for better logging
r901 def __repr__(self):
return "<%s('id:%s')>" % (self.__class__.__name__, self.repo_id)
fixed problem with uploading files into rhodecode that wasn't detected as streams
r1801
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366 class CachedRepoList(object):
Use simplified cached repos list for quick repo switcher, in some cases it can have 2-3x speed-up since it doesn't need to init the scms
r2604 """
Cached repo list, uses in-memory cache after initialization, that is
super fast
"""
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366
Group management delegation:...
r3222 def __init__(self, db_repo_list, repos_path, order_by=None, perm_set=None):
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366 self.db_repo_list = db_repo_list
self.repos_path = repos_path
self.order_by = order_by
self.reversed = (order_by or '').startswith('-')
Group management delegation:...
r3222 if not perm_set:
perm_set = ['repository.read', 'repository.write',
'repository.admin']
self.perm_set = perm_set
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366
def __len__(self):
return len(self.db_repo_list)
def __repr__(self):
return '<%s (%s)>' % (self.__class__.__name__, self.__len__())
def __iter__(self):
Mads Kiilerich
invalidation: merge .invalidate and .set_valid as .test_and_set_valid...
r3772 # pre-propagated valid_cache_keys to save executing select statements
Implemented cache-map on main page to save executing select...
r2352 # for each repo
Mads Kiilerich
invalidation: merge .invalidate and .set_valid as .test_and_set_valid...
r3772 valid_cache_keys = CacheInvalidation.get_valid_cache_keys()
Implemented cache-map on main page to save executing select...
r2352
fixed some issues with cache invalidation, and simplified invalidation codes
r1428 for dbr in self.db_repo_list:
Mads Kiilerich
invalidation: merge .invalidate and .set_valid as .test_and_set_valid...
r3772 scmr = dbr.scm_instance_cached(valid_cache_keys)
added welcome message if no repositories are present in current view
r1437 # check permission at this level
#227 Initial version of repository groups permissions system...
r1982 if not HasRepoPermissionAny(
Mads Kiilerich
Minor changes
r3717 *self.perm_set)(dbr.repo_name, 'get repo check'):
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366 continue
non-lightweight dashboard mode is now more error proof when it stumbles across bad or damaged repositories
r3360 try:
last_change = scmr.last_change
tip = h.get_changeset_safe(scmr, 'tip')
except Exception:
#227 Initial version of repository groups permissions system...
r1982 log.error(
'%s this repository is present in database but it '
non-lightweight dashboard mode is now more error proof when it stumbles across bad or damaged repositories
r3360 'cannot be created as an scm instance, org_exc:%s'
% (dbr.repo_name, traceback.format_exc())
#227 Initial version of repository groups permissions system...
r1982 )
Fixes issue #201...
r1373 continue
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366
tmp_d = {}
tmp_d['name'] = dbr.repo_name
tmp_d['name_sort'] = tmp_d['name'].lower()
Added lightweight dashboard option. ref #500
r2936 tmp_d['raw_name'] = tmp_d['name'].lower()
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366 tmp_d['description'] = dbr.description
Use simplified cached repos list for quick repo switcher, in some cases it can have 2-3x speed-up since it doesn't need to init the scms
r2604 tmp_d['description_sort'] = tmp_d['description'].lower()
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366 tmp_d['last_change'] = last_change
- fixes celery sqlalchemy session issues for async forking...
r1728 tmp_d['last_change_sort'] = time.mktime(last_change.timetuple())
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366 tmp_d['tip'] = tip.raw_id
tmp_d['tip_sort'] = tip.revision
tmp_d['rev'] = tip.revision
tmp_d['contact'] = dbr.user.full_contact
tmp_d['contact_sort'] = tmp_d['contact']
tmp_d['owner_sort'] = tmp_d['contact']
tmp_d['repo_archives'] = list(scmr._get_archives())
tmp_d['last_msg'] = tip.message
added author to main page tooltip
r1459 tmp_d['author'] = tip.author
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366 tmp_d['dbrepo'] = dbr.get_dict()
- fixes celery sqlalchemy session issues for async forking...
r1728 tmp_d['dbrepo_fork'] = dbr.fork.get_dict() if dbr.fork else {}
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366 yield tmp_d
#150 fixes for errors on repositories mapped in db but corrupted in filesystem
r1213
fixed problem with uploading files into rhodecode that wasn't detected as streams
r1801
Use simplified cached repos list for quick repo switcher, in some cases it can have 2-3x speed-up since it doesn't need to init the scms
r2604 class SimpleCachedRepoList(CachedRepoList):
"""
Lighter version of CachedRepoList without the scm initialisation
"""
def __iter__(self):
for dbr in self.db_repo_list:
# check permission at this level
if not HasRepoPermissionAny(
Mads Kiilerich
Minor changes
r3717 *self.perm_set)(dbr.repo_name, 'get repo check'):
Use simplified cached repos list for quick repo switcher, in some cases it can have 2-3x speed-up since it doesn't need to init the scms
r2604 continue
tmp_d = {}
tmp_d['name'] = dbr.repo_name
tmp_d['name_sort'] = tmp_d['name'].lower()
Added lightweight dashboard option. ref #500
r2936 tmp_d['raw_name'] = tmp_d['name'].lower()
Use simplified cached repos list for quick repo switcher, in some cases it can have 2-3x speed-up since it doesn't need to init the scms
r2604 tmp_d['description'] = dbr.description
tmp_d['description_sort'] = tmp_d['description'].lower()
tmp_d['dbrepo'] = dbr.get_dict()
tmp_d['dbrepo_fork'] = dbr.fork.get_dict() if dbr.fork else {}
yield tmp_d
- Manage User’s Groups: create, delete, rename, add/remove users inside....
r3714 class _PermCheckIterator(object):
def __init__(self, obj_list, obj_attr, perm_set, perm_checker):
Group management delegation:...
r3222 """
- Manage User’s Groups: create, delete, rename, add/remove users inside....
r3714 Creates iterator from given list of objects, additionally
Group management delegation:...
r3222 checking permission for them from perm_set var
- Manage User’s Groups: create, delete, rename, add/remove users inside....
r3714 :param obj_list: list of db objects
:param obj_attr: attribute of object to pass into perm_checker
:param perm_set: list of permissions to check
:param perm_checker: callable to check permissions against
Group management delegation:...
r3222 """
- Manage User’s Groups: create, delete, rename, add/remove users inside....
r3714 self.obj_list = obj_list
self.obj_attr = obj_attr
Group management delegation:...
r3222 self.perm_set = perm_set
- Manage User’s Groups: create, delete, rename, add/remove users inside....
r3714 self.perm_checker = perm_checker
#227 Initial version of repository groups permissions system...
r1982
def __len__(self):
- Manage User’s Groups: create, delete, rename, add/remove users inside....
r3714 return len(self.obj_list)
#227 Initial version of repository groups permissions system...
r1982
def __repr__(self):
return '<%s (%s)>' % (self.__class__.__name__, self.__len__())
def __iter__(self):
- Manage User’s Groups: create, delete, rename, add/remove users inside....
r3714 for db_obj in self.obj_list:
#227 Initial version of repository groups permissions system...
r1982 # check permission at this level
- Manage User’s Groups: create, delete, rename, add/remove users inside....
r3714 name = getattr(db_obj, self.obj_attr, None)
if not self.perm_checker(*self.perm_set)(name, self.__class__.__name__):
#227 Initial version of repository groups permissions system...
r1982 continue
- Manage User’s Groups: create, delete, rename, add/remove users inside....
r3714 yield db_obj
Do read only checks on attach as fork of repo list....
r3864 class RepoList(_PermCheckIterator):
def __init__(self, db_repo_list, perm_set=None):
if not perm_set:
perm_set = ['repository.read', 'repository.write', 'repository.admin']
super(RepoList, self).__init__(obj_list=db_repo_list,
obj_attr='repo_name', perm_set=perm_set,
perm_checker=HasRepoPermissionAny)
- Manage User’s Groups: create, delete, rename, add/remove users inside....
r3714 class RepoGroupList(_PermCheckIterator):
def __init__(self, db_repo_group_list, perm_set=None):
if not perm_set:
perm_set = ['group.read', 'group.write', 'group.admin']
super(RepoGroupList, self).__init__(obj_list=db_repo_group_list,
obj_attr='group_name', perm_set=perm_set,
perm_checker=HasReposGroupPermissionAny)
class UserGroupList(_PermCheckIterator):
def __init__(self, db_user_group_list, perm_set=None):
if not perm_set:
perm_set = ['usergroup.read', 'usergroup.write', 'usergroup.admin']
super(UserGroupList, self).__init__(obj_list=db_user_group_list,
obj_attr='users_group_name', perm_set=perm_set,
perm_checker=HasUserGroupPermissionAny)
#227 Initial version of repository groups permissions system...
r1982
fixed Example celery config to ampq,...
r752 class ScmModel(BaseModel):
notification to commit author + gardening
r1716 """
Generic Scm Model
Refactor codes for scm model...
r691 """
implements #239 manual marking of repos as forks for admins
r1755 def __get_repo(self, instance):
cls = Repository
if isinstance(instance, cls):
return instance
fixed possible unicode errors on repo get function
r2672 elif isinstance(instance, int) or safe_str(instance).isdigit():
implements #239 manual marking of repos as forks for admins
r1755 return cls.get(instance)
elif isinstance(instance, basestring):
return cls.get_by_repo_name(instance)
elif instance:
raise Exception('given object must be int, basestr or Instance'
' of %s got %s' % (type(cls), type(instance)))
Refactor codes for scm model...
r691 @LazyProperty
def repos_path(self):
notification to commit author + gardening
r1716 """
Get's the repositories root path from database
Refactor codes for scm model...
r691 """
docs updates
r811
Refactor codes for scm model...
r691 q = self.sa.query(RhodeCodeUi).filter(RhodeCodeUi.ui_key == '/').one()
return q.ui_value
another major code rafactor, reimplemented (almost from scratch)...
r1038 def repo_scan(self, repos_path=None):
notification to commit author + gardening
r1716 """
Listing of repositories in given path. This path should not be a
Refactor codes for scm model...
r691 repository itself. Return a dictionary of repository objects
source code cleanup: remove trailing white space, normalize file endings
r1203
Refactor codes for scm model...
r691 :param repos_path: path to directory containing repositories
"""
docs updates
r811
another major code rafactor, reimplemented (almost from scratch)...
r1038 if repos_path is None:
repos_path = self.repos_path
fixes issue #341, logger outputed invalid path name
r1925 log.info('scanning for repositories in %s' % repos_path)
another major code rafactor, reimplemented (almost from scratch)...
r1038 baseui = make_ui('db')
Summary page downloads limited to zip....
r1751 repos = {}
Refactor codes for scm model...
r691
Added recursive scanning for repositories in directory
r877 for name, path in get_filesystem_repos(repos_path, recursive=True):
fixes #245 Rescan of the repositories on Windows
r1554 # name need to be decomposed and put back together using the /
# since this is internal storage separator for rhodecode
fixed issues with getting repos by path on windows
r3152 name = Repository.normalize_repo_name(name)
notification to commit author + gardening
r1716
Refactor codes for scm model...
r691 try:
Summary page downloads limited to zip....
r1751 if name in repos:
Refactor codes for scm model...
r691 raise RepositoryError('Duplicate repository name %s '
fixes #245 Rescan of the repositories on Windows
r1554 'found in %s' % (name, path))
Refactor codes for scm model...
r691 else:
klass = get_backend(path[0])
Disable git support due to large problems with dulwich....
r710 if path[0] == 'hg' and path[0] in BACKENDS.keys():
moved soon-to-be-deleted code from vcs to rhodecode...
r1753 repos[name] = klass(safe_str(path[1]), baseui=baseui)
Refactor codes for scm model...
r691
Disable git support due to large problems with dulwich....
r710 if path[0] == 'git' and path[0] in BACKENDS.keys():
Summary page downloads limited to zip....
r1751 repos[name] = klass(path[1])
Refactor codes for scm model...
r691 except OSError:
continue
reposcann should skip directories with starting with '.'...
r3228 log.debug('found %s paths with repositories' % (len(repos)))
Summary page downloads limited to zip....
r1751 return repos
Refactor codes for scm model...
r691
Use simplified cached repos list for quick repo switcher, in some cases it can have 2-3x speed-up since it doesn't need to init the scms
r2604 def get_repos(self, all_repos=None, sort_key=None, simple=False):
#47 implemented basic gui for browsing repo groups
r1343 """
Get all repos from db and for each repo create it's
#150 fixes for errors on repositories mapped in db but corrupted in filesystem
r1213 backend instance and fill that backed with information from database
source code cleanup: remove trailing white space, normalize file endings
r1203
#47 implemented basic gui for browsing repo groups
r1343 :param all_repos: list of repository names as strings
give specific repositories list, good for filtering
Use simplified cached repos list for quick repo switcher, in some cases it can have 2-3x speed-up since it doesn't need to init the scms
r2604
:param sort_key: initial sorting of repos
:param simple: use SimpleCachedList - one without the SCM info
Refactor codes for scm model...
r691 """
bugfix, when user had no repos he would see all repos in my account, (correct commit)
r767 if all_repos is None:
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366 all_repos = self.sa.query(Repository)\
#47 implemented basic gui for browsing repo groups
r1343 .filter(Repository.group_id == None)\
fixed default sorting on main page with sorting using wrapped lower() call on database level
r2354 .order_by(func.lower(Repository.repo_name)).all()
Use simplified cached repos list for quick repo switcher, in some cases it can have 2-3x speed-up since it doesn't need to init the scms
r2604 if simple:
repo_iter = SimpleCachedRepoList(all_repos,
repos_path=self.repos_path,
order_by=sort_key)
else:
repo_iter = CachedRepoList(all_repos,
repos_path=self.repos_path,
order_by=sort_key)
Refactor codes for scm model...
r691
fixes #200, rewrote the whole caching mechanism to get rid of such problems. Now cached instances are attached...
r1366 return repo_iter
Refactor codes for scm model...
r691
#227 Initial version of repository groups permissions system...
r1982 def get_repos_groups(self, all_groups=None):
if all_groups is None:
all_groups = RepoGroup.query()\
.filter(RepoGroup.group_parent_id == None).all()
- Manage User’s Groups: create, delete, rename, add/remove users inside....
r3714 return [x for x in RepoGroupList(all_groups)]
#227 Initial version of repository groups permissions system...
r1982
#50 on point cache invalidation changes....
r692 def mark_for_invalidation(self, repo_name):
- #347 when running multiple RhodeCode instances, properly invalidates cache...
r2147 """
Mads Kiilerich
invalidation: some documentation and refactoring, second round
r3682 Mark caches of this repo invalid in the database.
source code cleanup: remove trailing white space, normalize file endings
r1203
Mads Kiilerich
invalidation: some documentation and refactoring, second round
r3682 :param repo_name: the repo for which caches should be marked invalid
#50 on point cache invalidation changes....
r692 """
Mads Kiilerich
api: don't report invalidated cache_keys after invalidating a repo...
r3759 CacheInvalidation.set_invalidate(repo_name)
always update changeset cache after invalidation signal
r3150 repo = Repository.get_by_repo_name(repo_name)
if repo:
repo.update_changeset_cache()
#50 on point cache invalidation changes....
r692
implemented user dashboards, and following system.
r734 def toggle_following_repo(self, follow_repo_id, user_id):
#50 on point cache invalidation changes....
r692
implemented user dashboards, and following system.
r734 f = self.sa.query(UserFollowing)\
.filter(UserFollowing.follows_repo_id == follow_repo_id)\
.filter(UserFollowing.user_id == user_id).scalar()
if f is not None:
try:
self.sa.delete(f)
added action loggers to following repositories,...
r735 action_logger(UserTemp(user_id),
'stopped_following_repo',
Added icons with numbers of followers and number of forks
r747 RepoTemp(follow_repo_id))
implemented user dashboards, and following system.
r734 return
Don't catch all exceptions
r3631 except Exception:
implemented user dashboards, and following system.
r734 log.error(traceback.format_exc())
raise
try:
f = UserFollowing()
f.user_id = user_id
f.follows_repo_id = follow_repo_id
self.sa.add(f)
#235 forking page repo group selection...
r1722
added action loggers to following repositories,...
r735 action_logger(UserTemp(user_id),
'started_following_repo',
Added icons with numbers of followers and number of forks
r747 RepoTemp(follow_repo_id))
Don't catch all exceptions
r3631 except Exception:
implemented user dashboards, and following system.
r734 log.error(traceback.format_exc())
raise
#150 fixes for errors on repositories mapped in db but corrupted in filesystem
r1213 def toggle_following_user(self, follow_user_id, user_id):
implemented user dashboards, and following system.
r734 f = self.sa.query(UserFollowing)\
.filter(UserFollowing.follows_user_id == follow_user_id)\
.filter(UserFollowing.user_id == user_id).scalar()
if f is not None:
try:
self.sa.delete(f)
return
Don't catch all exceptions
r3631 except Exception:
implemented user dashboards, and following system.
r734 log.error(traceback.format_exc())
raise
try:
f = UserFollowing()
f.user_id = user_id
f.follows_user_id = follow_user_id
self.sa.add(f)
Don't catch all exceptions
r3631 except Exception:
implemented user dashboards, and following system.
r734 log.error(traceback.format_exc())
raise
fixed following js snipet. It' can be called multiple times now next to each repository...
r999 def is_following_repo(self, repo_name, user_id, cache=False):
implemented user dashboards, and following system.
r734 r = self.sa.query(Repository)\
.filter(Repository.repo_name == repo_name).scalar()
f = self.sa.query(UserFollowing)\
.filter(UserFollowing.follows_repository == r)\
.filter(UserFollowing.user_id == user_id).scalar()
return f is not None
fixed following js snipet. It' can be called multiple times now next to each repository...
r999 def is_following_user(self, username, user_id, cache=False):
Refactoring of model get functions
r1530 u = User.get_by_username(username)
implemented user dashboards, and following system.
r734
f = self.sa.query(UserFollowing)\
.filter(UserFollowing.follows_user == u)\
.filter(UserFollowing.user_id == user_id).scalar()
return f is not None
#50 on point cache invalidation changes....
r692
- pull request generates overview based on it's params...
r2440 def get_followers(self, repo):
repo = self._get_repo(repo)
fixed condition evaluated for gitrepo that returned null, simplified scm functions
r1282
return self.sa.query(UserFollowing)\
- pull request generates overview based on it's params...
r2440 .filter(UserFollowing.follows_repository == repo).count()
Added icons with numbers of followers and number of forks
r747
- pull request generates overview based on it's params...
r2440 def get_forks(self, repo):
repo = self._get_repo(repo)
return self.sa.query(Repository)\
.filter(Repository.fork == repo).count()
fixed condition evaluated for gitrepo that returned null, simplified scm functions
r1282
- pull request generates overview based on it's params...
r2440 def get_pull_requests(self, repo):
repo = self._get_repo(repo)
return self.sa.query(PullRequest)\
show only open pull requests in the counter, and use repo context bar in pull requests view
r3580 .filter(PullRequest.other_repo == repo)\
.filter(PullRequest.status != PullRequest.STATUS_CLOSED).count()
#50 on point cache invalidation changes....
r692
implements #239 manual marking of repos as forks for admins
r1755 def mark_as_fork(self, repo, fork, user):
repo = self.__get_repo(repo)
fork = self.__get_repo(fork)
Fixed issue #501 error on setting set_as_fork to same repo...
r2629 if fork and repo.repo_id == fork.repo_id:
raise Exception("Cannot set repository as fork of itself")
implements #239 manual marking of repos as forks for admins
r1755 repo.fork = fork
self.sa.add(repo)
return repo
fixes #834 hooks error on remote pulling
r3878 def _handle_rc_scm_extras(self, username, repo_name, repo_alias,
action=None):
move out setting rc_extras for in-memory-push handlers to separate function
r3826 from rhodecode import CONFIG
from rhodecode.lib.base import _get_ip_addr
try:
from pylons import request
environ = request.environ
except TypeError:
# we might use this outside of request context, let's fake the
# environ data
from webob import Request
environ = Request.blank('').environ
extras = {
'ip': _get_ip_addr(environ),
'username': username,
fixes #834 hooks error on remote pulling
r3878 'action': action or 'push_local',
move out setting rc_extras for in-memory-push handlers to separate function
r3826 'repository': repo_name,
'scm': repo_alias,
'config': CONFIG['__file__'],
'server_url': get_server_url(environ),
'make_lock': None,
'locked_by': [None, None]
}
_set_extras(extras)
If commit operation is used out of pylons request scope use blank request instead
r3481 def _handle_push(self, repo, username, action, repo_name, revisions):
"""
Triggers push action hooks
:param repo: SCM repo
:param username: username who pushes
:param action: push/push_loca/push_remote
:param repo_name: name of repo
:param revisions: list of revisions that we pushed
"""
move out setting rc_extras for in-memory-push handlers to separate function
r3826 self._handle_rc_scm_extras(username, repo_name, repo_alias=repo.alias)
webinterface file commiting executes push hooks ref #594
r3478 _scm_repo = repo._repo
move out setting rc_extras for in-memory-push handlers to separate function
r3826 # trigger push hook
If commit operation is used out of pylons request scope use blank request instead
r3481 if repo.alias == 'hg':
webinterface file commiting executes push hooks ref #594
r3478 log_push_action(_scm_repo.ui, _scm_repo, node=revisions[0])
If commit operation is used out of pylons request scope use blank request instead
r3481 elif repo.alias == 'git':
kill depracated .ui objects on git repos
r3589 log_push_action(None, _scm_repo, _git_revs=revisions)
webinterface file commiting executes push hooks ref #594
r3478
If commit operation is used out of pylons request scope use blank request instead
r3481 def _get_IMC_module(self, scm_type):
"""
Returns InMemoryCommit class based on scm_type
:param scm_type:
"""
if scm_type == 'hg':
Cleanup code
r3952 from rhodecode.lib.vcs.backends.hg import MercurialInMemoryChangeset
return MercurialInMemoryChangeset
if scm_type == 'git':
from rhodecode.lib.vcs.backends.git import GitInMemoryChangeset
return GitInMemoryChangeset
raise Exception('Invalid scm_type, must be one of hg,git got %s'
% (scm_type,))
If commit operation is used out of pylons request scope use blank request instead
r3481
fixed pull method repo lookup
r2514 def pull_changes(self, repo, username):
dbrepo = self.__get_repo(repo)
API added checks for a valid repository on pull command...
r1508 clone_uri = dbrepo.clone_uri
if not clone_uri:
raise Exception("This repository doesn't have a clone uri")
Refactoring of model get functions
r1530
Fixed remote pull command from todays code refactoring
r1370 repo = dbrepo.scm_instance
webinterface file commiting executes push hooks ref #594
r3478 repo_name = dbrepo.repo_name
#109, added manual pull of changes for repositories that have remote location filled in....
r1114 try:
Don't do git pull on remote repos since they are bare now, we need to use git fetch on them
r2383 if repo.alias == 'git':
repo.fetch(clone_uri)
Fake post-push actions when doing git fetch. It's still want show...
r3880 # git doesn't really have something like post-fetch action
# we fake that now. #TODO: extract fetched revisions somehow
# here
self._handle_push(repo,
username=username,
action='push_remote',
repo_name=repo_name,
revisions=[])
Don't do git pull on remote repos since they are bare now, we need to use git fetch on them
r2383 else:
fixes #834 hooks error on remote pulling
r3878 self._handle_rc_scm_extras(username, dbrepo.repo_name,
repo.alias, action='push_remote')
Don't do git pull on remote repos since they are bare now, we need to use git fetch on them
r2383 repo.pull(clone_uri)
fixes #834 hooks error on remote pulling
r3878
webinterface file commiting executes push hooks ref #594
r3478 self.mark_for_invalidation(repo_name)
Don't catch all exceptions
r3631 except Exception:
#109, added manual pull of changes for repositories that have remote location filled in....
r1114 log.error(traceback.format_exc())
raise
#235 forking page repo group selection...
r1722 def commit_change(self, repo, repo_name, cs, user, author, message,
content, f_path):
Bumped mercurial version to 2.3...
r2684 """
Commits changes
:param repo: SCM instance
"""
If commit operation is used out of pylons request scope use blank request instead
r3481 user = self._get_user(user)
IMC = self._get_IMC_module(repo.alias)
moved out commit into scm model, and added cache invalidation after commit.
r1311
# decoding here will force that we have proper encoded values
# in any other case this will throw exceptions and deny commit
Unicode fixes, added safe_str method for global str() operations +better test sandboxing
r1401 content = safe_str(content)
path = safe_str(f_path)
various fixes for git and mercurial with InMemoryCommit backend and non-ascii files...
r2199 # message and author needs to be unicode
# proper backend should then translate that into required type
message = safe_unicode(message)
author = safe_unicode(author)
fixed issue with web-editor that didn't preserve executable bit...
r3836 imc = IMC(repo)
imc.change(FileNode(path, content, mode=cs.get_file_mode(f_path)))
tip = imc.commit(message=message,
various fixes for git and mercurial with InMemoryCommit backend and non-ascii files...
r2199 author=author,
parents=[cs], branch=cs.branch)
moved out commit into scm model, and added cache invalidation after commit.
r1311
self.mark_for_invalidation(repo_name)
webinterface file commiting executes push hooks ref #594
r3478 self._handle_push(repo,
username=user.username,
action='push_local',
repo_name=repo_name,
revisions=[tip.raw_id])
Bumped mercurial version to 2.3...
r2684 return tip
moved out commit into scm model, and added cache invalidation after commit.
r1311
Implemented simple gist functionality ref #530....
r3840 def create_nodes(self, user, repo, message, nodes, parent_cs=None,
author=None, trigger_push_hook=True):
"""
Commits given multiple nodes into repo
:param user: RhodeCode User object or user_id, the commiter
:param repo: RhodeCode Repository object
:param message: commit message
:param nodes: mapping {filename:{'content':content},...}
:param parent_cs: parent changeset, can be empty than it's initial commit
:param author: author of commit, cna be different that commiter only for git
:param trigger_push_hook: trigger push hooks
:returns: new commited changeset
"""
If commit operation is used out of pylons request scope use blank request instead
r3481 user = self._get_user(user)
Implemented simple gist functionality ref #530....
r3840 scm_instance = repo.scm_instance_no_cache()
If commit operation is used out of pylons request scope use blank request instead
r3481
Implemented simple gist functionality ref #530....
r3840 processed_nodes = []
for f_path in nodes:
if f_path.startswith('/') or f_path.startswith('.') or '../' in f_path:
raise NonRelativePathError('%s is not an relative path' % f_path)
if f_path:
f_path = os.path.normpath(f_path)
fixes issues #849 IMC failed for non-ascii files...
r3912 content = nodes[f_path]['content']
Implemented simple gist functionality ref #530....
r3840 f_path = safe_str(f_path)
# decoding here will force that we have proper encoded values
# in any other case this will throw exceptions and deny commit
if isinstance(content, (basestring,)):
content = safe_str(content)
elif isinstance(content, (file, cStringIO.OutputType,)):
content = content.read()
else:
raise Exception('Content is of unrecognized type %s' % (
type(content)
))
processed_nodes.append((f_path, content))
Refactoring of model get functions
r1530
various fixes for git and mercurial with InMemoryCommit backend and non-ascii files...
r2199 message = safe_unicode(message)
Implemented simple gist functionality ref #530....
r3840 commiter = user.full_contact
author = safe_unicode(author) if author else commiter
Added initial support for creating new nodes in repos
r1483
Implemented simple gist functionality ref #530....
r3840 IMC = self._get_IMC_module(scm_instance.alias)
imc = IMC(scm_instance)
if not parent_cs:
parent_cs = EmptyChangeset(alias=scm_instance.alias)
if isinstance(parent_cs, EmptyChangeset):
various fixes for git and mercurial with InMemoryCommit backend and non-ascii files...
r2199 # EmptyChangeset means we we're editing empty repository
Added initial support for creating new nodes in repos
r1483 parents = None
else:
Implemented simple gist functionality ref #530....
r3840 parents = [parent_cs]
# add multiple nodes
for path, content in processed_nodes:
imc.add(FileNode(path, content=content))
Added initial support for creating new nodes in repos
r1483
Implemented simple gist functionality ref #530....
r3840 tip = imc.commit(message=message,
author=author,
parents=parents,
branch=parent_cs.branch)
self.mark_for_invalidation(repo.repo_name)
if trigger_push_hook:
self._handle_push(scm_instance,
username=user.username,
action='push_local',
repo_name=repo.repo_name,
revisions=[tip.raw_id])
Bumped mercurial version to 2.3...
r2684 return tip
Added initial support for creating new nodes in repos
r1483
implements #330 api method for listing nodes at particular revision...
r1810 def get_nodes(self, repo_name, revision, root_path='/', flat=True):
"""
recursive walk in root dir and return a set of all path in that dir
based on repository walk function
:param repo_name: name of repository
:param revision: revision for which to list nodes
:param root_path: root path to list
:param flat: return as a list, if False returns a dict with decription
"""
_files = list()
_dirs = list()
try:
_repo = self.__get_repo(repo_name)
changeset = _repo.scm_instance.get_changeset(revision)
root_path = root_path.lstrip('/')
for topnode, dirs, files in changeset.walk(root_path):
for f in files:
_files.append(f.path if flat else {"name": f.path,
"type": "file"})
for d in dirs:
_dirs.append(d.path if flat else {"name": d.path,
"type": "dir"})
except RepositoryError:
log.debug(traceback.format_exc())
raise
return _dirs, _files
Implemented fancier top menu for logged and anonymous users...
r784 def get_unread_journal(self):
return self.sa.query(UserLog).count()
Initial version of landing revisions ref #483...
r2459
def get_repo_landing_revs(self, repo=None):
"""
Generates select option with tags branches and bookmarks (for hg only)
grouped by type
:param repo:
"""
validating choices for landing_rev
r2460
Initial version of landing revisions ref #483...
r2459 hist_l = []
validating choices for landing_rev
r2460 choices = []
Initial version of landing revisions ref #483...
r2459 repo = self.__get_repo(repo)
hist_l.append(['tip', _('latest tip')])
validating choices for landing_rev
r2460 choices.append('tip')
Initial version of landing revisions ref #483...
r2459 if not repo:
validating choices for landing_rev
r2460 return choices, hist_l
Initial version of landing revisions ref #483...
r2459
repo = repo.scm_instance
validating choices for landing_rev
r2460
Initial version of landing revisions ref #483...
r2459 branches_group = ([(k, k) for k, v in
repo.branches.iteritems()], _("Branches"))
hist_l.append(branches_group)
validating choices for landing_rev
r2460 choices.extend([x[0] for x in branches_group[0]])
Initial version of landing revisions ref #483...
r2459
if repo.alias == 'hg':
bookmarks_group = ([(k, k) for k, v in
repo.bookmarks.iteritems()], _("Bookmarks"))
hist_l.append(bookmarks_group)
validating choices for landing_rev
r2460 choices.extend([x[0] for x in bookmarks_group[0]])
Initial version of landing revisions ref #483...
r2459
tags_group = ([(k, k) for k, v in
repo.tags.iteritems()], _("Tags"))
hist_l.append(tags_group)
validating choices for landing_rev
r2460 choices.extend([x[0] for x in tags_group[0]])
Initial version of landing revisions ref #483...
r2459
validating choices for landing_rev
r2460 return choices, hist_l
Created install_git_hook more verbose version of previos code....
r2618
def install_git_hook(self, repo, force_create=False):
"""
Creates a rhodecode hook inside a git repository
:param repo: Instance of VCS repo
:param force_create: Create even if same name hook exists
"""
loc = jn(repo.path, 'hooks')
if not repo.bare:
loc = jn(repo.path, '.git', 'hooks')
if not os.path.isdir(loc):
os.makedirs(loc)
Implemented basic locking functionality....
r2726 tmpl_post = pkg_resources.resource_string(
Created install_git_hook more verbose version of previos code....
r2618 'rhodecode', jn('config', 'post_receive_tmpl.py')
)
Implemented basic locking functionality....
r2726 tmpl_pre = pkg_resources.resource_string(
'rhodecode', jn('config', 'pre_receive_tmpl.py')
)
Created install_git_hook more verbose version of previos code....
r2618
Implemented basic locking functionality....
r2726 for h_type, tmpl in [('pre', tmpl_pre), ('post', tmpl_post)]:
_hook_file = jn(loc, '%s-receive' % h_type)
_rhodecode_hook = False
log.debug('Installing git hook in repo %s' % repo)
if os.path.exists(_hook_file):
# let's take a look at this hook, maybe it's rhodecode ?
log.debug('hook exists, checking if it is from rhodecode')
with open(_hook_file, 'rb') as f:
data = f.read()
matches = re.compile(r'(?:%s)\s*=\s*(.*)'
% 'RC_HOOK_VER').search(data)
if matches:
try:
ver = matches.groups()[0]
log.debug('got %s it is rhodecode' % (ver))
_rhodecode_hook = True
Don't catch all exceptions
r3631 except Exception:
Implemented basic locking functionality....
r2726 log.error(traceback.format_exc())
else:
# there is no hook in this dir, so we want to create one
_rhodecode_hook = True
Created install_git_hook more verbose version of previos code....
r2618
Implemented basic locking functionality....
r2726 if _rhodecode_hook or force_create:
Cleanup code
r3952 log.debug('writing %s hook file !' % (h_type,))
accept that repos are read-only - very convenient for testing....
r3980 try:
with open(_hook_file, 'wb') as f:
tmpl = tmpl.replace('_TMPL_', rhodecode.__version__)
f.write(tmpl)
os.chmod(_hook_file, 0755)
except IOError, e:
log.error('error writing %s: %s' % (_hook_file, e))
Implemented basic locking functionality....
r2726 else:
log.debug('skipping writing hook file')