Blame progit/lib.py

Pierre-Yves Chibon 1e2e25
#-*- coding: utf-8 -*-
Pierre-Yves Chibon 1e2e25
Pierre-Yves Chibon 1e2e25
"""
Pierre-Yves Chibon 1e2e25
 (c) 2014 - Copyright Red Hat Inc
Pierre-Yves Chibon 1e2e25
Pierre-Yves Chibon 1e2e25
 Authors:
Pierre-Yves Chibon 1e2e25
   Pierre-Yves Chibon <pingou@pingoured.fr></pingou@pingoured.fr>
Pierre-Yves Chibon 1e2e25
Pierre-Yves Chibon 1e2e25
"""
Pierre-Yves Chibon 1e2e25
Pierre-Yves Chibon 1e2e25
Pierre-Yves Chibon d8110b
import os
Pierre-Yves Chibon d8110b
Pierre-Yves Chibon 1e2e25
import sqlalchemy
Pierre-Yves Chibon 1e2e25
from datetime import timedelta
Pierre-Yves Chibon 1e2e25
from sqlalchemy.orm import sessionmaker
Pierre-Yves Chibon 1e2e25
from sqlalchemy.orm import scoped_session
Pierre-Yves Chibon 1e2e25
from sqlalchemy.orm.exc import NoResultFound
Pierre-Yves Chibon 1e2e25
from sqlalchemy.exc import SQLAlchemyError
Pierre-Yves Chibon 1e2e25
Pierre-Yves Chibon d8110b
import pygit2
Pierre-Yves Chibon d8110b
Pierre-Yves Chibon d8110b
import progit.exceptions
Pierre-Yves Chibon 1e2e25
from progit import model
Pierre-Yves Chibon 1e2e25
Pierre-Yves Chibon 1e2e25
Pierre-Yves Chibon 1e2e25
def create_session(db_url, debug=False, pool_recycle=3600):
Pierre-Yves Chibon 695ef6
    ''' Create the Session object to use to query the database.
Pierre-Yves Chibon 1e2e25
Pierre-Yves Chibon 1e2e25
    :arg db_url: URL used to connect to the database. The URL contains
Pierre-Yves Chibon 1e2e25
    information with regards to the database engine, the host to connect
Pierre-Yves Chibon 1e2e25
    to, the user and password and the database name.
Pierre-Yves Chibon 1e2e25
      ie: <engine>://<user>:<password>@<host>/<dbname></dbname></host></password></user></engine>
Pierre-Yves Chibon 1e2e25
    :kwarg debug: a boolean specifying wether we should have the verbose
Pierre-Yves Chibon 1e2e25
        output of sqlalchemy or not.
Pierre-Yves Chibon 1e2e25
    :return a Session that can be used to query the database.
Pierre-Yves Chibon 1e2e25
Pierre-Yves Chibon 695ef6
    '''
Pierre-Yves Chibon 1e2e25
    engine = sqlalchemy.create_engine(
Pierre-Yves Chibon 1e2e25
        db_url, echo=debug, pool_recycle=pool_recycle)
Pierre-Yves Chibon 1e2e25
    scopedsession = scoped_session(sessionmaker(bind=engine))
Pierre-Yves Chibon 1e2e25
    return scopedsession
Pierre-Yves Chibon 1e2e25
Pierre-Yves Chibon 1e2e25
Pierre-Yves Chibon 1e2e25
def get_user_project(session, username):
Pierre-Yves Chibon 1e2e25
    ''' Retrieve the list of projects managed by a user.
Pierre-Yves Chibon 1e2e25
Pierre-Yves Chibon 1e2e25
    '''
Pierre-Yves Chibon 1e2e25
Pierre-Yves Chibon 1e2e25
    query = session.query(
Pierre-Yves Chibon 1e2e25
        model.Project
Pierre-Yves Chibon 1e2e25
    ).filter(
Pierre-Yves Chibon 1e2e25
        model.Project.user == username
Pierre-Yves Chibon 1e2e25
    )
Pierre-Yves Chibon 1e2e25
Pierre-Yves Chibon 1e2e25
    return query.all()
Pierre-Yves Chibon d8110b
Pierre-Yves Chibon d8110b
Pierre-Yves Chibon d8110b
def new_project(session, user, name, folder,
Pierre-Yves Chibon d8110b
                description=None, parent_id=None):
Pierre-Yves Chibon d8110b
    ''' Create a new project based on the information provided.
Pierre-Yves Chibon d8110b
    '''
Pierre-Yves Chibon d8110b
    gitrepo = os.path.join(folder, '%s.git' % name)
Pierre-Yves Chibon d8110b
    if os.path.exists(gitrepo):
Pierre-Yves Chibon d8110b
        raise progit.exceptions.RepoExistsException(
Pierre-Yves Chibon d8110b
            'The project "%s" already exists' % name
Pierre-Yves Chibon d8110b
        )
Pierre-Yves Chibon d8110b
Pierre-Yves Chibon d8110b
    project = model.Project(
Pierre-Yves Chibon d8110b
        name=name,
Pierre-Yves Chibon d8110b
        description=description,
Pierre-Yves Chibon d8110b
        user=user,
Pierre-Yves Chibon d8110b
        parent_id=parent_id
Pierre-Yves Chibon d8110b
    )
Pierre-Yves Chibon d8110b
    session.add(project)
Pierre-Yves Chibon d8110b
    # Make sure we won't have SQLAlchemy error before we create the repo
Pierre-Yves Chibon d8110b
    session.flush()
Pierre-Yves Chibon d8110b
Pierre-Yves Chibon d8110b
    pygit2.init_repository(gitrepo, bare=True)
Pierre-Yves Chibon d8110b
Pierre-Yves Chibon d8110b
    return 'Project "%s" created' % name
Mathieu Bridon eb729c
Pierre-Yves Chibon f74093
Pierre-Yves Chibon 33ff2c
def new_issue(session, repo, title, content, user):
Pierre-Yves Chibon 33ff2c
    ''' Create a new issue for the specified repo. '''
Pierre-Yves Chibon 33ff2c
    issue = model.Issue(
Pierre-Yves Chibon 33ff2c
        project_id=repo.id,
Pierre-Yves Chibon 33ff2c
        title=title,
Pierre-Yves Chibon 33ff2c
        content=content,
Pierre-Yves Chibon 33ff2c
        user=user,
Pierre-Yves Chibon 33ff2c
    )
Pierre-Yves Chibon 33ff2c
    session.add(issue)
Pierre-Yves Chibon 33ff2c
    # Make sure we won't have SQLAlchemy error before we create the repo
Pierre-Yves Chibon 33ff2c
    session.flush()
Pierre-Yves Chibon 33ff2c
Pierre-Yves Chibon 33ff2c
    return 'Issue created'
Pierre-Yves Chibon 33ff2c
Pierre-Yves Chibon 33ff2c
Pierre-Yves Chibon c71370
def edit_issue(session, issue, title, content):
Pierre-Yves Chibon c71370
    ''' Edit the specified issue.
Pierre-Yves Chibon c71370
    '''
Pierre-Yves Chibon c71370
    edit = []
Pierre-Yves Chibon c71370
    if title != issue.title:
Pierre-Yves Chibon c71370
        issue.title = title
Pierre-Yves Chibon c71370
        edit.append('title')
Pierre-Yves Chibon c71370
    if content != issue.content:
Pierre-Yves Chibon c71370
        issue.content = content
Pierre-Yves Chibon c71370
        edit.append('content')
Pierre-Yves Chibon c71370
Pierre-Yves Chibon c71370
    if not edit:
Pierre-Yves Chibon c71370
        return 'No changes to edit'
Pierre-Yves Chibon c71370
    else:
Pierre-Yves Chibon c71370
        session.add(issue)
Pierre-Yves Chibon c71370
        session.flush()
Pierre-Yves Chibon c71370
        return 'Edited successfully issue #%s' % issue.id
Pierre-Yves Chibon c71370
Pierre-Yves Chibon c71370
Pierre-Yves Chibon 652c2c
def fork_project(session, user, repo, repo_folder, fork_folder):
Pierre-Yves Chibon 652c2c
    ''' Fork a given project into the user's forks. '''
Pierre-Yves Chibon 652c2c
    reponame = os.path.join(repo_folder, repo.path)
Pierre-Yves Chibon 652c2c
    forkreponame = os.path.join(fork_folder, user, repo.path)
Pierre-Yves Chibon 652c2c
Pierre-Yves Chibon 652c2c
    if os.path.exists(forkreponame):
Pierre-Yves Chibon 652c2c
        raise progit.exceptions.RepoExistsException(
Pierre-Yves Chibon 652c2c
            'Repo "%s/%s" already exists' % (user, repo.name))
Pierre-Yves Chibon 652c2c
Pierre-Yves Chibon 652c2c
    project = model.Project(
Pierre-Yves Chibon 652c2c
        name=repo.name,
Pierre-Yves Chibon 652c2c
        description=repo.description,
Pierre-Yves Chibon 652c2c
        user=user,
Pierre-Yves Chibon 652c2c
        parent_id=repo.id
Pierre-Yves Chibon 652c2c
    )
Pierre-Yves Chibon 652c2c
    session.add(project)
Pierre-Yves Chibon 652c2c
    # Make sure we won't have SQLAlchemy error before we create the repo
Pierre-Yves Chibon 652c2c
    session.flush()
Pierre-Yves Chibon 652c2c
Pierre-Yves Chibon d01de7
    pygit2.clone_repository(reponame, forkreponame, bare=True)
Pierre-Yves Chibon 652c2c
Pierre-Yves Chibon 652c2c
    return 'Repo "%s" cloned to "%s/%s"' % (repo.name, user, repo.name)
Pierre-Yves Chibon 652c2c
Pierre-Yves Chibon 652c2c
Pierre-Yves Chibon ea0ee1
def list_projects(
Pierre-Yves Chibon 7752a8
        session, username=None, fork=None,
Pierre-Yves Chibon ea0ee1
        start=None, limit=None, count=False):
Pierre-Yves Chibon 695ef6
    '''List existing projects
Pierre-Yves Chibon 695ef6
    '''
Mathieu Bridon eb729c
    projects = session.query(model.Project)
Mathieu Bridon eb729c
Pierre-Yves Chibon ea0ee1
    if username is not None:
Pierre-Yves Chibon ea0ee1
        projects = projects.filter_by(
Pierre-Yves Chibon ea0ee1
            user=username
Pierre-Yves Chibon ea0ee1
        )
Pierre-Yves Chibon ea0ee1
Pierre-Yves Chibon 7752a8
    if fork is not None:
Pierre-Yves Chibon 7752a8
        if fork is True:
Pierre-Yves Chibon 7752a8
            projects = projects.filter(
Pierre-Yves Chibon 7752a8
                model.Project.parent_id != None
Pierre-Yves Chibon 7752a8
            )
Pierre-Yves Chibon 7752a8
        elif fork is False:
Pierre-Yves Chibon 2f8732
            projects = projects.filter(
Pierre-Yves Chibon 2f8732
                model.Project.parent_id == None
Pierre-Yves Chibon 7752a8
            )
Pierre-Yves Chibon 7752a8
Mathieu Bridon eb729c
    if start is not None:
Mathieu Bridon eb729c
        projects = projects.offset(start)
Mathieu Bridon eb729c
Mathieu Bridon eb729c
    if limit is not None:
Mathieu Bridon eb729c
        projects = projects.limit(limit)
Mathieu Bridon eb729c
Pierre-Yves Chibon f74093
    if count:
Pierre-Yves Chibon f74093
        return projects.count()
Pierre-Yves Chibon f74093
    else:
Pierre-Yves Chibon f74093
        return projects.all()
Mathieu Bridon eb729c
Mathieu Bridon 998605
Pierre-Yves Chibon 929595
def get_project(session, name, user=None):
Pierre-Yves Chibon 695ef6
    '''Get a project from the database
Pierre-Yves Chibon 695ef6
    '''
Pierre-Yves Chibon 929595
    query = session.query(
Pierre-Yves Chibon f74093
        model.Project
Pierre-Yves Chibon 178d6f
    ).filter(
Pierre-Yves Chibon 178d6f
        model.Project.name == name
Pierre-Yves Chibon 929595
    )
Pierre-Yves Chibon 1ac00b
Pierre-Yves Chibon 929595
    if user is not None:
Pierre-Yves Chibon 929595
        query = query.filter(
Pierre-Yves Chibon 929595
            model.Project.user == user
Pierre-Yves Chibon 1ac00b
        ).filter(
Pierre-Yves Chibon 1ac00b
            model.Project.parent_id != None
Pierre-Yves Chibon 929595
        )
Pierre-Yves Chibon 1ac00b
    else:
Pierre-Yves Chibon 1ac00b
        query = query.filter(
Pierre-Yves Chibon 1ac00b
            model.Project.parent_id == None
Pierre-Yves Chibon 1ac00b
        )
Pierre-Yves Chibon 1ac00b
Pierre-Yves Chibon 929595
    return query.first()
Pierre-Yves Chibon 562d75
Pierre-Yves Chibon 562d75
Pierre-Yves Chibon 562d75
def get_issues(session, repo):
Pierre-Yves Chibon 562d75
    ''' Retrieve all the issues associated to a project
Pierre-Yves Chibon 562d75
    '''
Pierre-Yves Chibon 562d75
    query = session.query(
Pierre-Yves Chibon 562d75
        model.Issue
Pierre-Yves Chibon 562d75
    ).filter(
Pierre-Yves Chibon 562d75
        model.Issue.project_id == repo.id
Pierre-Yves Chibon 562d75
    )
Pierre-Yves Chibon 562d75
Pierre-Yves Chibon 562d75
    return query.all()
Pierre-Yves Chibon 562d75
Pierre-Yves Chibon 562d75
Pierre-Yves Chibon feb7c1
def get_issue(session, issueid):
Pierre-Yves Chibon 562d75
    ''' Retrieve the specified issue
Pierre-Yves Chibon 562d75
    '''
Pierre-Yves Chibon 562d75
    query = session.query(
Pierre-Yves Chibon 562d75
        model.Issue
Pierre-Yves Chibon 562d75
    ).filter(
Pierre-Yves Chibon 562d75
        model.Issue.id == issueid
Pierre-Yves Chibon 562d75
    )
Pierre-Yves Chibon 562d75
Pierre-Yves Chibon 562d75
    return query.first()