|
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 |
9af5a0 |
import datetime
|
|
Pierre-Yves Chibon |
f7d963 |
import json
|
|
Pierre-Yves Chibon |
d8110b |
import os
|
|
Pierre-Yves Chibon |
e2a95c |
import random
|
|
Pierre-Yves Chibon |
d133cd |
import shutil
|
|
Pierre-Yves Chibon |
e2a95c |
import string
|
|
Pierre-Yves Chibon |
d133cd |
import tempfile
|
|
Pierre-Yves Chibon |
9cb884 |
import uuid
|
|
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 |
4b55b4 |
import progit.notify
|
|
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 |
e2a95c |
def id_generator(size=15, chars=string.ascii_uppercase + string.digits):
|
|
Pierre-Yves Chibon |
e2a95c |
""" Generates a random identifier for the given size and using the
|
|
Pierre-Yves Chibon |
e2a95c |
specified characters.
|
|
Pierre-Yves Chibon |
e2a95c |
If no size is specified, it uses 15 as default.
|
|
Pierre-Yves Chibon |
e2a95c |
If no characters are specified, it uses ascii char upper case and
|
|
Pierre-Yves Chibon |
e2a95c |
digits.
|
|
Pierre-Yves Chibon |
e2a95c |
:arg size: the size of the identifier to return.
|
|
Pierre-Yves Chibon |
e2a95c |
:arg chars: the list of characters that can be used in the
|
|
Pierre-Yves Chibon |
e2a95c |
idenfitier.
|
|
Pierre-Yves Chibon |
e2a95c |
"""
|
|
Pierre-Yves Chibon |
e2a95c |
return ''.join(random.choice(chars) for x in range(size))
|
|
Pierre-Yves Chibon |
e2a95c |
|
|
Pierre-Yves Chibon |
e2a95c |
|
|
Pierre-Yves Chibon |
f0256a |
def commit_to_patch(repo_obj, commits):
|
|
Pierre-Yves Chibon |
9af5a0 |
''' For a given commit (PyGit2 commit object) of a specified git repo,
|
|
Pierre-Yves Chibon |
9af5a0 |
returns a string representation of the changes the commit did in a
|
|
Pierre-Yves Chibon |
9af5a0 |
format that allows it to be used as patch.
|
|
Pierre-Yves Chibon |
9af5a0 |
'''
|
|
Pierre-Yves Chibon |
f0256a |
if not isinstance(commits, list):
|
|
Pierre-Yves Chibon |
f0256a |
commits = [commits]
|
|
Pierre-Yves Chibon |
9af5a0 |
|
|
Pierre-Yves Chibon |
f0256a |
patch = ""
|
|
Pierre-Yves Chibon |
f0256a |
for cnt, commit in enumerate(commits):
|
|
Pierre-Yves Chibon |
f0256a |
if commit.parents:
|
|
Pierre-Yves Chibon |
f0256a |
diff = commit.tree.diff_to_tree()
|
|
Pierre-Yves Chibon |
9af5a0 |
|
|
Pierre-Yves Chibon |
f0256a |
parent = repo_obj.revparse_single('%s^' % commit.oid.hex)
|
|
Pierre-Yves Chibon |
f0256a |
diff = repo_obj.diff(parent, commit)
|
|
Pierre-Yves Chibon |
f0256a |
else:
|
|
Pierre-Yves Chibon |
f0256a |
# First commit in the repo
|
|
Pierre-Yves Chibon |
f0256a |
diff = commit.tree.diff_to_tree(swap=True)
|
|
Pierre-Yves Chibon |
f0256a |
|
|
Pierre-Yves Chibon |
b93113 |
subject = message = ''
|
|
Pierre-Yves Chibon |
b93113 |
if '\n' in commit.message:
|
|
Pierre-Yves Chibon |
b93113 |
subject, message = commit.message.split('\n', 1)
|
|
Pierre-Yves Chibon |
b93113 |
else:
|
|
Pierre-Yves Chibon |
b93113 |
subject = commit.message
|
|
Pierre-Yves Chibon |
f0256a |
|
|
Pierre-Yves Chibon |
f0256a |
if len(commits) > 1:
|
|
Pierre-Yves Chibon |
f0256a |
subject = '[PATCH %s/%s] %s' % (cnt + 1, len(commits), subject)
|
|
Pierre-Yves Chibon |
f0256a |
|
|
Pierre-Yves Chibon |
f0256a |
patch += """From %(commit)s Mon Sep 17 00:00:00 2001
|
|
Pierre-Yves Chibon |
9af5a0 |
From: %(author_name)s <%(author_email)s>
|
|
Pierre-Yves Chibon |
9af5a0 |
Date: %(date)s
|
|
Pierre-Yves Chibon |
f0256a |
Subject: %(subject)s
|
|
Pierre-Yves Chibon |
9af5a0 |
|
|
Pierre-Yves Chibon |
9af5a0 |
%(msg)s
|
|
Pierre-Yves Chibon |
f0256a |
---
|
|
Pierre-Yves Chibon |
9af5a0 |
|
|
Pierre-Yves Chibon |
9af5a0 |
%(patch)s
|
|
Pierre-Yves Chibon |
9af5a0 |
""" % (
|
|
Pierre-Yves Chibon |
f0256a |
{
|
|
Pierre-Yves Chibon |
f0256a |
'commit': commit.oid.hex,
|
|
Pierre-Yves Chibon |
f0256a |
'author_name': commit.author.name,
|
|
Pierre-Yves Chibon |
f0256a |
'author_email': commit.author.email,
|
|
Pierre-Yves Chibon |
f0256a |
'date': datetime.datetime.utcfromtimestamp(
|
|
Pierre-Yves Chibon |
f0256a |
commit.commit_time).strftime('%b %d %Y %H:%M:%S +0000'),
|
|
Pierre-Yves Chibon |
f0256a |
'subject': subject,
|
|
Pierre-Yves Chibon |
f0256a |
'msg': message,
|
|
Pierre-Yves Chibon |
f0256a |
'patch': diff.patch,
|
|
Pierre-Yves Chibon |
f0256a |
}
|
|
Pierre-Yves Chibon |
f0256a |
)
|
|
Pierre-Yves Chibon |
9af5a0 |
return patch
|
|
Pierre-Yves Chibon |
9af5a0 |
|
|
Pierre-Yves Chibon |
9af5a0 |
|
|
Pierre-Yves Chibon |
03c11f |
def get_user(session, username):
|
|
Pierre-Yves Chibon |
03c11f |
''' Return the user corresponding to this username, or None. '''
|
|
Pierre-Yves Chibon |
03c11f |
user = session.query(
|
|
Pierre-Yves Chibon |
e1372f |
model.User
|
|
Pierre-Yves Chibon |
e1372f |
).filter(
|
|
Pierre-Yves Chibon |
03c11f |
model.User.user == username
|
|
Pierre-Yves Chibon |
e1372f |
).first()
|
|
Pierre-Yves Chibon |
03c11f |
return user
|
|
Pierre-Yves Chibon |
03c11f |
|
|
Pierre-Yves Chibon |
03c11f |
|
|
Pierre-Yves Chibon |
b81780 |
def get_user_by_email(session, user_mail):
|
|
Pierre-Yves Chibon |
b81780 |
''' Return the user corresponding to this email, or None. '''
|
|
Pierre-Yves Chibon |
b81780 |
mail = session.query(
|
|
Pierre-Yves Chibon |
b81780 |
model.UserEmail
|
|
Pierre-Yves Chibon |
b81780 |
).filter(
|
|
Pierre-Yves Chibon |
b81780 |
model.UserEmail.email == user_mail
|
|
Pierre-Yves Chibon |
b81780 |
).first()
|
|
Pierre-Yves Chibon |
b81780 |
if mail:
|
|
Pierre-Yves Chibon |
b81780 |
return mail.user
|
|
Pierre-Yves Chibon |
b81780 |
|
|
Pierre-Yves Chibon |
b81780 |
|
|
Pierre-Yves Chibon |
34cbca |
def get_user_by_token(session, token):
|
|
Pierre-Yves Chibon |
34cbca |
''' Return a specified User via its token.
|
|
Pierre-Yves Chibon |
34cbca |
|
|
Pierre-Yves Chibon |
34cbca |
:arg session: the session with which to connect to the database.
|
|
Pierre-Yves Chibon |
34cbca |
|
|
Pierre-Yves Chibon |
34cbca |
'''
|
|
Pierre-Yves Chibon |
34cbca |
user = session.query(
|
|
Pierre-Yves Chibon |
34cbca |
model.User
|
|
Pierre-Yves Chibon |
34cbca |
).filter(
|
|
Pierre-Yves Chibon |
34cbca |
model.User.token == token
|
|
Pierre-Yves Chibon |
34cbca |
).first()
|
|
Pierre-Yves Chibon |
34cbca |
return user
|
|
Pierre-Yves Chibon |
34cbca |
|
|
Pierre-Yves Chibon |
34cbca |
|
|
Pierre-Yves Chibon |
556d85 |
def get_all_users(session):
|
|
Pierre-Yves Chibon |
556d85 |
''' Return the user corresponding to this username, or None. '''
|
|
Pierre-Yves Chibon |
556d85 |
users = session.query(
|
|
Pierre-Yves Chibon |
556d85 |
model.User
|
|
Pierre-Yves Chibon |
613fab |
).order_by(
|
|
Pierre-Yves Chibon |
613fab |
model.User.user
|
|
Pierre-Yves Chibon |
556d85 |
).all()
|
|
Pierre-Yves Chibon |
556d85 |
return users
|
|
Pierre-Yves Chibon |
556d85 |
|
|
Pierre-Yves Chibon |
556d85 |
|
|
Pierre-Yves Chibon |
a34835 |
def add_issue_comment(session, issue, comment, user, ticketfolder):
|
|
Pierre-Yves Chibon |
03c11f |
''' Add a comment to an issue. '''
|
|
Pierre-Yves Chibon |
3ddae1 |
user_obj = get_user(session, user)
|
|
Pierre-Yves Chibon |
496a35 |
if not user_obj:
|
|
Pierre-Yves Chibon |
496a35 |
user_obj = get_user_by_email(session, user)
|
|
Pierre-Yves Chibon |
e1372f |
|
|
Pierre-Yves Chibon |
e1372f |
if not user_obj:
|
|
Pierre-Yves Chibon |
e1372f |
raise progit.exceptions.ProgitException(
|
|
Pierre-Yves Chibon |
e1372f |
'No user "%s" found' % user
|
|
Pierre-Yves Chibon |
e1372f |
)
|
|
Pierre-Yves Chibon |
e1372f |
|
|
Pierre-Yves Chibon |
00c3f0 |
issue_comment = model.IssueComment(
|
|
Pierre-Yves Chibon |
359db9 |
issue_id=issue.id,
|
|
Pierre-Yves Chibon |
359db9 |
comment=comment,
|
|
Pierre-Yves Chibon |
e1372f |
user_id=user_obj.id,
|
|
Pierre-Yves Chibon |
359db9 |
)
|
|
Pierre-Yves Chibon |
00c3f0 |
session.add(issue_comment)
|
|
Pierre-Yves Chibon |
359db9 |
# Make sure we won't have SQLAlchemy error before we create the repo
|
|
Pierre-Yves Chibon |
359db9 |
session.flush()
|
|
Pierre-Yves Chibon |
359db9 |
|
|
Pierre-Yves Chibon |
a34835 |
update_git_ticket(issue, repo=issue.project, ticketfolder=ticketfolder)
|
|
Pierre-Yves Chibon |
a34835 |
|
|
Pierre-Yves Chibon |
caaa01 |
globalid = get_issue_global_id(session, issue.project.id, issue.id)
|
|
Pierre-Yves Chibon |
caaa01 |
|
|
Pierre-Yves Chibon |
caaa01 |
progit.notify.notify_new_comment(issue_comment, globalid)
|
|
Pierre-Yves Chibon |
4b55b4 |
|
|
Pierre-Yves Chibon |
359db9 |
return 'Comment added'
|
|
Pierre-Yves Chibon |
359db9 |
|
|
Pierre-Yves Chibon |
359db9 |
|
|
Pierre-Yves Chibon |
aafc66 |
def add_issue_tag(session, issue, tag, user, ticketfolder):
|
|
Pierre-Yves Chibon |
aafc66 |
''' Add a tag to an issue. '''
|
|
Pierre-Yves Chibon |
aafc66 |
user_obj = get_user(session, user)
|
|
Pierre-Yves Chibon |
aafc66 |
if not user_obj:
|
|
Pierre-Yves Chibon |
aafc66 |
user_obj = get_user_by_email(session, user)
|
|
Pierre-Yves Chibon |
aafc66 |
|
|
Pierre-Yves Chibon |
aafc66 |
if not user_obj:
|
|
Pierre-Yves Chibon |
aafc66 |
raise progit.exceptions.ProgitException(
|
|
Pierre-Yves Chibon |
aafc66 |
'No user "%s" found' % user
|
|
Pierre-Yves Chibon |
aafc66 |
)
|
|
Pierre-Yves Chibon |
aafc66 |
|
|
Pierre-Yves Chibon |
a77b8c |
tagobj = get_tag(session, tag)
|
|
Pierre-Yves Chibon |
a77b8c |
if not tagobj:
|
|
Pierre-Yves Chibon |
a77b8c |
tagobj = model.Tag(tag=tag)
|
|
Pierre-Yves Chibon |
a77b8c |
session.add(tagobj)
|
|
Pierre-Yves Chibon |
a77b8c |
|
|
Pierre-Yves Chibon |
3df2cd |
issue_tag = model.TagIssue(
|
|
Pierre-Yves Chibon |
aafc66 |
issue_id=issue.id,
|
|
Pierre-Yves Chibon |
a77b8c |
tag=tagobj.tag,
|
|
Pierre-Yves Chibon |
aafc66 |
)
|
|
Pierre-Yves Chibon |
aafc66 |
session.add(issue_tag)
|
|
Pierre-Yves Chibon |
aafc66 |
# Make sure we won't have SQLAlchemy error before we create the repo
|
|
Pierre-Yves Chibon |
aafc66 |
session.flush()
|
|
Pierre-Yves Chibon |
aafc66 |
|
|
Pierre-Yves Chibon |
aafc66 |
update_git_ticket(issue, repo=issue.project, ticketfolder=ticketfolder)
|
|
Pierre-Yves Chibon |
aafc66 |
|
|
Pierre-Yves Chibon |
aafc66 |
return 'Tag added'
|
|
Pierre-Yves Chibon |
aafc66 |
|
|
Pierre-Yves Chibon |
aafc66 |
|
|
Pierre-Yves Chibon |
83cba8 |
def remove_issue_tags(session, project, tags):
|
|
Pierre-Yves Chibon |
83cba8 |
''' Removes the specified tag of a project. '''
|
|
Pierre-Yves Chibon |
83cba8 |
|
|
Pierre-Yves Chibon |
83cba8 |
if not isinstance(tags, list):
|
|
Pierre-Yves Chibon |
83cba8 |
tags = [tags]
|
|
Pierre-Yves Chibon |
83cba8 |
|
|
Pierre-Yves Chibon |
83cba8 |
issues = get_issues(session, project, closed=False, tags=tags)
|
|
Pierre-Yves Chibon |
83cba8 |
issues.extend(get_issues(session, project, closed=True, tags=tags))
|
|
Pierre-Yves Chibon |
83cba8 |
|
|
Pierre-Yves Chibon |
83cba8 |
msgs = []
|
|
Pierre-Yves Chibon |
83cba8 |
if not issues:
|
|
Pierre-Yves Chibon |
83cba8 |
raise progit.exceptions.ProgitException(
|
|
Pierre-Yves Chibon |
83cba8 |
'No issue found with the tag: %s' % tag)
|
|
Pierre-Yves Chibon |
83cba8 |
else:
|
|
Pierre-Yves Chibon |
83cba8 |
for issue in issues:
|
|
Pierre-Yves Chibon |
83cba8 |
for issue_tag in issue[0].tags:
|
|
Pierre-Yves Chibon |
83cba8 |
if issue_tag.tag in tags:
|
|
Pierre-Yves Chibon |
83cba8 |
tag = issue_tag.tag
|
|
Pierre-Yves Chibon |
83cba8 |
session.delete(issue_tag)
|
|
Pierre-Yves Chibon |
83cba8 |
msgs.append('Removed tag: %s' % tag)
|
|
Pierre-Yves Chibon |
83cba8 |
return msgs
|
|
Pierre-Yves Chibon |
83cba8 |
|
|
Pierre-Yves Chibon |
83cba8 |
|
|
Pierre-Yves Chibon |
9d0844 |
def edit_issue_tags(session, project, old_tag, new_tag):
|
|
Pierre-Yves Chibon |
9d0844 |
''' Removes the specified tag of a project. '''
|
|
Pierre-Yves Chibon |
9d0844 |
|
|
Pierre-Yves Chibon |
9d0844 |
if not isinstance(old_tag, list):
|
|
Pierre-Yves Chibon |
9d0844 |
old_tags = [old_tag]
|
|
Pierre-Yves Chibon |
9d0844 |
|
|
Pierre-Yves Chibon |
9d0844 |
issues = get_issues(session, project, closed=False, tags=old_tags)
|
|
Pierre-Yves Chibon |
9d0844 |
issues.extend(get_issues(session, project, closed=True, tags=old_tags))
|
|
Pierre-Yves Chibon |
9d0844 |
|
|
Pierre-Yves Chibon |
9d0844 |
msgs = []
|
|
Pierre-Yves Chibon |
9d0844 |
if not issues:
|
|
Pierre-Yves Chibon |
9d0844 |
raise progit.exceptions.ProgitException(
|
|
Pierre-Yves Chibon |
9d0844 |
'No issue found with the tags: %s' % old_tag)
|
|
Pierre-Yves Chibon |
9d0844 |
else:
|
|
Pierre-Yves Chibon |
9d0844 |
tagobj = get_tag(session, new_tag)
|
|
Pierre-Yves Chibon |
9d0844 |
if not tagobj:
|
|
Pierre-Yves Chibon |
9d0844 |
tagobj = model.Tag(tag=new_tag)
|
|
Pierre-Yves Chibon |
9d0844 |
session.add(tagobj)
|
|
Pierre-Yves Chibon |
9d0844 |
|
|
Pierre-Yves Chibon |
9d0844 |
for issue in issues:
|
|
Pierre-Yves Chibon |
9d0844 |
# Drop the old tag
|
|
Pierre-Yves Chibon |
9d0844 |
for issue_tag in issue[0].tags:
|
|
Pierre-Yves Chibon |
9d0844 |
if issue_tag.tag in old_tags:
|
|
Pierre-Yves Chibon |
9d0844 |
tag = issue_tag.tag
|
|
Pierre-Yves Chibon |
9d0844 |
session.delete(issue_tag)
|
|
Pierre-Yves Chibon |
9d0844 |
# Add the new one
|
|
Pierre-Yves Chibon |
9d0844 |
issue_tag = model.TagIssue(
|
|
Pierre-Yves Chibon |
9d0844 |
issue_id=issue[0].id,
|
|
Pierre-Yves Chibon |
9d0844 |
tag=new_tag
|
|
Pierre-Yves Chibon |
9d0844 |
)
|
|
Pierre-Yves Chibon |
9d0844 |
session.add(issue_tag)
|
|
Pierre-Yves Chibon |
9d0844 |
msgs.append('Edited tag: %s to %s' % (old_tag, new_tag))
|
|
Pierre-Yves Chibon |
9d0844 |
|
|
Pierre-Yves Chibon |
9d0844 |
return msgs
|
|
Pierre-Yves Chibon |
9d0844 |
|
|
Pierre-Yves Chibon |
b9cb1e |
def add_user_to_project(session, project, user):
|
|
Pierre-Yves Chibon |
b9cb1e |
''' Add a specified user to a specified project. '''
|
|
Pierre-Yves Chibon |
b9cb1e |
user_obj = get_user(session, user)
|
|
Pierre-Yves Chibon |
b9cb1e |
if not user_obj:
|
|
Pierre-Yves Chibon |
b9cb1e |
user_obj = get_user_by_email(session, user)
|
|
Pierre-Yves Chibon |
b9cb1e |
|
|
Pierre-Yves Chibon |
b9cb1e |
if not user_obj:
|
|
Pierre-Yves Chibon |
b9cb1e |
raise progit.exceptions.ProgitException(
|
|
Pierre-Yves Chibon |
b9cb1e |
'No user "%s" found' % user
|
|
Pierre-Yves Chibon |
b9cb1e |
)
|
|
Pierre-Yves Chibon |
b9cb1e |
|
|
Pierre-Yves Chibon |
b9cb1e |
project_user = model.ProjectUser(
|
|
Pierre-Yves Chibon |
b9cb1e |
project_id=project.id,
|
|
Pierre-Yves Chibon |
b9cb1e |
user_id=user_obj.id,
|
|
Pierre-Yves Chibon |
b9cb1e |
)
|
|
Pierre-Yves Chibon |
b9cb1e |
session.add(project_user)
|
|
Pierre-Yves Chibon |
b9cb1e |
# Make sure we won't have SQLAlchemy error before we create the repo
|
|
Pierre-Yves Chibon |
b9cb1e |
session.flush()
|
|
Pierre-Yves Chibon |
b9cb1e |
|
|
Pierre-Yves Chibon |
b9cb1e |
return 'Comment added'
|
|
Pierre-Yves Chibon |
b9cb1e |
|
|
Pierre-Yves Chibon |
a8a719 |
|
|
Pierre-Yves Chibon |
2c11b4 |
def add_pull_request_comment(session, request, commit, row, comment, user):
|
|
Pierre-Yves Chibon |
2c11b4 |
''' Add a comment to a pull-request. '''
|
|
Pierre-Yves Chibon |
2c11b4 |
user_obj = get_user(session, user)
|
|
Pierre-Yves Chibon |
2c11b4 |
if not user_obj:
|
|
Pierre-Yves Chibon |
2c11b4 |
user_obj = get_user_by_email(session, user)
|
|
Pierre-Yves Chibon |
2c11b4 |
|
|
Pierre-Yves Chibon |
2c11b4 |
if not user_obj:
|
|
Pierre-Yves Chibon |
2c11b4 |
raise progit.exceptions.ProgitException(
|
|
Pierre-Yves Chibon |
2c11b4 |
'No user "%s" found' % user
|
|
Pierre-Yves Chibon |
2c11b4 |
)
|
|
Pierre-Yves Chibon |
2c11b4 |
|
|
Pierre-Yves Chibon |
2c11b4 |
pr_comment = model.PullRequestComment(
|
|
Pierre-Yves Chibon |
2c11b4 |
pull_request_id=request.id,
|
|
Pierre-Yves Chibon |
2c11b4 |
commit_id=commit,
|
|
Pierre-Yves Chibon |
2c11b4 |
line=row,
|
|
Pierre-Yves Chibon |
2c11b4 |
comment=comment,
|
|
Pierre-Yves Chibon |
2c11b4 |
user_id=user_obj.id,
|
|
Pierre-Yves Chibon |
2c11b4 |
)
|
|
Pierre-Yves Chibon |
2c11b4 |
session.add(pr_comment)
|
|
Pierre-Yves Chibon |
2c11b4 |
# Make sure we won't have SQLAlchemy error before we create the repo
|
|
Pierre-Yves Chibon |
2c11b4 |
session.flush()
|
|
Pierre-Yves Chibon |
2c11b4 |
|
|
Pierre-Yves Chibon |
2c11b4 |
return 'Comment added'
|
|
Pierre-Yves Chibon |
2c11b4 |
|
|
Pierre-Yves Chibon |
2c11b4 |
|
|
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 |
49b899 |
def new_project(session, user, name, gitfolder, docfolder, ticketfolder,
|
|
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 |
6160b6 |
gitrepo = os.path.join(gitfolder, '%s.git' % name)
|
|
Pierre-Yves Chibon |
d8110b |
if os.path.exists(gitrepo):
|
|
Pierre-Yves Chibon |
d8110b |
raise progit.exceptions.RepoExistsException(
|
|
Pierre-Yves Chibon |
ca47fa |
'The project repo "%s" already exists' % name
|
|
Pierre-Yves Chibon |
d8110b |
)
|
|
Pierre-Yves Chibon |
d8110b |
|
|
Pierre-Yves Chibon |
3ddae1 |
user_obj = get_user(session, user)
|
|
Pierre-Yves Chibon |
e1372f |
|
|
Pierre-Yves Chibon |
e1372f |
if not user_obj:
|
|
Pierre-Yves Chibon |
e1372f |
raise progit.exceptions.ProgitException(
|
|
Pierre-Yves Chibon |
e1372f |
'No user "%s" found' % user
|
|
Pierre-Yves Chibon |
e1372f |
)
|
|
Pierre-Yves Chibon |
e1372f |
|
|
Pierre-Yves Chibon |
d8110b |
project = model.Project(
|
|
Pierre-Yves Chibon |
d8110b |
name=name,
|
|
Pierre-Yves Chibon |
d8110b |
description=description,
|
|
Pierre-Yves Chibon |
e1372f |
user_id=user_obj.id,
|
|
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 |
6160b6 |
gitrepo = os.path.join(docfolder, project.path)
|
|
Pierre-Yves Chibon |
6160b6 |
if os.path.exists(gitrepo):
|
|
Pierre-Yves Chibon |
6160b6 |
raise progit.exceptions.RepoExistsException(
|
|
Pierre-Yves Chibon |
ca47fa |
'The docs repo "%s" already exists' % project.path
|
|
Pierre-Yves Chibon |
6160b6 |
)
|
|
Pierre-Yves Chibon |
6160b6 |
pygit2.init_repository(gitrepo, bare=True)
|
|
Pierre-Yves Chibon |
6160b6 |
|
|
Pierre-Yves Chibon |
49b899 |
gitrepo = os.path.join(ticketfolder, project.path)
|
|
Pierre-Yves Chibon |
49b899 |
if os.path.exists(gitrepo):
|
|
Pierre-Yves Chibon |
49b899 |
raise progit.exceptions.RepoExistsException(
|
|
Pierre-Yves Chibon |
49b899 |
'The tickets repo "%s" already exists' % project.path
|
|
Pierre-Yves Chibon |
49b899 |
)
|
|
Pierre-Yves Chibon |
49b899 |
pygit2.init_repository(gitrepo, bare=True)
|
|
Pierre-Yves Chibon |
49b899 |
|
|
Pierre-Yves Chibon |
d8110b |
return 'Project "%s" created' % name
|
|
Mathieu Bridon |
eb729c |
|
|
Pierre-Yves Chibon |
f74093 |
|
|
Pierre-Yves Chibon |
a34835 |
def new_issue(session, repo, title, content, user, ticketfolder):
|
|
Pierre-Yves Chibon |
33ff2c |
''' Create a new issue for the specified repo. '''
|
|
Pierre-Yves Chibon |
3ddae1 |
user_obj = get_user(session, user)
|
|
Pierre-Yves Chibon |
e1372f |
|
|
Pierre-Yves Chibon |
e1372f |
if not user_obj:
|
|
Pierre-Yves Chibon |
e1372f |
raise progit.exceptions.ProgitException(
|
|
Pierre-Yves Chibon |
e1372f |
'No user "%s" found' % user
|
|
Pierre-Yves Chibon |
e1372f |
)
|
|
Pierre-Yves Chibon |
e1372f |
|
|
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 |
e1372f |
user_id=user_obj.id,
|
|
Pierre-Yves Chibon |
9cb884 |
uid=uuid.uuid4().hex,
|
|
Pierre-Yves Chibon |
33ff2c |
)
|
|
Pierre-Yves Chibon |
33ff2c |
session.add(issue)
|
|
Pierre-Yves Chibon |
057ee1 |
# Make sure we won't have SQLAlchemy error before we create the issue
|
|
Pierre-Yves Chibon |
33ff2c |
session.flush()
|
|
Pierre-Yves Chibon |
33ff2c |
|
|
Pierre-Yves Chibon |
e1690f |
global_id = model.GlobalId(
|
|
Pierre-Yves Chibon |
e1690f |
project_id=repo.id,
|
|
Pierre-Yves Chibon |
e1690f |
issue_id=issue.id,
|
|
Pierre-Yves Chibon |
e1690f |
)
|
|
Pierre-Yves Chibon |
e1690f |
|
|
Pierre-Yves Chibon |
e1690f |
session.add(global_id)
|
|
Pierre-Yves Chibon |
e1690f |
session.flush()
|
|
Pierre-Yves Chibon |
e1690f |
|
|
Pierre-Yves Chibon |
a34835 |
update_git_ticket(issue, repo=repo, ticketfolder=ticketfolder)
|
|
Pierre-Yves Chibon |
a34835 |
|
|
Pierre-Yves Chibon |
fe205b |
globalid = get_issue_global_id(session, issue.project.id, issue.id)
|
|
Pierre-Yves Chibon |
fe205b |
|
|
Pierre-Yves Chibon |
fe205b |
progit.notify.notify_new_issue(issue, globalid)
|
|
Pierre-Yves Chibon |
142bae |
|
|
Pierre-Yves Chibon |
33ff2c |
return 'Issue created'
|
|
Pierre-Yves Chibon |
33ff2c |
|
|
Pierre-Yves Chibon |
33ff2c |
|
|
Pierre-Yves Chibon |
62ec72 |
def new_pull_request(
|
|
Pierre-Yves Chibon |
8e8a9f |
session, repo, repo_from, branch, title, user, stop_id,
|
|
Pierre-Yves Chibon |
8e8a9f |
start_id=None):
|
|
Pierre-Yves Chibon |
472a61 |
''' Create a new pull request on the specified repo. '''
|
|
Pierre-Yves Chibon |
3ddae1 |
user_obj = get_user(session, user)
|
|
Pierre-Yves Chibon |
7d23c0 |
|
|
Pierre-Yves Chibon |
7d23c0 |
if not user_obj:
|
|
Pierre-Yves Chibon |
7d23c0 |
raise progit.exceptions.ProgitException(
|
|
Pierre-Yves Chibon |
7d23c0 |
'No user "%s" found' % user
|
|
Pierre-Yves Chibon |
7d23c0 |
)
|
|
Pierre-Yves Chibon |
7d23c0 |
|
|
Pierre-Yves Chibon |
472a61 |
request = model.PullRequest(
|
|
Pierre-Yves Chibon |
472a61 |
project_id=repo.id,
|
|
Pierre-Yves Chibon |
62ec72 |
project_id_from=repo_from.id,
|
|
Pierre-Yves Chibon |
8e8a9f |
branch=branch,
|
|
Pierre-Yves Chibon |
472a61 |
title=title,
|
|
Pierre-Yves Chibon |
472a61 |
start_id=start_id,
|
|
Pierre-Yves Chibon |
472a61 |
stop_id=stop_id,
|
|
Pierre-Yves Chibon |
7d23c0 |
user_id=user_obj.id,
|
|
Pierre-Yves Chibon |
472a61 |
)
|
|
Pierre-Yves Chibon |
472a61 |
session.add(request)
|
|
Pierre-Yves Chibon |
472a61 |
# Make sure we won't have SQLAlchemy error before we create the request
|
|
Pierre-Yves Chibon |
472a61 |
session.flush()
|
|
Pierre-Yves Chibon |
472a61 |
|
|
Pierre-Yves Chibon |
3a3f5e |
global_id = model.GlobalId(
|
|
Pierre-Yves Chibon |
3a3f5e |
project_id=repo.id,
|
|
Pierre-Yves Chibon |
3a3f5e |
request_id=request.id,
|
|
Pierre-Yves Chibon |
3a3f5e |
)
|
|
Pierre-Yves Chibon |
3a3f5e |
|
|
Pierre-Yves Chibon |
3a3f5e |
session.add(global_id)
|
|
Pierre-Yves Chibon |
3a3f5e |
session.flush()
|
|
Pierre-Yves Chibon |
3a3f5e |
|
|
Pierre-Yves Chibon |
dabdba |
globalid = get_pull_request_global_id(
|
|
Pierre-Yves Chibon |
dabdba |
session, request.project.id, request.id)
|
|
Pierre-Yves Chibon |
dabdba |
|
|
Pierre-Yves Chibon |
dabdba |
progit.notify.notify_new_pull_request(request, globalid)
|
|
Pierre-Yves Chibon |
e0589f |
|
|
Pierre-Yves Chibon |
472a61 |
return 'Request created'
|
|
Pierre-Yves Chibon |
472a61 |
|
|
Pierre-Yves Chibon |
472a61 |
|
|
Pierre-Yves Chibon |
a34835 |
def edit_issue(session, issue, ticketfolder,
|
|
Pierre-Yves Chibon |
a34835 |
title=None, content=None, status=None):
|
|
Pierre-Yves Chibon |
c71370 |
''' Edit the specified issue.
|
|
Pierre-Yves Chibon |
c71370 |
'''
|
|
Pierre-Yves Chibon |
c71370 |
edit = []
|
|
Pierre-Yves Chibon |
fb8b6c |
if title and title != issue.title:
|
|
Pierre-Yves Chibon |
c71370 |
issue.title = title
|
|
Pierre-Yves Chibon |
c71370 |
edit.append('title')
|
|
Pierre-Yves Chibon |
fb8b6c |
if content and content != issue.content:
|
|
Pierre-Yves Chibon |
c71370 |
issue.content = content
|
|
Pierre-Yves Chibon |
c71370 |
edit.append('content')
|
|
Pierre-Yves Chibon |
fb8b6c |
if status and status != issue.status:
|
|
Pierre-Yves Chibon |
4d1cbe |
issue.status = status
|
|
Pierre-Yves Chibon |
4d1cbe |
edit.append('status')
|
|
Pierre-Yves Chibon |
c71370 |
|
|
Pierre-Yves Chibon |
65c8d7 |
update_git_ticket(issue, repo=issue.project, ticketfolder=ticketfolder)
|
|
Pierre-Yves Chibon |
a34835 |
|
|
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 |
b39aa4 |
def update_project_settings(session, repo, issue_tracker, project_docs):
|
|
Pierre-Yves Chibon |
b39aa4 |
''' Update the settings of a project. '''
|
|
Pierre-Yves Chibon |
b39aa4 |
update = []
|
|
Pierre-Yves Chibon |
b39aa4 |
if issue_tracker != repo.issue_tracker:
|
|
Pierre-Yves Chibon |
b39aa4 |
repo.issue_tracker = issue_tracker
|
|
Pierre-Yves Chibon |
b39aa4 |
update.append('issue_tracker')
|
|
Pierre-Yves Chibon |
b39aa4 |
if project_docs != repo.project_docs:
|
|
Pierre-Yves Chibon |
b39aa4 |
repo.project_docs = project_docs
|
|
Pierre-Yves Chibon |
b39aa4 |
update.append('project_docs')
|
|
Pierre-Yves Chibon |
b39aa4 |
|
|
Pierre-Yves Chibon |
b39aa4 |
if not update:
|
|
Pierre-Yves Chibon |
b39aa4 |
return 'No settings to change'
|
|
Pierre-Yves Chibon |
b39aa4 |
else:
|
|
Pierre-Yves Chibon |
b39aa4 |
session.add(repo)
|
|
Pierre-Yves Chibon |
b39aa4 |
session.flush()
|
|
Pierre-Yves Chibon |
b39aa4 |
return 'Edited successfully setting of repo: %s' % repo.fullname
|
|
Pierre-Yves Chibon |
b39aa4 |
|
|
Pierre-Yves Chibon |
b39aa4 |
|
|
Pierre-Yves Chibon |
a33978 |
def fork_project(session, user, repo, gitfolder,
|
|
Pierre-Yves Chibon |
a33978 |
forkfolder, docfolder,ticketfolder):
|
|
Pierre-Yves Chibon |
652c2c |
''' Fork a given project into the user's forks. '''
|
|
Pierre-Yves Chibon |
df2470 |
if repo.is_fork:
|
|
Pierre-Yves Chibon |
df2470 |
reponame = os.path.join(forkfolder, repo.path)
|
|
Pierre-Yves Chibon |
df2470 |
else:
|
|
Pierre-Yves Chibon |
df2470 |
reponame = os.path.join(gitfolder, repo.path)
|
|
Pierre-Yves Chibon |
df2470 |
forkreponame = '%s.git' % os.path.join(forkfolder, user, repo.name)
|
|
Pierre-Yves Chibon |
652c2c |
|
|
Pierre-Yves Chibon |
9e91eb |
if repo.user.user == user:
|
|
Pierre-Yves Chibon |
9e91eb |
raise progit.exceptions.RepoExistsException(
|
|
Pierre-Yves Chibon |
9e91eb |
'You may not fork your own repo')
|
|
Pierre-Yves Chibon |
9e91eb |
|
|
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 |
3ddae1 |
user_obj = get_user(session, user)
|
|
Pierre-Yves Chibon |
e1372f |
|
|
Pierre-Yves Chibon |
e1372f |
if not user_obj:
|
|
Pierre-Yves Chibon |
e1372f |
raise progit.exceptions.ProgitException(
|
|
Pierre-Yves Chibon |
e1372f |
'No user "%s" found' % user
|
|
Pierre-Yves Chibon |
e1372f |
)
|
|
Pierre-Yves Chibon |
e1372f |
|
|
Pierre-Yves Chibon |
652c2c |
project = model.Project(
|
|
Pierre-Yves Chibon |
652c2c |
name=repo.name,
|
|
Pierre-Yves Chibon |
652c2c |
description=repo.description,
|
|
Pierre-Yves Chibon |
e1372f |
user_id=user_obj.id,
|
|
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 |
6160b6 |
gitrepo = os.path.join(docfolder, project.path)
|
|
Pierre-Yves Chibon |
6160b6 |
if os.path.exists(gitrepo):
|
|
Pierre-Yves Chibon |
6160b6 |
raise progit.exceptions.RepoExistsException(
|
|
Pierre-Yves Chibon |
4b7a7d |
'The docs "%s" already exists' % project.path
|
|
Pierre-Yves Chibon |
6160b6 |
)
|
|
Pierre-Yves Chibon |
a33978 |
pygit2.init_repository(gitrepo, bare=True)
|
|
Pierre-Yves Chibon |
a33978 |
|
|
Pierre-Yves Chibon |
a33978 |
gitrepo = os.path.join(ticketfolder, project.path)
|
|
Pierre-Yves Chibon |
a33978 |
if os.path.exists(gitrepo):
|
|
Pierre-Yves Chibon |
a33978 |
raise progit.exceptions.RepoExistsException(
|
|
Pierre-Yves Chibon |
a33978 |
'The tickets repo "%s" already exists' % project.path
|
|
Pierre-Yves Chibon |
a33978 |
)
|
|
Pierre-Yves Chibon |
6160b6 |
pygit2.init_repository(gitrepo, bare=True)
|
|
Pierre-Yves Chibon |
6160b6 |
|
|
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 |
'''
|
|
Pierre-Yves Chibon |
0b9290 |
projects = session.query(
|
|
Pierre-Yves Chibon |
0b9290 |
model.Project
|
|
Pierre-Yves Chibon |
0b9290 |
).order_by(
|
|
Pierre-Yves Chibon |
0b9290 |
model.Project.date_created
|
|
Pierre-Yves Chibon |
0b9290 |
)
|
|
Mathieu Bridon |
eb729c |
|
|
Pierre-Yves Chibon |
ea0ee1 |
if username is not None:
|
|
Pierre-Yves Chibon |
e1372f |
projects = projects.filter(
|
|
Pierre-Yves Chibon |
e1372f |
model.User.user == username
|
|
Pierre-Yves Chibon |
e1372f |
).filter(
|
|
Pierre-Yves Chibon |
e1372f |
model.User.id == model.Project.user_id
|
|
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 |
e1372f |
model.User.user == user
|
|
Pierre-Yves Chibon |
e1372f |
).filter(
|
|
Pierre-Yves Chibon |
e1372f |
model.User.id == model.Project.user_id
|
|
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 |
bc60cc |
def get_issues(session, repo, status=None, closed=False, tags=None):
|
|
Pierre-Yves Chibon |
562d75 |
''' Retrieve all the issues associated to a project
|
|
Pierre-Yves Chibon |
b6df7d |
|
|
Pierre-Yves Chibon |
b6df7d |
Watch out that the closed argument is incompatible with the status
|
|
Pierre-Yves Chibon |
b6df7d |
argument. The closed argument will return all the issues whose status
|
|
Pierre-Yves Chibon |
b6df7d |
is not 'Open', otherwise it will return the issues having the specified
|
|
Pierre-Yves Chibon |
b6df7d |
status.
|
|
Pierre-Yves Chibon |
bc60cc |
The `tags` argument can be used to filter the issues returned based on
|
|
Pierre-Yves Chibon |
bc60cc |
a certain tag.
|
|
Pierre-Yves Chibon |
bc60cc |
|
|
Pierre-Yves Chibon |
562d75 |
'''
|
|
Pierre-Yves Chibon |
77e16c |
subquery = session.query(
|
|
Pierre-Yves Chibon |
77e16c |
model.GlobalId,
|
|
Pierre-Yves Chibon |
77e16c |
sqlalchemy.over(
|
|
Pierre-Yves Chibon |
77e16c |
sqlalchemy.func.row_number(),
|
|
Pierre-Yves Chibon |
77e16c |
partition_by=model.GlobalId.project_id,
|
|
Pierre-Yves Chibon |
77e16c |
order_by=model.GlobalId.id
|
|
Pierre-Yves Chibon |
77e16c |
).label('global_id')
|
|
Pierre-Yves Chibon |
77e16c |
).subquery()
|
|
Pierre-Yves Chibon |
77e16c |
|
|
Pierre-Yves Chibon |
562d75 |
query = session.query(
|
|
Pierre-Yves Chibon |
77e16c |
model.Issue,
|
|
Pierre-Yves Chibon |
77e16c |
subquery.c.global_id
|
|
Pierre-Yves Chibon |
77e16c |
).filter(
|
|
Pierre-Yves Chibon |
77e16c |
subquery.c.issue_id == model.Issue.id
|
|
Pierre-Yves Chibon |
562d75 |
).filter(
|
|
Pierre-Yves Chibon |
77e16c |
subquery.c.project_id == model.Issue.project_id
|
|
Pierre-Yves Chibon |
95f042 |
).filter(
|
|
Pierre-Yves Chibon |
95f042 |
model.Issue.project_id == repo.id
|
|
Pierre-Yves Chibon |
3a2a1c |
).order_by(
|
|
Pierre-Yves Chibon |
3a2a1c |
model.Issue.id
|
|
Pierre-Yves Chibon |
562d75 |
)
|
|
Pierre-Yves Chibon |
562d75 |
|
|
Pierre-Yves Chibon |
b6df7d |
if status is not None and not closed:
|
|
Pierre-Yves Chibon |
4d1cbe |
query = query.filter(
|
|
Pierre-Yves Chibon |
4d1cbe |
model.Issue.status == status
|
|
Pierre-Yves Chibon |
4d1cbe |
)
|
|
Pierre-Yves Chibon |
b6df7d |
if closed:
|
|
Pierre-Yves Chibon |
b6df7d |
query = query.filter(
|
|
Pierre-Yves Chibon |
b6df7d |
model.Issue.status != 'Open'
|
|
Pierre-Yves Chibon |
b6df7d |
)
|
|
Pierre-Yves Chibon |
d01150 |
if tags is not None and tags != []:
|
|
Pierre-Yves Chibon |
bc60cc |
query = query.filter(
|
|
Pierre-Yves Chibon |
bc60cc |
model.Issue.id == model.TagIssue.issue_id
|
|
Pierre-Yves Chibon |
bc60cc |
).filter(
|
|
Pierre-Yves Chibon |
bc60cc |
model.TagIssue.tag.in_(tags)
|
|
Pierre-Yves Chibon |
bc60cc |
)
|
|
Pierre-Yves Chibon |
4d1cbe |
|
|
Pierre-Yves Chibon |
562d75 |
return query.all()
|
|
Pierre-Yves Chibon |
562d75 |
|
|
Pierre-Yves Chibon |
562d75 |
|
|
Pierre-Yves Chibon |
b922fe |
def get_issue_global_id(session, projectid, issueid):
|
|
Pierre-Yves Chibon |
b922fe |
''' Retrieve the global identifier of a specific issue based on its
|
|
Pierre-Yves Chibon |
b922fe |
identifier.
|
|
Pierre-Yves Chibon |
b922fe |
'''
|
|
Pierre-Yves Chibon |
b922fe |
subquery = session.query(
|
|
Pierre-Yves Chibon |
b922fe |
model.GlobalId,
|
|
Pierre-Yves Chibon |
b922fe |
sqlalchemy.over(
|
|
Pierre-Yves Chibon |
b922fe |
sqlalchemy.func.row_number(),
|
|
Pierre-Yves Chibon |
b922fe |
partition_by=model.GlobalId.project_id,
|
|
Pierre-Yves Chibon |
b922fe |
order_by=model.GlobalId.id
|
|
Pierre-Yves Chibon |
b922fe |
).label('global_id')
|
|
Pierre-Yves Chibon |
b922fe |
).subquery()
|
|
Pierre-Yves Chibon |
b922fe |
|
|
Pierre-Yves Chibon |
b922fe |
query = session.query(
|
|
Pierre-Yves Chibon |
b922fe |
subquery.c.global_id
|
|
Pierre-Yves Chibon |
b922fe |
).filter(
|
|
Pierre-Yves Chibon |
b922fe |
subquery.c.project_id == projectid
|
|
Pierre-Yves Chibon |
b922fe |
).filter(
|
|
Pierre-Yves Chibon |
b922fe |
subquery.c.issue_id == issueid
|
|
Pierre-Yves Chibon |
b922fe |
)
|
|
Pierre-Yves Chibon |
b922fe |
|
|
Pierre-Yves Chibon |
b922fe |
data = query.first()
|
|
Pierre-Yves Chibon |
b922fe |
|
|
Pierre-Yves Chibon |
b922fe |
return data[0]
|
|
Pierre-Yves Chibon |
b922fe |
|
|
Pierre-Yves Chibon |
b922fe |
|
|
Pierre-Yves Chibon |
bcb038 |
def get_issue(session, projectid, issueid):
|
|
Pierre-Yves Chibon |
562d75 |
''' Retrieve the specified issue
|
|
Pierre-Yves Chibon |
562d75 |
'''
|
|
Pierre-Yves Chibon |
251d96 |
subquery = session.query(
|
|
Pierre-Yves Chibon |
251d96 |
model.GlobalId,
|
|
Pierre-Yves Chibon |
251d96 |
sqlalchemy.over(
|
|
Pierre-Yves Chibon |
251d96 |
sqlalchemy.func.row_number(),
|
|
Pierre-Yves Chibon |
251d96 |
partition_by=model.GlobalId.project_id,
|
|
Pierre-Yves Chibon |
251d96 |
order_by=model.GlobalId.id
|
|
Pierre-Yves Chibon |
251d96 |
).label('global_id')
|
|
Pierre-Yves Chibon |
251d96 |
).subquery()
|
|
Pierre-Yves Chibon |
251d96 |
|
|
Pierre-Yves Chibon |
562d75 |
query = session.query(
|
|
Pierre-Yves Chibon |
562d75 |
model.Issue
|
|
Pierre-Yves Chibon |
562d75 |
).filter(
|
|
Pierre-Yves Chibon |
bcb038 |
model.Issue.project_id == projectid
|
|
Pierre-Yves Chibon |
bcb038 |
).filter(
|
|
Pierre-Yves Chibon |
bcb038 |
model.Issue.project_id == projectid
|
|
Pierre-Yves Chibon |
bcb038 |
).filter(
|
|
Pierre-Yves Chibon |
251d96 |
subquery.c.project_id == model.Issue.project_id
|
|
Pierre-Yves Chibon |
251d96 |
).filter(
|
|
Pierre-Yves Chibon |
a93753 |
subquery.c.issue_id == model.Issue.id
|
|
Pierre-Yves Chibon |
a93753 |
).filter(
|
|
Pierre-Yves Chibon |
251d96 |
subquery.c.global_id == issueid
|
|
Pierre-Yves Chibon |
3a2a1c |
).order_by(
|
|
Pierre-Yves Chibon |
3a2a1c |
model.Issue.id
|
|
Pierre-Yves Chibon |
562d75 |
)
|
|
Pierre-Yves Chibon |
562d75 |
|
|
Pierre-Yves Chibon |
562d75 |
return query.first()
|
|
Pierre-Yves Chibon |
35112d |
|
|
Pierre-Yves Chibon |
8efc30 |
def get_tags_of_project(session, project):
|
|
Pierre-Yves Chibon |
8efc30 |
''' Returns the list of tags associated with the issues of a project.
|
|
Pierre-Yves Chibon |
8efc30 |
'''
|
|
Pierre-Yves Chibon |
8efc30 |
query = session.query(
|
|
Pierre-Yves Chibon |
8efc30 |
model.Tag
|
|
Pierre-Yves Chibon |
8efc30 |
).filter(
|
|
Pierre-Yves Chibon |
8efc30 |
model.Tag.tag == model.TagIssue.tag
|
|
Pierre-Yves Chibon |
8efc30 |
).filter(
|
|
Pierre-Yves Chibon |
8efc30 |
model.TagIssue.issue_id == model.Issue.id
|
|
Pierre-Yves Chibon |
8efc30 |
).filter(
|
|
Pierre-Yves Chibon |
8efc30 |
model.Issue.project_id == project.id
|
|
Pierre-Yves Chibon |
8efc30 |
).order_by(
|
|
Pierre-Yves Chibon |
8efc30 |
model.Tag.tag
|
|
Pierre-Yves Chibon |
8efc30 |
)
|
|
Pierre-Yves Chibon |
8efc30 |
|
|
Pierre-Yves Chibon |
8efc30 |
return query.all()
|
|
Pierre-Yves Chibon |
8efc30 |
|
|
Pierre-Yves Chibon |
8efc30 |
|
|
Pierre-Yves Chibon |
2e810e |
def get_tag(session, tag):
|
|
Pierre-Yves Chibon |
2e810e |
''' Returns a Tag object for the given tag text.
|
|
Pierre-Yves Chibon |
2e810e |
'''
|
|
Pierre-Yves Chibon |
2e810e |
query = session.query(
|
|
Pierre-Yves Chibon |
2e810e |
model.Tag
|
|
Pierre-Yves Chibon |
2e810e |
).filter(
|
|
Pierre-Yves Chibon |
2e810e |
model.Tag.tag == tag
|
|
Pierre-Yves Chibon |
2e810e |
)
|
|
Pierre-Yves Chibon |
2e810e |
|
|
Pierre-Yves Chibon |
2e810e |
return query.first()
|
|
Pierre-Yves Chibon |
2e810e |
|
|
Pierre-Yves Chibon |
35112d |
|
|
Pierre-Yves Chibon |
b0265c |
def get_pull_requests(
|
|
Pierre-Yves Chibon |
b0265c |
session, project_id=None, project_id_from=None, status=None):
|
|
Pierre-Yves Chibon |
b0265c |
''' Retrieve the specified issue
|
|
Pierre-Yves Chibon |
b0265c |
'''
|
|
Pierre-Yves Chibon |
33e9fc |
|
|
Pierre-Yves Chibon |
33e9fc |
subquery = session.query(
|
|
Pierre-Yves Chibon |
33e9fc |
model.GlobalId,
|
|
Pierre-Yves Chibon |
33e9fc |
sqlalchemy.over(
|
|
Pierre-Yves Chibon |
33e9fc |
sqlalchemy.func.row_number(),
|
|
Pierre-Yves Chibon |
33e9fc |
partition_by=model.GlobalId.project_id,
|
|
Pierre-Yves Chibon |
33e9fc |
order_by=model.GlobalId.id
|
|
Pierre-Yves Chibon |
33e9fc |
).label('global_id')
|
|
Pierre-Yves Chibon |
33e9fc |
).subquery()
|
|
Pierre-Yves Chibon |
33e9fc |
|
|
Pierre-Yves Chibon |
b0265c |
query = session.query(
|
|
Pierre-Yves Chibon |
33e9fc |
model.PullRequest,
|
|
Pierre-Yves Chibon |
33e9fc |
subquery.c.global_id
|
|
Pierre-Yves Chibon |
33e9fc |
).filter(
|
|
Pierre-Yves Chibon |
33e9fc |
subquery.c.request_id == model.PullRequest.id
|
|
Pierre-Yves Chibon |
33e9fc |
).filter(
|
|
Pierre-Yves Chibon |
33e9fc |
subquery.c.project_id == model.PullRequest.project_id
|
|
Pierre-Yves Chibon |
3a2a1c |
).order_by(
|
|
Pierre-Yves Chibon |
3a2a1c |
model.PullRequest.id
|
|
Pierre-Yves Chibon |
b0265c |
)
|
|
Pierre-Yves Chibon |
b0265c |
|
|
Pierre-Yves Chibon |
b0265c |
if project_id:
|
|
Pierre-Yves Chibon |
b0265c |
query = query.filter(
|
|
Pierre-Yves Chibon |
b0265c |
model.PullRequest.project_id == project_id
|
|
Pierre-Yves Chibon |
b0265c |
)
|
|
Pierre-Yves Chibon |
b0265c |
|
|
Pierre-Yves Chibon |
b0265c |
if project_id_from:
|
|
Pierre-Yves Chibon |
b0265c |
query = query.filter(
|
|
Pierre-Yves Chibon |
b0265c |
model.PullRequest.project_id_from == project_id_from
|
|
Pierre-Yves Chibon |
b0265c |
)
|
|
Pierre-Yves Chibon |
b0265c |
|
|
Pierre-Yves Chibon |
b0265c |
if status is not None:
|
|
Pierre-Yves Chibon |
b0265c |
query = query.filter(
|
|
Pierre-Yves Chibon |
b0265c |
model.PullRequest.status == status
|
|
Pierre-Yves Chibon |
b0265c |
)
|
|
Pierre-Yves Chibon |
b0265c |
|
|
Pierre-Yves Chibon |
b0265c |
return query.all()
|
|
Pierre-Yves Chibon |
b0265c |
|
|
Pierre-Yves Chibon |
b0265c |
|
|
Pierre-Yves Chibon |
35112d |
def get_pull_request(
|
|
Pierre-Yves Chibon |
35112d |
session, requestid, project_id=None, project_id_from=None):
|
|
Pierre-Yves Chibon |
35112d |
''' Retrieve the specified issue
|
|
Pierre-Yves Chibon |
35112d |
'''
|
|
Pierre-Yves Chibon |
3f844b |
|
|
Pierre-Yves Chibon |
3f844b |
subquery = session.query(
|
|
Pierre-Yves Chibon |
3f844b |
model.GlobalId,
|
|
Pierre-Yves Chibon |
3f844b |
sqlalchemy.over(
|
|
Pierre-Yves Chibon |
3f844b |
sqlalchemy.func.row_number(),
|
|
Pierre-Yves Chibon |
3f844b |
partition_by=model.GlobalId.project_id,
|
|
Pierre-Yves Chibon |
3f844b |
order_by=model.GlobalId.id
|
|
Pierre-Yves Chibon |
3f844b |
).label('global_id')
|
|
Pierre-Yves Chibon |
3f844b |
).subquery()
|
|
Pierre-Yves Chibon |
3f844b |
|
|
Pierre-Yves Chibon |
35112d |
query = session.query(
|
|
Pierre-Yves Chibon |
35112d |
model.PullRequest
|
|
Pierre-Yves Chibon |
35112d |
).filter(
|
|
Pierre-Yves Chibon |
3f844b |
subquery.c.project_id == model.PullRequest.project_id
|
|
Pierre-Yves Chibon |
3f844b |
).filter(
|
|
Pierre-Yves Chibon |
9a1f18 |
subquery.c.request_id == model.PullRequest.id
|
|
Pierre-Yves Chibon |
9a1f18 |
).filter(
|
|
Pierre-Yves Chibon |
3f844b |
subquery.c.global_id == requestid
|
|
Pierre-Yves Chibon |
9a1f18 |
).order_by(
|
|
Pierre-Yves Chibon |
9a1f18 |
model.PullRequest.id
|
|
Pierre-Yves Chibon |
35112d |
)
|
|
Pierre-Yves Chibon |
35112d |
|
|
Pierre-Yves Chibon |
35112d |
if project_id:
|
|
Pierre-Yves Chibon |
35112d |
query = query.filter(
|
|
Pierre-Yves Chibon |
35112d |
model.PullRequest.project_id == project_id
|
|
Pierre-Yves Chibon |
35112d |
)
|
|
Pierre-Yves Chibon |
35112d |
|
|
Pierre-Yves Chibon |
35112d |
if project_id_from:
|
|
Pierre-Yves Chibon |
35112d |
query = query.filter(
|
|
Pierre-Yves Chibon |
35112d |
model.PullRequest.project_id_from == project_id_from
|
|
Pierre-Yves Chibon |
35112d |
)
|
|
Pierre-Yves Chibon |
35112d |
|
|
Pierre-Yves Chibon |
35112d |
return query.first()
|
|
Pierre-Yves Chibon |
42a02c |
|
|
Pierre-Yves Chibon |
42a02c |
|
|
Pierre-Yves Chibon |
fc841e |
def get_pull_request_global_id(session, projectid, requestid):
|
|
Pierre-Yves Chibon |
fc841e |
''' Retrieve the global identifier of a specific request based on its
|
|
Pierre-Yves Chibon |
fc841e |
identifier.
|
|
Pierre-Yves Chibon |
fc841e |
'''
|
|
Pierre-Yves Chibon |
fc841e |
subquery = session.query(
|
|
Pierre-Yves Chibon |
fc841e |
model.GlobalId,
|
|
Pierre-Yves Chibon |
fc841e |
sqlalchemy.over(
|
|
Pierre-Yves Chibon |
fc841e |
sqlalchemy.func.row_number(),
|
|
Pierre-Yves Chibon |
fc841e |
partition_by=model.GlobalId.project_id,
|
|
Pierre-Yves Chibon |
fc841e |
order_by=model.GlobalId.id
|
|
Pierre-Yves Chibon |
fc841e |
).label('global_id')
|
|
Pierre-Yves Chibon |
fc841e |
).subquery()
|
|
Pierre-Yves Chibon |
fc841e |
|
|
Pierre-Yves Chibon |
fc841e |
query = session.query(
|
|
Pierre-Yves Chibon |
fc841e |
subquery.c.global_id
|
|
Pierre-Yves Chibon |
fc841e |
).filter(
|
|
Pierre-Yves Chibon |
fc841e |
subquery.c.project_id == projectid
|
|
Pierre-Yves Chibon |
fc841e |
).filter(
|
|
Pierre-Yves Chibon |
fc841e |
subquery.c.request_id == requestid
|
|
Pierre-Yves Chibon |
fc841e |
)
|
|
Pierre-Yves Chibon |
fc841e |
|
|
Pierre-Yves Chibon |
fc841e |
data = query.first()
|
|
Pierre-Yves Chibon |
fc841e |
|
|
Pierre-Yves Chibon |
fc841e |
return data[0]
|
|
Pierre-Yves Chibon |
fc841e |
|
|
Pierre-Yves Chibon |
fc841e |
|
|
Pierre-Yves Chibon |
375fde |
def close_pull_request(session, request, user, merged=True):
|
|
Pierre-Yves Chibon |
42a02c |
''' Close the provided pull-request.
|
|
Pierre-Yves Chibon |
42a02c |
'''
|
|
Pierre-Yves Chibon |
42a02c |
request.status = False
|
|
Pierre-Yves Chibon |
42a02c |
session.add(request)
|
|
Pierre-Yves Chibon |
42a02c |
session.flush()
|
|
Pierre-Yves Chibon |
4d1cbe |
|
|
Pierre-Yves Chibon |
00aee8 |
globalid = get_pull_request_global_id(
|
|
Pierre-Yves Chibon |
00aee8 |
session, request.project.id, request.id)
|
|
Pierre-Yves Chibon |
00aee8 |
|
|
Johan Cwiklinski |
86d9c4 |
if merged == True:
|
|
Pierre-Yves Chibon |
00aee8 |
progit.notify.notify_merge_pull_request(request, user, globalid)
|
|
Johan Cwiklinski |
86d9c4 |
else:
|
|
Pierre-Yves Chibon |
00aee8 |
progit.notify.notify_cancelled_pull_request(request, user, globalid)
|
|
Pierre-Yves Chibon |
5fdf85 |
|
|
Pierre-Yves Chibon |
4d1cbe |
|
|
Pierre-Yves Chibon |
4d1cbe |
def get_issue_statuses(session):
|
|
Pierre-Yves Chibon |
4d1cbe |
''' Return the complete list of status an issue can have.
|
|
Pierre-Yves Chibon |
4d1cbe |
'''
|
|
Pierre-Yves Chibon |
4d1cbe |
output = []
|
|
Pierre-Yves Chibon |
4d1cbe |
statuses = session.query(model.StatusIssue).all()
|
|
Pierre-Yves Chibon |
4d1cbe |
for status in statuses:
|
|
Pierre-Yves Chibon |
4d1cbe |
output.append(status.status)
|
|
Pierre-Yves Chibon |
4d1cbe |
return output
|
|
Pierre-Yves Chibon |
7c47d2 |
|
|
Pierre-Yves Chibon |
7c47d2 |
|
|
Pierre-Yves Chibon |
7c47d2 |
def generate_gitolite_acls(session, configfile):
|
|
Pierre-Yves Chibon |
7c47d2 |
''' Generate the configuration file for gitolite for all projects
|
|
Pierre-Yves Chibon |
7c47d2 |
on the forge.
|
|
Pierre-Yves Chibon |
7c47d2 |
'''
|
|
Pierre-Yves Chibon |
7c47d2 |
config = []
|
|
Pierre-Yves Chibon |
7c47d2 |
for project in session.query(model.Project).all():
|
|
Pierre-Yves Chibon |
7f72e8 |
if project.parent_id:
|
|
Pierre-Yves Chibon |
7f72e8 |
config.append('repo forks/%s' % project.fullname)
|
|
Pierre-Yves Chibon |
7f72e8 |
else:
|
|
Pierre-Yves Chibon |
7f72e8 |
config.append('repo %s' % project.fullname)
|
|
Pierre-Yves Chibon |
dfe989 |
config.append(' RW+ = %s' % project.user.user)
|
|
Pierre-Yves Chibon |
7c47d2 |
for user in project.users:
|
|
Pierre-Yves Chibon |
7c47d2 |
if user != project.user:
|
|
Pierre-Yves Chibon |
3562ab |
config.append(' RW+ = %s' % user.user.user)
|
|
Pierre-Yves Chibon |
7c47d2 |
config.append('')
|
|
Pierre-Yves Chibon |
7c47d2 |
|
|
Pierre-Yves Chibon |
3cec45 |
config.append('repo docs/%s' % project.fullname)
|
|
Pierre-Yves Chibon |
3cec45 |
config.append(' RW+ = %s' % project.user.user)
|
|
Pierre-Yves Chibon |
3cec45 |
for user in project.users:
|
|
Pierre-Yves Chibon |
3cec45 |
if user != project.user:
|
|
Pierre-Yves Chibon |
3562ab |
config.append(' RW+ = %s' % user.user.user)
|
|
Pierre-Yves Chibon |
3cec45 |
config.append('')
|
|
Pierre-Yves Chibon |
3cec45 |
|
|
Pierre-Yves Chibon |
1a37c6 |
config.append('repo tickets/%s' % project.fullname)
|
|
Pierre-Yves Chibon |
1a37c6 |
config.append(' RW+ = %s' % project.user.user)
|
|
Pierre-Yves Chibon |
1a37c6 |
for user in project.users:
|
|
Pierre-Yves Chibon |
1a37c6 |
if user != project.user:
|
|
Pierre-Yves Chibon |
3562ab |
config.append(' RW+ = %s' % user.user.user)
|
|
Pierre-Yves Chibon |
1a37c6 |
config.append('')
|
|
Pierre-Yves Chibon |
1a37c6 |
|
|
Pierre-Yves Chibon |
edd115 |
with open(configfile, 'w') as stream:
|
|
Pierre-Yves Chibon |
9df3ed |
for row in config:
|
|
Pierre-Yves Chibon |
30ec31 |
stream.write(row + '\n')
|
|
Pierre-Yves Chibon |
c2aa0d |
|
|
Pierre-Yves Chibon |
c2aa0d |
|
|
Pierre-Yves Chibon |
c2aa0d |
def set_up_user(session, username, fullname, user_email):
|
|
Pierre-Yves Chibon |
c2aa0d |
''' Set up a new user into the database or update its information. '''
|
|
Pierre-Yves Chibon |
03c11f |
user = get_user(session, username)
|
|
Pierre-Yves Chibon |
c2aa0d |
if not user:
|
|
Pierre-Yves Chibon |
c2aa0d |
user = model.User(
|
|
Pierre-Yves Chibon |
c2aa0d |
user=username,
|
|
Pierre-Yves Chibon |
c2aa0d |
fullname=fullname)
|
|
Pierre-Yves Chibon |
c2aa0d |
session.add(user)
|
|
Pierre-Yves Chibon |
c2aa0d |
session.flush()
|
|
Pierre-Yves Chibon |
c2aa0d |
|
|
Pierre-Yves Chibon |
c2aa0d |
if user.fullname != fullname:
|
|
Pierre-Yves Chibon |
c2aa0d |
user.fullname = fullname
|
|
Pierre-Yves Chibon |
c2aa0d |
session.add(user)
|
|
Pierre-Yves Chibon |
c2aa0d |
session.flush()
|
|
Pierre-Yves Chibon |
c2aa0d |
|
|
Pierre-Yves Chibon |
8b2894 |
emails = [email.email for email in user.emails]
|
|
Pierre-Yves Chibon |
8b2894 |
if user_email not in emails:
|
|
Pierre-Yves Chibon |
c2aa0d |
useremail = model.UserEmail(
|
|
Pierre-Yves Chibon |
c2aa0d |
user_id=user.id,
|
|
Pierre-Yves Chibon |
c2aa0d |
email=user_email)
|
|
Pierre-Yves Chibon |
c2aa0d |
session.add(useremail)
|
|
Pierre-Yves Chibon |
c2aa0d |
session.flush()
|
|
Pierre-Yves Chibon |
8f25f2 |
|
|
Pierre-Yves Chibon |
8f25f2 |
|
|
Pierre-Yves Chibon |
8f25f2 |
def update_user_ssh(session, user, ssh_key):
|
|
Pierre-Yves Chibon |
8f25f2 |
''' Set up a new user into the database or update its information. '''
|
|
Pierre-Yves Chibon |
8f25f2 |
if isinstance(user, basestring):
|
|
Pierre-Yves Chibon |
8f25f2 |
user = get_user(session, user)
|
|
Pierre-Yves Chibon |
8f25f2 |
|
|
Pierre-Yves Chibon |
8f25f2 |
message = 'Nothing to update'
|
|
Pierre-Yves Chibon |
8f25f2 |
|
|
Pierre-Yves Chibon |
8f25f2 |
if ssh_key != user.public_ssh_key:
|
|
Pierre-Yves Chibon |
8f25f2 |
user.public_ssh_key = ssh_key
|
|
Pierre-Yves Chibon |
8f25f2 |
session.add(user)
|
|
Pierre-Yves Chibon |
8f25f2 |
session.flush()
|
|
Pierre-Yves Chibon |
8f25f2 |
message = 'Public ssh key updated'
|
|
Pierre-Yves Chibon |
8f25f2 |
|
|
Pierre-Yves Chibon |
8f25f2 |
return message
|
|
Pierre-Yves Chibon |
f7d963 |
|
|
Pierre-Yves Chibon |
f7d963 |
|
|
Pierre-Yves Chibon |
f7d963 |
def issue_to_json(issue):
|
|
Pierre-Yves Chibon |
f7d963 |
""" Convert all the data related to an issue (a ticket) as json object.
|
|
Pierre-Yves Chibon |
f7d963 |
|
|
Pierre-Yves Chibon |
f7d963 |
"""
|
|
Pierre-Yves Chibon |
f7d963 |
output = {
|
|
Pierre-Yves Chibon |
f7d963 |
'title': issue.title,
|
|
Pierre-Yves Chibon |
f7d963 |
'content': issue.content,
|
|
Pierre-Yves Chibon |
f7d963 |
'status': issue.status,
|
|
Pierre-Yves Chibon |
f7d963 |
'date_created': issue.date_created.strftime('%s'),
|
|
Pierre-Yves Chibon |
f7d963 |
'user': {
|
|
Pierre-Yves Chibon |
f7d963 |
'name': issue.user.user,
|
|
Pierre-Yves Chibon |
f7d963 |
'emails': [email.email for email in issue.user.emails],
|
|
Pierre-Yves Chibon |
f7d963 |
}
|
|
Pierre-Yves Chibon |
f7d963 |
}
|
|
Pierre-Yves Chibon |
f7d963 |
|
|
Pierre-Yves Chibon |
f7d963 |
comments = []
|
|
Pierre-Yves Chibon |
f7d963 |
for comment in issue.comments:
|
|
Pierre-Yves Chibon |
f7d963 |
cmt = {
|
|
Pierre-Yves Chibon |
f7d963 |
'id': comment.id,
|
|
Pierre-Yves Chibon |
f7d963 |
'comment': comment.comment,
|
|
Pierre-Yves Chibon |
f7d963 |
'parent': comment.parent_id,
|
|
Pierre-Yves Chibon |
f7d963 |
'date_created': comment.date_created.strftime('%s'),
|
|
Pierre-Yves Chibon |
f7d963 |
'user': {
|
|
Pierre-Yves Chibon |
f7d963 |
'name': comment.user.user,
|
|
Pierre-Yves Chibon |
f7d963 |
'emails': [email.email for email in comment.user.emails],
|
|
Pierre-Yves Chibon |
f7d963 |
}
|
|
Pierre-Yves Chibon |
f7d963 |
}
|
|
Pierre-Yves Chibon |
f7d963 |
comments.append(cmt)
|
|
Pierre-Yves Chibon |
f7d963 |
|
|
Pierre-Yves Chibon |
f7d963 |
output['comments'] = comments
|
|
Pierre-Yves Chibon |
f7d963 |
|
|
Pierre-Yves Chibon |
f7d963 |
return json.dumps(output)
|
|
Pierre-Yves Chibon |
d133cd |
|
|
Pierre-Yves Chibon |
d133cd |
|
|
Pierre-Yves Chibon |
d133cd |
def update_git_ticket(issue, repo, ticketfolder):
|
|
Pierre-Yves Chibon |
d133cd |
""" Update the given issue in its git.
|
|
Pierre-Yves Chibon |
d133cd |
|
|
Pierre-Yves Chibon |
d133cd |
This method forks the provided repo, add/edit the issue whose file name
|
|
Pierre-Yves Chibon |
d133cd |
is defined by the uid field of the issue and if there are additions/
|
|
Pierre-Yves Chibon |
d133cd |
changes commit them and push them back to the original repo.
|
|
Pierre-Yves Chibon |
d133cd |
|
|
Pierre-Yves Chibon |
d133cd |
"""
|
|
Pierre-Yves Chibon |
d133cd |
|
|
Pierre-Yves Chibon |
d133cd |
# Get the fork
|
|
Pierre-Yves Chibon |
d133cd |
repopath = os.path.join(ticketfolder, repo.path)
|
|
Pierre-Yves Chibon |
d133cd |
ticket_repo = pygit2.Repository(repopath)
|
|
Pierre-Yves Chibon |
d133cd |
|
|
Pierre-Yves Chibon |
d133cd |
# Clone the repo into a temp folder
|
|
Pierre-Yves Chibon |
d133cd |
newpath = tempfile.mkdtemp()
|
|
Pierre-Yves Chibon |
d133cd |
new_repo = pygit2.clone_repository(repopath, newpath)
|
|
Pierre-Yves Chibon |
d133cd |
|
|
Pierre-Yves Chibon |
d133cd |
file_path = os.path.join(newpath, issue.uid)
|
|
Pierre-Yves Chibon |
d133cd |
|
|
Pierre-Yves Chibon |
d133cd |
# Get the current index
|
|
Pierre-Yves Chibon |
d133cd |
index = new_repo.index
|
|
Pierre-Yves Chibon |
d133cd |
|
|
Pierre-Yves Chibon |
d133cd |
# Are we adding files
|
|
Pierre-Yves Chibon |
d133cd |
added = False
|
|
Pierre-Yves Chibon |
d133cd |
if not os.path.exists(file_path):
|
|
Pierre-Yves Chibon |
d133cd |
added = True
|
|
Pierre-Yves Chibon |
d133cd |
|
|
Pierre-Yves Chibon |
d133cd |
# Write down what changed
|
|
Pierre-Yves Chibon |
d133cd |
with open(file_path, 'w') as stream:
|
|
Pierre-Yves Chibon |
d133cd |
stream.write(issue_to_json(issue))
|
|
Pierre-Yves Chibon |
d133cd |
|
|
Pierre-Yves Chibon |
d133cd |
# Retrieve the list of files that changed
|
|
Pierre-Yves Chibon |
d133cd |
diff = new_repo.diff()
|
|
Pierre-Yves Chibon |
d133cd |
files = [patch.new_file_path for patch in diff]
|
|
Pierre-Yves Chibon |
d133cd |
|
|
Pierre-Yves Chibon |
d133cd |
# Add the changes to the index
|
|
Pierre-Yves Chibon |
d133cd |
if added:
|
|
Pierre-Yves Chibon |
d133cd |
index.add(issue.uid)
|
|
Pierre-Yves Chibon |
d133cd |
for filename in files:
|
|
Pierre-Yves Chibon |
d133cd |
index.add(filename)
|
|
Pierre-Yves Chibon |
d133cd |
|
|
Pierre-Yves Chibon |
d133cd |
# If not change, return
|
|
Pierre-Yves Chibon |
63324c |
if not files and not added:
|
|
Pierre-Yves Chibon |
d133cd |
shutil.rmtree(newpath)
|
|
Pierre-Yves Chibon |
d133cd |
return
|
|
Pierre-Yves Chibon |
d133cd |
|
|
Pierre-Yves Chibon |
d133cd |
# See if there is a parent to this commit
|
|
Pierre-Yves Chibon |
d133cd |
parent = None
|
|
Pierre-Yves Chibon |
d133cd |
try:
|
|
Pierre-Yves Chibon |
d133cd |
parent = new_repo.head.get_object().oid
|
|
Pierre-Yves Chibon |
d133cd |
except pygit2.GitError:
|
|
Pierre-Yves Chibon |
d133cd |
pass
|
|
Pierre-Yves Chibon |
d133cd |
|
|
Pierre-Yves Chibon |
d133cd |
parents = []
|
|
Pierre-Yves Chibon |
d133cd |
if parent:
|
|
Pierre-Yves Chibon |
d133cd |
parents.append(parent)
|
|
Pierre-Yves Chibon |
d133cd |
|
|
Pierre-Yves Chibon |
d133cd |
# Author/commiter will always be this one
|
|
Pierre-Yves Chibon |
d133cd |
author = pygit2.Signature(name='progit', email='progit')
|
|
Pierre-Yves Chibon |
d133cd |
|
|
Pierre-Yves Chibon |
d133cd |
# Actually commit
|
|
Pierre-Yves Chibon |
d133cd |
sha = new_repo.create_commit(
|
|
Pierre-Yves Chibon |
d133cd |
'refs/heads/master',
|
|
Pierre-Yves Chibon |
d133cd |
author,
|
|
Pierre-Yves Chibon |
d133cd |
author,
|
|
Pierre-Yves Chibon |
d133cd |
'Updated ticket %s: %s' % (issue.uid, issue.title),
|
|
Pierre-Yves Chibon |
d133cd |
new_repo.index.write_tree(),
|
|
Pierre-Yves Chibon |
d133cd |
parents)
|
|
Pierre-Yves Chibon |
d133cd |
index.write()
|
|
Pierre-Yves Chibon |
d133cd |
|
|
Pierre-Yves Chibon |
d133cd |
# Push to origin
|
|
Pierre-Yves Chibon |
d133cd |
ori_remote = new_repo.remotes[0]
|
|
Pierre-Yves Chibon |
d133cd |
master_ref = new_repo.lookup_reference('HEAD').resolve()
|
|
Pierre-Yves Chibon |
d133cd |
refname = '%s:%s' % (master_ref.name, master_ref.name)
|
|
Pierre-Yves Chibon |
d133cd |
|
|
Pierre-Yves Chibon |
d133cd |
ori_remote.push(refname)
|
|
Pierre-Yves Chibon |
d133cd |
|
|
Pierre-Yves Chibon |
d133cd |
# Remove the clone
|
|
Pierre-Yves Chibon |
d133cd |
shutil.rmtree(newpath)
|
|
Pierre-Yves Chibon |
95245b |
|
|
Pierre-Yves Chibon |
95245b |
|
|
Pierre-Yves Chibon |
95245b |
def avatar_url(username, size=64, default='retro'):
|
|
Pierre-Yves Chibon |
95245b |
openid = "http://%s.id.fedoraproject.org/" % username
|
|
Pierre-Yves Chibon |
95245b |
return avatar_url_from_openid(openid, size, default)
|
|
Pierre-Yves Chibon |
95245b |
|
|
Pierre-Yves Chibon |
95245b |
|
|
Pierre-Yves Chibon |
95245b |
def avatar_url_from_openid(openid, size=64, default='retro', dns=False):
|
|
Pierre-Yves Chibon |
95245b |
"""
|
|
Pierre-Yves Chibon |
95245b |
Our own implementation since fas doesn't support this nicely yet.
|
|
Pierre-Yves Chibon |
95245b |
"""
|
|
Pierre-Yves Chibon |
95245b |
|
|
Pierre-Yves Chibon |
95245b |
if dns: # pragma: no cover
|
|
Pierre-Yves Chibon |
95245b |
# This makes an extra DNS SRV query, which can slow down our webapps.
|
|
Pierre-Yves Chibon |
95245b |
# It is necessary for libravatar federation, though.
|
|
Pierre-Yves Chibon |
95245b |
import libravatar
|
|
Pierre-Yves Chibon |
95245b |
return libravatar.libravatar_url(
|
|
Pierre-Yves Chibon |
95245b |
openid=openid,
|
|
Pierre-Yves Chibon |
95245b |
size=size,
|
|
Pierre-Yves Chibon |
95245b |
default=default,
|
|
Pierre-Yves Chibon |
95245b |
)
|
|
Pierre-Yves Chibon |
95245b |
else:
|
|
Pierre-Yves Chibon |
95245b |
import urllib, hashlib
|
|
Pierre-Yves Chibon |
95245b |
query = urllib.urlencode({'s': size, 'd': default})
|
|
Pierre-Yves Chibon |
95245b |
hash = hashlib.sha256(openid).hexdigest()
|
|
Pierre-Yves Chibon |
95245b |
return "https://seccdn.libravatar.org/avatar/%s?%s" % (hash, query)
|
|
Pierre-Yves Chibon |
b0d578 |
|
|
Pierre-Yves Chibon |
b0d578 |
|
|
Pierre-Yves Chibon |
b0d578 |
def get_session_by_visitkey(session, sessionid):
|
|
Pierre-Yves Chibon |
b0d578 |
''' Return a specified VisitUser via its session identifier (visit_key).
|
|
Pierre-Yves Chibon |
b0d578 |
|
|
Pierre-Yves Chibon |
b0d578 |
:arg session: the session with which to connect to the database.
|
|
Pierre-Yves Chibon |
b0d578 |
|
|
Pierre-Yves Chibon |
b0d578 |
'''
|
|
Pierre-Yves Chibon |
b0d578 |
query = session.query(
|
|
Pierre-Yves Chibon |
4313f4 |
model.ProgitUserVisit
|
|
Pierre-Yves Chibon |
b0d578 |
).filter(
|
|
Pierre-Yves Chibon |
4313f4 |
model.ProgitUserVisit.visit_key == sessionid
|
|
Pierre-Yves Chibon |
b0d578 |
)
|
|
Pierre-Yves Chibon |
b0d578 |
|
|
Pierre-Yves Chibon |
b0d578 |
return query.first()
|
|
Pierre-Yves Chibon |
a8a719 |
|
|
Pierre-Yves Chibon |
a8a719 |
|
|
Pierre-Yves Chibon |
a8a719 |
def get_groups(session):
|
|
Pierre-Yves Chibon |
a8a719 |
''' Return the list of groups present in the database.
|
|
Pierre-Yves Chibon |
a8a719 |
|
|
Pierre-Yves Chibon |
a8a719 |
:arg session: the session with which to connect to the database.
|
|
Pierre-Yves Chibon |
a8a719 |
|
|
Pierre-Yves Chibon |
a8a719 |
'''
|
|
Pierre-Yves Chibon |
a8a719 |
query = session.query(
|
|
Pierre-Yves Chibon |
a8a719 |
model.ProgitGroup
|
|
Pierre-Yves Chibon |
a8a719 |
).order_by(
|
|
Pierre-Yves Chibon |
a8a719 |
model.ProgitGroup.group_name
|
|
Pierre-Yves Chibon |
a8a719 |
)
|
|
Pierre-Yves Chibon |
a8a719 |
|
|
Pierre-Yves Chibon |
a8a719 |
return query.all()
|
|
Pierre-Yves Chibon |
b97cda |
|
|
Pierre-Yves Chibon |
b97cda |
|
|
Pierre-Yves Chibon |
b97cda |
def get_group(session, group):
|
|
Pierre-Yves Chibon |
b97cda |
''' Return a specific group for the specified group name.
|
|
Pierre-Yves Chibon |
b97cda |
|
|
Pierre-Yves Chibon |
b97cda |
:arg session: the session with which to connect to the database.
|
|
Pierre-Yves Chibon |
b97cda |
|
|
Pierre-Yves Chibon |
b97cda |
'''
|
|
Pierre-Yves Chibon |
b97cda |
query = session.query(
|
|
Pierre-Yves Chibon |
b97cda |
model.ProgitGroup
|
|
Pierre-Yves Chibon |
b97cda |
).filter(
|
|
Pierre-Yves Chibon |
b97cda |
model.ProgitGroup.group_name == group
|
|
Pierre-Yves Chibon |
b97cda |
).order_by(
|
|
Pierre-Yves Chibon |
b97cda |
model.ProgitGroup.group_name
|
|
Pierre-Yves Chibon |
b97cda |
)
|
|
Pierre-Yves Chibon |
b97cda |
|
|
Pierre-Yves Chibon |
b97cda |
return query.first()
|
|
Pierre-Yves Chibon |
025568 |
|
|
Pierre-Yves Chibon |
025568 |
|
|
Pierre-Yves Chibon |
025568 |
def get_users_by_group(session, group):
|
|
Pierre-Yves Chibon |
025568 |
''' Return the list of users for a specified group.
|
|
Pierre-Yves Chibon |
025568 |
|
|
Pierre-Yves Chibon |
025568 |
:arg session: the session with which to connect to the database.
|
|
Pierre-Yves Chibon |
025568 |
|
|
Pierre-Yves Chibon |
025568 |
'''
|
|
Pierre-Yves Chibon |
025568 |
query = session.query(
|
|
Pierre-Yves Chibon |
025568 |
model.User
|
|
Pierre-Yves Chibon |
025568 |
).filter(
|
|
Pierre-Yves Chibon |
025568 |
model.User.id == model.ProgitUserGroup.user_id
|
|
Pierre-Yves Chibon |
025568 |
).filter(
|
|
Pierre-Yves Chibon |
025568 |
model.ProgitUserGroup.group_id == model.ProgitGroup.id
|
|
Pierre-Yves Chibon |
025568 |
).filter(
|
|
Pierre-Yves Chibon |
025568 |
model.ProgitGroup.group_name == group
|
|
Pierre-Yves Chibon |
025568 |
).order_by(
|
|
Pierre-Yves Chibon |
025568 |
model.User.user
|
|
Pierre-Yves Chibon |
025568 |
)
|
|
Pierre-Yves Chibon |
025568 |
|
|
Pierre-Yves Chibon |
025568 |
return query.all()
|
|
Pierre-Yves Chibon |
f77dac |
|
|
Pierre-Yves Chibon |
f77dac |
|
|
Pierre-Yves Chibon |
f77dac |
def get_user_group(session, userid, groupid):
|
|
Pierre-Yves Chibon |
f77dac |
''' Return a specific user_group for the specified group and user
|
|
Pierre-Yves Chibon |
f77dac |
identifiers.
|
|
Pierre-Yves Chibon |
f77dac |
|
|
Pierre-Yves Chibon |
f77dac |
:arg session: the session with which to connect to the database.
|
|
Pierre-Yves Chibon |
f77dac |
|
|
Pierre-Yves Chibon |
f77dac |
'''
|
|
Pierre-Yves Chibon |
f77dac |
query = session.query(
|
|
Pierre-Yves Chibon |
f77dac |
model.ProgitUserGroup
|
|
Pierre-Yves Chibon |
f77dac |
).filter(
|
|
Pierre-Yves Chibon |
f77dac |
model.ProgitUserGroup.user_id == userid
|
|
Pierre-Yves Chibon |
f77dac |
).filter(
|
|
Pierre-Yves Chibon |
f77dac |
model.ProgitUserGroup.group_id == groupid
|
|
Pierre-Yves Chibon |
f77dac |
)
|
|
Pierre-Yves Chibon |
f77dac |
|
|
Pierre-Yves Chibon |
f77dac |
return query.first()
|