def test_push_unlocks_repository_git(self, webserver): # enable locking fork_name = '%s_fork%s' % (GIT_REPO, _RandomNameSequence().next()) fixture.create_fork(GIT_REPO, fork_name) r = Repository.get_by_repo_name(fork_name) r.enable_locking = True Session().commit() #clone some temp DEST = _get_tmp_dir() clone_url = webserver.repo_url(fork_name) stdout, stderr = Command(TESTS_TMP_PATH).execute('git clone', clone_url, DEST) #check for lock repo after clone r = Repository.get_by_repo_name(fork_name) assert r.locked[0] == User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id #push is ok and repo is now unlocked stdout, stderr = _add_files_and_push(webserver, 'git', DEST, clone_url=clone_url) _check_proper_git_push(stdout, stderr) assert ('remote: Released lock on repo `%s`' % fork_name) in stderr #we need to cleanup the Session Here ! Session.remove() r = Repository.get_by_repo_name(fork_name) assert r.locked == [None, None]
def index(self, repo_name): c.compare_home = True org_repo = c.db_repo.repo_name other_repo = request.GET.get('other_repo', org_repo) c.a_repo = Repository.get_by_repo_name(org_repo) c.cs_repo = Repository.get_by_repo_name(other_repo) c.a_ref_name = c.cs_ref_name = _('Select changeset') return render('compare/compare_diff.html')
def setup_method(self, method): r = Repository.get_by_repo_name(GIT_REPO) Repository.unlock(r) r.enable_locking = False Session().commit() r = Repository.get_by_repo_name(HG_REPO) Repository.unlock(r) r.enable_locking = False Session().commit()
def test_set_fork_of_other_type_repo(self): self.log_user() repo = Repository.get_by_repo_name(self.REPO) repo2 = Repository.get_by_repo_name(self.OTHER_TYPE_REPO) response = self.app.put(url('edit_repo_advanced_fork', repo_name=self.REPO), params=dict(id_fork_of=repo2.repo_id, _authentication_token=self.authentication_token())) repo = Repository.get_by_repo_name(self.REPO) repo2 = Repository.get_by_repo_name(self.OTHER_TYPE_REPO) self.checkSessionFlash(response, 'Cannot set repository as fork of repository with other type')
def test_set_fork_of_none(self): self.log_user() ## mark it as None response = self.app.put(url('edit_repo_advanced_fork', repo_name=self.REPO), params=dict(id_fork_of=None, _authentication_token=self.authentication_token())) repo = Repository.get_by_repo_name(self.REPO) repo2 = Repository.get_by_repo_name(self.OTHER_TYPE_REPO) self.checkSessionFlash(response, 'Marked repo %s as fork of %s' % (repo.repo_name, "Nothing")) assert repo.fork is None
def test_clone_and_create_lock_git(self, webserver): # enable locking r = Repository.get_by_repo_name(GIT_REPO) r.enable_locking = True Session().commit() # clone clone_url = webserver.repo_url(GIT_REPO) stdout, stderr = Command(TESTS_TMP_PATH).execute('git clone', clone_url, _get_tmp_dir()) #check if lock was made r = Repository.get_by_repo_name(GIT_REPO) assert r.locked[0] == User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id
def setUp(self): r = Repository.get_by_repo_name(GIT_REPO) Repository.unlock(r) r.enable_locking = False Session().add(r) Session().commit() r = Repository.get_by_repo_name(HG_REPO) Repository.unlock(r) r.enable_locking = False Session().add(r) Session().commit()
def test_clone_and_create_lock_git(self): # enable locking r = Repository.get_by_repo_name(GIT_REPO) r.enable_locking = True Session().add(r) Session().commit() # clone clone_url = _construct_url(GIT_REPO) stdout, stderr = Command('/tmp').execute('git clone', clone_url) #check if lock was made r = Repository.get_by_repo_name(GIT_REPO) assert r.locked[0] == User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id
def test_fork_unicode(self): self.log_user() # create a fork repo_name = self.REPO org_repo = Repository.get_by_repo_name(repo_name) fork_name = safe_str(self.REPO_FORK + u'-rødgrød') creation_args = { 'repo_name': fork_name, 'repo_group': u'-1', 'fork_parent_id': org_repo.repo_id, 'repo_type': self.REPO_TYPE, 'description': 'unicode repo 1', 'private': 'False', 'landing_rev': 'rev:tip', '_authentication_token': self.authentication_token()} self.app.post(url(controller='forks', action='fork_create', repo_name=repo_name), creation_args) response = self.app.get(url(controller='forks', action='forks', repo_name=repo_name)) response.mustcontain( """<a href="/%s">%s</a>""" % (urllib.quote(fork_name), fork_name) ) fork_repo = Repository.get_by_repo_name(safe_unicode(fork_name)) assert fork_repo # fork the fork fork_name_2 = safe_str(self.REPO_FORK + u'-blåbærgrød') creation_args = { 'repo_name': fork_name_2, 'repo_group': u'-1', 'fork_parent_id': fork_repo.repo_id, 'repo_type': self.REPO_TYPE, 'description': 'unicode repo 2', 'private': 'False', 'landing_rev': 'rev:tip', '_authentication_token': self.authentication_token()} self.app.post(url(controller='forks', action='fork_create', repo_name=fork_name), creation_args) response = self.app.get(url(controller='forks', action='forks', repo_name=fork_name)) response.mustcontain( """<a href="/%s">%s</a>""" % (urllib.quote(fork_name_2), fork_name_2) ) # remove these forks response = self.app.post(url('delete_repo', repo_name=fork_name_2), params={'_authentication_token': self.authentication_token()}) response = self.app.post(url('delete_repo', repo_name=fork_name), params={'_authentication_token': self.authentication_token()})
def create_repo(self, name, **kwargs): if 'skip_if_exists' in kwargs: del kwargs['skip_if_exists'] r = Repository.get_by_repo_name(name) if r: return r if isinstance(kwargs.get('repo_group'), RepoGroup): kwargs['repo_group'] = kwargs['repo_group'].group_id form_data = self._get_repo_create_params(repo_name=name, **kwargs) cur_user = kwargs.get('cur_user', TEST_USER_ADMIN_LOGIN) RepoModel().create(form_data, cur_user) Session().commit() return Repository.get_by_repo_name(name)
def test_user_permissions_on_group_with_recursive_mode_for_default_user(): # set permission to g0 recursive mode, all children including # other repos and groups should have this permission now set ! recursive = 'all' group = u'g0' default_user_id = User.get_default_user().user_id permissions_setup_func(group, 'group.write', recursive=recursive, user_id=default_user_id) # change default to get perms for default user _get_repo_perms = functools.partial(_get_perms, key='repositories', test_u1_id=default_user_id) _get_group_perms = functools.partial(_get_perms, key='repositories_groups', test_u1_id=default_user_id) repo_items = [x for x in _get_repo_perms(group, recursive)] items = [x for x in _get_group_perms(group, recursive)] _check_expected_count(items, repo_items, expected_count(group, True)) for name, perm in repo_items: # default user permissions do not "recurse into" private repos is_private = Repository.get_by_repo_name(name).private check_tree_perms(name, perm, group, 'repository.none' if is_private else 'repository.write') for name, perm in items: check_tree_perms(name, perm, group, 'group.write')
def test_index_hg(self): self.log_user() ID = Repository.get_by_repo_name(HG_REPO).repo_id response = self.app.get(url(controller='summary', action='index', repo_name=HG_REPO)) #repo type response.mustcontain( """<span class="repotag">hg""" ) #public/private response.mustcontain( """<i class="icon-globe">""" ) # clone url... response.mustcontain( '''<input class="form-control" size="80" readonly="readonly" value="http://%s@localhost:80/%s"/>''' % (TEST_USER_ADMIN_LOGIN, HG_REPO) ) response.mustcontain( '''<input class="form-control" size="80" readonly="readonly" value="http://%s@localhost:80/_%s"/>''' % (TEST_USER_ADMIN_LOGIN, ID) )
def _get_index_revision(self, repo): db_repo = Repository.get_by_repo_name(repo.name_unicode) landing_rev = 'tip' if db_repo: _rev_type, _rev = db_repo.landing_rev landing_rev = _rev return landing_rev
def _get_permission_for_user(user, repo): perm = UserRepoToPerm.query()\ .filter(UserRepoToPerm.repository == Repository.get_by_repo_name(repo))\ .filter(UserRepoToPerm.user == User.get_by_username(user))\ .all() return perm
def test_set_fork_of_same_repo(self): self.log_user() repo = Repository.get_by_repo_name(self.REPO) response = self.app.put(url('edit_repo_advanced_fork', repo_name=self.REPO), params=dict(id_fork_of=repo.repo_id, _authentication_token=self.authentication_token())) self.checkSessionFlash(response, 'An error occurred during this operation')
def fork_create(self, repo_name): self.__load_defaults() c.repo_info = Repository.get_by_repo_name(repo_name) _form = RepoForkForm(old_data={'repo_type': c.repo_info.repo_type}, repo_groups=c.repo_groups, landing_revs=c.landing_revs_choices)() form_result = {} task_id = None try: form_result = _form.to_python(dict(request.POST)) # an approximation that is better than nothing if not Ui.get_by_key('hooks', Ui.HOOK_UPDATE).ui_active: form_result['update_after_clone'] = False # create fork is done sometimes async on celery, db transaction # management is handled there. task = RepoModel().create_fork(form_result, request.authuser.user_id) task_id = task.task_id except formencode.Invalid as errors: return htmlfill.render( render('forks/fork.html'), defaults=errors.value, errors=errors.error_dict or {}, prefix_error=False, encoding="UTF-8", force_defaults=False) except Exception: log.error(traceback.format_exc()) h.flash(_('An error occurred during repository forking %s') % repo_name, category='error') raise HTTPFound(location=h.url('repo_creating_home', repo_name=form_result['repo_name_full'], task_id=task_id))
def fork_create(self, repo_name): self.__load_defaults() c.repo_info = Repository.get_by_repo_name(repo_name) _form = RepoForkForm(old_data={'repo_type': c.repo_info.repo_type}, repo_groups=c.repo_groups_choices, landing_revs=c.landing_revs_choices)() form_result = {} task_id = None try: form_result = _form.to_python(dict(request.POST)) # an approximation that is better than nothing if not Ui.get_by_key(Ui.HOOK_UPDATE).ui_active: form_result['update_after_clone'] = False # create fork is done sometimes async on celery, db transaction # management is handled there. task = RepoModel().create_fork(form_result, self.authuser.user_id) from celery.result import BaseAsyncResult if isinstance(task, BaseAsyncResult): task_id = task.task_id except formencode.Invalid, errors: c.new_repo = errors.value['repo_name'] return htmlfill.render( render('forks/fork.html'), defaults=errors.value, errors=errors.error_dict or {}, prefix_error=False, encoding="UTF-8", force_defaults=False)
def test_index_with_fork(self): self.log_user() # create a fork fork_name = self.REPO_FORK description = 'fork of vcs test' repo_name = self.REPO org_repo = Repository.get_by_repo_name(repo_name) creation_args = { 'repo_name': fork_name, 'repo_group': u'-1', 'fork_parent_id': org_repo.repo_id, 'repo_type': self.REPO_TYPE, 'description': description, 'private': 'False', 'landing_rev': 'rev:tip', '_authentication_token': self.authentication_token()} self.app.post(url(controller='forks', action='fork_create', repo_name=repo_name), creation_args) response = self.app.get(url(controller='forks', action='forks', repo_name=repo_name)) response.mustcontain( """<a href="/%s">%s</a>""" % (fork_name, fork_name) ) # remove this fork response = self.app.post(url('delete_repo', repo_name=fork_name), params={'_authentication_token': self.authentication_token()})
def test_push_on_locked_repo_by_other_user_git(self): #clone some temp DEST = _get_tmp_dir() clone_url = _construct_url(GIT_REPO, dest=DEST) stdout, stderr = Command('/tmp').execute('git clone', clone_url) #lock repo r = Repository.get_by_repo_name(GIT_REPO) # let this user actually push ! RepoModel().grant_user_permission(repo=r, user=TEST_USER_REGULAR_LOGIN, perm='repository.write') Session().commit() Repository.lock(r, User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id) #push fails repo is locked by other user ! stdout, stderr = _add_files_and_push('git', DEST, user=TEST_USER_REGULAR_LOGIN, passwd=TEST_USER_REGULAR_PASS) err = 'Repository `%s` locked by user `%s`' % (GIT_REPO, TEST_USER_ADMIN_LOGIN) assert err in stderr #TODO: fix this somehow later on Git, Git is stupid and even if we throw #back 423 to it, it makes ANOTHER request and we fail there with 405 :/ msg = ("""abort: HTTP Error 423: Repository `%s` locked by user `%s`""" % (GIT_REPO, TEST_USER_ADMIN_LOGIN))
def test_push_on_locked_repo_by_other_user_git(self, webserver): # Note: Git hooks must be executable on unix. This test will thus fail # for example on Linux if /tmp is mounted noexec. #clone some temp DEST = _get_tmp_dir() clone_url = webserver.repo_url(GIT_REPO) stdout, stderr = Command(TESTS_TMP_PATH).execute('git clone', clone_url, DEST) #lock repo r = Repository.get_by_repo_name(GIT_REPO) # let this user actually push ! RepoModel().grant_user_permission(repo=r, user=TEST_USER_REGULAR_LOGIN, perm='repository.write') Session().commit() Repository.lock(r, User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id) #push fails repo is locked by other user ! stdout, stderr = _add_files_and_push(webserver, 'git', DEST, username=TEST_USER_REGULAR_LOGIN, password=TEST_USER_REGULAR_PASS, ignoreReturnCode=True) err = 'Repository `%s` locked by user `%s`' % (GIT_REPO, TEST_USER_ADMIN_LOGIN) assert err in stderr #TODO: fix this somehow later on Git, Git is stupid and even if we throw #back 423 to it, it makes ANOTHER request and we fail there with 405 :/ msg = ("""abort: HTTP Error 423: Repository `%s` locked by user `%s`""" % (GIT_REPO, TEST_USER_ADMIN_LOGIN))
def repo_check(self, repo_name): c.repo = repo_name task_id = request.GET.get('task_id') if task_id and task_id not in ['None']: from kallithea import CELERY_ON from celery.result import AsyncResult if CELERY_ON: task = AsyncResult(task_id) if task.failed(): raise HTTPInternalServerError(task.traceback) repo = Repository.get_by_repo_name(repo_name) if repo and repo.repo_state == Repository.STATE_CREATED: if repo.clone_uri: clone_uri = repo.clone_uri_hidden h.flash(_('Created repository %s from %s') % (repo.repo_name, clone_uri), category='success') else: repo_url = h.link_to(repo.repo_name, h.url('summary_home', repo_name=repo.repo_name)) fork = repo.fork if fork: fork_name = fork.repo_name h.flash(h.literal(_('Forked repository %s as %s') % (fork_name, repo_url)), category='success') else: h.flash(h.literal(_('Created repository %s') % repo_url), category='success') return {'result': True} return {'result': False}
def commit_change(self, repo, filename, content, message, vcs_type, parent=None, newfile=False): repo = Repository.get_by_repo_name(repo) _cs = parent if not parent: _cs = EmptyChangeset(alias=vcs_type) if newfile: nodes = { filename: { 'content': content } } cs = ScmModel().create_nodes( user=TEST_USER_ADMIN_LOGIN, repo=repo, message=message, nodes=nodes, parent_cs=_cs, author=TEST_USER_ADMIN_LOGIN, ) else: cs = ScmModel().commit_change( repo=repo.scm_instance, repo_name=repo.repo_name, cs=parent, user=TEST_USER_ADMIN_LOGIN, author=TEST_USER_ADMIN_LOGIN, message=message, content=content, f_path=filename ) return cs
def log_pull_action(ui, repo, **kwargs): """ Logs user last pull action :param ui: :param repo: """ ex = _extract_extras() user = User.get_by_username(ex.username) action = 'pull' action_logger(user, action, ex.repository, ex.ip, commit=True) # extension hook call from kallithea import EXTENSIONS callback = getattr(EXTENSIONS, 'PULL_HOOK', None) if callable(callback): kw = {} kw.update(ex) callback(**kw) if ex.make_lock is not None and ex.make_lock: Repository.lock(Repository.get_by_repo_name(ex.repository), user.user_id) #msg = 'Made lock on repo `%s`' % repository #sys.stdout.write(msg) if ex.locked_by[0]: locked_by = User.get(ex.locked_by[0]).username _http_ret = HTTPLockedRC(ex.repository, locked_by) if str(_http_ret.code).startswith('2'): #2xx Codes don't raise exceptions sys.stdout.write(_http_ret.title) return 0
def branch_tag_switcher(self, repo_name): if request.is_xhr: c.db_repo = Repository.get_by_repo_name(repo_name) if c.db_repo: c.db_repo_scm_instance = c.db_repo.scm_instance return render('/switch_to_list.html') raise HTTPBadRequest()
def repo_refs_data(self, repo_name): repo = Repository.get_by_repo_name(repo_name).scm_instance res = [] _branches = repo.branches.items() if _branches: res.append({ 'text': _('Branch'), 'children': [{'id': rev, 'text': name, 'type': 'branch'} for name, rev in _branches] }) _tags = repo.tags.items() if _tags: res.append({ 'text': _('Tag'), 'children': [{'id': rev, 'text': name, 'type': 'tag'} for name, rev in _tags] }) _bookmarks = repo.bookmarks.items() if _bookmarks: res.append({ 'text': _('Bookmark'), 'children': [{'id': rev, 'text': name, 'type': 'book'} for name, rev in _bookmarks] }) data = { 'more': False, 'results': res } return data
def create_repo(self, name, repo_group=None, **kwargs): if 'skip_if_exists' in kwargs: del kwargs['skip_if_exists'] r = Repository.get_by_repo_name(name) if r: return r if isinstance(repo_group, RepoGroup): repo_group = repo_group.group_id form_data = self._get_repo_create_params(repo_name=name, **kwargs) form_data['repo_group'] = repo_group # patch form dict so it can be used directly by model cur_user = kwargs.get('cur_user', TEST_USER_ADMIN_LOGIN) RepoModel().create(form_data, cur_user) Session().commit() ScmModel().mark_for_invalidation(name) return Repository.get_by_repo_name(name)
def test_remove_repo(self): repo = fixture.create_repo(name=u'test-repo-1') Session().commit() RepoModel().delete(repo=repo) Session().commit() self.assertEqual(None, Repository.get_by_repo_name(repo_name=u'test-repo-1'))
def test_remove_repo_delete_forks(self): repo = fixture.create_repo(name=u'test-repo-1') Session().commit() fork = fixture.create_fork(repo.repo_name, u'test-repo-fork-1') Session().commit() #fork of fork fixture.create_fork(fork.repo_name, u'test-repo-fork-fork-1') Session().commit() RepoModel().delete(repo=repo, forks='delete') Session().commit() self.assertEqual(None, Repository.get_by_repo_name(repo_name=u'test-repo-1')) self.assertEqual(None, Repository.get_by_repo_name(repo_name=u'test-repo-fork-1')) self.assertEqual(None, Repository.get_by_repo_name(repo_name=u'test-repo-fork-fork-1'))
def _load_repo(self, repo_name): repo_obj = Repository.get_by_repo_name(repo_name) if repo_obj is None: h.not_mapped_error(repo_name) raise HTTPFound(location=url('repos')) return repo_obj
def _load_repo(self, repo_name): repo_obj = Repository.get_by_repo_name(repo_name) if repo_obj is None: h.not_mapped_error(repo_name) return redirect(url('repos')) return repo_obj
def test_clone_after_repo_was_locked_hg(self): #lock repo r = Repository.get_by_repo_name(HG_REPO) Repository.lock(r, User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id) #pull fails since repo is locked clone_url = _construct_url(HG_REPO) stdout, stderr = Command('/tmp').execute('hg clone', clone_url) msg = ("""abort: HTTP Error 423: Repository `%s` locked by user `%s`""" % (HG_REPO, TEST_USER_ADMIN_LOGIN)) assert msg in stderr
def mark_for_invalidation(self, repo_name, delete=False): """ Mark caches of this repo invalid in the database. :param repo_name: the repo for which caches should be marked invalid """ CacheInvalidation.set_invalidate(repo_name, delete=delete) repo = Repository.get_by_repo_name(repo_name) if repo: repo.update_changeset_cache()
def test_remove_repo_delete_forks(self): repo = fixture.create_repo(name=u'test-repo-1') Session().commit() fork = fixture.create_fork(repo.repo_name, u'test-repo-fork-1') Session().commit() #fork of fork fixture.create_fork(fork.repo_name, u'test-repo-fork-fork-1') Session().commit() RepoModel().delete(repo=repo, forks='delete') Session().commit() assert None == Repository.get_by_repo_name(repo_name=u'test-repo-1') assert None == Repository.get_by_repo_name( repo_name=u'test-repo-fork-1') assert None == Repository.get_by_repo_name( repo_name=u'test-repo-fork-fork-1')
def _get_defaults(self, repo_name): """ Gets information about repository, and returns a dict for usage in forms :param repo_name: """ repo_info = Repository.get_by_repo_name(repo_name) if repo_info is None: return None defaults = repo_info.get_dict() group, repo_name, repo_name_full = repo_info.groups_and_repo defaults['repo_name'] = repo_name defaults['repo_group'] = getattr(group[-1] if group else None, 'group_id', None) for strip, k in [(0, 'repo_type'), (1, 'repo_enable_downloads'), (1, 'repo_description'), (1, 'repo_enable_locking'), (1, 'repo_landing_rev'), (0, 'clone_uri'), (1, 'repo_private'), (1, 'repo_enable_statistics')]: attr = k if strip: attr = remove_prefix(k, 'repo_') val = defaults[attr] if k == 'repo_landing_rev': val = ':'.join(defaults[attr]) defaults[k] = val if k == 'clone_uri': defaults['clone_uri_hidden'] = repo_info.clone_uri_hidden # fill owner if repo_info.user: defaults.update({'user': repo_info.user.username}) else: replacement_user = User.query().filter( User.admin == True).first().username defaults.update({'user': replacement_user}) # fill repository users for p in repo_info.repo_to_perm: defaults.update( {'u_perm_%s' % p.user.username: p.permission.permission_name}) # fill repository groups for p in repo_info.users_group_to_perm: defaults.update({ 'g_perm_%s' % p.users_group.users_group_name: p.permission.permission_name }) return defaults
def action_logger(user, action, repo, ipaddr='', sa=None, commit=False): """ Action logger for various actions made by users :param user: user that made this action, can be a unique username string or object containing user_id attribute :param action: action to log, should be on of predefined unique actions for easy translations :param repo: string name of repository or object containing repo_id, that action was made on :param ipaddr: optional ip address from what the action was made :param sa: optional sqlalchemy session """ if not sa: sa = meta.Session() # if we don't get explicit IP address try to get one from registered user # in tmpl context var if not ipaddr: ipaddr = getattr(get_current_authuser(), 'ip_addr', '') if getattr(user, 'user_id', None): user_obj = User.get(user.user_id) elif isinstance(user, basestring): user_obj = User.get_by_username(user) else: raise Exception('You have to provide a user object or a username') if getattr(repo, 'repo_id', None): repo_obj = Repository.get(repo.repo_id) repo_name = repo_obj.repo_name elif isinstance(repo, basestring): repo_name = repo.lstrip('/') repo_obj = Repository.get_by_repo_name(repo_name) else: repo_obj = None repo_name = '' user_log = UserLog() user_log.user_id = user_obj.user_id user_log.username = user_obj.username user_log.action = safe_unicode(action) user_log.repository = repo_obj user_log.repository_name = repo_name user_log.action_date = datetime.datetime.now() user_log.user_ip = ipaddr sa.add(user_log) log.info('Logging action:%s on %s by user:%s ip:%s' % (action, safe_unicode(repo), user_obj, ipaddr)) if commit: sa.commit()
def test_z_fork_create(self): self.log_user() fork_name = self.REPO_FORK description = 'fork of vcs test' repo_name = self.REPO org_repo = Repository.get_by_repo_name(repo_name) creation_args = { 'repo_name': fork_name, 'repo_group': u'-1', 'fork_parent_id': org_repo.repo_id, 'repo_type': self.REPO_TYPE, 'description': description, 'private': 'False', 'landing_rev': 'rev:tip', '_authentication_token': self.authentication_token() } self.app.post( url(controller='forks', action='fork_create', repo_name=repo_name), creation_args) repo = Repository.get_by_repo_name(self.REPO_FORK) assert repo.fork.repo_name == self.REPO ## run the check page that triggers the flash message response = self.app.get(url('repo_check_home', repo_name=fork_name)) #test if we have a message that fork is ok self.checkSessionFlash( response, 'Forked repository %s as <a href="/%s">%s</a>' % (repo_name, fork_name, fork_name)) #test if the fork was created in the database fork_repo = Session().query(Repository) \ .filter(Repository.repo_name == fork_name).one() assert fork_repo.repo_name == fork_name assert fork_repo.fork.repo_name == repo_name # test if the repository is visible in the list ? response = self.app.get(url('summary_home', repo_name=fork_name)) response.mustcontain(fork_name) response.mustcontain(self.REPO_TYPE) response.mustcontain('Fork of "<a href="/%s">%s</a>"' % (repo_name, repo_name))
def mark_for_invalidation(self, repo_name): """ Mark caches of this repo invalid in the database. :param repo_name: the repo for which caches should be marked invalid """ log.debug("Marking %s as invalidated and update cache", repo_name) repo = Repository.get_by_repo_name(repo_name) if repo is not None: repo.set_invalidate() repo.update_changeset_cache()
def log_push_action(ui, repo, **kwargs): """ Register that changes have been pushed. Mercurial invokes this directly as a hook, git uses handle_git_receive. """ ex = _extract_extras() action_tmpl = ex.action + ':%s' revs = [] if ex.scm == 'hg': node = kwargs['node'] def get_revs(repo, rev_opt): if rev_opt: revs = revrange(repo, rev_opt) if len(revs) == 0: return (nullrev, nullrev) return max(revs), min(revs) else: return len(repo) - 1, 0 stop, start = get_revs(repo, [node + ':']) _h = binascii.hexlify revs = [_h(repo[r].node()) for r in xrange(start, stop + 1)] elif ex.scm == 'git': revs = kwargs.get('_git_revs', []) if '_git_revs' in kwargs: kwargs.pop('_git_revs') action = action_tmpl % ','.join(revs) action_logger(ex.username, action, ex.repository, ex.ip, commit=True) # extension hook call from kallithea import EXTENSIONS callback = getattr(EXTENSIONS, 'PUSH_HOOK', None) if callable(callback): kw = {'pushed_revs': revs} kw.update(ex) callback(**kw) if ex.make_lock is not None and not ex.make_lock: Repository.unlock(Repository.get_by_repo_name(ex.repository)) ui.status(safe_str('Released lock on repo `%s`\n' % ex.repository)) if ex.locked_by[0]: locked_by = User.get(ex.locked_by[0]).username _http_ret = HTTPLockedRC(ex.repository, locked_by) if str(_http_ret.code).startswith('2'): #2xx Codes don't raise exceptions ui.status(safe_str(_http_ret.title)) return 0
def create_fork(self, repo_to_fork, fork_name, **kwargs): repo_to_fork = Repository.get_by_repo_name(repo_to_fork) form_data = self._get_repo_create_params( repo_name=fork_name, fork_parent_id=repo_to_fork, repo_type=repo_to_fork.repo_type, **kwargs) # patch form dict so it can be used directly by model form_data['description'] = form_data['repo_description'] form_data['private'] = form_data['repo_private'] form_data['landing_rev'] = form_data['repo_landing_rev'] owner = kwargs.get('cur_user', TEST_USER_ADMIN_LOGIN) RepoModel().create_fork(form_data, cur_user=owner) Session().commit() ScmModel().mark_for_invalidation(fork_name) r = Repository.get_by_repo_name(fork_name) assert r return r
def wrapper_app(environ, start_response): if (parsed_request.cmd == 'info/refs' and parsed_request.service == 'git-upload-pack'): baseui = make_ui() repo = Repository.get_by_repo_name(parsed_request.repo_name) scm_repo = repo.scm_instance # Run hooks, like Mercurial outgoing.pull_logger does log_pull_action(ui=baseui, repo=scm_repo._repo) # Note: push hooks are handled by post-receive hook return pygrack_app(environ, start_response)
def test_index_by_repo_having_id_path_in_name_hg(self): self.log_user() fixture.create_repo(name='repo_1') response = self.app.get( url(controller='summary', action='index', repo_name='repo_1')) try: response.mustcontain("repo_1") finally: RepoModel().delete(Repository.get_by_repo_name('repo_1')) Session().commit()
def test_set_private_flag_sets_default_to_none(self): self.log_user() #initially repository perm should be read perm = _get_permission_for_user(user='******', repo=self.REPO) assert len(perm), 1 assert perm[0].permission.permission_name == 'repository.read' assert Repository.get_by_repo_name(self.REPO).private == False response = self.app.post(url('update_repo', repo_name=self.REPO), fixture._get_repo_create_params(repo_private=1, repo_name=self.REPO, repo_type=self.REPO_TYPE, owner=TEST_USER_ADMIN_LOGIN, _authentication_token=self.authentication_token())) self.checkSessionFlash(response, msg='Repository %s updated successfully' % (self.REPO)) assert Repository.get_by_repo_name(self.REPO).private == True #now the repo default permission should be None perm = _get_permission_for_user(user='******', repo=self.REPO) assert len(perm), 1 assert perm[0].permission.permission_name == 'repository.none' response = self.app.post(url('update_repo', repo_name=self.REPO), fixture._get_repo_create_params(repo_private=False, repo_name=self.REPO, repo_type=self.REPO_TYPE, owner=TEST_USER_ADMIN_LOGIN, _authentication_token=self.authentication_token())) self.checkSessionFlash(response, msg='Repository %s updated successfully' % (self.REPO)) assert Repository.get_by_repo_name(self.REPO).private == False #we turn off private now the repo default permission should stay None perm = _get_permission_for_user(user='******', repo=self.REPO) assert len(perm), 1 assert perm[0].permission.permission_name == 'repository.none' #update this permission back perm[0].permission = Permission.get_by_key('repository.read') Session().commit()
def validate_python(self, value, state): repo_name = value.get('repo_name') repo_name_full = value.get('repo_name_full') group_path = value.get('group_path') group_name = value.get('group_name') if repo_name in [ADMIN_PREFIX, '']: msg = M(self, 'invalid_repo_name', state, repo=repo_name) raise formencode.Invalid(msg, value, state, error_dict=dict(repo_name=msg)) rename = old_data.get('repo_name') != repo_name_full create = not edit if rename or create: if group_path != '': if Repository.get_by_repo_name(repo_name_full): msg = M(self, 'repository_in_group_exists', state, repo=repo_name, group=group_name) raise formencode.Invalid( msg, value, state, error_dict=dict(repo_name=msg)) elif RepoGroup.get_by_group_name(repo_name_full): msg = M(self, 'same_group_exists', state, repo=repo_name) raise formencode.Invalid(msg, value, state, error_dict=dict(repo_name=msg)) elif Repository.get_by_repo_name(repo_name_full): msg = M(self, 'repository_exists', state, repo=repo_name) raise formencode.Invalid(msg, value, state, error_dict=dict(repo_name=msg)) return value
def test_clone_after_repo_was_locked_git(self, webserver): #lock repo r = Repository.get_by_repo_name(GIT_REPO) Repository.lock(r, User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id) #pull fails since repo is locked clone_url = webserver.repo_url(GIT_REPO) stdout, stderr = Command(TESTS_TMP_PATH).execute('git clone', clone_url, _get_tmp_dir(), ignoreReturnCode=True) msg = ("""The requested URL returned error: 423""") assert msg in stderr
def create_fork(self, repo_to_fork, fork_name, **kwargs): repo_to_fork = Repository.get_by_repo_name(repo_to_fork) form_data = self._get_repo_create_params( repo_name=fork_name, fork_parent_id=repo_to_fork, repo_type=repo_to_fork.repo_type, **kwargs) form_data['update_after_clone'] = False #TODO: fix it !! form_data['description'] = form_data['repo_description'] form_data['private'] = form_data['repo_private'] form_data['landing_rev'] = form_data['repo_landing_rev'] owner = kwargs.get('cur_user', TEST_USER_ADMIN_LOGIN) RepoModel().create_fork(form_data, cur_user=owner) Session().commit() r = Repository.get_by_repo_name(fork_name) assert r return r
def fork(self, repo_name): c.repo_info = Repository.get_by_repo_name(repo_name) if not c.repo_info: h.not_mapped_error(repo_name) raise HTTPFound(location=url('home')) defaults = self.__load_data() return htmlfill.render(render('forks/fork.html'), defaults=defaults, encoding="UTF-8", force_defaults=False)
def test_set_fork_of_other_repo(self): self.log_user() other_repo = u'other_%s' % self.REPO_TYPE fixture.create_repo(other_repo, repo_type=self.REPO_TYPE) repo = Repository.get_by_repo_name(self.REPO) repo2 = Repository.get_by_repo_name(other_repo) response = self.app.post(url('edit_repo_advanced_fork', repo_name=self.REPO), params=dict(id_fork_of=repo2.repo_id, _authentication_token=self.authentication_token())) repo = Repository.get_by_repo_name(self.REPO) repo2 = Repository.get_by_repo_name(other_repo) self.checkSessionFlash(response, 'Marked repository %s as fork of %s' % (repo.repo_name, repo2.repo_name)) assert repo.fork == repo2 response = response.follow() # check if given repo is selected opt = """<option value="%s" selected="selected">%s</option>""" % ( repo2.repo_id, repo2.repo_name) response.mustcontain(opt) fixture.destroy_repo(other_repo, forks='detach')
def test_index_by_id_git(self): self.log_user() ID = Repository.get_by_repo_name(base.GIT_REPO).repo_id response = self.app.get( base.url(controller='summary', action='index', repo_name='_%s' % ID)) # repo type response.mustcontain( """<span class="label label-repo" title="Git repository">git""") # public/private response.mustcontain("""<i class="icon-globe">""")
def test_push_unlocks_repository_hg(self): # enable locking r = Repository.get_by_repo_name(HG_REPO) r.enable_locking = True Session().add(r) Session().commit() #clone some temp DEST = _get_tmp_dir() clone_url = _construct_url(HG_REPO, dest=DEST) stdout, stderr = Command('/tmp').execute('hg clone', clone_url) #check for lock repo after clone r = Repository.get_by_repo_name(HG_REPO) uid = User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id assert r.locked[0] == uid #push is ok and repo is now unlocked stdout, stderr = _add_files_and_push('hg', DEST) assert ('remote: Released lock on repo `%s`' % HG_REPO) in stdout #we need to cleanup the Session Here ! Session.remove() r = Repository.get_by_repo_name(HG_REPO) assert r.locked == [None, None]
def update(self, repo_name): """ PUT /repos/repo_name: Update an existing item""" # Forms posted to this method should contain a hidden field: # <input type="hidden" name="_method" value="PUT" /> # Or using helpers: # h.form(url('repo', repo_name=ID), # method='put') # url('repo', repo_name=ID) c.repo_info = self._load_repo(repo_name) c.active = 'settings' c.repo_fields = RepositoryField.query()\ .filter(RepositoryField.repository == c.repo_info).all() self.__load_defaults(c.repo_info) repo_model = RepoModel() changed_name = repo_name #override the choices with extracted revisions ! choices, c.landing_revs = ScmModel().get_repo_landing_revs(repo_name) c.landing_revs_choices = choices repo = Repository.get_by_repo_name(repo_name) old_data = { 'repo_name': repo_name, 'repo_group': repo.group.get_dict() if repo.group else {}, 'repo_type': repo.repo_type, } _form = RepoForm(edit=True, old_data=old_data, repo_groups=c.repo_groups_choices, landing_revs=c.landing_revs_choices)() try: form_result = _form.to_python(dict(request.POST)) repo = repo_model.update(repo_name, **form_result) ScmModel().mark_for_invalidation(repo_name) h.flash(_('Repository %s updated successfully') % repo_name, category='success') changed_name = repo.repo_name action_logger(self.authuser, 'admin_updated_repo', changed_name, self.ip_addr, self.sa) Session().commit() except formencode.Invalid, errors: defaults = self.__load_data(repo_name) defaults.update(errors.value) return htmlfill.render(render('admin/repos/repo_edit.html'), defaults=defaults, errors=errors.error_dict or {}, prefix_error=False, encoding="UTF-8", force_defaults=False)
def test_clone_after_repo_was_locked_hg(self, webserver): #lock repo r = Repository.get_by_repo_name(HG_REPO) Repository.lock(r, User.get_by_username(TEST_USER_ADMIN_LOGIN).user_id) #pull fails since repo is locked clone_url = webserver.repo_url(HG_REPO) stdout, stderr = Command(TESTS_TMP_PATH).execute('hg clone', clone_url, _get_tmp_dir(), ignoreReturnCode=True) msg = ( """abort: HTTP Error 423: Repository `%s` locked by user `%s`""" % (HG_REPO, TEST_USER_ADMIN_LOGIN)) assert msg in stderr
def repo_refs_data(self, repo_name): repo = Repository.get_by_repo_name(repo_name).scm_instance res = [] _branches = repo.branches.items() if _branches: res.append({ 'text': _('Branch'), 'children': [{ 'id': safe_str(rev), 'text': safe_str(name), 'type': 'branch' } for name, rev in _branches] }) _closed_branches = repo.closed_branches.items() if _closed_branches: res.append({ 'text': _('Closed Branches'), 'children': [{ 'id': safe_str(rev), 'text': safe_str(name), 'type': 'closed-branch' } for name, rev in _closed_branches] }) _tags = repo.tags.items() if _tags: res.append({ 'text': _('Tag'), 'children': [{ 'id': safe_str(rev), 'text': safe_str(name), 'type': 'tag' } for name, rev in _tags] }) _bookmarks = repo.bookmarks.items() if _bookmarks: res.append({ 'text': _('Bookmark'), 'children': [{ 'id': safe_str(rev), 'text': safe_str(name), 'type': 'book' } for name, rev in _bookmarks] }) data = {'more': False, 'results': res} return data
def test_remove_repo_detach_forks(self): repo = fixture.create_repo(name='test-repo-1') Session().commit() fork = fixture.create_fork(repo.repo_name, 'test-repo-fork-1') Session().commit() # fork of fork fixture.create_fork(fork.repo_name, 'test-repo-fork-fork-1') Session().commit() RepoModel().delete(repo=repo, forks='detach') Session().commit() try: assert Repository.get_by_repo_name(repo_name='test-repo-1') is None assert Repository.get_by_repo_name( repo_name='test-repo-fork-1') is not None assert Repository.get_by_repo_name( repo_name='test-repo-fork-fork-1') is not None finally: RepoModel().delete(repo='test-repo-fork-fork-1') RepoModel().delete(repo='test-repo-fork-1') Session().commit()
def update(self, repo_name): c.repo_info = self._load_repo() self.__load_defaults(c.repo_info) c.active = 'settings' c.repo_fields = RepositoryField.query() \ .filter(RepositoryField.repository == c.repo_info).all() repo_model = RepoModel() changed_name = repo_name repo = Repository.get_by_repo_name(repo_name) old_data = { 'repo_name': repo_name, 'repo_group': repo.group.get_dict() if repo.group else {}, 'repo_type': repo.repo_type, } _form = RepoForm(edit=True, old_data=old_data, repo_groups=c.repo_groups, landing_revs=c.landing_revs_choices)() try: form_result = _form.to_python(dict(request.POST)) repo = repo_model.update(repo_name, **form_result) ScmModel().mark_for_invalidation(repo_name) h.flash(_('Repository %s updated successfully') % repo_name, category='success') changed_name = repo.repo_name action_logger(request.authuser, 'admin_updated_repo', changed_name, request.ip_addr) Session().commit() except formencode.Invalid as errors: log.info(errors) defaults = self.__load_data() defaults.update(errors.value) return htmlfill.render(render('admin/repos/repo_edit.html'), defaults=defaults, errors=errors.error_dict or {}, prefix_error=False, encoding="UTF-8", force_defaults=False) except Exception: log.error(traceback.format_exc()) h.flash(_('Error occurred during update of repository %s') % repo_name, category='error') raise HTTPFound(location=url('edit_repo', repo_name=changed_name))
def edit_advanced_locking(self, repo_name): """ Unlock repository when it is locked ! :param repo_name: """ try: repo = Repository.get_by_repo_name(repo_name) if request.POST.get('set_lock'): Repository.lock(repo, c.authuser.user_id) h.flash(_('Locked repository'), category='success') elif request.POST.get('set_unlock'): Repository.unlock(repo) h.flash(_('Unlocked repository'), category='success') except Exception, e: log.error(traceback.format_exc()) h.flash(_('An error occurred during unlocking'), category='error')
def __get_codes_stats(repo_name): from kallithea.config.conf import LANGUAGES_EXTENSIONS_MAP repo = Repository.get_by_repo_name(repo_name).scm_instance tip = repo.get_changeset() code_stats = {} for _topnode, _dirnodes, filenodes in tip.walk('/'): for filenode in filenodes: ext = filenode.extension.lower() if ext in LANGUAGES_EXTENSIONS_MAP and not filenode.is_binary: if ext in code_stats: code_stats[ext] += 1 else: code_stats[ext] = 1 return code_stats or {}
def validate_python(self, value, state): repo_name = value.get('repo_name') repo_name_full = value.get('repo_name_full') group_path = value.get('group_path') group_name = value.get('group_name') if repo_name in [ADMIN_PREFIX, '']: msg = self.message('invalid_repo_name', state, repo=repo_name) raise formencode.Invalid(msg, value, state, error_dict=dict(repo_name=msg)) rename = old_data.get('repo_name') != repo_name_full create = not edit if rename or create: repo = Repository.get_by_repo_name(repo_name_full, case_insensitive=True) repo_group = RepoGroup.get_by_group_name(repo_name_full, case_insensitive=True) if group_path != '': if repo is not None: msg = self.message('repository_in_group_exists', state, repo=repo.repo_name, group=group_name) raise formencode.Invalid( msg, value, state, error_dict=dict(repo_name=msg)) elif repo_group is not None: msg = self.message('same_group_exists', state, repo=repo_name) raise formencode.Invalid(msg, value, state, error_dict=dict(repo_name=msg)) elif repo is not None: msg = self.message('repository_exists', state, repo=repo.repo_name) raise formencode.Invalid(msg, value, state, error_dict=dict(repo_name=msg)) return value
def _check_locking_state(self, environ, action, repo, user_id): """ Checks locking on this repository, if locking is enabled and lock is present returns a tuple of make_lock, locked, locked_by. make_lock can have 3 states None (do nothing) True, make lock False release lock, This value is later propagated to hooks, which do the locking. Think about this as signals passed to hooks what to do. """ locked = False # defines that locked error should be thrown to user make_lock = None repo = Repository.get_by_repo_name(repo) user = User.get(user_id) # this is kind of hacky, but due to how mercurial handles client-server # server see all operation on changeset; bookmarks, phases and # obsolescence marker in different transaction, we don't want to check # locking on those obsolete_call = environ['QUERY_STRING'] in [ 'cmd=listkeys', ] locked_by = repo.locked if repo and repo.enable_locking and not obsolete_call: if action == 'push': #check if it's already locked !, if it is compare users user_id, _date = repo.locked if user.user_id == user_id: log.debug('Got push from user %s, now unlocking' % (user)) # unlock if we have push from user who locked make_lock = False else: # we're not the same user who locked, ban with 423 ! locked = True if action == 'pull': if repo.locked[0] and repo.locked[1]: locked = True else: log.debug('Setting lock on repo %s by %s' % (repo, user)) make_lock = True else: log.debug('Repository %s do not have locking enabled' % (repo)) log.debug('FINAL locking values make_lock:%s,locked:%s,locked_by:%s' % (make_lock, locked, locked_by)) return make_lock, locked, locked_by
def toggle_locking(self, repo_name): try: repo = Repository.get_by_repo_name(repo_name) if repo.enable_locking: if repo.locked[0]: Repository.unlock(repo) h.flash(_('Repository has been unlocked'), category='success') else: Repository.lock(repo, request.authuser.user_id) h.flash(_('Repository has been locked'), category='success') except Exception as e: log.error(traceback.format_exc()) h.flash(_('An error occurred during unlocking'), category='error') raise HTTPFound(location=url('summary_home', repo_name=repo_name))
def test_index_git(self): self.log_user() ID = Repository.get_by_repo_name(GIT_REPO).repo_id response = self.app.get( url(controller='summary', action='index', repo_name=GIT_REPO)) #repo type response.mustcontain("""<span class="repotag">git""") #public/private response.mustcontain("""<i class="icon-globe">""") # clone url... response.mustcontain( '''id="clone_url" readonly="readonly" value="http://test_admin@localhost:80/%s"''' % GIT_REPO) response.mustcontain( '''id="clone_url_id" readonly="readonly" value="http://test_admin@localhost:80/_%s"''' % ID)