|
Pierre-Yves Chibon |
33b534 |
# -*- coding: utf-8 -*-
|
|
Pierre-Yves Chibon |
413073 |
|
|
Pierre-Yves Chibon |
413073 |
"""
|
|
Pierre-Yves Chibon |
517d69 |
(c) 2015-2018 - Copyright Red Hat Inc
|
|
Pierre-Yves Chibon |
413073 |
|
|
Pierre-Yves Chibon |
413073 |
Authors:
|
|
Pierre-Yves Chibon |
413073 |
Pierre-Yves Chibon <pingou@pingoured.fr></pingou@pingoured.fr>
|
|
Pierre-Yves Chibon |
413073 |
|
|
Pierre-Yves Chibon |
413073 |
"""
|
|
Pierre-Yves Chibon |
413073 |
|
|
Aurélien Bompard |
626417 |
from __future__ import unicode_literals
|
|
Aurélien Bompard |
626417 |
|
|
Pierre-Yves Chibon |
413073 |
__requires__ = ['SQLAlchemy >= 0.7']
|
|
Pierre-Yves Chibon |
413073 |
import pkg_resources
|
|
Pierre-Yves Chibon |
413073 |
|
|
Aurélien Bompard |
626417 |
import imp
|
|
Aurélien Bompard |
f61bb3 |
import json
|
|
Pierre-Yves Chibon |
59df6f |
import logging
|
|
Pierre-Yves Chibon |
59e3b9 |
import os
|
|
Pierre-Yves Chibon |
59e3b9 |
import re
|
|
Pierre-Yves Chibon |
59e3b9 |
import resource
|
|
Pierre-Yves Chibon |
59d644 |
import shutil
|
|
Patrick Uiterwijk |
55e7e0 |
import subprocess
|
|
Pierre-Yves Chibon |
413073 |
import sys
|
|
Pierre-Yves Chibon |
c27b0d |
import tempfile
|
|
Patrick Uiterwijk |
114ca2 |
import time
|
|
Pierre-Yves Chibon |
59e3b9 |
import unittest
|
|
Aurélien Bompard |
619e2a |
from io import open, StringIO
|
|
Pierre-Yves Chibon |
59df6f |
logging.basicConfig(stream=sys.stderr)
|
|
Pierre-Yves Chibon |
413073 |
|
|
Aurélien Bompard |
626417 |
from bs4 import BeautifulSoup
|
|
Pierre-Yves Chibon |
a324b4 |
from contextlib import contextmanager
|
|
Pierre-Yves Chibon |
413073 |
from datetime import date
|
|
Pierre-Yves Chibon |
21f499 |
from datetime import datetime
|
|
Pierre-Yves Chibon |
413073 |
from datetime import timedelta
|
|
Pierre-Yves Chibon |
413073 |
from functools import wraps
|
|
Aurélien Bompard |
626417 |
from six.moves.urllib.parse import urlparse, parse_qs
|
|
Pierre-Yves Chibon |
413073 |
|
|
Pierre-Yves Chibon |
a324b4 |
import mock
|
|
Pierre-Yves Chibon |
4e9b76 |
import pygit2
|
|
Aurélien Bompard |
00115d |
import redis
|
|
Aurélien Bompard |
626417 |
import six
|
|
Pierre-Yves Chibon |
4e9b76 |
|
|
Pierre-Yves Chibon |
675b89 |
from bs4 import BeautifulSoup
|
|
Aurélien Bompard |
00115d |
from celery.app.task import EagerResult
|
|
Pierre-Yves Chibon |
413073 |
from sqlalchemy import create_engine
|
|
Pierre-Yves Chibon |
413073 |
from sqlalchemy.orm import sessionmaker
|
|
Pierre-Yves Chibon |
413073 |
from sqlalchemy.orm import scoped_session
|
|
Pierre-Yves Chibon |
413073 |
|
|
Aurélien Bompard |
626417 |
if six.PY2:
|
|
Aurélien Bompard |
626417 |
# Always enable performance counting for tests
|
|
Aurélien Bompard |
626417 |
os.environ['PAGURE_PERFREPO'] = 'true'
|
|
Aurélien Bompard |
626417 |
|
|
Pierre-Yves Chibon |
413073 |
sys.path.insert(0, os.path.join(os.path.dirname(
|
|
Pierre-Yves Chibon |
413073 |
os.path.abspath(__file__)), '..'))
|
|
Pierre-Yves Chibon |
413073 |
|
|
Pierre-Yves Chibon |
fe5017 |
import pagure
|
|
Pierre-Yves Chibon |
b130e5 |
import pagure.api
|
|
Patrick Uiterwijk |
3f97f6 |
from pagure.api.ci import jenkins
|
|
Pierre-Yves Chibon |
b130e5 |
import pagure.flask_app
|
|
Pierre-Yves Chibon |
6fdafd |
import pagure.lib.git
|
|
Pierre-Yves Chibon |
fe5017 |
import pagure.lib.model
|
|
Pierre-Yves Chibon |
930073 |
import pagure.lib.query
|
|
Patrick Uiterwijk |
4012dc |
import pagure.lib.tasks_mirror
|
|
Patrick Uiterwijk |
fcd520 |
import pagure.perfrepo as perfrepo
|
|
Aurélien Bompard |
e78d79 |
from pagure.config import config as pagure_config, reload_config
|
|
Pierre-Yves Chibon |
b130e5 |
from pagure.lib.repo import PagureRepo
|
|
Pierre-Yves Chibon |
413073 |
|
|
Pierre-Yves Chibon |
f62635 |
HERE = os.path.join(os.path.dirname(os.path.abspath(__file__)))
|
|
Pierre-Yves Chibon |
b73de8 |
LOG = logging.getLogger(__name__)
|
|
Pierre-Yves Chibon |
b130e5 |
LOG.setLevel(logging.INFO)
|
|
Pierre-Yves Chibon |
413073 |
|
|
Pierre-Yves Chibon |
b73de8 |
PAGLOG = logging.getLogger('pagure')
|
|
Pierre-Yves Chibon |
b73de8 |
PAGLOG.setLevel(logging.CRITICAL)
|
|
Pierre-Yves Chibon |
b73de8 |
PAGLOG.handlers = []
|
|
Pierre-Yves Chibon |
b73de8 |
|
|
Patrick Uiterwijk |
b2cb9c |
if 'PYTHONPATH' not in os.environ:
|
|
Patrick Uiterwijk |
b2cb9c |
os.environ['PYTHONPATH'] = os.path.normpath(os.path.join(HERE, '../'))
|
|
Patrick Uiterwijk |
b2cb9c |
|
|
Patrick Uiterwijk |
55e7e0 |
CONFIG_TEMPLATE = """
|
|
Patrick Uiterwijk |
55e7e0 |
GIT_FOLDER = '%(path)s/repos'
|
|
Aurélien Bompard |
e78d79 |
ENABLE_DOCS = %(enable_docs)s
|
|
Aurélien Bompard |
e78d79 |
ENABLE_TICKETS = %(enable_tickets)s
|
|
Patrick Uiterwijk |
55e7e0 |
REMOTE_GIT_FOLDER = '%(path)s/remotes'
|
|
Patrick Uiterwijk |
55e7e0 |
DB_URL = '%(dburl)s'
|
|
Patrick Uiterwijk |
7b9080 |
ALLOW_PROJECT_DOWAIT = True
|
|
Aurélien Bompard |
e78d79 |
PAGURE_CI_SERVICES = ['jenkins']
|
|
Aurélien Bompard |
e78d79 |
EMAIL_SEND = False
|
|
Aurélien Bompard |
e78d79 |
TESTING = True
|
|
Aurélien Bompard |
e78d79 |
GIT_FOLDER = '%(path)s/repos'
|
|
Aurélien Bompard |
e78d79 |
REQUESTS_FOLDER = '%(path)s/repos/requests'
|
|
Aurélien Bompard |
e78d79 |
TICKETS_FOLDER = %(tickets_folder)r
|
|
Aurélien Bompard |
e78d79 |
DOCS_FOLDER = %(docs_folder)r
|
|
Patrick Uiterwijk |
3f97f6 |
REPOSPANNER_PSEUDO_FOLDER = '%(path)s/repos/pseudo'
|
|
Aurélien Bompard |
e78d79 |
ATTACHMENTS_FOLDER = '%(path)s/attachments'
|
|
Aurélien Bompard |
e78d79 |
BROKER_URL = 'redis+socket://%(global_path)s/broker'
|
|
Aurélien Bompard |
00115d |
CELERY_CONFIG = {
|
|
Aurélien Bompard |
00115d |
"task_always_eager": True,
|
|
Aurélien Bompard |
626417 |
#"task_eager_propagates": True,
|
|
Aurélien Bompard |
00115d |
}
|
|
Patrick Uiterwijk |
b2cb9c |
GIT_AUTH_BACKEND = '%(authbackend)s'
|
|
Patrick Uiterwijk |
b2cb9c |
TEST_AUTH_STATUS = '%(path)s/testauth_status.json'
|
|
Patrick Uiterwijk |
8174a4 |
REPOBRIDGE_BINARY = '%(repobridge_binary)s'
|
|
Patrick Uiterwijk |
3f97f6 |
REPOSPANNER_NEW_REPO = %(repospanner_new_repo)s
|
|
Patrick Uiterwijk |
3f97f6 |
REPOSPANNER_NEW_REPO_ADMIN_OVERRIDE = %(repospanner_admin_override)s
|
|
Patrick Uiterwijk |
3f97f6 |
REPOSPANNER_NEW_FORK = %(repospanner_new_fork)s
|
|
Patrick Uiterwijk |
3f97f6 |
REPOSPANNER_ADMIN_MIGRATION = %(repospanner_admin_migration)s
|
|
Patrick Uiterwijk |
3f97f6 |
REPOSPANNER_REGIONS = {
|
|
Patrick Uiterwijk |
3f97f6 |
'default': {'url': 'https://nodea.regiona.repospanner.local:%(repospanner_gitport)s',
|
|
Patrick Uiterwijk |
3f97f6 |
'repo_prefix': 'pagure/',
|
|
Patrick Uiterwijk |
d29158 |
'hook': None,
|
|
Patrick Uiterwijk |
3f97f6 |
'ca': '%(path)s/repospanner/pki/ca.crt',
|
|
Patrick Uiterwijk |
3f97f6 |
'admin_cert': {'cert': '%(path)s/repospanner/pki/admin.crt',
|
|
Patrick Uiterwijk |
3f97f6 |
'key': '%(path)s/repospanner/pki/admin.key'},
|
|
Patrick Uiterwijk |
3f97f6 |
'push_cert': {'cert': '%(path)s/repospanner/pki/pagure.crt',
|
|
Patrick Uiterwijk |
3f97f6 |
'key': '%(path)s/repospanner/pki/pagure.key'}}
|
|
Patrick Uiterwijk |
3f97f6 |
}
|
|
Patrick Uiterwijk |
55e7e0 |
"""
|
|
Aurélien Bompard |
00115d |
# The Celery docs warn against using task_always_eager:
|
|
Aurélien Bompard |
00115d |
# http://docs.celeryproject.org/en/latest/userguide/testing.html
|
|
Aurélien Bompard |
00115d |
# but that warning is only valid when testing the async nature of the task, not
|
|
Aurélien Bompard |
00115d |
# what the task actually does.
|
|
Patrick Uiterwijk |
55e7e0 |
|
|
Pierre-Yves Chibon |
413073 |
|
|
Pierre-Yves Chibon |
59df6f |
LOG.info('BUILD_ID: %s', os.environ.get('BUILD_ID'))
|
|
Pierre-Yves Chibon |
413073 |
|
|
Patrick Uiterwijk |
114ca2 |
|
|
Karsten Hopp |
b310af |
WAIT_REGEX = re.compile(r"""var _url = '(\/wait\/[a-z0-9-]+\??.*)'""")
|
|
Patrick Uiterwijk |
114ca2 |
def get_wait_target(html):
|
|
Patrick Uiterwijk |
114ca2 |
""" This parses the window.location out of the HTML for the wait page. """
|
|
Patrick Uiterwijk |
114ca2 |
found = WAIT_REGEX.findall(html)
|
|
Pierre-Yves Chibon |
f341aa |
if len(found) == 0:
|
|
Patrick Uiterwijk |
114ca2 |
raise Exception("Not able to get wait target in %s" % html)
|
|
Pierre-Yves Chibon |
f341aa |
return found[-1]
|
|
Patrick Uiterwijk |
114ca2 |
|
|
Patrick Uiterwijk |
114ca2 |
|
|
Pierre-Yves Chibon |
517d69 |
def get_post_target(html):
|
|
Pierre-Yves Chibon |
675b89 |
""" This parses the wait page form to get the POST url. """
|
|
Pierre-Yves Chibon |
675b89 |
soup = BeautifulSoup(html, 'html.parser')
|
|
Pierre-Yves Chibon |
675b89 |
form = soup.find(id='waitform')
|
|
Pierre-Yves Chibon |
675b89 |
if not form:
|
|
Pierre-Yves Chibon |
517d69 |
raise Exception("Not able to get the POST url in %s" % html)
|
|
Pierre-Yves Chibon |
675b89 |
return form.get('action')
|
|
Pierre-Yves Chibon |
517d69 |
|
|
Pierre-Yves Chibon |
517d69 |
|
|
Pierre-Yves Chibon |
517d69 |
def get_post_args(html):
|
|
Pierre-Yves Chibon |
675b89 |
""" This parses the wait page for the hidden arguments of the form. """
|
|
Pierre-Yves Chibon |
675b89 |
soup = BeautifulSoup(html, 'html.parser')
|
|
Pierre-Yves Chibon |
517d69 |
output = {}
|
|
Pierre-Yves Chibon |
675b89 |
inputs = soup.find_all('input')
|
|
Pierre-Yves Chibon |
675b89 |
if not inputs:
|
|
Pierre-Yves Chibon |
675b89 |
raise Exception("Not able to get the POST arguments in %s" % html)
|
|
Pierre-Yves Chibon |
675b89 |
for inp in inputs:
|
|
Pierre-Yves Chibon |
675b89 |
if inp.get('type') == 'hidden':
|
|
Pierre-Yves Chibon |
675b89 |
output[inp.get('name')] = inp.get('value')
|
|
Pierre-Yves Chibon |
517d69 |
return output
|
|
Pierre-Yves Chibon |
517d69 |
|
|
Pierre-Yves Chibon |
517d69 |
|
|
Patrick Uiterwijk |
114ca2 |
def create_maybe_waiter(method, getter):
|
|
Patrick Uiterwijk |
114ca2 |
def maybe_waiter(*args, **kwargs):
|
|
Patrick Uiterwijk |
114ca2 |
""" A wrapper for self.app.get()/.post() that will resolve wait's """
|
|
Patrick Uiterwijk |
114ca2 |
result = method(*args, **kwargs)
|
|
Pierre-Yves Chibon |
517d69 |
|
|
Pierre-Yves Chibon |
517d69 |
# Handle the POST wait case
|
|
Pierre-Yves Chibon |
517d69 |
form_url = None
|
|
Pierre-Yves Chibon |
517d69 |
form_args = None
|
|
Aurélien Bompard |
626417 |
try:
|
|
Aurélien Bompard |
626417 |
result_text = result.get_data(as_text=True)
|
|
Aurélien Bompard |
626417 |
except UnicodeDecodeError:
|
|
Aurélien Bompard |
626417 |
return result
|
|
Aurélien Bompard |
626417 |
if 'id="waitform"' in result_text:
|
|
Aurélien Bompard |
626417 |
form_url = get_post_target(result_text)
|
|
Aurélien Bompard |
626417 |
form_args = get_post_args(result_text)
|
|
Aurélien Bompard |
626417 |
form_args['csrf_token'] = result_text.split(
|
|
Pierre-Yves Chibon |
517d69 |
'name="csrf_token" type="hidden" value="')[1].split('">')[0]
|
|
Pierre-Yves Chibon |
517d69 |
|
|
Patrick Uiterwijk |
114ca2 |
count = 0
|
|
Aurélien Bompard |
626417 |
while 'We are waiting for your task to finish.' in result_text:
|
|
Patrick Uiterwijk |
114ca2 |
# Resolve wait page
|
|
Aurélien Bompard |
626417 |
target_url = get_wait_target(result_text)
|
|
Patrick Uiterwijk |
114ca2 |
if count > 10:
|
|
Patrick Uiterwijk |
114ca2 |
time.sleep(0.5)
|
|
Patrick Uiterwijk |
114ca2 |
else:
|
|
Patrick Uiterwijk |
114ca2 |
time.sleep(0.1)
|
|
Patrick Uiterwijk |
114ca2 |
result = getter(target_url, follow_redirects=True)
|
|
Aurélien Bompard |
626417 |
try:
|
|
Aurélien Bompard |
626417 |
result_text = result.get_data(as_text=True)
|
|
Aurélien Bompard |
626417 |
except UnicodeDecodeError:
|
|
Aurélien Bompard |
626417 |
return result
|
|
Patrick Uiterwijk |
114ca2 |
if count > 50:
|
|
Patrick Uiterwijk |
114ca2 |
raise Exception('Had to wait too long')
|
|
Patrick Uiterwijk |
114ca2 |
else:
|
|
Pierre-Yves Chibon |
517d69 |
if form_url and form_args:
|
|
Pierre-Yves Chibon |
517d69 |
return method(form_url, data=form_args, follow_redirects=True)
|
|
Patrick Uiterwijk |
114ca2 |
return result
|
|
Patrick Uiterwijk |
114ca2 |
return maybe_waiter
|
|
Patrick Uiterwijk |
114ca2 |
|
|
Patrick Uiterwijk |
114ca2 |
|
|
Pierre-Yves Chibon |
413073 |
@contextmanager
|
|
Patrick Uiterwijk |
3d2cb5 |
def user_set(APP, user, keep_get_user=False):
|
|
Pierre-Yves Chibon |
413073 |
""" Set the provided user as fas_user in the provided application."""
|
|
Pierre-Yves Chibon |
413073 |
|
|
Pierre-Yves Chibon |
413073 |
# Hack used to remove the before_request function set by
|
|
Pierre-Yves Chibon |
413073 |
# flask.ext.fas_openid.FAS which otherwise kills our effort to set a
|
|
Pierre-Yves Chibon |
413073 |
# flask.g.fas_user.
|
|
Pierre-Yves Chibon |
413073 |
from flask import appcontext_pushed, g
|
|
Pierre-Yves Chibon |
4ad0bb |
keep = []
|
|
Pierre-Yves Chibon |
4ad0bb |
for meth in APP.before_request_funcs[None]:
|
|
Pierre-Yves Chibon |
4ad0bb |
if 'flask_fas_openid.FAS' in str(meth):
|
|
Pierre-Yves Chibon |
4ad0bb |
continue
|
|
Pierre-Yves Chibon |
4ad0bb |
keep.append(meth)
|
|
Pierre-Yves Chibon |
4ad0bb |
APP.before_request_funcs[None] = keep
|
|
Pierre-Yves Chibon |
413073 |
|
|
Pierre-Yves Chibon |
413073 |
def handler(sender, **kwargs):
|
|
Pierre-Yves Chibon |
413073 |
g.fas_user = user
|
|
Pierre-Yves Chibon |
e120d5 |
g.fas_session_id = b'123'
|
|
Pierre-Yves Chibon |
392277 |
g.authenticated = True
|
|
Patrick Uiterwijk |
3d2cb5 |
old_get_user = pagure.flask_app._get_user
|
|
Patrick Uiterwijk |
3d2cb5 |
if not keep_get_user:
|
|
Patrick Uiterwijk |
3d2cb5 |
pagure.flask_app._get_user = mock.MagicMock(
|
|
Patrick Uiterwijk |
3d2cb5 |
return_value=pagure.lib.model.User())
|
|
Pierre-Yves Chibon |
413073 |
|
|
Pierre-Yves Chibon |
413073 |
with appcontext_pushed.connected_to(handler, APP):
|
|
Pierre-Yves Chibon |
413073 |
yield
|
|
Pierre-Yves Chibon |
413073 |
|
|
Patrick Uiterwijk |
3d2cb5 |
pagure.flask_app._get_user = old_get_user
|
|
Patrick Uiterwijk |
3d2cb5 |
|
|
Slavek Kabrda |
7713cf |
|
|
Aurélien Bompard |
e78d79 |
tests_state = {
|
|
Aurélien Bompard |
e78d79 |
"path": tempfile.mkdtemp(prefix='pagure-tests-'),
|
|
Aurélien Bompard |
e78d79 |
"broker": None,
|
|
Aurélien Bompard |
00115d |
"broker_client": None,
|
|
Aurélien Bompard |
00115d |
"results": {},
|
|
Aurélien Bompard |
e78d79 |
}
|
|
Slavek Kabrda |
7713cf |
|
|
Slavek Kabrda |
7713cf |
|
|
Aurélien Bompard |
e78d79 |
def _populate_db(session):
|
|
Slavek Kabrda |
7713cf |
# Create a couple of users
|
|
Slavek Kabrda |
7713cf |
item = pagure.lib.model.User(
|
|
Slavek Kabrda |
7713cf |
user='pingou',
|
|
Slavek Kabrda |
7713cf |
fullname='PY C',
|
|
Aurélien Bompard |
626417 |
password=b'foo',
|
|
Slavek Kabrda |
7713cf |
default_email='bar@pingou.com',
|
|
Slavek Kabrda |
7713cf |
)
|
|
Slavek Kabrda |
7713cf |
session.add(item)
|
|
Slavek Kabrda |
7713cf |
item = pagure.lib.model.UserEmail(
|
|
Slavek Kabrda |
7713cf |
user_id=1,
|
|
Slavek Kabrda |
7713cf |
email='bar@pingou.com')
|
|
Slavek Kabrda |
7713cf |
session.add(item)
|
|
Slavek Kabrda |
7713cf |
item = pagure.lib.model.UserEmail(
|
|
Slavek Kabrda |
7713cf |
user_id=1,
|
|
Slavek Kabrda |
7713cf |
email='foo@pingou.com')
|
|
Slavek Kabrda |
7713cf |
session.add(item)
|
|
Slavek Kabrda |
7713cf |
|
|
Slavek Kabrda |
7713cf |
item = pagure.lib.model.User(
|
|
Slavek Kabrda |
7713cf |
user='foo',
|
|
Slavek Kabrda |
7713cf |
fullname='foo bar',
|
|
Aurélien Bompard |
626417 |
password=b'foo',
|
|
Slavek Kabrda |
7713cf |
default_email='foo@bar.com',
|
|
Slavek Kabrda |
7713cf |
)
|
|
Slavek Kabrda |
7713cf |
session.add(item)
|
|
Slavek Kabrda |
7713cf |
item = pagure.lib.model.UserEmail(
|
|
Slavek Kabrda |
7713cf |
user_id=2,
|
|
Slavek Kabrda |
7713cf |
email='foo@bar.com')
|
|
Slavek Kabrda |
7713cf |
session.add(item)
|
|
Slavek Kabrda |
7713cf |
|
|
Slavek Kabrda |
7713cf |
session.commit()
|
|
Slavek Kabrda |
7713cf |
|
|
Slavek Kabrda |
7713cf |
|
|
Aurélien Bompard |
00115d |
def store_eager_results(*args, **kwargs):
|
|
Aurélien Bompard |
00115d |
"""A wrapper for EagerResult that stores the instance."""
|
|
Aurélien Bompard |
00115d |
result = EagerResult(*args, **kwargs)
|
|
Aurélien Bompard |
00115d |
tests_state["results"][result.id] = result
|
|
Aurélien Bompard |
00115d |
return result
|
|
Slavek Kabrda |
7713cf |
|
|
Aurélien Bompard |
e78d79 |
|
|
Aurélien Bompard |
e78d79 |
def setUp():
|
|
Aurélien Bompard |
e78d79 |
# In order to save time during local test execution, we create sqlite DB
|
|
Aurélien Bompard |
e78d79 |
# file only once and then we populate it and empty it for every test case
|
|
Aurélien Bompard |
e78d79 |
# (as opposed to creating DB file for every test case).
|
|
Aurélien Bompard |
e78d79 |
session = pagure.lib.model.create_tables(
|
|
Aurélien Bompard |
e78d79 |
'sqlite:///%s/db.sqlite' % tests_state["path"],
|
|
Aurélien Bompard |
e78d79 |
acls=pagure_config.get('ACLS', {}),
|
|
Aurélien Bompard |
e78d79 |
)
|
|
Aurélien Bompard |
e78d79 |
tests_state["db_session"] = session
|
|
Slavek Kabrda |
7713cf |
|
|
Slavek Kabrda |
3cb529 |
# Create a broker
|
|
Aurélien Bompard |
e78d79 |
broker_url = os.path.join(tests_state["path"], 'broker')
|
|
Aurélien Bompard |
e78d79 |
|
|
Aurélien Bompard |
e78d79 |
tests_state["broker"] = broker = subprocess.Popen(
|
|
Slavek Kabrda |
3cb529 |
['/usr/bin/redis-server', '--unixsocket', broker_url, '--port',
|
|
Slavek Kabrda |
3cb529 |
'0', '--loglevel', 'warning', '--logfile', '/dev/null'],
|
|
Slavek Kabrda |
3cb529 |
stdout=None, stderr=None)
|
|
Slavek Kabrda |
3cb529 |
broker.poll()
|
|
Slavek Kabrda |
3cb529 |
if broker.returncode is not None:
|
|
Slavek Kabrda |
3cb529 |
raise Exception('Broker failed to start')
|
|
Aurélien Bompard |
00115d |
tests_state["broker_client"] = redis.Redis(unix_socket_path=broker_url)
|
|
Aurélien Bompard |
00115d |
|
|
Aurélien Bompard |
00115d |
# Store the EagerResults to be able to retrieve them later
|
|
Aurélien Bompard |
00115d |
tests_state["eg_patcher"] = mock.patch('celery.app.task.EagerResult')
|
|
Aurélien Bompard |
00115d |
eg_mock = tests_state["eg_patcher"].start()
|
|
Aurélien Bompard |
00115d |
eg_mock.side_effect = store_eager_results
|
|
Slavek Kabrda |
7713cf |
|
|
Pierre-Yves Chibon |
2d5c52 |
|
|
Slavek Kabrda |
3cb529 |
def tearDown():
|
|
Aurélien Bompard |
e78d79 |
tests_state["db_session"].close()
|
|
Aurélien Bompard |
00115d |
tests_state["eg_patcher"].stop()
|
|
Aurélien Bompard |
e78d79 |
broker = tests_state["broker"]
|
|
Slavek Kabrda |
3cb529 |
broker.kill()
|
|
Slavek Kabrda |
3cb529 |
broker.wait()
|
|
Aurélien Bompard |
e78d79 |
shutil.rmtree(tests_state["path"])
|
|
Pierre-Yves Chibon |
59e3b9 |
|
|
Pierre-Yves Chibon |
59e3b9 |
|
|
Clement Verna |
109c4b |
class SimplePagureTest(unittest.TestCase):
|
|
Clement Verna |
109c4b |
"""
|
|
Clement Verna |
109c4b |
Simple Test class that does not set a broker/worker
|
|
Clement Verna |
109c4b |
"""
|
|
Pierre-Yves Chibon |
413073 |
|
|
Aurélien Bompard |
e78d79 |
populate_db = True
|
|
Aurélien Bompard |
e78d79 |
config_values = {}
|
|
Aurélien Bompard |
e78d79 |
|
|
Pierre-Yves Chibon |
a324b4 |
@mock.patch('pagure.lib.notify.fedmsg_publish', mock.MagicMock())
|
|
Pierre-Yves Chibon |
413073 |
def __init__(self, method_name='runTest'):
|
|
Pierre-Yves Chibon |
413073 |
""" Constructor. """
|
|
Pierre-Yves Chibon |
413073 |
unittest.TestCase.__init__(self, method_name)
|
|
Pierre-Yves Chibon |
413073 |
self.session = None
|
|
Jeremy Cline |
20109f |
self.path = None
|
|
Pierre-Yves Chibon |
3a4d42 |
self.gitrepo = None
|
|
Pierre-Yves Chibon |
619b9a |
self.gitrepos = None
|
|
Pierre-Yves Chibon |
413073 |
|
|
Patrick Uiterwijk |
fcd520 |
def perfMaxWalks(self, max_walks, max_steps):
|
|
Patrick Uiterwijk |
fcd520 |
""" Check that we have not performed too many walks/steps. """
|
|
Patrick Uiterwijk |
fcd520 |
num_walks = 0
|
|
Patrick Uiterwijk |
fcd520 |
num_steps = 0
|
|
Patrick Uiterwijk |
fcd520 |
for reqstat in perfrepo.REQUESTS:
|
|
Patrick Uiterwijk |
fcd520 |
for walk in reqstat['walks'].values():
|
|
Patrick Uiterwijk |
fcd520 |
num_walks += 1
|
|
Patrick Uiterwijk |
fcd520 |
num_steps += walk['steps']
|
|
Patrick Uiterwijk |
fcd520 |
self.assertLessEqual(num_walks, max_walks,
|
|
Patrick Uiterwijk |
fcd520 |
'%s git repo walks performed, at most %s allowed'
|
|
Patrick Uiterwijk |
fcd520 |
% (num_walks, max_walks))
|
|
Patrick Uiterwijk |
fcd520 |
self.assertLessEqual(num_steps, max_steps,
|
|
Patrick Uiterwijk |
fcd520 |
'%s git repo steps performed, at most %s allowed'
|
|
Patrick Uiterwijk |
fcd520 |
% (num_steps, max_steps))
|
|
Patrick Uiterwijk |
fcd520 |
|
|
Patrick Uiterwijk |
fcd520 |
def perfReset(self):
|
|
Patrick Uiterwijk |
fcd520 |
""" Reset perfrepo stats. """
|
|
Patrick Uiterwijk |
fcd520 |
perfrepo.reset_stats()
|
|
Patrick Uiterwijk |
fcd520 |
perfrepo.REQUESTS = []
|
|
Patrick Uiterwijk |
fcd520 |
|
|
Clement Verna |
109c4b |
def setUp(self):
|
|
Patrick Uiterwijk |
8a2282 |
if self.path:
|
|
Patrick Uiterwijk |
8a2282 |
# This prevents test state leakage.
|
|
Patrick Uiterwijk |
8a2282 |
# This should be None if the previous runs' tearDown didn't finish,
|
|
Patrick Uiterwijk |
8a2282 |
# leaving behind a self.path.
|
|
Patrick Uiterwijk |
8a2282 |
# If we continue in this case, not only did the previous worker and
|
|
Patrick Uiterwijk |
8a2282 |
# redis instances not exit, we also might accidentally use the
|
|
Patrick Uiterwijk |
8a2282 |
# old database connection.
|
|
Patrick Uiterwijk |
8a2282 |
# @pingou, don't delete this again... :)
|
|
Patrick Uiterwijk |
8a2282 |
raise Exception('Previous test failed!')
|
|
Patrick Uiterwijk |
8a2282 |
|
|
Clement Verna |
109c4b |
self.perfReset()
|
|
Patrick Uiterwijk |
fcd520 |
|
|
Patrick Uiterwijk |
8a2282 |
self.path = tempfile.mkdtemp(prefix='pagure-tests-path-')
|
|
Pierre-Yves Chibon |
8b2c5c |
|
|
Pierre-Yves Chibon |
b130e5 |
LOG.debug('Testdir: %s', self.path)
|
|
Slavek Kabrda |
adea20 |
for folder in ['repos', 'forks', 'releases', 'remotes', 'attachments']:
|
|
Jeremy Cline |
20109f |
os.mkdir(os.path.join(self.path, folder))
|
|
Pierre-Yves Chibon |
58e731 |
|
|
Pierre-Yves Chibon |
930073 |
if hasattr(pagure.lib.query, 'REDIS') and pagure.lib.query.REDIS:
|
|
Pierre-Yves Chibon |
930073 |
pagure.lib.query.REDIS.connection_pool.disconnect()
|
|
Pierre-Yves Chibon |
930073 |
pagure.lib.query.REDIS = None
|
|
Slavek Kabrda |
afb8f6 |
|
|
Aurélien Bompard |
e78d79 |
# Database
|
|
Aurélien Bompard |
e78d79 |
self._prepare_db()
|
|
Patrick Uiterwijk |
55e7e0 |
|
|
Patrick Uiterwijk |
55e7e0 |
# Write a config file
|
|
Aurélien Bompard |
e78d79 |
config_values = {
|
|
Aurélien Bompard |
e78d79 |
'path': self.path, 'dburl': self.dbpath,
|
|
Aurélien Bompard |
e78d79 |
'enable_docs': True,
|
|
Aurélien Bompard |
e78d79 |
'docs_folder': '%s/repos/docs' % self.path,
|
|
Aurélien Bompard |
e78d79 |
'enable_tickets': True,
|
|
Aurélien Bompard |
e78d79 |
'tickets_folder': '%s/repos/tickets' % self.path,
|
|
Aurélien Bompard |
e78d79 |
'global_path': tests_state["path"],
|
|
Patrick Uiterwijk |
b2cb9c |
'authbackend': 'gitolite3',
|
|
Patrick Uiterwijk |
3f97f6 |
|
|
Patrick Uiterwijk |
8174a4 |
'repobridge_binary': '/usr/libexec/repobridge',
|
|
Patrick Uiterwijk |
7b18a6 |
'repospanner_gitport': str(8443 + sys.version_info.major),
|
|
Patrick Uiterwijk |
3f97f6 |
'repospanner_new_repo': 'None',
|
|
Patrick Uiterwijk |
3f97f6 |
'repospanner_admin_override': 'False',
|
|
Patrick Uiterwijk |
3f97f6 |
'repospanner_new_fork': 'True',
|
|
Patrick Uiterwijk |
3f97f6 |
'repospanner_admin_migration': 'False',
|
|
Aurélien Bompard |
e78d79 |
}
|
|
Aurélien Bompard |
e78d79 |
config_values.update(self.config_values)
|
|
Pierre-Yves Chibon |
8b2c5c |
config_path = os.path.join(self.path, 'config')
|
|
Pierre-Yves Chibon |
8b2c5c |
if not os.path.exists(config_path):
|
|
Pierre-Yves Chibon |
8b2c5c |
with open(config_path, 'w') as f:
|
|
Pierre-Yves Chibon |
8b2c5c |
f.write(CONFIG_TEMPLATE % config_values)
|
|
Aurélien Bompard |
e78d79 |
os.environ["PAGURE_CONFIG"] = config_path
|
|
Aurélien Bompard |
e78d79 |
pagure_config.update(reload_config())
|
|
Patrick Uiterwijk |
55e7e0 |
|
|
Aurélien Bompard |
626417 |
imp.reload(pagure.lib.tasks)
|
|
Pierre-Yves Chibon |
893d4f |
imp.reload(pagure.lib.tasks_mirror)
|
|
Aurélien Bompard |
626417 |
imp.reload(pagure.lib.tasks_services)
|
|
Pierre-Yves Chibon |
b130e5 |
|
|
Slavek Kabrda |
3675ce |
self._app = pagure.flask_app.create_app({'DB_URL': self.dbpath})
|
|
Pierre-Yves Chibon |
b130e5 |
# Remove the log handlers for the tests
|
|
Slavek Kabrda |
3675ce |
self._app.logger.handlers = []
|
|
Pierre-Yves Chibon |
b130e5 |
|
|
Slavek Kabrda |
3675ce |
self.app = self._app.test_client()
|
|
Aurélien Bompard |
00115d |
self.gr_patcher = mock.patch('pagure.lib.tasks.get_result')
|
|
Aurélien Bompard |
00115d |
gr_mock = self.gr_patcher.start()
|
|
Aurélien Bompard |
00115d |
gr_mock.side_effect = lambda tid: tests_state["results"][tid]
|
|
Pierre-Yves Chibon |
564e63 |
|
|
Clement Verna |
109c4b |
def tearDown(self):
|
|
Aurélien Bompard |
00115d |
self.gr_patcher.stop()
|
|
Aurélien Bompard |
e78d79 |
self.session.rollback()
|
|
Aurélien Bompard |
e78d79 |
self._clear_database()
|
|
Pierre-Yves Chibon |
7cbc4e |
|
|
Patrick Uiterwijk |
55e7e0 |
# Remove testdir
|
|
Pierre-Yves Chibon |
e49b79 |
try:
|
|
Pierre-Yves Chibon |
e49b79 |
shutil.rmtree(self.path)
|
|
Pierre-Yves Chibon |
e49b79 |
except:
|
|
Pierre-Yves Chibon |
e49b79 |
# Sometimes there is a race condition that makes deleting the folder
|
|
Pierre-Yves Chibon |
e49b79 |
# fail during the first attempt. So just try a second time if that's
|
|
Pierre-Yves Chibon |
e49b79 |
# the case.
|
|
Pierre-Yves Chibon |
e49b79 |
shutil.rmtree(self.path)
|
|
Patrick Uiterwijk |
55e7e0 |
self.path = None
|
|
Patrick Uiterwijk |
55e7e0 |
|
|
Slavek Kabrda |
3675ce |
del self.app
|
|
Slavek Kabrda |
3675ce |
del self._app
|
|
Slavek Kabrda |
3675ce |
|
|
Aurélien Bompard |
f61bb3 |
def shortDescription(self):
|
|
Aurélien Bompard |
00115d |
doc = self.__str__() + ": " + self._testMethodDoc
|
|
Aurélien Bompard |
00115d |
return doc or None
|
|
Aurélien Bompard |
f61bb3 |
|
|
Aurélien Bompard |
e78d79 |
def _prepare_db(self):
|
|
Aurélien Bompard |
e78d79 |
self.dbpath = 'sqlite:///%s' % os.path.join(
|
|
Aurélien Bompard |
e78d79 |
tests_state["path"], 'db.sqlite')
|
|
Aurélien Bompard |
e78d79 |
self.session = tests_state["db_session"]
|
|
Aurélien Bompard |
e78d79 |
pagure.lib.model.create_default_status(
|
|
Aurélien Bompard |
e78d79 |
self.session, acls=pagure_config.get('ACLS', {}))
|
|
Aurélien Bompard |
e78d79 |
if self.populate_db:
|
|
Aurélien Bompard |
e78d79 |
_populate_db(self.session)
|
|
Aurélien Bompard |
e78d79 |
|
|
Aurélien Bompard |
e78d79 |
def _clear_database(self):
|
|
Pierre-Yves Chibon |
930073 |
tables = reversed(pagure.lib.model_base.BASE.metadata.sorted_tables)
|
|
Aurélien Bompard |
e78d79 |
if self.dbpath.startswith('postgresql'):
|
|
Aurélien Bompard |
e78d79 |
self.session.execute("TRUNCATE %s CASCADE" % ", ".join(
|
|
Aurélien Bompard |
e78d79 |
[t.name for t in tables]))
|
|
Aurélien Bompard |
e78d79 |
elif self.dbpath.startswith('sqlite'):
|
|
Aurélien Bompard |
e78d79 |
for table in tables:
|
|
Aurélien Bompard |
e78d79 |
self.session.execute("DELETE FROM %s" % table.name)
|
|
Aurélien Bompard |
e78d79 |
elif self.dbpath.startswith('mysql'):
|
|
Aurélien Bompard |
e78d79 |
self.session.execute("SET FOREIGN_KEY_CHECKS = 0")
|
|
Aurélien Bompard |
e78d79 |
for table in tables:
|
|
Aurélien Bompard |
e78d79 |
self.session.execute("TRUNCATE %s" % table.name)
|
|
Aurélien Bompard |
e78d79 |
self.session.execute("SET FOREIGN_KEY_CHECKS = 1")
|
|
Aurélien Bompard |
e78d79 |
self.session.commit()
|
|
Aurélien Bompard |
e78d79 |
|
|
Patrick Uiterwijk |
b2cb9c |
def set_auth_status(self, value):
|
|
Patrick Uiterwijk |
b2cb9c |
""" Set the return value for the test auth """
|
|
Patrick Uiterwijk |
b2cb9c |
with open(os.path.join(self.path, 'testauth_status.json'), 'w') as statusfile:
|
|
Patrick Uiterwijk |
b2cb9c |
statusfile.write(six.u(json.dumps(value)))
|
|
Patrick Uiterwijk |
b2cb9c |
|
|
Pierre-Yves Chibon |
a754ea |
def get_csrf(self, url='/new', output=None):
|
|
Pierre-Yves Chibon |
d596a9 |
"""Retrieve a CSRF token from given URL."""
|
|
Pierre-Yves Chibon |
a754ea |
if output is None:
|
|
Pierre-Yves Chibon |
a754ea |
output = self.app.get(url)
|
|
Pierre-Yves Chibon |
a754ea |
self.assertEqual(output.status_code, 200)
|
|
Pierre-Yves Chibon |
d596a9 |
|
|
Aurélien Bompard |
626417 |
return output.get_data(as_text=True).split(
|
|
Pierre-Yves Chibon |
d596a9 |
'name="csrf_token" type="hidden" value="')[1].split('">')[0]
|
|
Pierre-Yves Chibon |
d596a9 |
|
|
Pierre-Yves Chibon |
3e9b1d |
def get_wtforms_version(self):
|
|
Pierre-Yves Chibon |
3e9b1d |
"""Returns the wtforms version as a tuple."""
|
|
Pierre-Yves Chibon |
3e9b1d |
import wtforms
|
|
Pierre-Yves Chibon |
3e9b1d |
wtforms_v = wtforms.__version__.split('.')
|
|
Pierre-Yves Chibon |
3e9b1d |
for idx, val in enumerate(wtforms_v):
|
|
Pierre-Yves Chibon |
3e9b1d |
try:
|
|
Pierre-Yves Chibon |
3e9b1d |
val = int(val)
|
|
Pierre-Yves Chibon |
3e9b1d |
except ValueError:
|
|
Pierre-Yves Chibon |
3e9b1d |
pass
|
|
Pierre-Yves Chibon |
3e9b1d |
wtforms_v[idx] = val
|
|
Pierre-Yves Chibon |
3e9b1d |
return tuple(wtforms_v)
|
|
Pierre-Yves Chibon |
3e9b1d |
|
|
Aurélien Bompard |
f61bb3 |
def assertURLEqual(self, url_1, url_2):
|
|
Aurélien Bompard |
f61bb3 |
url_parsed_1 = list(urlparse(url_1))
|
|
Aurélien Bompard |
f61bb3 |
url_parsed_1[4] = parse_qs(url_parsed_1[4])
|
|
Aurélien Bompard |
f61bb3 |
url_parsed_2 = list(urlparse(url_2))
|
|
Aurélien Bompard |
f61bb3 |
url_parsed_2[4] = parse_qs(url_parsed_2[4])
|
|
Aurélien Bompard |
f61bb3 |
return self.assertListEqual(url_parsed_1, url_parsed_2)
|
|
Aurélien Bompard |
f61bb3 |
|
|
Aurélien Bompard |
f61bb3 |
def assertJSONEqual(self, json_1, json_2):
|
|
Aurélien Bompard |
f61bb3 |
return self.assertEqual(json.loads(json_1), json.loads(json_2))
|
|
Aurélien Bompard |
f61bb3 |
|
|
Pierre-Yves Chibon |
b130e5 |
|
|
Clement Verna |
109c4b |
class Modeltests(SimplePagureTest):
|
|
Clement Verna |
109c4b |
""" Model tests. """
|
|
Clement Verna |
109c4b |
|
|
Clement Verna |
109c4b |
def setUp(self): # pylint: disable=invalid-name
|
|
Clement Verna |
109c4b |
""" Set up the environnment, ran before every tests. """
|
|
Clement Verna |
109c4b |
# Clean up test performance info
|
|
Clement Verna |
109c4b |
super(Modeltests, self).setUp()
|
|
Clement Verna |
109c4b |
self.app.get = create_maybe_waiter(self.app.get, self.app.get)
|
|
Clement Verna |
109c4b |
self.app.post = create_maybe_waiter(self.app.post, self.app.get)
|
|
Clement Verna |
109c4b |
|
|
Clement Verna |
109c4b |
def tearDown(self): # pylint: disable=invalid-name
|
|
Clement Verna |
109c4b |
""" Remove the test.db database if there is one. """
|
|
Aurélien Bompard |
00115d |
tests_state["broker_client"].flushall()
|
|
Aurélien Bompard |
e78d79 |
super(Modeltests, self).tearDown()
|
|
Clement Verna |
109c4b |
|
|
Patrick Uiterwijk |
390193 |
def create_project_full(self, projectname, extra=None):
|
|
Patrick Uiterwijk |
b2cb9c |
""" Create a project via the API.
|
|
Patrick Uiterwijk |
b2cb9c |
|
|
Patrick Uiterwijk |
b2cb9c |
This makes sure that the repo is fully setup the way a normal new
|
|
Patrick Uiterwijk |
b2cb9c |
project would be, with hooks and all setup.
|
|
Patrick Uiterwijk |
b2cb9c |
"""
|
|
Patrick Uiterwijk |
b2cb9c |
|
|
Patrick Uiterwijk |
b2cb9c |
headers = {'Authorization': 'token aaabbbcccddd'}
|
|
Patrick Uiterwijk |
b2cb9c |
data = {
|
|
Patrick Uiterwijk |
b2cb9c |
'name': projectname,
|
|
Patrick Uiterwijk |
b2cb9c |
'description': 'A test repo',
|
|
Patrick Uiterwijk |
b2cb9c |
}
|
|
Patrick Uiterwijk |
390193 |
if extra:
|
|
Patrick Uiterwijk |
390193 |
data.update(extra)
|
|
Patrick Uiterwijk |
b2cb9c |
|
|
Patrick Uiterwijk |
b2cb9c |
# Valid request
|
|
Patrick Uiterwijk |
b2cb9c |
output = self.app.post(
|
|
Patrick Uiterwijk |
b2cb9c |
'/api/0/new/', data=data, headers=headers)
|
|
Patrick Uiterwijk |
b2cb9c |
self.assertEqual(output.status_code, 200)
|
|
Patrick Uiterwijk |
b2cb9c |
data = json.loads(output.get_data(as_text=True))
|
|
Patrick Uiterwijk |
b2cb9c |
self.assertDictEqual(
|
|
Patrick Uiterwijk |
b2cb9c |
data,
|
|
Patrick Uiterwijk |
b2cb9c |
{'message': 'Project "%s" created' % projectname}
|
|
Patrick Uiterwijk |
b2cb9c |
)
|
|
Patrick Uiterwijk |
b2cb9c |
|
|
Pierre-Yves Chibon |
413073 |
|
|
Adam Williamson |
8dc0a9 |
class FakeGroup(object): # pylint: disable=too-few-public-methods
|
|
Pierre-Yves Chibon |
413073 |
""" Fake object used to make the FakeUser object closer to the
|
|
Pierre-Yves Chibon |
413073 |
expectations.
|
|
Pierre-Yves Chibon |
413073 |
"""
|
|
Pierre-Yves Chibon |
413073 |
|
|
Pierre-Yves Chibon |
413073 |
def __init__(self, name):
|
|
Pierre-Yves Chibon |
413073 |
""" Constructor.
|
|
Pierre-Yves Chibon |
413073 |
:arg name: the name given to the name attribute of this object.
|
|
Pierre-Yves Chibon |
413073 |
"""
|
|
Pierre-Yves Chibon |
413073 |
self.name = name
|
|
Pierre-Yves Chibon |
413073 |
self.group_type = 'cla'
|
|
Pierre-Yves Chibon |
413073 |
|
|
Pierre-Yves Chibon |
413073 |
|
|
Adam Williamson |
8dc0a9 |
class FakeUser(object): # pylint: disable=too-few-public-methods
|
|
Pierre-Yves Chibon |
413073 |
""" Fake user used to test the fedocallib library. """
|
|
Pierre-Yves Chibon |
413073 |
|
|
Pierre-Yves Chibon |
11ad7c |
def __init__(self, groups=None, username='username', cla_done=True, id=None):
|
|
Pierre-Yves Chibon |
413073 |
""" Constructor.
|
|
Pierre-Yves Chibon |
413073 |
:arg groups: list of the groups in which this fake user is
|
|
Pierre-Yves Chibon |
413073 |
supposed to be.
|
|
Pierre-Yves Chibon |
413073 |
"""
|
|
Aurélien Bompard |
626417 |
if isinstance(groups, six.string_types):
|
|
Pierre-Yves Chibon |
413073 |
groups = [groups]
|
|
Pierre-Yves Chibon |
ad2b94 |
self.id = id
|
|
Pierre-Yves Chibon |
a71ef5 |
self.groups = groups or []
|
|
Pierre-Yves Chibon |
ad2b94 |
self.user = username
|
|
Pierre-Yves Chibon |
413073 |
self.username = username
|
|
Pierre-Yves Chibon |
413073 |
self.name = username
|
|
Pierre-Yves Chibon |
c52718 |
self.email = 'foo@bar.com'
|
|
Ryan Lerch |
5682fd |
self.default_email = 'foo@bar.com'
|
|
Ryan Lerch |
5682fd |
|
|
Pierre-Yves Chibon |
413073 |
self.approved_memberships = [
|
|
Pierre-Yves Chibon |
413073 |
FakeGroup('packager'),
|
|
Pierre-Yves Chibon |
413073 |
FakeGroup('design-team')
|
|
Pierre-Yves Chibon |
413073 |
]
|
|
Pierre-Yves Chibon |
413073 |
self.dic = {}
|
|
Pierre-Yves Chibon |
413073 |
self.dic['timezone'] = 'Europe/Paris'
|
|
Pierre-Yves Chibon |
9fe7c1 |
self.login_time = datetime.utcnow()
|
|
Pierre-Yves Chibon |
413073 |
self.cla_done = cla_done
|
|
Pierre-Yves Chibon |
413073 |
|
|
Pierre-Yves Chibon |
413073 |
def __getitem__(self, key):
|
|
Pierre-Yves Chibon |
413073 |
return self.dic[key]
|
|
Pierre-Yves Chibon |
413073 |
|
|
Pierre-Yves Chibon |
413073 |
|
|
Patrick Uiterwijk |
3f97f6 |
def create_locks(session, project):
|
|
Patrick Uiterwijk |
3f97f6 |
for ltype in ('WORKER', 'WORKER_TICKET', 'WORKER_REQUEST'):
|
|
Patrick Uiterwijk |
3f97f6 |
lock = pagure.lib.model.ProjectLock(
|
|
Patrick Uiterwijk |
3f97f6 |
project_id=project.id,
|
|
Patrick Uiterwijk |
3f97f6 |
lock_type=ltype)
|
|
Patrick Uiterwijk |
3f97f6 |
session.add(lock)
|
|
Patrick Uiterwijk |
3f97f6 |
|
|
Patrick Uiterwijk |
3f97f6 |
|
|
Pierre-Yves Chibon |
11d019 |
def create_projects(session, is_fork=False, user_id=1, hook_token_suffix=''):
|
|
Pierre-Yves Chibon |
413073 |
""" Create some projects in the database. """
|
|
Pierre-Yves Chibon |
fe5017 |
item = pagure.lib.model.Project(
|
|
Pierre-Yves Chibon |
11d019 |
user_id=user_id, # pingou
|
|
Pierre-Yves Chibon |
413073 |
name='test',
|
|
Pierre-Yves Chibon |
11d019 |
is_fork=is_fork,
|
|
Pierre-Yves Chibon |
11d019 |
parent_id=1 if is_fork else None,
|
|
Pierre-Yves Chibon |
413073 |
description='test project #1',
|
|
Pierre-Yves Chibon |
11d019 |
hook_token='aaabbbccc' + hook_token_suffix,
|
|
Pierre-Yves Chibon |
413073 |
)
|
|
Pierre-Yves Chibon |
2aa887 |
item.close_status = ['Invalid', 'Insufficient data', 'Fixed', 'Duplicate']
|
|
Pierre-Yves Chibon |
413073 |
session.add(item)
|
|
Patrick Uiterwijk |
3f97f6 |
session.flush()
|
|
Patrick Uiterwijk |
3f97f6 |
create_locks(session, item)
|
|
Pierre-Yves Chibon |
413073 |
|
|
Pierre-Yves Chibon |
fe5017 |
item = pagure.lib.model.Project(
|
|
Pierre-Yves Chibon |
11d019 |
user_id=user_id, # pingou
|
|
Pierre-Yves Chibon |
413073 |
name='test2',
|
|
Pierre-Yves Chibon |
11d019 |
is_fork=is_fork,
|
|
Pierre-Yves Chibon |
11d019 |
parent_id=2 if is_fork else None,
|
|
Pierre-Yves Chibon |
413073 |
description='test project #2',
|
|
Pierre-Yves Chibon |
11d019 |
hook_token='aaabbbddd' + hook_token_suffix,
|
|
Pierre-Yves Chibon |
413073 |
)
|
|
Pierre-Yves Chibon |
2aa887 |
item.close_status = ['Invalid', 'Insufficient data', 'Fixed', 'Duplicate']
|
|
Pierre-Yves Chibon |
413073 |
session.add(item)
|
|
Pierre-Yves Chibon |
930073 |
session.flush()
|
|
Pierre-Yves Chibon |
930073 |
create_locks(session, item)
|
|
Pierre-Yves Chibon |
413073 |
|
|
clime |
afed57 |
item = pagure.lib.model.Project(
|
|
Pierre-Yves Chibon |
11d019 |
user_id=user_id, # pingou
|
|
clime |
afed57 |
name='test3',
|
|
Pierre-Yves Chibon |
11d019 |
is_fork=is_fork,
|
|
Pierre-Yves Chibon |
11d019 |
parent_id=3 if is_fork else None,
|
|
clime |
afed57 |
description='namespaced test project',
|
|
Pierre-Yves Chibon |
11d019 |
hook_token='aaabbbeee' + hook_token_suffix,
|
|
clime |
afed57 |
namespace='somenamespace',
|
|
clime |
afed57 |
)
|
|
clime |
afed57 |
item.close_status = ['Invalid', 'Insufficient data', 'Fixed', 'Duplicate']
|
|
clime |
afed57 |
session.add(item)
|
|
Pierre-Yves Chibon |
930073 |
session.flush()
|
|
Pierre-Yves Chibon |
930073 |
create_locks(session, item)
|
|
clime |
afed57 |
|
|
Pierre-Yves Chibon |
413073 |
session.commit()
|
|
Pierre-Yves Chibon |
413073 |
|
|
Pierre-Yves Chibon |
413073 |
|
|
Pierre-Yves Chibon |
05b648 |
def create_projects_git(folder, bare=False):
|
|
Pierre-Yves Chibon |
4e9b76 |
""" Create some projects in the database. """
|
|
Pierre-Yves Chibon |
4e9b76 |
repos = []
|
|
clime |
afed57 |
for project in ['test.git', 'test2.git',
|
|
clime |
afed57 |
os.path.join('somenamespace', 'test3.git')]:
|
|
Pierre-Yves Chibon |
4e9b76 |
repo_path = os.path.join(folder, project)
|
|
Pierre-Yves Chibon |
4e9b76 |
repos.append(repo_path)
|
|
Pierre-Yves Chibon |
63d161 |
if not os.path.exists(repo_path):
|
|
Pierre-Yves Chibon |
63d161 |
os.makedirs(repo_path)
|
|
Pierre-Yves Chibon |
05b648 |
pygit2.init_repository(repo_path, bare=bare)
|
|
Pierre-Yves Chibon |
4e9b76 |
|
|
Pierre-Yves Chibon |
4e9b76 |
return repos
|
|
Pierre-Yves Chibon |
4e9b76 |
|
|
Pierre-Yves Chibon |
4e9b76 |
|
|
Pierre-Yves Chibon |
a14636 |
def create_tokens(session, user_id=1, project_id=1):
|
|
Pierre-Yves Chibon |
c0b635 |
""" Create some tokens for the project in the database. """
|
|
Pierre-Yves Chibon |
c0b635 |
item = pagure.lib.model.Token(
|
|
Pierre-Yves Chibon |
c0b635 |
id='aaabbbcccddd',
|
|
Pierre-Yves Chibon |
c0b635 |
user_id=user_id,
|
|
Pierre-Yves Chibon |
a14636 |
project_id=project_id,
|
|
Pierre-Yves Chibon |
c0b635 |
expiration=datetime.utcnow() + timedelta(days=30)
|
|
Pierre-Yves Chibon |
c0b635 |
)
|
|
Pierre-Yves Chibon |
c0b635 |
session.add(item)
|
|
Pierre-Yves Chibon |
c0b635 |
|
|
Pierre-Yves Chibon |
c0b635 |
item = pagure.lib.model.Token(
|
|
Pierre-Yves Chibon |
c0b635 |
id='foo_token',
|
|
Pierre-Yves Chibon |
c0b635 |
user_id=user_id,
|
|
Pierre-Yves Chibon |
a14636 |
project_id=project_id,
|
|
Pierre-Yves Chibon |
c0b635 |
expiration=datetime.utcnow() + timedelta(days=30)
|
|
Pierre-Yves Chibon |
c0b635 |
)
|
|
Pierre-Yves Chibon |
c0b635 |
session.add(item)
|
|
Pierre-Yves Chibon |
c0b635 |
|
|
Pierre-Yves Chibon |
c0b635 |
item = pagure.lib.model.Token(
|
|
Pierre-Yves Chibon |
c0b635 |
id='expired_token',
|
|
Pierre-Yves Chibon |
c0b635 |
user_id=user_id,
|
|
Pierre-Yves Chibon |
a14636 |
project_id=project_id,
|
|
Pierre-Yves Chibon |
c0b635 |
expiration=datetime.utcnow() - timedelta(days=1)
|
|
Pierre-Yves Chibon |
c0b635 |
)
|
|
Pierre-Yves Chibon |
c0b635 |
session.add(item)
|
|
Pierre-Yves Chibon |
c0b635 |
|
|
Pierre-Yves Chibon |
c0b635 |
session.commit()
|
|
Pierre-Yves Chibon |
c0b635 |
|
|
Pierre-Yves Chibon |
c0b635 |
|
|
Matt Prahl |
30f8b1 |
def create_tokens_acl(session, token_id='aaabbbcccddd', acl_name=None):
|
|
Matt Prahl |
30f8b1 |
""" Create some ACLs for the token. If acl_name is not set, the token will
|
|
Matt Prahl |
30f8b1 |
have all the ACLs enabled.
|
|
Matt Prahl |
30f8b1 |
"""
|
|
Matt Prahl |
30f8b1 |
if acl_name is None:
|
|
Pierre-Yves Chibon |
b130e5 |
for aclid in range(len(pagure_config['ACLS'])):
|
|
Matt Prahl |
30f8b1 |
token_acl = pagure.lib.model.TokenAcl(
|
|
Matt Prahl |
30f8b1 |
token_id=token_id,
|
|
Matt Prahl |
30f8b1 |
acl_id=aclid + 1,
|
|
Matt Prahl |
30f8b1 |
)
|
|
Matt Prahl |
30f8b1 |
session.add(token_acl)
|
|
Matt Prahl |
30f8b1 |
else:
|
|
Matt Prahl |
30f8b1 |
acl = session.query(pagure.lib.model.ACL).filter_by(
|
|
Matt Prahl |
30f8b1 |
name=acl_name).one()
|
|
Matt Prahl |
30f8b1 |
token_acl = pagure.lib.model.TokenAcl(
|
|
Pierre-Yves Chibon |
631c33 |
token_id=token_id,
|
|
Matt Prahl |
30f8b1 |
acl_id=acl.id,
|
|
Pierre-Yves Chibon |
955beb |
)
|
|
Matt Prahl |
30f8b1 |
session.add(token_acl)
|
|
Pierre-Yves Chibon |
955beb |
|
|
Pierre-Yves Chibon |
955beb |
session.commit()
|
|
Pierre-Yves Chibon |
955beb |
|
|
Pierre-Yves Chibon |
955beb |
|
|
Pierre-Yves Chibon |
8a76fa |
def _clone_and_top_commits(folder, branch, branch_ref=False):
|
|
Pierre-Yves Chibon |
8a76fa |
""" Clone the repository, checkout the specified branch and return
|
|
Pierre-Yves Chibon |
8a76fa |
the top commit of that branch if there is one.
|
|
Pierre-Yves Chibon |
8a76fa |
Returns the repo, the path to the clone and the top commit(s) in a tuple
|
|
Pierre-Yves Chibon |
8a76fa |
or the repo, the path to the clone and the reference to the branch
|
|
Pierre-Yves Chibon |
8a76fa |
object if branch_ref is True.
|
|
Pierre-Yves Chibon |
8a76fa |
"""
|
|
Pierre-Yves Chibon |
f0ad75 |
if not os.path.exists(folder):
|
|
Pierre-Yves Chibon |
f0ad75 |
os.makedirs(folder)
|
|
Pierre-Yves Chibon |
128dfb |
brepo = pygit2.init_repository(folder, bare=True)
|
|
Pierre-Yves Chibon |
128dfb |
|
|
Pierre-Yves Chibon |
128dfb |
newfolder = tempfile.mkdtemp(prefix='pagure-tests')
|
|
Pierre-Yves Chibon |
128dfb |
repo = pygit2.clone_repository(folder, newfolder)
|
|
Pierre-Yves Chibon |
f0ad75 |
|
|
Pierre-Yves Chibon |
6fdafd |
branch_ref_obj = None
|
|
Pierre-Yves Chibon |
6fdafd |
if "origin/%s" % branch in repo.listall_branches(pygit2.GIT_BRANCH_ALL):
|
|
Pierre-Yves Chibon |
6fdafd |
branch_ref_obj = pagure.lib.git.get_branch_ref(repo, branch)
|
|
Pierre-Yves Chibon |
6fdafd |
repo.checkout(branch_ref_obj)
|
|
Pierre-Yves Chibon |
f0ad75 |
|
|
Pierre-Yves Chibon |
8a76fa |
if branch_ref:
|
|
Pierre-Yves Chibon |
8a76fa |
return (repo, newfolder, branch_ref_obj)
|
|
Pierre-Yves Chibon |
8a76fa |
|
|
Pierre-Yves Chibon |
a71c8d |
parents = []
|
|
Pierre-Yves Chibon |
a71c8d |
commit = None
|
|
Pierre-Yves Chibon |
a71c8d |
try:
|
|
Pierre-Yves Chibon |
6fdafd |
if branch_ref_obj:
|
|
Pierre-Yves Chibon |
6fdafd |
commit = repo[branch_ref_obj.get_object().hex]
|
|
Pierre-Yves Chibon |
6fdafd |
else:
|
|
Pierre-Yves Chibon |
6fdafd |
commit = repo.revparse_single('HEAD')
|
|
Pierre-Yves Chibon |
a71c8d |
except KeyError:
|
|
Pierre-Yves Chibon |
a71c8d |
pass
|
|
Pierre-Yves Chibon |
a71c8d |
if commit:
|
|
Pierre-Yves Chibon |
a71c8d |
parents = [commit.oid.hex]
|
|
Pierre-Yves Chibon |
a71c8d |
|
|
Pierre-Yves Chibon |
8a76fa |
return (repo, newfolder, parents)
|
|
Pierre-Yves Chibon |
8a76fa |
|
|
Pierre-Yves Chibon |
8a76fa |
|
|
Pierre-Yves Chibon |
8a76fa |
def add_content_git_repo(folder, branch='master', append=None):
|
|
Pierre-Yves Chibon |
8a76fa |
""" Create some content for the specified git repo. """
|
|
Pierre-Yves Chibon |
8a76fa |
repo, newfolder, parents = _clone_and_top_commits(folder, branch)
|
|
Pierre-Yves Chibon |
8a76fa |
|
|
Pierre-Yves Chibon |
6fdafd |
# Create a file in that git repo
|
|
Pierre-Yves Chibon |
6fdafd |
filename = os.path.join(newfolder, 'sources')
|
|
Pierre-Yves Chibon |
6fdafd |
content = 'foo\n bar'
|
|
Pierre-Yves Chibon |
6fdafd |
if os.path.exists(filename):
|
|
Pierre-Yves Chibon |
6fdafd |
content = 'foo\n bar\nbaz'
|
|
Pierre-Yves Chibon |
6fdafd |
if append:
|
|
Pierre-Yves Chibon |
6fdafd |
content += append
|
|
Pierre-Yves Chibon |
6fdafd |
with open(filename, 'w') as stream:
|
|
Pierre-Yves Chibon |
6fdafd |
stream.write(content)
|
|
Pierre-Yves Chibon |
6fdafd |
repo.index.add('sources')
|
|
Pierre-Yves Chibon |
6fdafd |
repo.index.write()
|
|
Pierre-Yves Chibon |
6fdafd |
|
|
Pierre-Yves Chibon |
f0ad75 |
# Commits the files added
|
|
Pierre-Yves Chibon |
f0ad75 |
tree = repo.index.write_tree()
|
|
Pierre-Yves Chibon |
f0ad75 |
author = pygit2.Signature(
|
|
Pierre-Yves Chibon |
f0ad75 |
'Alice Author', 'alice@authors.tld')
|
|
Pierre-Yves Chibon |
f0ad75 |
committer = pygit2.Signature(
|
|
Pierre-Yves Chibon |
f0ad75 |
'Cecil Committer', 'cecil@committers.tld')
|
|
Pierre-Yves Chibon |
6fdafd |
commit = repo.create_commit(
|
|
Pierre-Yves Chibon |
62e16b |
'refs/heads/%s' % branch, # the name of the reference to update
|
|
Pierre-Yves Chibon |
f0ad75 |
author,
|
|
Pierre-Yves Chibon |
f0ad75 |
committer,
|
|
Pierre-Yves Chibon |
f0ad75 |
'Add sources file for testing',
|
|
Pierre-Yves Chibon |
f0ad75 |
# binary string representing the tree object ID
|
|
Pierre-Yves Chibon |
f0ad75 |
tree,
|
|
Pierre-Yves Chibon |
f0ad75 |
# list of binary strings representing parents of the new commit
|
|
Pierre-Yves Chibon |
a71c8d |
parents,
|
|
Pierre-Yves Chibon |
f0ad75 |
)
|
|
Pierre-Yves Chibon |
a71c8d |
|
|
Pierre-Yves Chibon |
a71c8d |
if commit:
|
|
Pierre-Yves Chibon |
6fdafd |
parents = [commit.hex]
|
|
Pierre-Yves Chibon |
f0ad75 |
|
|
Pierre-Yves Chibon |
f0ad75 |
subfolder = os.path.join('folder1', 'folder2')
|
|
Pierre-Yves Chibon |
128dfb |
if not os.path.exists(os.path.join(newfolder, subfolder)):
|
|
Pierre-Yves Chibon |
128dfb |
os.makedirs(os.path.join(newfolder, subfolder))
|
|
Pierre-Yves Chibon |
f0ad75 |
# Create a file in that git repo
|
|
Pierre-Yves Chibon |
128dfb |
with open(os.path.join(newfolder, subfolder, 'file'), 'w') as stream:
|
|
Pierre-Yves Chibon |
f0ad75 |
stream.write('foo\n bar\nbaz')
|
|
Pierre-Yves Chibon |
f0ad75 |
repo.index.add(os.path.join(subfolder, 'file'))
|
|
Alex Gleason |
633b65 |
with open(os.path.join(newfolder, subfolder, 'fileŠ'), 'w') as stream:
|
|
Alex Gleason |
633b65 |
stream.write('foo\n bar\nbaz')
|
|
Alex Gleason |
633b65 |
repo.index.add(os.path.join(subfolder, 'fileŠ'))
|
|
Pierre-Yves Chibon |
f0ad75 |
repo.index.write()
|
|
Pierre-Yves Chibon |
f0ad75 |
|
|
Pierre-Yves Chibon |
f0ad75 |
# Commits the files added
|
|
Pierre-Yves Chibon |
f0ad75 |
tree = repo.index.write_tree()
|
|
Pierre-Yves Chibon |
f0ad75 |
author = pygit2.Signature(
|
|
Pierre-Yves Chibon |
f0ad75 |
'Alice Author', 'alice@authors.tld')
|
|
Pierre-Yves Chibon |
f0ad75 |
committer = pygit2.Signature(
|
|
Pierre-Yves Chibon |
f0ad75 |
'Cecil Committer', 'cecil@committers.tld')
|
|
Pierre-Yves Chibon |
6fdafd |
commit =repo.create_commit(
|
|
Pierre-Yves Chibon |
62e16b |
'refs/heads/%s' % branch, # the name of the reference to update
|
|
Pierre-Yves Chibon |
f0ad75 |
author,
|
|
Pierre-Yves Chibon |
f0ad75 |
committer,
|
|
Pierre-Yves Chibon |
f0ad75 |
'Add some directory and a file for more testing',
|
|
Pierre-Yves Chibon |
f0ad75 |
# binary string representing the tree object ID
|
|
Pierre-Yves Chibon |
f0ad75 |
tree,
|
|
Pierre-Yves Chibon |
f0ad75 |
# list of binary strings representing parents of the new commit
|
|
Pierre-Yves Chibon |
a71c8d |
parents
|
|
Pierre-Yves Chibon |
f0ad75 |
)
|
|
Pierre-Yves Chibon |
f0ad75 |
|
|
Pierre-Yves Chibon |
128dfb |
# Push to origin
|
|
Pierre-Yves Chibon |
128dfb |
ori_remote = repo.remotes[0]
|
|
Pierre-Yves Chibon |
62e16b |
master_ref = repo.lookup_reference(
|
|
Pierre-Yves Chibon |
62e16b |
'HEAD' if branch == 'master' else 'refs/heads/%s' % branch).resolve()
|
|
Pierre-Yves Chibon |
128dfb |
refname = '%s:%s' % (master_ref.name, master_ref.name)
|
|
Pierre-Yves Chibon |
128dfb |
|
|
Pierre-Yves Chibon |
27a73d |
PagureRepo.push(ori_remote, refname)
|
|
Pierre-Yves Chibon |
128dfb |
|
|
Pierre-Yves Chibon |
128dfb |
shutil.rmtree(newfolder)
|
|
Pierre-Yves Chibon |
128dfb |
|
|
Pierre-Yves Chibon |
f0ad75 |
|
|
Pierre-Yves Chibon |
6fdafd |
def add_readme_git_repo(folder, readme_name='README.rst', branch='master'):
|
|
Pierre-Yves Chibon |
87ffe2 |
""" Create a README file for the specified git repo. """
|
|
Pierre-Yves Chibon |
8a76fa |
repo, newfolder, parents = _clone_and_top_commits(folder, branch)
|
|
Pierre-Yves Chibon |
6fdafd |
|
|
Karsten Hopp |
5192eb |
if readme_name == 'README.rst':
|
|
Karsten Hopp |
5192eb |
content = """Pagure
|
|
Pierre-Yves Chibon |
87ffe2 |
======
|
|
Pierre-Yves Chibon |
87ffe2 |
|
|
Pierre-Yves Chibon |
87ffe2 |
:Author: Pierre-Yves Chibon <pingou@pingoured.fr></pingou@pingoured.fr>
|
|
Pierre-Yves Chibon |
87ffe2 |
|
|
Pierre-Yves Chibon |
87ffe2 |
|
|
Pierre-Yves Chibon |
fe5017 |
Pagure is a light-weight git-centered forge based on pygit2.
|
|
Pierre-Yves Chibon |
87ffe2 |
|
|
Pierre-Yves Chibon |
fe5017 |
Currently, Pagure offers a web-interface for git repositories, a ticket
|
|
Pierre-Yves Chibon |
fe5017 |
system and possibilities to create new projects, fork existing ones and
|
|
Pierre-Yves Chibon |
fe5017 |
create/merge pull-requests across or within projects.
|
|
Pierre-Yves Chibon |
87ffe2 |
|
|
Pierre-Yves Chibon |
87ffe2 |
|
|
Pierre-Yves Chibon |
fe5017 |
Homepage: https://github.com/pypingou/pagure
|
|
Pierre-Yves Chibon |
87ffe2 |
|
|
Pierre-Yves Chibon |
87ffe2 |
Dev instance: http://209.132.184.222/ (/!\\ May change unexpectedly, it's a dev instance ;-))
|
|
Pierre-Yves Chibon |
87ffe2 |
"""
|
|
Karsten Hopp |
5192eb |
else:
|
|
Karsten Hopp |
5192eb |
content = """Pagure
|
|
Karsten Hopp |
5192eb |
======
|
|
Karsten Hopp |
5192eb |
|
|
Karsten Hopp |
5192eb |
This is a placeholder """ + readme_name + """
|
|
Karsten Hopp |
5192eb |
that should never get displayed on the website if there is a README.rst in the repo.
|
|
Karsten Hopp |
5192eb |
"""
|
|
Pierre-Yves Chibon |
87ffe2 |
|
|
Pierre-Yves Chibon |
87ffe2 |
# Create a file in that git repo
|
|
Karsten Hopp |
5192eb |
with open(os.path.join(newfolder, readme_name), 'w') as stream:
|
|
Pierre-Yves Chibon |
87ffe2 |
stream.write(content)
|
|
Karsten Hopp |
5192eb |
repo.index.add(readme_name)
|
|
Pierre-Yves Chibon |
87ffe2 |
repo.index.write()
|
|
Pierre-Yves Chibon |
87ffe2 |
|
|
Pierre-Yves Chibon |
87ffe2 |
# Commits the files added
|
|
Pierre-Yves Chibon |
87ffe2 |
tree = repo.index.write_tree()
|
|
Pierre-Yves Chibon |
87ffe2 |
author = pygit2.Signature(
|
|
Pierre-Yves Chibon |
87ffe2 |
'Alice Author', 'alice@authors.tld')
|
|
Pierre-Yves Chibon |
87ffe2 |
committer = pygit2.Signature(
|
|
Pierre-Yves Chibon |
87ffe2 |
'Cecil Committer', 'cecil@committers.tld')
|
|
Pierre-Yves Chibon |
6fdafd |
branch_ref = "refs/heads/%s" % branch
|
|
Pierre-Yves Chibon |
87ffe2 |
repo.create_commit(
|
|
Pierre-Yves Chibon |
6fdafd |
branch_ref, # the name of the reference to update
|
|
Pierre-Yves Chibon |
87ffe2 |
author,
|
|
Pierre-Yves Chibon |
87ffe2 |
committer,
|
|
Pierre-Yves Chibon |
87ffe2 |
'Add a README file',
|
|
Pierre-Yves Chibon |
87ffe2 |
# binary string representing the tree object ID
|
|
Pierre-Yves Chibon |
87ffe2 |
tree,
|
|
Pierre-Yves Chibon |
87ffe2 |
# list of binary strings representing parents of the new commit
|
|
Pierre-Yves Chibon |
87ffe2 |
parents
|
|
Pierre-Yves Chibon |
87ffe2 |
)
|
|
Pierre-Yves Chibon |
87ffe2 |
|
|
Pierre-Yves Chibon |
128dfb |
# Push to origin
|
|
Pierre-Yves Chibon |
128dfb |
ori_remote = repo.remotes[0]
|
|
Pierre-Yves Chibon |
128dfb |
|
|
Pierre-Yves Chibon |
6fdafd |
PagureRepo.push(ori_remote, '%s:%s' % (branch_ref, branch_ref))
|
|
Pierre-Yves Chibon |
128dfb |
|
|
Pierre-Yves Chibon |
128dfb |
shutil.rmtree(newfolder)
|
|
Pierre-Yves Chibon |
128dfb |
|
|
Pierre-Yves Chibon |
87ffe2 |
|
|
Patrick Uiterwijk |
02a7cc |
def add_commit_git_repo(folder, ncommits=10, filename='sources',
|
|
Patrick Uiterwijk |
02a7cc |
branch='master'):
|
|
Pierre-Yves Chibon |
595b4e |
""" Create some more commits for the specified git repo. """
|
|
Pierre-Yves Chibon |
8a76fa |
repo, newfolder, branch_ref_obj = _clone_and_top_commits(
|
|
Pierre-Yves Chibon |
8a76fa |
folder, branch, branch_ref=True)
|
|
Pierre-Yves Chibon |
6fdafd |
|
|
Pierre-Yves Chibon |
595b4e |
for index in range(ncommits):
|
|
Pierre-Yves Chibon |
595b4e |
# Create a file in that git repo
|
|
Pierre-Yves Chibon |
a48463 |
with open(os.path.join(newfolder, filename), 'a') as stream:
|
|
Pierre-Yves Chibon |
595b4e |
stream.write('Row %s\n' % index)
|
|
Pierre-Yves Chibon |
a48463 |
repo.index.add(filename)
|
|
Pierre-Yves Chibon |
595b4e |
repo.index.write()
|
|
Pierre-Yves Chibon |
595b4e |
|
|
Pierre-Yves Chibon |
595b4e |
parents = []
|
|
Pierre-Yves Chibon |
595b4e |
commit = None
|
|
Pierre-Yves Chibon |
595b4e |
try:
|
|
Pierre-Yves Chibon |
6fdafd |
if branch_ref_obj:
|
|
Pierre-Yves Chibon |
6fdafd |
commit = repo[branch_ref_obj.get_object().hex]
|
|
Pierre-Yves Chibon |
6fdafd |
else:
|
|
Pierre-Yves Chibon |
6fdafd |
commit = repo.revparse_single('HEAD')
|
|
Pierre-Yves Chibon |
6fdafd |
except (KeyError, AttributeError):
|
|
Pierre-Yves Chibon |
595b4e |
pass
|
|
Pierre-Yves Chibon |
595b4e |
if commit:
|
|
Pierre-Yves Chibon |
595b4e |
parents = [commit.oid.hex]
|
|
Pierre-Yves Chibon |
595b4e |
|
|
Pierre-Yves Chibon |
595b4e |
# Commits the files added
|
|
Pierre-Yves Chibon |
595b4e |
tree = repo.index.write_tree()
|
|
Pierre-Yves Chibon |
595b4e |
author = pygit2.Signature(
|
|
Pierre-Yves Chibon |
595b4e |
'Alice Author', 'alice@authors.tld')
|
|
Pierre-Yves Chibon |
595b4e |
committer = pygit2.Signature(
|
|
Pierre-Yves Chibon |
595b4e |
'Cecil Committer', 'cecil@committers.tld')
|
|
Pierre-Yves Chibon |
6fdafd |
branch_ref = "refs/heads/%s" % branch
|
|
Pierre-Yves Chibon |
595b4e |
repo.create_commit(
|
|
Pierre-Yves Chibon |
6fdafd |
branch_ref,
|
|
Pierre-Yves Chibon |
595b4e |
author,
|
|
Pierre-Yves Chibon |
595b4e |
committer,
|
|
Pierre-Yves Chibon |
a48463 |
'Add row %s to %s file' % (index, filename),
|
|
Pierre-Yves Chibon |
595b4e |
# binary string representing the tree object ID
|
|
Pierre-Yves Chibon |
595b4e |
tree,
|
|
Pierre-Yves Chibon |
595b4e |
# list of binary strings representing parents of the new commit
|
|
Pierre-Yves Chibon |
595b4e |
parents,
|
|
Pierre-Yves Chibon |
595b4e |
)
|
|
Pierre-Yves Chibon |
6fdafd |
branch_ref_obj = pagure.lib.git.get_branch_ref(repo, branch)
|
|
Pierre-Yves Chibon |
595b4e |
|
|
Pierre-Yves Chibon |
128dfb |
# Push to origin
|
|
Pierre-Yves Chibon |
128dfb |
ori_remote = repo.remotes[0]
|
|
Pierre-Yves Chibon |
6fdafd |
PagureRepo.push(ori_remote, '%s:%s' % (branch_ref, branch_ref))
|
|
Pierre-Yves Chibon |
1cd41d |
|
|
Pierre-Yves Chibon |
1cd41d |
shutil.rmtree(newfolder)
|
|
Pierre-Yves Chibon |
1cd41d |
|
|
Pierre-Yves Chibon |
1cd41d |
|
|
Pierre-Yves Chibon |
ec5e38 |
def add_content_to_git(
|
|
Pierre-Yves Chibon |
722f04 |
folder, branch='master', filename='sources', content='foo',
|
|
Pierre-Yves Chibon |
722f04 |
message=None):
|
|
Pierre-Yves Chibon |
1cd41d |
""" Create some more commits for the specified git repo. """
|
|
Pierre-Yves Chibon |
ec5e38 |
repo, newfolder, branch_ref_obj = _clone_and_top_commits(
|
|
Pierre-Yves Chibon |
ec5e38 |
folder, branch, branch_ref=True)
|
|
Pierre-Yves Chibon |
1cd41d |
|
|
Pierre-Yves Chibon |
1cd41d |
# Create a file in that git repo
|
|
Aurélien Bompard |
619e2a |
with open(os.path.join(newfolder, filename), 'a', encoding="utf-8") as stream:
|
|
Pierre-Yves Chibon |
1cd41d |
stream.write('%s\n' % content)
|
|
Pierre-Yves Chibon |
1cd41d |
repo.index.add(filename)
|
|
Pierre-Yves Chibon |
1cd41d |
repo.index.write()
|
|
Pierre-Yves Chibon |
1cd41d |
|
|
Pierre-Yves Chibon |
ec5e38 |
parents = []
|
|
Pierre-Yves Chibon |
ec5e38 |
commit = None
|
|
Pierre-Yves Chibon |
ec5e38 |
try:
|
|
Pierre-Yves Chibon |
ec5e38 |
if branch_ref_obj:
|
|
Pierre-Yves Chibon |
ec5e38 |
commit = repo[branch_ref_obj.get_object().hex]
|
|
Pierre-Yves Chibon |
ec5e38 |
else:
|
|
Pierre-Yves Chibon |
ec5e38 |
commit = repo.revparse_single('HEAD')
|
|
Pierre-Yves Chibon |
ec5e38 |
except (KeyError, AttributeError):
|
|
Pierre-Yves Chibon |
ec5e38 |
pass
|
|
Pierre-Yves Chibon |
ec5e38 |
if commit:
|
|
Pierre-Yves Chibon |
ec5e38 |
parents = [commit.oid.hex]
|
|
Pierre-Yves Chibon |
ec5e38 |
|
|
Pierre-Yves Chibon |
1cd41d |
# Commits the files added
|
|
Pierre-Yves Chibon |
1cd41d |
tree = repo.index.write_tree()
|
|
Pierre-Yves Chibon |
1cd41d |
author = pygit2.Signature(
|
|
Pierre-Yves Chibon |
1cd41d |
'Alice Author', 'alice@authors.tld')
|
|
Pierre-Yves Chibon |
1cd41d |
committer = pygit2.Signature(
|
|
Pierre-Yves Chibon |
1cd41d |
'Cecil Committer', 'cecil@committers.tld')
|
|
Pierre-Yves Chibon |
ec5e38 |
branch_ref = "refs/heads/%s" % branch
|
|
Pierre-Yves Chibon |
722f04 |
message = message or 'Add content to file %s' % (filename)
|
|
Pierre-Yves Chibon |
1cd41d |
repo.create_commit(
|
|
Pierre-Yves Chibon |
ec5e38 |
branch_ref, # the name of the reference to update
|
|
Pierre-Yves Chibon |
1cd41d |
author,
|
|
Pierre-Yves Chibon |
1cd41d |
committer,
|
|
Pierre-Yves Chibon |
722f04 |
message,
|
|
Pierre-Yves Chibon |
1cd41d |
# binary string representing the tree object ID
|
|
Pierre-Yves Chibon |
1cd41d |
tree,
|
|
Pierre-Yves Chibon |
1cd41d |
# list of binary strings representing parents of the new commit
|
|
Pierre-Yves Chibon |
1cd41d |
parents,
|
|
Pierre-Yves Chibon |
1cd41d |
)
|
|
Pierre-Yves Chibon |
1cd41d |
|
|
Pierre-Yves Chibon |
1cd41d |
# Push to origin
|
|
Pierre-Yves Chibon |
1cd41d |
ori_remote = repo.remotes[0]
|
|
Pierre-Yves Chibon |
ec5e38 |
PagureRepo.push(ori_remote, '%s:%s' % (branch_ref, branch_ref))
|
|
Pierre-Yves Chibon |
128dfb |
|
|
Pierre-Yves Chibon |
128dfb |
shutil.rmtree(newfolder)
|
|
Pierre-Yves Chibon |
128dfb |
|
|
Pierre-Yves Chibon |
595b4e |
|
|
Pierre-Yves Chibon |
6e857b |
def add_binary_git_repo(folder, filename):
|
|
Pierre-Yves Chibon |
6e857b |
""" Create a fake image file for the specified git repo. """
|
|
Pierre-Yves Chibon |
8a76fa |
repo, newfolder, parents = _clone_and_top_commits(folder, 'master')
|
|
Pierre-Yves Chibon |
6e857b |
|
|
Pierre-Yves Chibon |
945241 |
content = b"""\x00\x00\x01\x00\x01\x00\x18\x18\x00\x00\x01\x00 \x00\x88
|
|
Pierre-Yves Chibon |
945241 |
\t\x00\x00\x16\x00\x00\x00(\x00\x00\x00\x18\x00x00\x00\x01\x00 \x00\x00\x00
|
|
Pierre-Yves Chibon |
945241 |
\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00
|
|
Pierre-Yves Chibon |
945241 |
00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xa7lM\x01\xa6kM\t\xa6kM\x01
|
|
Pierre-Yves Chibon |
945241 |
\xa4fF\x04\xa2dE\x95\xa2cD8\xa1a
|
|
Pierre-Yves Chibon |
6e857b |
"""
|
|
Pierre-Yves Chibon |
6e857b |
|
|
Pierre-Yves Chibon |
6e857b |
# Create a file in that git repo
|
|
Pierre-Yves Chibon |
945241 |
with open(os.path.join(newfolder, filename), 'wb') as stream:
|
|
Pierre-Yves Chibon |
6e857b |
stream.write(content)
|
|
Pierre-Yves Chibon |
6e857b |
repo.index.add(filename)
|
|
Pierre-Yves Chibon |
6e857b |
repo.index.write()
|
|
Pierre-Yves Chibon |
6e857b |
|
|
Pierre-Yves Chibon |
6e857b |
# Commits the files added
|
|
Pierre-Yves Chibon |
6e857b |
tree = repo.index.write_tree()
|
|
Pierre-Yves Chibon |
6e857b |
author = pygit2.Signature(
|
|
Pierre-Yves Chibon |
6e857b |
'Alice Author', 'alice@authors.tld')
|
|
Pierre-Yves Chibon |
6e857b |
committer = pygit2.Signature(
|
|
Pierre-Yves Chibon |
6e857b |
'Cecil Committer', 'cecil@committers.tld')
|
|
Pierre-Yves Chibon |
6e857b |
repo.create_commit(
|
|
Pierre-Yves Chibon |
6e857b |
'refs/heads/master', # the name of the reference to update
|
|
Pierre-Yves Chibon |
6e857b |
author,
|
|
Pierre-Yves Chibon |
6e857b |
committer,
|
|
Pierre-Yves Chibon |
6e857b |
'Add a fake image file',
|
|
Pierre-Yves Chibon |
6e857b |
# binary string representing the tree object ID
|
|
Pierre-Yves Chibon |
6e857b |
tree,
|
|
Pierre-Yves Chibon |
6e857b |
# list of binary strings representing parents of the new commit
|
|
Pierre-Yves Chibon |
6e857b |
parents
|
|
Pierre-Yves Chibon |
6e857b |
)
|
|
Pierre-Yves Chibon |
6e857b |
|
|
Pierre-Yves Chibon |
128dfb |
# Push to origin
|
|
Pierre-Yves Chibon |
128dfb |
ori_remote = repo.remotes[0]
|
|
Pierre-Yves Chibon |
128dfb |
master_ref = repo.lookup_reference('HEAD').resolve()
|
|
Pierre-Yves Chibon |
128dfb |
refname = '%s:%s' % (master_ref.name, master_ref.name)
|
|
Pierre-Yves Chibon |
128dfb |
|
|
Pierre-Yves Chibon |
27a73d |
PagureRepo.push(ori_remote, refname)
|
|
Pierre-Yves Chibon |
128dfb |
|
|
Pierre-Yves Chibon |
128dfb |
shutil.rmtree(newfolder)
|
|
Pierre-Yves Chibon |
128dfb |
|
|
Pierre-Yves Chibon |
652aff |
|
|
Pierre-Yves Chibon |
3470e1 |
def remove_file_git_repo(folder, filename, branch='master'):
|
|
Pierre-Yves Chibon |
3470e1 |
""" Delete the specified file on the give git repo and branch. """
|
|
Pierre-Yves Chibon |
8a76fa |
repo, newfolder, parents = _clone_and_top_commits(folder, branch)
|
|
Pierre-Yves Chibon |
3470e1 |
|
|
Pierre-Yves Chibon |
3470e1 |
# Remove file
|
|
Pierre-Yves Chibon |
3470e1 |
repo.index.remove(filename)
|
|
Pierre-Yves Chibon |
3470e1 |
|
|
Pierre-Yves Chibon |
3470e1 |
# Write the change and commit it
|
|
Pierre-Yves Chibon |
3470e1 |
tree = repo.index.write_tree()
|
|
Pierre-Yves Chibon |
3470e1 |
|
|
Pierre-Yves Chibon |
3470e1 |
author = pygit2.Signature(
|
|
Pierre-Yves Chibon |
3470e1 |
'Alice Author', 'alice@authors.tld')
|
|
Pierre-Yves Chibon |
3470e1 |
committer = pygit2.Signature(
|
|
Pierre-Yves Chibon |
3470e1 |
'Cecil Committer', 'cecil@committers.tld')
|
|
Pierre-Yves Chibon |
3470e1 |
branch_ref = "refs/heads/%s" % branch
|
|
Pierre-Yves Chibon |
3470e1 |
repo.create_commit(
|
|
Pierre-Yves Chibon |
3470e1 |
branch_ref, # the name of the reference to update
|
|
Pierre-Yves Chibon |
3470e1 |
author,
|
|
Pierre-Yves Chibon |
3470e1 |
committer,
|
|
Pierre-Yves Chibon |
3470e1 |
'Remove file %s' % filename,
|
|
Pierre-Yves Chibon |
3470e1 |
# binary string representing the tree object ID
|
|
Pierre-Yves Chibon |
3470e1 |
tree,
|
|
Pierre-Yves Chibon |
3470e1 |
# list of binary strings representing parents of the new commit
|
|
Pierre-Yves Chibon |
3470e1 |
parents
|
|
Pierre-Yves Chibon |
3470e1 |
)
|
|
Pierre-Yves Chibon |
3470e1 |
|
|
Pierre-Yves Chibon |
3470e1 |
# Push to origin
|
|
Pierre-Yves Chibon |
3470e1 |
ori_remote = repo.remotes[0]
|
|
Pierre-Yves Chibon |
3470e1 |
|
|
Pierre-Yves Chibon |
3470e1 |
PagureRepo.push(ori_remote, '%s:%s' % (branch_ref, branch_ref))
|
|
Pierre-Yves Chibon |
3470e1 |
|
|
Pierre-Yves Chibon |
3470e1 |
shutil.rmtree(newfolder)
|
|
Pierre-Yves Chibon |
3470e1 |
|
|
Pierre-Yves Chibon |
3470e1 |
|
|
Aurélien Bompard |
a29742 |
@contextmanager
|
|
Aurélien Bompard |
a29742 |
def capture_output(merge_stderr=True):
|
|
Aurélien Bompard |
a29742 |
oldout, olderr = sys.stdout, sys.stderr
|
|
Aurélien Bompard |
a29742 |
try:
|
|
Aurélien Bompard |
a29742 |
out = StringIO()
|
|
Aurélien Bompard |
a29742 |
err = StringIO()
|
|
Aurélien Bompard |
a29742 |
if merge_stderr:
|
|
Aurélien Bompard |
a29742 |
sys.stdout = sys.stderr = out
|
|
Aurélien Bompard |
a29742 |
yield out
|
|
Aurélien Bompard |
a29742 |
else:
|
|
Aurélien Bompard |
a29742 |
sys.stdout, sys.stderr = out, err
|
|
Aurélien Bompard |
a29742 |
yield out, err
|
|
Aurélien Bompard |
a29742 |
finally:
|
|
Aurélien Bompard |
a29742 |
sys.stdout, sys.stderr = oldout, olderr
|
|
Aurélien Bompard |
a29742 |
|
|
Aurélien Bompard |
a29742 |
|
|
Aurélien Bompard |
626417 |
def get_alerts(html):
|
|
Aurélien Bompard |
626417 |
soup = BeautifulSoup(html, "html.parser")
|
|
Aurélien Bompard |
626417 |
alerts = []
|
|
Aurélien Bompard |
626417 |
for element in soup.find_all("div", class_="alert"):
|
|
Aurélien Bompard |
626417 |
severity = None
|
|
Aurélien Bompard |
626417 |
for class_ in element["class"]:
|
|
Aurélien Bompard |
626417 |
if not class_.startswith("alert-"):
|
|
Aurélien Bompard |
626417 |
continue
|
|
Aurélien Bompard |
626417 |
if class_ == "alert-dismissible":
|
|
Aurélien Bompard |
626417 |
continue
|
|
Aurélien Bompard |
626417 |
severity = class_[len("alert-"):]
|
|
Aurélien Bompard |
626417 |
break
|
|
Aurélien Bompard |
626417 |
element.find("button").decompose() # close button
|
|
Aurélien Bompard |
626417 |
alerts.append(dict(
|
|
Aurélien Bompard |
626417 |
severity=severity,
|
|
Aurélien Bompard |
626417 |
text="".join(element.stripped_strings)
|
|
Aurélien Bompard |
626417 |
))
|
|
Aurélien Bompard |
626417 |
return alerts
|
|
Aurélien Bompard |
626417 |
|
|
Aurélien Bompard |
626417 |
|
|
Patrick Uiterwijk |
3f97f6 |
def definitely_wait(result):
|
|
Patrick Uiterwijk |
3f97f6 |
""" Helper function for definitely waiting in _maybe_wait. """
|
|
Patrick Uiterwijk |
3f97f6 |
result.wait()
|
|
Patrick Uiterwijk |
3f97f6 |
|
|
Patrick Uiterwijk |
3f97f6 |
|
|
Pierre-Yves Chibon |
413073 |
if __name__ == '__main__':
|
|
Pierre-Yves Chibon |
413073 |
SUITE = unittest.TestLoader().loadTestsFromTestCase(Modeltests)
|
|
Pierre-Yves Chibon |
413073 |
unittest.TextTestRunner(verbosity=2).run(SUITE)
|