|
Pierre-Yves Chibon |
33b534 |
# -*- coding: utf-8 -*-
|
|
Pierre-Yves Chibon |
a27356 |
|
|
Pierre-Yves Chibon |
a27356 |
"""
|
|
Pierre-Yves Chibon |
c70df4 |
(c) 2015-2016 - Copyright Red Hat Inc
|
|
Pierre-Yves Chibon |
a27356 |
|
|
Pierre-Yves Chibon |
a27356 |
Authors:
|
|
Pierre-Yves Chibon |
a27356 |
Pierre-Yves Chibon <pingou@pingoured.fr></pingou@pingoured.fr>
|
|
Pierre-Yves Chibon |
a27356 |
|
|
Pierre-Yves Chibon |
a27356 |
"""
|
|
Pierre-Yves Chibon |
67d1cc |
from __future__ import print_function, unicode_literals, absolute_import
|
|
Pierre-Yves Chibon |
a27356 |
|
|
Pierre-Yves Chibon |
22a554 |
# pylint: disable=too-many-branches
|
|
Pierre-Yves Chibon |
22a554 |
# pylint: disable=too-many-arguments
|
|
Pierre-Yves Chibon |
22a554 |
# pylint: disable=too-many-locals
|
|
Pierre-Yves Chibon |
22a554 |
# pylint: disable=too-many-statements
|
|
Pierre-Yves Chibon |
22a554 |
# pylint: disable=too-many-lines
|
|
Pierre-Yves Chibon |
22a554 |
|
|
Pierre-Yves Chibon |
a27356 |
import datetime
|
|
Pierre-Yves Chibon |
a27356 |
import json
|
|
Pierre-Yves Chibon |
b73de8 |
import logging
|
|
Pierre-Yves Chibon |
a27356 |
import os
|
|
Pierre-Yves Chibon |
a27356 |
import shutil
|
|
Pierre-Yves Chibon |
2ed535 |
import subprocess
|
|
Patrick Uiterwijk |
3f97f6 |
import requests
|
|
Pierre-Yves Chibon |
a27356 |
import tempfile
|
|
Pierre-Yves Chibon |
ded1fa |
import tarfile
|
|
Pierre-Yves Chibon |
ded1fa |
import zipfile
|
|
Pierre-Yves Chibon |
a27356 |
|
|
Pierre-Yves Chibon |
7772c6 |
import arrow
|
|
Pierre-Yves Chibon |
a27356 |
import pygit2
|
|
Aurélien Bompard |
831553 |
import six
|
|
Pierre-Yves Chibon |
a27356 |
|
|
Pierre-Yves Chibon |
b1fc61 |
from sqlalchemy.exc import SQLAlchemyError
|
|
Patrick Uiterwijk |
4012dc |
|
|
Patrick Uiterwijk |
4012dc |
# from sqlalchemy.orm.session import Session
|
|
Pierre-Yves Chibon |
acd3eb |
from pygit2.remote import RemoteCollection
|
|
Pierre-Yves Chibon |
acd3eb |
|
|
Pierre-Yves Chibon |
b130e5 |
import pagure.utils
|
|
Pierre-Yves Chibon |
fe5017 |
import pagure.exceptions
|
|
Pierre-Yves Chibon |
930073 |
import pagure.lib.query
|
|
Pierre-Yves Chibon |
fe5017 |
import pagure.lib.notify
|
|
Pierre-Yves Chibon |
eb5f49 |
import pagure.lib.tasks
|
|
Pierre-Yves Chibon |
b130e5 |
from pagure.config import config as pagure_config
|
|
Pierre-Yves Chibon |
fe5017 |
from pagure.lib import model
|
|
Pierre-Yves Chibon |
609965 |
from pagure.lib.repo import PagureRepo
|
|
Patrick Uiterwijk |
d29158 |
import pagure.hooks
|
|
Pierre-Yves Chibon |
a27356 |
|
|
Patrick Uiterwijk |
4012dc |
# from pagure.hooks import run_project_hooks
|
|
Patrick Uiterwijk |
4012dc |
|
|
Pierre-Yves Chibon |
c70df4 |
|
|
Pierre-Yves Chibon |
b73de8 |
_log = logging.getLogger(__name__)
|
|
Pierre-Yves Chibon |
b73de8 |
|
|
Pierre-Yves Chibon |
b73de8 |
|
|
Pierre-Yves Chibon |
86e455 |
def commit_to_patch(
|
|
Pierre-Yves Chibon |
9c2953 |
repo_obj, commits, diff_view=False, find_similar=False, separated=False
|
|
Pierre-Yves Chibon |
9c2953 |
):
|
|
Pierre-Yves Chibon |
9c2953 |
""" For a given commit (PyGit2 commit object) of a specified git repo,
|
|
Pierre-Yves Chibon |
a27356 |
returns a string representation of the changes the commit did in a
|
|
Pierre-Yves Chibon |
a27356 |
format that allows it to be used as patch.
|
|
Pierre-Yves Chibon |
7f7053 |
|
|
Pierre-Yves Chibon |
7f7053 |
:arg repo_obj: the `pygit2.Repository` object of the git repo to
|
|
Pierre-Yves Chibon |
7f7053 |
retrieve the commits in
|
|
Pierre-Yves Chibon |
7f7053 |
:type repo_obj: `pygit2.Repository`
|
|
Pierre-Yves Chibon |
7f7053 |
:arg commits: the list of commits to convert to path
|
|
Pierre-Yves Chibon |
7f7053 |
:type commits: str or list
|
|
Pierre-Yves Chibon |
7f7053 |
:kwarg diff_view: a boolean specifying if what is returned is a git
|
|
Pierre-Yves Chibon |
7f7053 |
patch or a git diff
|
|
Pierre-Yves Chibon |
7f7053 |
:type diff_view: boolean
|
|
Ryan Lerch |
e2f045 |
:kwarg find_similar: a boolean specifying if what we run find_similar
|
|
Ryan Lerch |
e2f045 |
on the diff to group renamed files
|
|
Ryan Lerch |
e2f045 |
:type find_similar: boolean
|
|
Pierre-Yves Chibon |
86e455 |
:kwarg separated: a boolean specifying if the data returned should be
|
|
Pierre-Yves Chibon |
86e455 |
returned as one text blob or not. If diff_view is True, then the diff
|
|
Pierre-Yves Chibon |
86e455 |
are also split by file, otherwise, the different patches are returned
|
|
Pierre-Yves Chibon |
86e455 |
as different text blob.
|
|
Pierre-Yves Chibon |
86e455 |
:type separated: boolean
|
|
Pierre-Yves Chibon |
7f7053 |
:return: the patch or diff representation of the provided commits
|
|
Pierre-Yves Chibon |
7f7053 |
:rtype: str
|
|
Pierre-Yves Chibon |
7f7053 |
|
|
Pierre-Yves Chibon |
9c2953 |
"""
|
|
Pierre-Yves Chibon |
a27356 |
if not isinstance(commits, list):
|
|
Pierre-Yves Chibon |
a27356 |
commits = [commits]
|
|
Pierre-Yves Chibon |
a27356 |
|
|
Pierre-Yves Chibon |
4f92f0 |
patch = []
|
|
Pierre-Yves Chibon |
a27356 |
for cnt, commit in enumerate(commits):
|
|
Pierre-Yves Chibon |
a27356 |
if commit.parents:
|
|
Carlos Mogas da Silva |
dbd6dd |
diff = repo_obj.diff(commit.parents[0], commit)
|
|
Pierre-Yves Chibon |
a27356 |
else:
|
|
Pierre-Yves Chibon |
a27356 |
# First commit in the repo
|
|
Pierre-Yves Chibon |
a27356 |
diff = commit.tree.diff_to_tree(swap=True)
|
|
Ryan Lerch |
e2f045 |
|
|
Julen Landa Alustiza |
05156b |
if diff.patch is None:
|
|
Julen Landa Alustiza |
05156b |
continue
|
|
Julen Landa Alustiza |
05156b |
|
|
Ryan Lerch |
e2f045 |
if find_similar and diff:
|
|
Ryan Lerch |
e2f045 |
diff.find_similar()
|
|
Ryan Lerch |
e2f045 |
|
|
Pierre-Yves Chibon |
4b90cc |
if diff_view:
|
|
Pierre-Yves Chibon |
86e455 |
if separated:
|
|
Pierre-Yves Chibon |
9c2953 |
for el in diff.patch.split("\ndiff --git a/"):
|
|
Pierre-Yves Chibon |
9c2953 |
if el and not el.startswith("diff --git a/"):
|
|
Pierre-Yves Chibon |
9c2953 |
patch.append("\ndiff --git a/" + el)
|
|
Pierre-Yves Chibon |
ed25f0 |
elif el:
|
|
Pierre-Yves Chibon |
ed25f0 |
patch.append(el)
|
|
Pierre-Yves Chibon |
86e455 |
else:
|
|
Pierre-Yves Chibon |
86e455 |
patch.append(diff.patch)
|
|
Pierre-Yves Chibon |
a27356 |
else:
|
|
Pierre-Yves Chibon |
a27356 |
|
|
Pierre-Yves Chibon |
9c2953 |
subject = message = ""
|
|
Pierre-Yves Chibon |
9c2953 |
if "\n" in commit.message:
|
|
Pierre-Yves Chibon |
9c2953 |
subject, message = commit.message.split("\n", 1)
|
|
Pierre-Yves Chibon |
4b90cc |
else:
|
|
Pierre-Yves Chibon |
4b90cc |
subject = commit.message
|
|
Pierre-Yves Chibon |
4b90cc |
|
|
Pierre-Yves Chibon |
4b90cc |
if len(commits) > 1:
|
|
Pierre-Yves Chibon |
9c2953 |
subject = "[PATCH %s/%s] %s" % (cnt + 1, len(commits), subject)
|
|
Pierre-Yves Chibon |
a27356 |
|
|
Pierre-Yves Chibon |
9c2953 |
patch.append(
|
|
Pierre-Yves Chibon |
9c2953 |
"""From {commit} Mon Sep 17 00:00:00 2001
|
|
Pierre-Yves Chibon |
b8c7ae |
From: {author_name} <{author_email}>
|
|
Pierre-Yves Chibon |
b8c7ae |
Date: {date}
|
|
Pierre-Yves Chibon |
b8c7ae |
Subject: {subject}
|
|
Pierre-Yves Chibon |
a27356 |
|
|
Pierre-Yves Chibon |
b8c7ae |
{msg}
|
|
Pierre-Yves Chibon |
a27356 |
---
|
|
Pierre-Yves Chibon |
a27356 |
|
|
Pierre-Yves Chibon |
b8c7ae |
{patch}
|
|
Pierre-Yves Chibon |
4b90cc |
""".format(
|
|
Pierre-Yves Chibon |
9c2953 |
commit=commit.oid.hex,
|
|
Pierre-Yves Chibon |
9c2953 |
author_name=commit.author.name,
|
|
Pierre-Yves Chibon |
9c2953 |
author_email=commit.author.email,
|
|
Pierre-Yves Chibon |
9c2953 |
date=datetime.datetime.utcfromtimestamp(
|
|
Pierre-Yves Chibon |
9c2953 |
commit.commit_time
|
|
Pierre-Yves Chibon |
9c2953 |
).strftime("%b %d %Y %H:%M:%S +0000"),
|
|
Pierre-Yves Chibon |
9c2953 |
subject=subject,
|
|
Pierre-Yves Chibon |
9c2953 |
msg=message,
|
|
Pierre-Yves Chibon |
9c2953 |
patch=diff.patch,
|
|
Pierre-Yves Chibon |
9c2953 |
)
|
|
Pierre-Yves Chibon |
9c2953 |
)
|
|
Pierre-Yves Chibon |
86e455 |
|
|
Pierre-Yves Chibon |
86e455 |
if separated:
|
|
Pierre-Yves Chibon |
86e455 |
return patch
|
|
Pierre-Yves Chibon |
86e455 |
else:
|
|
Julen Landa Alustiza |
05156b |
return "".join(filter(None, patch))
|
|
Pierre-Yves Chibon |
459834 |
|
|
Pierre-Yves Chibon |
459834 |
|
|
Pierre-Yves Chibon |
ccb160 |
def generate_gitolite_acls(project=None, group=None):
|
|
Pierre-Yves Chibon |
274e60 |
""" Generate the gitolite configuration file.
|
|
Pierre-Yves Chibon |
274e60 |
|
|
Pierre-Yves Chibon |
274e60 |
:arg project: the project of which to update the ACLs. This argument
|
|
Pierre-Yves Chibon |
274e60 |
can take three values: ``-1``, ``None`` and a project.
|
|
Pierre-Yves Chibon |
274e60 |
If project is ``-1``, the configuration should be refreshed for
|
|
Pierre-Yves Chibon |
274e60 |
*all* projects.
|
|
Pierre-Yves Chibon |
274e60 |
If project is ``None``, there no specific project to refresh
|
|
Pierre-Yves Chibon |
274e60 |
but the ssh key of an user was added and updated.
|
|
Pierre-Yves Chibon |
274e60 |
If project is a pagure.lib.model.Project, the configuration of
|
|
Pierre-Yves Chibon |
274e60 |
this project should be updated.
|
|
Pierre-Yves Chibon |
274e60 |
:type project: None, int or pagure.lib.model.Project
|
|
Pierre-Yves Chibon |
ccb160 |
:kwarg group: the group to refresh the members of
|
|
Pierre-Yves Chibon |
ccb160 |
:type group: None or str
|
|
Pierre-Yves Chibon |
274e60 |
|
|
Pierre-Yves Chibon |
274e60 |
"""
|
|
Pierre-Yves Chibon |
274e60 |
if project != -1:
|
|
Pierre-Yves Chibon |
eb5f49 |
task = pagure.lib.tasks.generate_gitolite_acls.delay(
|
|
Pierre-Yves Chibon |
274e60 |
namespace=project.namespace if project else None,
|
|
Pierre-Yves Chibon |
274e60 |
name=project.name if project else None,
|
|
Pierre-Yves Chibon |
ccb160 |
user=project.user.user if project and project.is_fork else None,
|
|
Pierre-Yves Chibon |
9c2953 |
group=group,
|
|
Pierre-Yves Chibon |
274e60 |
)
|
|
Pierre-Yves Chibon |
274e60 |
else:
|
|
Pierre-Yves Chibon |
eb5f49 |
task = pagure.lib.tasks.generate_gitolite_acls.delay(
|
|
Pierre-Yves Chibon |
eb5f49 |
name=-1, group=group
|
|
Pierre-Yves Chibon |
eb5f49 |
)
|
|
Pierre-Yves Chibon |
f629e8 |
return task
|
|
Patrick Uiterwijk |
4e3dbd |
|
|
Patrick Uiterwijk |
4e3dbd |
|
|
Patrick Uiterwijk |
3f97f6 |
def update_git(obj, repo):
|
|
Patrick Uiterwijk |
8e1ee6 |
""" Schedules an update_repo task after determining arguments. """
|
|
Patrick Uiterwijk |
8e1ee6 |
ticketuid = None
|
|
Patrick Uiterwijk |
8e1ee6 |
requestuid = None
|
|
Pierre-Yves Chibon |
9c2953 |
if obj.isa == "issue":
|
|
Patrick Uiterwijk |
8e1ee6 |
ticketuid = obj.uid
|
|
Pierre-Yves Chibon |
9c2953 |
elif obj.isa == "pull-request":
|
|
Patrick Uiterwijk |
8e1ee6 |
requestuid = obj.uid
|
|
Patrick Uiterwijk |
8e1ee6 |
else:
|
|
Pierre-Yves Chibon |
9c2953 |
raise NotImplementedError("Unknown object type %s" % obj.isa)
|
|
Patrick Uiterwijk |
8e1ee6 |
|
|
Patrick Uiterwijk |
b71da2 |
queued = pagure.lib.tasks.update_git.delay(
|
|
Pierre-Yves Chibon |
9c2953 |
repo.name,
|
|
Pierre-Yves Chibon |
9c2953 |
repo.namespace,
|
|
Patrick Uiterwijk |
eb9395 |
repo.user.username if repo.is_fork else None,
|
|
Pierre-Yves Chibon |
9c2953 |
ticketuid,
|
|
Pierre-Yves Chibon |
9c2953 |
requestuid,
|
|
Pierre-Yves Chibon |
9c2953 |
)
|
|
Patrick Uiterwijk |
b71da2 |
_maybe_wait(queued)
|
|
Patrick Uiterwijk |
b71da2 |
return queued
|
|
Patrick Uiterwijk |
b71da2 |
|
|
Patrick Uiterwijk |
b71da2 |
|
|
Patrick Uiterwijk |
b71da2 |
def _maybe_wait(result):
|
|
Patrick Uiterwijk |
b71da2 |
""" Function to patch if one wants to wait for finish.
|
|
Patrick Uiterwijk |
b71da2 |
|
|
Pierre-Yves Chibon |
8312e7 |
This function should only ever be overridden by a few tests that depend
|
|
Pierre-Yves Chibon |
8312e7 |
on counting and very precise timing. """
|
|
Patrick Uiterwijk |
b71da2 |
pass
|
|
Patrick Uiterwijk |
8e1ee6 |
|
|
Patrick Uiterwijk |
8e1ee6 |
|
|
Aurélien Bompard |
831553 |
def _make_signature(name, email):
|
|
Aurélien Bompard |
831553 |
if six.PY2:
|
|
Aurélien Bompard |
831553 |
if isinstance(name, six.text_type):
|
|
Aurélien Bompard |
831553 |
name = name.encode("utf-8")
|
|
Aurélien Bompard |
831553 |
if isinstance(email, six.text_type):
|
|
Aurélien Bompard |
831553 |
email = email.encode("utf-8")
|
|
Aurélien Bompard |
831553 |
return pygit2.Signature(name=name, email=email)
|
|
Aurélien Bompard |
831553 |
|
|
Aurélien Bompard |
831553 |
|
|
Patrick Uiterwijk |
3f97f6 |
def _update_git(obj, repo):
|
|
Pierre-Yves Chibon |
c8b13b |
""" Update the given issue in its git.
|
|
Pierre-Yves Chibon |
c8b13b |
|
|
Pierre-Yves Chibon |
c8b13b |
This method forks the provided repo, add/edit the issue whose file name
|
|
Pierre-Yves Chibon |
c8b13b |
is defined by the uid field of the issue and if there are additions/
|
|
Pierre-Yves Chibon |
c8b13b |
changes commit them and push them back to the original repo.
|
|
Pierre-Yves Chibon |
c8b13b |
|
|
Pierre-Yves Chibon |
c8b13b |
"""
|
|
Pierre-Yves Chibon |
9c2953 |
_log.info("Update the git repo: %s for: %s", repo.path, obj)
|
|
Pierre-Yves Chibon |
c8b13b |
|
|
Patrick Uiterwijk |
3f97f6 |
with TemporaryClone(repo, obj.repotype, "update_git") as tempclone:
|
|
Patrick Uiterwijk |
3f97f6 |
if tempclone is None:
|
|
Patrick Uiterwijk |
3f97f6 |
# Turns out we don't have a repo for this kind of object.
|
|
Patrick Uiterwijk |
3f97f6 |
return
|
|
Pierre-Yves Chibon |
c8b13b |
|
|
Patrick Uiterwijk |
3f97f6 |
newpath = tempclone.repopath
|
|
Patrick Uiterwijk |
3f97f6 |
new_repo = tempclone.repo
|
|
Patrick Uiterwijk |
0a0334 |
|
|
Patrick Uiterwijk |
3f97f6 |
file_path = os.path.join(newpath, obj.uid)
|
|
Patrick Uiterwijk |
0a0334 |
|
|
Patrick Uiterwijk |
3f97f6 |
# Get the current index
|
|
Patrick Uiterwijk |
3f97f6 |
index = new_repo.index
|
|
Patrick Uiterwijk |
0a0334 |
|
|
Patrick Uiterwijk |
3f97f6 |
# Are we adding files
|
|
Patrick Uiterwijk |
3f97f6 |
added = False
|
|
Patrick Uiterwijk |
3f97f6 |
if not os.path.exists(file_path):
|
|
Patrick Uiterwijk |
3f97f6 |
added = True
|
|
Patrick Uiterwijk |
0a0334 |
|
|
Patrick Uiterwijk |
3f97f6 |
# Write down what changed
|
|
Patrick Uiterwijk |
3f97f6 |
with open(file_path, "w") as stream:
|
|
Patrick Uiterwijk |
3f97f6 |
stream.write(
|
|
Patrick Uiterwijk |
3f97f6 |
json.dumps(
|
|
Patrick Uiterwijk |
3f97f6 |
obj.to_json(),
|
|
Patrick Uiterwijk |
3f97f6 |
sort_keys=True,
|
|
Patrick Uiterwijk |
3f97f6 |
indent=4,
|
|
Patrick Uiterwijk |
3f97f6 |
separators=(",", ": "),
|
|
Patrick Uiterwijk |
3f97f6 |
)
|
|
Pierre-Yves Chibon |
9c2953 |
)
|
|
Patrick Uiterwijk |
0a0334 |
|
|
Patrick Uiterwijk |
3f97f6 |
# Retrieve the list of files that changed
|
|
Patrick Uiterwijk |
3f97f6 |
diff = new_repo.diff()
|
|
Patrick Uiterwijk |
3f97f6 |
files = []
|
|
Patrick Uiterwijk |
3f97f6 |
for patch in diff:
|
|
Patrick Uiterwijk |
3f97f6 |
files.append(patch.delta.new_file.path)
|
|
Patrick Uiterwijk |
0a0334 |
|
|
Patrick Uiterwijk |
3f97f6 |
# Add the changes to the index
|
|
Patrick Uiterwijk |
3f97f6 |
if added:
|
|
Patrick Uiterwijk |
3f97f6 |
index.add(obj.uid)
|
|
Patrick Uiterwijk |
3f97f6 |
for filename in files:
|
|
Patrick Uiterwijk |
3f97f6 |
index.add(filename)
|
|
Patrick Uiterwijk |
0a0334 |
|
|
Patrick Uiterwijk |
3f97f6 |
# If not change, return
|
|
Patrick Uiterwijk |
3f97f6 |
if not files and not added:
|
|
Patrick Uiterwijk |
3f97f6 |
return
|
|
Patrick Uiterwijk |
0a0334 |
|
|
Patrick Uiterwijk |
3f97f6 |
# See if there is a parent to this commit
|
|
Patrick Uiterwijk |
3f97f6 |
parent = None
|
|
Patrick Uiterwijk |
3f97f6 |
try:
|
|
Pierre-Yves Chibon |
29ff0a |
parent = new_repo.head.peel().oid
|
|
Patrick Uiterwijk |
3f97f6 |
except pygit2.GitError:
|
|
Patrick Uiterwijk |
3f97f6 |
pass
|
|
Pierre-Yves Chibon |
08eaf8 |
|
|
Patrick Uiterwijk |
3f97f6 |
parents = []
|
|
Patrick Uiterwijk |
3f97f6 |
if parent:
|
|
Patrick Uiterwijk |
3f97f6 |
parents.append(parent)
|
|
Patrick Uiterwijk |
3f97f6 |
|
|
Patrick Uiterwijk |
3f97f6 |
# Author/commiter will always be this one
|
|
Patrick Uiterwijk |
3f97f6 |
author = _make_signature(name="pagure", email="pagure")
|
|
Patrick Uiterwijk |
3f97f6 |
|
|
Patrick Uiterwijk |
3f97f6 |
# Actually commit
|
|
Patrick Uiterwijk |
3f97f6 |
new_repo.create_commit(
|
|
Patrick Uiterwijk |
3f97f6 |
"refs/heads/master",
|
|
Patrick Uiterwijk |
3f97f6 |
author,
|
|
Patrick Uiterwijk |
3f97f6 |
author,
|
|
Patrick Uiterwijk |
3f97f6 |
"Updated %s %s: %s" % (obj.isa, obj.uid, obj.title),
|
|
Patrick Uiterwijk |
3f97f6 |
new_repo.index.write_tree(),
|
|
Patrick Uiterwijk |
3f97f6 |
parents,
|
|
Patrick Uiterwijk |
3f97f6 |
)
|
|
Patrick Uiterwijk |
3f97f6 |
index.write()
|
|
Pierre-Yves Chibon |
c7f9fa |
|
|
Patrick Uiterwijk |
3f97f6 |
# And push it back
|
|
Patrick Uiterwijk |
03a519 |
tempclone.push("pagure", "master", internal="yes")
|
|
Pierre-Yves Chibon |
c7f9fa |
|
|
Patrick Uiterwijk |
84b223 |
|
|
Patrick Uiterwijk |
3f97f6 |
def clean_git(repo, obj_repotype, obj_uid):
|
|
Patrick Uiterwijk |
3f97f6 |
if repo is None:
|
|
Patrick Uiterwijk |
3f97f6 |
return
|
|
Patrick Uiterwijk |
189fa8 |
|
|
Patrick Uiterwijk |
3f97f6 |
task = pagure.lib.tasks.clean_git.delay(
|
|
Pierre-Yves Chibon |
9c2953 |
repo.name,
|
|
Pierre-Yves Chibon |
9c2953 |
repo.namespace,
|
|
Patrick Uiterwijk |
fce947 |
repo.user.username if repo.is_fork else None,
|
|
Patrick Uiterwijk |
3f97f6 |
obj_repotype,
|
|
Patrick Uiterwijk |
3f97f6 |
obj_uid,
|
|
Pierre-Yves Chibon |
9c2953 |
)
|
|
Patrick Uiterwijk |
3f97f6 |
_maybe_wait(task)
|
|
Patrick Uiterwijk |
3f97f6 |
return task
|
|
Patrick Uiterwijk |
189fa8 |
|
|
Patrick Uiterwijk |
189fa8 |
|
|
Patrick Uiterwijk |
3f97f6 |
def _clean_git(repo, obj_repotype, obj_uid):
|
|
Pierre-Yves Chibon |
83115e |
""" Update the given issue remove it from its git.
|
|
Pierre-Yves Chibon |
83115e |
|
|
Pierre-Yves Chibon |
83115e |
"""
|
|
Patrick Uiterwijk |
3f97f6 |
_log.info("Update the git repo: %s to remove: %s", repo.path, obj_uid)
|
|
Pierre-Yves Chibon |
83115e |
|
|
Patrick Uiterwijk |
3f97f6 |
with TemporaryClone(repo, obj_repotype, "clean_git") as tempclone:
|
|
Patrick Uiterwijk |
3f97f6 |
if tempclone is None:
|
|
Patrick Uiterwijk |
3f97f6 |
# This repo is not tracked on disk
|
|
Patrick Uiterwijk |
3f97f6 |
return
|
|
Pierre-Yves Chibon |
b73de8 |
|
|
Patrick Uiterwijk |
3f97f6 |
newpath = tempclone.repopath
|
|
Patrick Uiterwijk |
3f97f6 |
new_repo = tempclone.repo
|
|
Pierre-Yves Chibon |
83115e |
|
|
Patrick Uiterwijk |
3f97f6 |
file_path = os.path.join(newpath, obj_uid)
|
|
Pierre-Yves Chibon |
eccb1c |
|
|
Patrick Uiterwijk |
3f97f6 |
# Get the current index
|
|
Patrick Uiterwijk |
3f97f6 |
index = new_repo.index
|
|
Pierre-Yves Chibon |
83115e |
|
|
Patrick Uiterwijk |
3f97f6 |
# Are we adding files
|
|
Patrick Uiterwijk |
3f97f6 |
if not os.path.exists(file_path):
|
|
Patrick Uiterwijk |
3f97f6 |
return
|
|
Pierre-Yves Chibon |
83115e |
|
|
Patrick Uiterwijk |
3f97f6 |
# Remove the file
|
|
Patrick Uiterwijk |
3f97f6 |
os.unlink(file_path)
|
|
Pierre-Yves Chibon |
83115e |
|
|
Patrick Uiterwijk |
3f97f6 |
# Add the changes to the index
|
|
Patrick Uiterwijk |
3f97f6 |
index.remove(obj_uid)
|
|
Pierre-Yves Chibon |
83115e |
|
|
Patrick Uiterwijk |
3f97f6 |
# See if there is a parent to this commit
|
|
Patrick Uiterwijk |
3f97f6 |
parent = None
|
|
Patrick Uiterwijk |
3f97f6 |
if not new_repo.is_empty:
|
|
Pierre-Yves Chibon |
29ff0a |
parent = new_repo.head.peel().oid
|
|
Patrick Uiterwijk |
3f97f6 |
|
|
Patrick Uiterwijk |
3f97f6 |
parents = []
|
|
Patrick Uiterwijk |
3f97f6 |
if parent:
|
|
Patrick Uiterwijk |
3f97f6 |
parents.append(parent)
|
|
Patrick Uiterwijk |
3f97f6 |
|
|
Patrick Uiterwijk |
3f97f6 |
# Author/commiter will always be this one
|
|
Patrick Uiterwijk |
3f97f6 |
author = _make_signature(name="pagure", email="pagure")
|
|
Patrick Uiterwijk |
3f97f6 |
|
|
Patrick Uiterwijk |
3f97f6 |
# Actually commit
|
|
Patrick Uiterwijk |
3f97f6 |
new_repo.create_commit(
|
|
Patrick Uiterwijk |
3f97f6 |
"refs/heads/master",
|
|
Patrick Uiterwijk |
3f97f6 |
author,
|
|
Patrick Uiterwijk |
3f97f6 |
author,
|
|
Patrick Uiterwijk |
3f97f6 |
"Removed object %s: %s" % (obj_repotype, obj_uid),
|
|
Patrick Uiterwijk |
3f97f6 |
new_repo.index.write_tree(),
|
|
Patrick Uiterwijk |
3f97f6 |
parents,
|
|
Patrick Uiterwijk |
3f97f6 |
)
|
|
Patrick Uiterwijk |
3f97f6 |
index.write()
|
|
Patrick Uiterwijk |
0a0334 |
|
|
Patrick Uiterwijk |
3f97f6 |
master_ref = new_repo.lookup_reference("HEAD").resolve().name
|
|
Patrick Uiterwijk |
03a519 |
tempclone.push("pagure", master_ref, internal="yes")
|
|
Pierre-Yves Chibon |
774fee |
|
|
Pierre-Yves Chibon |
83115e |
|
|
Pierre-Yves Chibon |
9c2953 |
def get_user_from_json(session, jsondata, key="user"):
|
|
Pierre-Yves Chibon |
c7f9fa |
""" From the given json blob, retrieve the user info and search for it
|
|
Pierre-Yves Chibon |
c7f9fa |
in the db and create the user if it does not already exist.
|
|
Pierre-Yves Chibon |
c7f9fa |
"""
|
|
Pierre-Yves Chibon |
c7f9fa |
user = None
|
|
Pierre-Yves Chibon |
c7f9fa |
|
|
Pierre-Yves Chibon |
ae1e93 |
username = fullname = useremails = default_email = None
|
|
Pierre-Yves Chibon |
67357e |
|
|
Pierre-Yves Chibon |
441f62 |
data = jsondata.get(key, None)
|
|
Pierre-Yves Chibon |
67357e |
|
|
Pierre-Yves Chibon |
ae1e93 |
if data:
|
|
Pierre-Yves Chibon |
9c2953 |
username = data.get("name")
|
|
Pierre-Yves Chibon |
9c2953 |
fullname = data.get("fullname")
|
|
Pierre-Yves Chibon |
9c2953 |
useremails = data.get("emails")
|
|
Pierre-Yves Chibon |
9c2953 |
default_email = data.get("default_email")
|
|
Pierre-Yves Chibon |
67357e |
|
|
Pierre-Yves Chibon |
67357e |
if not default_email and useremails:
|
|
Pierre-Yves Chibon |
67357e |
default_email = useremails[0]
|
|
Pierre-Yves Chibon |
67357e |
|
|
Pierre-Yves Chibon |
ac2bce |
if not username and not useremails:
|
|
Pierre-Yves Chibon |
ac2bce |
return
|
|
Pierre-Yves Chibon |
ac2bce |
|
|
Pierre-Yves Chibon |
930073 |
user = pagure.lib.query.search_user(session, username=username)
|
|
Pierre-Yves Chibon |
c7f9fa |
if not user:
|
|
Pierre-Yves Chibon |
c7f9fa |
for email in useremails:
|
|
Pierre-Yves Chibon |
930073 |
user = pagure.lib.query.search_user(session, email=email)
|
|
Pierre-Yves Chibon |
c7f9fa |
if user:
|
|
Pierre-Yves Chibon |
c7f9fa |
break
|
|
Pierre-Yves Chibon |
c7f9fa |
|
|
Pierre-Yves Chibon |
c7f9fa |
if not user:
|
|
Pierre-Yves Chibon |
930073 |
user = pagure.lib.query.set_up_user(
|
|
Pierre-Yves Chibon |
c7f9fa |
session=session,
|
|
Pierre-Yves Chibon |
c7f9fa |
username=username,
|
|
Pierre-Yves Chibon |
c7f9fa |
fullname=fullname or username,
|
|
Pierre-Yves Chibon |
96eb13 |
default_email=default_email,
|
|
Pierre-Yves Chibon |
96eb13 |
emails=useremails,
|
|
Pierre-Yves Chibon |
9c2953 |
keydir=pagure_config.get("GITOLITE_KEYDIR", None),
|
|
Pierre-Yves Chibon |
c7f9fa |
)
|
|
Pierre-Yves Chibon |
c7f9fa |
session.commit()
|
|
Pierre-Yves Chibon |
c7f9fa |
|
|
Pierre-Yves Chibon |
c7f9fa |
return user
|
|
Pierre-Yves Chibon |
c7f9fa |
|
|
Pierre-Yves Chibon |
c7f9fa |
|
|
Pierre-Yves Chibon |
50d6b6 |
def get_project_from_json(session, jsondata):
|
|
Pierre-Yves Chibon |
a6c9f2 |
""" From the given json blob, retrieve the project info and search for
|
|
Pierre-Yves Chibon |
a6c9f2 |
it in the db and create the projec if it does not already exist.
|
|
Pierre-Yves Chibon |
a6c9f2 |
"""
|
|
Pierre-Yves Chibon |
a6c9f2 |
project = None
|
|
Pierre-Yves Chibon |
a6c9f2 |
|
|
Pierre-Yves Chibon |
a6c9f2 |
user = get_user_from_json(session, jsondata)
|
|
Pierre-Yves Chibon |
9c2953 |
name = jsondata.get("name")
|
|
Pierre-Yves Chibon |
9c2953 |
namespace = jsondata.get("namespace")
|
|
Pierre-Yves Chibon |
a6c9f2 |
project_user = None
|
|
Pierre-Yves Chibon |
9c2953 |
if jsondata.get("parent"):
|
|
Pierre-Yves Chibon |
a6c9f2 |
project_user = user.username
|
|
Pierre-Yves Chibon |
edbdc9 |
|
|
Pierre-Yves Chibon |
930073 |
project = pagure.lib.query._get_project(
|
|
Pierre-Yves Chibon |
9c2953 |
session, name, user=project_user, namespace=namespace
|
|
Pierre-Yves Chibon |
9c2953 |
)
|
|
Pierre-Yves Chibon |
a6c9f2 |
|
|
Pierre-Yves Chibon |
a6c9f2 |
if not project:
|
|
Pierre-Yves Chibon |
a6c9f2 |
parent = None
|
|
Pierre-Yves Chibon |
9c2953 |
if jsondata.get("parent"):
|
|
Pierre-Yves Chibon |
9c2953 |
parent = get_project_from_json(session, jsondata.get("parent"))
|
|
Pierre-Yves Chibon |
a6c9f2 |
|
|
Pierre-Yves Chibon |
930073 |
pagure.lib.query.fork_project(
|
|
Patrick Uiterwijk |
3f97f6 |
session=session, repo=parent, user=user.username
|
|
Pierre-Yves Chibon |
9c2953 |
)
|
|
Pierre-Yves Chibon |
824828 |
|
|
Pierre-Yves Chibon |
824828 |
else:
|
|
Pierre-Yves Chibon |
930073 |
pagure.lib.query.new_project(
|
|
Pierre-Yves Chibon |
824828 |
session,
|
|
Pierre-Yves Chibon |
824828 |
user=user.username,
|
|
Pierre-Yves Chibon |
824828 |
name=name,
|
|
clime |
afed57 |
namespace=namespace,
|
|
Patrick Uiterwijk |
3f97f6 |
repospanner_region=None,
|
|
Pierre-Yves Chibon |
9c2953 |
description=jsondata.get("description"),
|
|
Pierre-Yves Chibon |
824828 |
parent_id=parent.id if parent else None,
|
|
Pierre-Yves Chibon |
9c2953 |
blacklist=pagure_config.get("BLACKLISTED_PROJECTS", []),
|
|
Pierre-Yves Chibon |
9c2953 |
allowed_prefix=pagure_config.get("ALLOWED_PREFIX", []),
|
|
Pierre-Yves Chibon |
b130e5 |
prevent_40_chars=pagure_config.get(
|
|
Pierre-Yves Chibon |
9c2953 |
"OLD_VIEW_COMMIT_ENABLED", False
|
|
Pierre-Yves Chibon |
9c2953 |
),
|
|
Pierre-Yves Chibon |
824828 |
)
|
|
Pierre-Yves Chibon |
a6c9f2 |
|
|
Pierre-Yves Chibon |
a6c9f2 |
session.commit()
|
|
Pierre-Yves Chibon |
930073 |
project = pagure.lib.query._get_project(
|
|
Pierre-Yves Chibon |
9c2953 |
session, name, user=user.username, namespace=namespace
|
|
Pierre-Yves Chibon |
9c2953 |
)
|
|
clime |
afed57 |
|
|
Pierre-Yves Chibon |
9c2953 |
tags = jsondata.get("tags", None)
|
|
Pierre-Yves Chibon |
513113 |
if tags:
|
|
Pierre-Yves Chibon |
930073 |
pagure.lib.query.add_tag_obj(
|
|
Patrick Uiterwijk |
3f97f6 |
session, project, tags=tags, user=user.username
|
|
Pierre-Yves Chibon |
9c2953 |
)
|
|
Pierre-Yves Chibon |
a6c9f2 |
|
|
Pierre-Yves Chibon |
a6c9f2 |
return project
|
|
Pierre-Yves Chibon |
a6c9f2 |
|
|
Pierre-Yves Chibon |
a6c9f2 |
|
|
Pierre-Yves Chibon |
1878ce |
def update_custom_field_from_json(session, repo, issue, json_data):
|
|
Pierre-Yves Chibon |
9c2953 |
""" Update the custom fields according to the custom fields of
|
|
Vivek Anand |
50c877 |
the issue. If the custom field is not present for the repo in
|
|
Vivek Anand |
50c877 |
it's settings, this will create them.
|
|
Vivek Anand |
50c877 |
|
|
Vivek Anand |
50c877 |
:arg session: the session to connect to the database with.
|
|
Vivek Anand |
50c877 |
:arg repo: the sqlalchemy object of the project
|
|
Vivek Anand |
50c877 |
:arg issue: the sqlalchemy object of the issue
|
|
Vivek Anand |
50c877 |
:arg json_data: the json representation of the issue taken from the git
|
|
Vivek Anand |
50c877 |
and used to update the data in the database.
|
|
Pierre-Yves Chibon |
9c2953 |
"""
|
|
Vivek Anand |
50c877 |
|
|
Vivek Anand |
50c877 |
# Update custom key value, if present
|
|
Pierre-Yves Chibon |
9c2953 |
custom_fields = json_data.get("custom_fields")
|
|
Vivek Anand |
50c877 |
if not custom_fields:
|
|
Vivek Anand |
50c877 |
return
|
|
Vivek Anand |
50c877 |
|
|
Vivek Anand |
50c877 |
current_keys = []
|
|
Vivek Anand |
50c877 |
for key in repo.issue_keys:
|
|
Vivek Anand |
50c877 |
current_keys.append(key.name)
|
|
Vivek Anand |
50c877 |
|
|
Vivek Anand |
50c877 |
for new_key in custom_fields:
|
|
Pierre-Yves Chibon |
9c2953 |
if new_key["name"] not in current_keys:
|
|
Vivek Anand |
50c877 |
issuekey = model.IssueKeys(
|
|
Vivek Anand |
50c877 |
project_id=repo.id,
|
|
Pierre-Yves Chibon |
9c2953 |
name=new_key["name"],
|
|
Pierre-Yves Chibon |
9c2953 |
key_type=new_key["key_type"],
|
|
Vivek Anand |
50c877 |
)
|
|
Vivek Anand |
50c877 |
try:
|
|
Vivek Anand |
50c877 |
session.add(issuekey)
|
|
Vivek Anand |
50c877 |
session.commit()
|
|
Vivek Anand |
50c877 |
except SQLAlchemyError:
|
|
Vivek Anand |
50c877 |
session.rollback()
|
|
Vivek Anand |
50c877 |
continue
|
|
Vivek Anand |
50c877 |
|
|
Vivek Anand |
50c877 |
# The key should be present in the database now
|
|
Pierre-Yves Chibon |
930073 |
key_obj = pagure.lib.query.get_custom_key(
|
|
Pierre-Yves Chibon |
930073 |
session, repo, new_key["name"]
|
|
Pierre-Yves Chibon |
930073 |
)
|
|
Vivek Anand |
50c877 |
|
|
Pierre-Yves Chibon |
9c2953 |
value = new_key.get("value")
|
|
Vivek Anand |
50c877 |
if value:
|
|
Vivek Anand |
50c877 |
value = value.strip()
|
|
Pierre-Yves Chibon |
930073 |
pagure.lib.query.set_custom_key_value(
|
|
Pierre-Yves Chibon |
9c2953 |
session, issue=issue, key=key_obj, value=value
|
|
Vivek Anand |
50c877 |
)
|
|
Vivek Anand |
50c877 |
try:
|
|
Vivek Anand |
50c877 |
session.commit()
|
|
Vivek Anand |
50c877 |
except SQLAlchemyError:
|
|
Vivek Anand |
50c877 |
session.rollback()
|
|
Vivek Anand |
50c877 |
|
|
Vivek Anand |
50c877 |
|
|
Pierre-Yves Chibon |
c7f9fa |
def update_ticket_from_git(
|
|
Pierre-Yves Chibon |
9c2953 |
session, reponame, namespace, username, issue_uid, json_data, agent
|
|
Pierre-Yves Chibon |
9c2953 |
):
|
|
Pierre-Yves Chibon |
c7f9fa |
""" Update the specified issue (identified by its unique identifier)
|
|
Pierre-Yves Chibon |
c7f9fa |
with the data present in the json blob provided.
|
|
Pierre-Yves Chibon |
c7f9fa |
|
|
Pierre-Yves Chibon |
c7f9fa |
:arg session: the session to connect to the database with.
|
|
Pierre-Yves Chibon |
c7f9fa |
:arg repo: the name of the project to update
|
|
Pierre-Yves Chibon |
b7eec1 |
:arg namespace: the namespace of the project to update
|
|
Pierre-Yves Chibon |
b7eec1 |
:arg username: the username of the project to update (if the project
|
|
Pierre-Yves Chibon |
b7eec1 |
is a fork)
|
|
Pierre-Yves Chibon |
c7f9fa |
:arg issue_uid: the unique identifier of the issue to update
|
|
Pierre-Yves Chibon |
c7f9fa |
:arg json_data: the json representation of the issue taken from the git
|
|
Pierre-Yves Chibon |
c7f9fa |
and used to update the data in the database.
|
|
Pierre-Yves Chibon |
b7eec1 |
:arg agent: the username of the person who pushed the changes (and thus
|
|
Pierre-Yves Chibon |
b7eec1 |
is assumed did the action).
|
|
Pierre-Yves Chibon |
c7f9fa |
|
|
Pierre-Yves Chibon |
c7f9fa |
"""
|
|
Pierre-Yves Chibon |
c7f9fa |
|
|
Pierre-Yves Chibon |
930073 |
repo = pagure.lib.query._get_project(
|
|
Pierre-Yves Chibon |
9c2953 |
session, reponame, user=username, namespace=namespace
|
|
Pierre-Yves Chibon |
9c2953 |
)
|
|
Farhaan Bukhsh |
8267d1 |
|
|
Pierre-Yves Chibon |
c7f9fa |
if not repo:
|
|
Pierre-Yves Chibon |
fe5017 |
raise pagure.exceptions.PagureException(
|
|
Pierre-Yves Chibon |
9c2953 |
"Unknown repo %s of username: %s in namespace: %s"
|
|
Pierre-Yves Chibon |
9c2953 |
% (reponame, username, namespace)
|
|
Pierre-Yves Chibon |
9c2953 |
)
|
|
Pierre-Yves Chibon |
c7f9fa |
|
|
Pierre-Yves Chibon |
c7f9fa |
user = get_user_from_json(session, json_data)
|
|
Pierre-Yves Chibon |
b7eec1 |
# rely on the agent provided, but if something goes wrong, behave as
|
|
Pierre-Yves Chibon |
b7eec1 |
# ticket creator
|
|
Pierre-Yves Chibon |
930073 |
agent = pagure.lib.query.search_user(session, username=agent) or user
|
|
Pierre-Yves Chibon |
c7f9fa |
|
|
Pierre-Yves Chibon |
930073 |
issue = pagure.lib.query.get_issue_by_uid(session, issue_uid=issue_uid)
|
|
Pierre-Yves Chibon |
1878ce |
messages = []
|
|
Pierre-Yves Chibon |
c7f9fa |
if not issue:
|
|
Pierre-Yves Chibon |
c7f9fa |
# Create new issue
|
|
Pierre-Yves Chibon |
930073 |
pagure.lib.query.new_issue(
|
|
Pierre-Yves Chibon |
c7f9fa |
session,
|
|
Pierre-Yves Chibon |
c7f9fa |
repo=repo,
|
|
Pierre-Yves Chibon |
9c2953 |
title=json_data.get("title"),
|
|
Pierre-Yves Chibon |
9c2953 |
content=json_data.get("content"),
|
|
Pierre-Yves Chibon |
9c2953 |
priority=json_data.get("priority"),
|
|
Pierre-Yves Chibon |
c7f9fa |
user=user.username,
|
|
Pierre-Yves Chibon |
9c2953 |
issue_id=json_data.get("id"),
|
|
Pierre-Yves Chibon |
c7f9fa |
issue_uid=issue_uid,
|
|
Pierre-Yves Chibon |
9c2953 |
private=json_data.get("private"),
|
|
Pierre-Yves Chibon |
9c2953 |
status=json_data.get("status"),
|
|
Pierre-Yves Chibon |
9c2953 |
close_status=json_data.get("close_status"),
|
|
Clement Verna |
f45e89 |
date_created=datetime.datetime.utcfromtimestamp(
|
|
Pierre-Yves Chibon |
9c2953 |
float(json_data.get("date_created"))
|
|
Pierre-Yves Chibon |
9c2953 |
),
|
|
Pierre-Yves Chibon |
c7f9fa |
notify=False,
|
|
Pierre-Yves Chibon |
c7f9fa |
)
|
|
Pierre-Yves Chibon |
c7f9fa |
|
|
Pierre-Yves Chibon |
c7f9fa |
else:
|
|
Pierre-Yves Chibon |
c7f9fa |
# Edit existing issue
|
|
Pierre-Yves Chibon |
930073 |
msgs = pagure.lib.query.edit_issue(
|
|
Pierre-Yves Chibon |
c7f9fa |
session,
|
|
Pierre-Yves Chibon |
c7f9fa |
issue=issue,
|
|
Pierre-Yves Chibon |
b7eec1 |
user=agent.username,
|
|
Pierre-Yves Chibon |
9c2953 |
title=json_data.get("title"),
|
|
Pierre-Yves Chibon |
9c2953 |
content=json_data.get("content"),
|
|
Pierre-Yves Chibon |
9c2953 |
priority=json_data.get("priority"),
|
|
Pierre-Yves Chibon |
9c2953 |
status=json_data.get("status"),
|
|
Pierre-Yves Chibon |
9c2953 |
close_status=json_data.get("close_status"),
|
|
Pierre-Yves Chibon |
9c2953 |
private=json_data.get("private"),
|
|
Pierre-Yves Chibon |
74ab5f |
)
|
|
Pierre-Yves Chibon |
74ab5f |
if msgs:
|
|
Pierre-Yves Chibon |
74ab5f |
messages.extend(msgs)
|
|
Pierre-Yves Chibon |
1878ce |
|
|
Pierre-Yves Chibon |
c7f9fa |
session.commit()
|
|
Pierre-Yves Chibon |
c7f9fa |
|
|
Pierre-Yves Chibon |
930073 |
issue = pagure.lib.query.get_issue_by_uid(session, issue_uid=issue_uid)
|
|
Pierre-Yves Chibon |
c7f9fa |
|
|
Vivek Anand |
50c877 |
update_custom_field_from_json(
|
|
Pierre-Yves Chibon |
9c2953 |
session, repo=repo, issue=issue, json_data=json_data
|
|
Vivek Anand |
50c877 |
)
|
|
Vivek Anand |
50c877 |
|
|
Vivek Anand |
7bf8e2 |
# Update milestone
|
|
Pierre-Yves Chibon |
9c2953 |
milestone = json_data.get("milestone")
|
|
Vivek Anand |
7bf8e2 |
|
|
Vivek Anand |
7bf8e2 |
# If milestone is not in the repo settings, add it
|
|
Vivek Anand |
7bf8e2 |
if milestone:
|
|
Vivek Anand |
7bf8e2 |
if milestone.strip() not in repo.milestones:
|
|
Vivek Anand |
7bf8e2 |
try:
|
|
Clement Verna |
b30f33 |
tmp_milestone = repo.milestones.copy()
|
|
Clement Verna |
b30f33 |
tmp_milestone[milestone.strip()] = None
|
|
Clement Verna |
b30f33 |
repo.milestones = tmp_milestone
|
|
Vivek Anand |
7bf8e2 |
session.add(repo)
|
|
Vivek Anand |
7bf8e2 |
session.commit()
|
|
Vivek Anand |
7bf8e2 |
except SQLAlchemyError:
|
|
Vivek Anand |
7bf8e2 |
session.rollback()
|
|
Vivek Anand |
7bf8e2 |
try:
|
|
Pierre-Yves Chibon |
930073 |
msgs = pagure.lib.query.edit_issue(
|
|
Vivek Anand |
7bf8e2 |
session,
|
|
Vivek Anand |
7bf8e2 |
issue=issue,
|
|
Pierre-Yves Chibon |
b7eec1 |
user=agent.username,
|
|
Vivek Anand |
7bf8e2 |
milestone=milestone,
|
|
Pierre-Yves Chibon |
9c2953 |
title=json_data.get("title"),
|
|
Pierre-Yves Chibon |
9c2953 |
content=json_data.get("content"),
|
|
Pierre-Yves Chibon |
9c2953 |
status=json_data.get("status"),
|
|
Pierre-Yves Chibon |
9c2953 |
close_status=json_data.get("close_status"),
|
|
Pierre-Yves Chibon |
9c2953 |
private=json_data.get("private"),
|
|
Vivek Anand |
7bf8e2 |
)
|
|
Pierre-Yves Chibon |
1878ce |
if msgs:
|
|
Pierre-Yves Chibon |
1878ce |
messages.extend(msgs)
|
|
Vivek Anand |
7bf8e2 |
except SQLAlchemyError:
|
|
Vivek Anand |
7bf8e2 |
session.rollback()
|
|
Vivek Anand |
7bf8e2 |
|
|
Vivek Anand |
1db9ed |
# Update close_status
|
|
Pierre-Yves Chibon |
9c2953 |
close_status = json_data.get("close_status")
|
|
Vivek Anand |
1db9ed |
|
|
Vivek Anand |
1db9ed |
if close_status:
|
|
Vivek Anand |
1db9ed |
if close_status.strip() not in repo.close_status:
|
|
Vivek Anand |
1db9ed |
try:
|
|
Vivek Anand |
1db9ed |
repo.close_status.append(close_status.strip())
|
|
Vivek Anand |
1db9ed |
session.add(repo)
|
|
Vivek Anand |
1db9ed |
session.commit()
|
|
Vivek Anand |
1db9ed |
except SQLAlchemyError:
|
|
Vivek Anand |
1db9ed |
session.rollback()
|
|
Vivek Anand |
1db9ed |
|
|
Pierre-Yves Chibon |
afa3e7 |
# Update tags
|
|
Pierre-Yves Chibon |
9c2953 |
tags = json_data.get("tags", [])
|
|
Pierre-Yves Chibon |
930073 |
msgs = pagure.lib.query.update_tags(
|
|
Pierre-Yves Chibon |
930073 |
session, issue, tags, username=user.user
|
|
Pierre-Yves Chibon |
930073 |
)
|
|
Pierre-Yves Chibon |
74ab5f |
if msgs:
|
|
Pierre-Yves Chibon |
74ab5f |
messages.extend(msgs)
|
|
Pierre-Yves Chibon |
afa3e7 |
|
|
Pierre-Yves Chibon |
95e2ea |
# Update assignee
|
|
Pierre-Yves Chibon |
9c2953 |
assignee = get_user_from_json(session, json_data, key="assignee")
|
|
Pierre-Yves Chibon |
5622fc |
if assignee:
|
|
Pierre-Yves Chibon |
930073 |
msg = pagure.lib.query.add_issue_assignee(
|
|
Patrick Uiterwijk |
3f97f6 |
session, issue, assignee.username, user=agent.user, notify=False
|
|
Pierre-Yves Chibon |
9c2953 |
)
|
|
Pierre-Yves Chibon |
74ab5f |
if msg:
|
|
Pierre-Yves Chibon |
74ab5f |
messages.append(msg)
|
|
Pierre-Yves Chibon |
95e2ea |
|
|
Pierre-Yves Chibon |
afa3e7 |
# Update depends
|
|
Pierre-Yves Chibon |
9c2953 |
depends = json_data.get("depends", [])
|
|
Pierre-Yves Chibon |
930073 |
msgs = pagure.lib.query.update_dependency_issue(
|
|
Patrick Uiterwijk |
3f97f6 |
session, issue.project, issue, depends, username=agent.user
|
|
Pierre-Yves Chibon |
9c2953 |
)
|
|
Pierre-Yves Chibon |
74ab5f |
if msgs:
|
|
Pierre-Yves Chibon |
74ab5f |
messages.extend(msgs)
|
|
Pierre-Yves Chibon |
afa3e7 |
|
|
Pierre-Yves Chibon |
afa3e7 |
# Update blocks
|
|
Pierre-Yves Chibon |
9c2953 |
blocks = json_data.get("blocks", [])
|
|
Pierre-Yves Chibon |
930073 |
msgs = pagure.lib.query.update_blocked_issue(
|
|
Patrick Uiterwijk |
3f97f6 |
session, issue.project, issue, blocks, username=agent.user
|
|
Pierre-Yves Chibon |
9c2953 |
)
|
|
Pierre-Yves Chibon |
74ab5f |
if msgs:
|
|
Pierre-Yves Chibon |
74ab5f |
messages.extend(msgs)
|
|
Pierre-Yves Chibon |
afa3e7 |
|
|
Pierre-Yves Chibon |
9c2953 |
for comment in json_data["comments"]:
|
|
Pierre-Yves Chibon |
74ab5f |
usercomment = get_user_from_json(session, comment)
|
|
Pierre-Yves Chibon |
930073 |
commentobj = pagure.lib.query.get_issue_comment_by_user_and_comment(
|
|
Pierre-Yves Chibon |
9c2953 |
session, issue_uid, usercomment.id, comment["comment"]
|
|
Pierre-Yves Chibon |
9c2953 |
)
|
|
Pierre-Yves Chibon |
c7f9fa |
if not commentobj:
|
|
Pierre-Yves Chibon |
930073 |
pagure.lib.query.add_issue_comment(
|
|
Pierre-Yves Chibon |
c7f9fa |
session,
|
|
Pierre-Yves Chibon |
c7f9fa |
issue=issue,
|
|
Pierre-Yves Chibon |
9c2953 |
comment=comment["comment"],
|
|
Pierre-Yves Chibon |
74ab5f |
user=usercomment.username,
|
|
Pierre-Yves Chibon |
c7f9fa |
notify=False,
|
|
Pierre-Yves Chibon |
7b6a9d |
date_created=datetime.datetime.fromtimestamp(
|
|
Pierre-Yves Chibon |
9c2953 |
float(comment["date_created"])
|
|
Pierre-Yves Chibon |
9c2953 |
),
|
|
Pierre-Yves Chibon |
c7f9fa |
)
|
|
Pierre-Yves Chibon |
74ab5f |
|
|
Pierre-Yves Chibon |
1878ce |
if messages:
|
|
Pierre-Yves Chibon |
930073 |
pagure.lib.query.add_metadata_update_notif(
|
|
Patrick Uiterwijk |
3f97f6 |
session=session, obj=issue, messages=messages, user=agent.username
|
|
Pierre-Yves Chibon |
1878ce |
)
|
|
Pierre-Yves Chibon |
c7f9fa |
session.commit()
|
|
Pierre-Yves Chibon |
852918 |
|
|
Pierre-Yves Chibon |
cac223 |
|
|
Pierre-Yves Chibon |
a6c9f2 |
def update_request_from_git(
|
|
Pierre-Yves Chibon |
9c2953 |
session, reponame, namespace, username, request_uid, json_data
|
|
Pierre-Yves Chibon |
9c2953 |
):
|
|
Pierre-Yves Chibon |
a6c9f2 |
""" Update the specified request (identified by its unique identifier)
|
|
Pierre-Yves Chibon |
a6c9f2 |
with the data present in the json blob provided.
|
|
Pierre-Yves Chibon |
a6c9f2 |
|
|
Pierre-Yves Chibon |
a6c9f2 |
:arg session: the session to connect to the database with.
|
|
Pierre-Yves Chibon |
a6c9f2 |
:arg repo: the name of the project to update
|
|
Pierre-Yves Chibon |
a6c9f2 |
:arg username: the username to find the repo, is not None for forked
|
|
Pierre-Yves Chibon |
a6c9f2 |
projects
|
|
Pierre-Yves Chibon |
a6c9f2 |
:arg request_uid: the unique identifier of the issue to update
|
|
Pierre-Yves Chibon |
a6c9f2 |
:arg json_data: the json representation of the issue taken from the git
|
|
Pierre-Yves Chibon |
a6c9f2 |
and used to update the data in the database.
|
|
Pierre-Yves Chibon |
a6c9f2 |
|
|
Pierre-Yves Chibon |
a6c9f2 |
"""
|
|
Pierre-Yves Chibon |
a6c9f2 |
|
|
Pierre-Yves Chibon |
930073 |
repo = pagure.lib.query._get_project(
|
|
Pierre-Yves Chibon |
9c2953 |
session, reponame, user=username, namespace=namespace
|
|
Pierre-Yves Chibon |
9c2953 |
)
|
|
Pierre-Yves Chibon |
edbdc9 |
|
|
Pierre-Yves Chibon |
a6c9f2 |
if not repo:
|
|
Pierre-Yves Chibon |
fe5017 |
raise pagure.exceptions.PagureException(
|
|
Pierre-Yves Chibon |
9c2953 |
"Unknown repo %s of username: %s in namespace: %s"
|
|
Pierre-Yves Chibon |
9c2953 |
% (reponame, username, namespace)
|
|
Pierre-Yves Chibon |
9c2953 |
)
|
|
Pierre-Yves Chibon |
a6c9f2 |
|
|
Pierre-Yves Chibon |
a6c9f2 |
user = get_user_from_json(session, json_data)
|
|
Pierre-Yves Chibon |
a6c9f2 |
|
|
Pierre-Yves Chibon |
930073 |
request = pagure.lib.query.get_request_by_uid(
|
|
Pierre-Yves Chibon |
930073 |
session, request_uid=request_uid
|
|
Pierre-Yves Chibon |
930073 |
)
|
|
Pierre-Yves Chibon |
a6c9f2 |
|
|
Pierre-Yves Chibon |
a6c9f2 |
if not request:
|
|
Pierre-Yves Chibon |
9c2953 |
repo_from = get_project_from_json(session, json_data.get("repo_from"))
|
|
Pierre-Yves Chibon |
a6c9f2 |
|
|
Pierre-Yves Chibon |
9c2953 |
repo_to = get_project_from_json(session, json_data.get("project"))
|
|
Pierre-Yves Chibon |
a6c9f2 |
|
|
Pierre-Yves Chibon |
9c2953 |
status = json_data.get("status")
|
|
Aurélien Bompard |
619e2a |
if pagure.utils.is_true(status):
|
|
Pierre-Yves Chibon |
9c2953 |
status = "Open"
|
|
Pierre-Yves Chibon |
9c2953 |
elif pagure.utils.is_true(status, ["false"]):
|
|
Pierre-Yves Chibon |
9c2953 |
status = "Merged"
|
|
Pierre-Yves Chibon |
1c34ea |
|
|
Pierre-Yves Chibon |
a6c9f2 |
# Create new request
|
|
Pierre-Yves Chibon |
930073 |
pagure.lib.query.new_pull_request(
|
|
Pierre-Yves Chibon |
a6c9f2 |
session,
|
|
Pierre-Yves Chibon |
a6c9f2 |
repo_from=repo_from,
|
|
Pierre-Yves Chibon |
9c2953 |
branch_from=json_data.get("branch_from"),
|
|
Pierre-Yves Chibon |
9a5539 |
repo_to=repo_to if repo_to else None,
|
|
Pierre-Yves Chibon |
9c2953 |
remote_git=json_data.get("remote_git"),
|
|
Pierre-Yves Chibon |
9c2953 |
branch_to=json_data.get("branch"),
|
|
Pierre-Yves Chibon |
9c2953 |
title=json_data.get("title"),
|
|
Pierre-Yves Chibon |
a6c9f2 |
user=user.username,
|
|
Pierre-Yves Chibon |
9c2953 |
requestuid=json_data.get("uid"),
|
|
Pierre-Yves Chibon |
9c2953 |
requestid=json_data.get("id"),
|
|
Pierre-Yves Chibon |
1c34ea |
status=status,
|
|
Pierre-Yves Chibon |
a6c9f2 |
notify=False,
|
|
Pierre-Yves Chibon |
a6c9f2 |
)
|
|
Pierre-Yves Chibon |
a6c9f2 |
session.commit()
|
|
Pierre-Yves Chibon |
a6c9f2 |
|
|
Pierre-Yves Chibon |
930073 |
request = pagure.lib.query.get_request_by_uid(
|
|
Pierre-Yves Chibon |
930073 |
session, request_uid=request_uid
|
|
Pierre-Yves Chibon |
930073 |
)
|
|
Pierre-Yves Chibon |
a6c9f2 |
|
|
Pierre-Yves Chibon |
a5fbfd |
# Update start and stop commits
|
|
Pierre-Yves Chibon |
9c2953 |
request.commit_start = json_data.get("commit_start")
|
|
Pierre-Yves Chibon |
9c2953 |
request.commit_stop = json_data.get("commit_stop")
|
|
Pierre-Yves Chibon |
7a6b27 |
|
|
Pierre-Yves Chibon |
a5fbfd |
# Update assignee
|
|
Pierre-Yves Chibon |
9c2953 |
assignee = get_user_from_json(session, json_data, key="assignee")
|
|
Pierre-Yves Chibon |
a5fbfd |
if assignee:
|
|
Pierre-Yves Chibon |
930073 |
pagure.lib.query.add_pull_request_assignee(
|
|
Patrick Uiterwijk |
3f97f6 |
session, request, assignee.username, user=user.user
|
|
Pierre-Yves Chibon |
9c2953 |
)
|
|
Pierre-Yves Chibon |
a5fbfd |
|
|
Pierre-Yves Chibon |
9c2953 |
for comment in json_data["comments"]:
|
|
Pierre-Yves Chibon |
a6c9f2 |
user = get_user_from_json(session, comment)
|
|
Pierre-Yves Chibon |
930073 |
commentobj = pagure.lib.query.get_request_comment(
|
|
Pierre-Yves Chibon |
9c2953 |
session, request_uid, comment["id"]
|
|
Pierre-Yves Chibon |
9c2953 |
)
|
|
Pierre-Yves Chibon |
a6c9f2 |
if not commentobj:
|
|
Pierre-Yves Chibon |
930073 |
pagure.lib.query.add_pull_request_comment(
|
|
Pierre-Yves Chibon |
a6c9f2 |
session,
|
|
Pierre-Yves Chibon |
a6c9f2 |
request,
|
|
Pierre-Yves Chibon |
9c2953 |
commit=comment["commit"],
|
|
Pierre-Yves Chibon |
9c2953 |
tree_id=comment.get("tree_id") or None,
|
|
Pierre-Yves Chibon |
9c2953 |
filename=comment["filename"],
|
|
Pierre-Yves Chibon |
9c2953 |
row=comment["line"],
|
|
Pierre-Yves Chibon |
9c2953 |
comment=comment["comment"],
|
|
Pierre-Yves Chibon |
a6c9f2 |
user=user.username,
|
|
Pierre-Yves Chibon |
519dc0 |
notify=False,
|
|
Pierre-Yves Chibon |
a6c9f2 |
)
|
|
Pierre-Yves Chibon |
31a638 |
|
|
Pierre-Yves Chibon |
31a638 |
# Add/update tags:
|
|
Pierre-Yves Chibon |
31a638 |
tags = json_data.get("tags") or []
|
|
Pierre-Yves Chibon |
31a638 |
if tags:
|
|
Pierre-Yves Chibon |
31a638 |
user = get_user_from_json(session, json_data)
|
|
Pierre-Yves Chibon |
31a638 |
pagure.lib.query.add_tag_obj(session, request, tags, user.username)
|
|
Pierre-Yves Chibon |
31a638 |
|
|
Pierre-Yves Chibon |
a6c9f2 |
session.commit()
|
|
Pierre-Yves Chibon |
a6c9f2 |
|
|
Pierre-Yves Chibon |
852918 |
|
|
Patrick Uiterwijk |
3f97f6 |
def _add_file_to_git(repo, issue, attachmentfolder, user, filename):
|
|
Pierre-Yves Chibon |
9c2953 |
""" Add a given file to the specified ticket git repository.
|
|
Pierre-Yves Chibon |
852918 |
|
|
Pierre-Yves Chibon |
852918 |
:arg repo: the Project object from the database
|
|
Patrick Uiterwijk |
96c928 |
:arg attachmentfolder: the folder on the filesystem where the attachments
|
|
Patrick Uiterwijk |
96c928 |
are stored
|
|
Pierre-Yves Chibon |
852918 |
:arg ticketfolder: the folder on the filesystem where the git repo for
|
|
Pierre-Yves Chibon |
852918 |
tickets are stored
|
|
Pierre-Yves Chibon |
852918 |
:arg user: the user object with its username and email
|
|
Pierre-Yves Chibon |
852918 |
:arg filename: the name of the file to save
|
|
Pierre-Yves Chibon |
852918 |
|
|
Pierre-Yves Chibon |
9c2953 |
"""
|
|
Patrick Uiterwijk |
3f97f6 |
with TemporaryClone(repo, issue.repotype, "add_file_to_git") as tempclone:
|
|
Patrick Uiterwijk |
3f97f6 |
newpath = tempclone.repopath
|
|
Patrick Uiterwijk |
3f97f6 |
new_repo = tempclone.repo
|
|
Pierre-Yves Chibon |
852918 |
|
|
Patrick Uiterwijk |
3f97f6 |
folder_path = os.path.join(newpath, "files")
|
|
Patrick Uiterwijk |
3f97f6 |
file_path = os.path.join(folder_path, filename)
|
|
Pierre-Yves Chibon |
852918 |
|
|
Patrick Uiterwijk |
3f97f6 |
# Get the current index
|
|
Patrick Uiterwijk |
3f97f6 |
index = new_repo.index
|
|
Pierre-Yves Chibon |
852918 |
|
|
Patrick Uiterwijk |
3f97f6 |
# Are we adding files
|
|
Patrick Uiterwijk |
3f97f6 |
if os.path.exists(file_path):
|
|
Patrick Uiterwijk |
3f97f6 |
# File exists, remove the clone and return
|
|
Patrick Uiterwijk |
3f97f6 |
shutil.rmtree(newpath)
|
|
Patrick Uiterwijk |
3f97f6 |
return os.path.join("files", filename)
|
|
Pierre-Yves Chibon |
852918 |
|
|
Patrick Uiterwijk |
3f97f6 |
if not os.path.exists(folder_path):
|
|
Patrick Uiterwijk |
3f97f6 |
os.mkdir(folder_path)
|
|
Pierre-Yves Chibon |
852918 |
|
|
Patrick Uiterwijk |
3f97f6 |
# Copy from attachments directory
|
|
Patrick Uiterwijk |
3f97f6 |
src = os.path.join(attachmentfolder, repo.fullname, "files", filename)
|
|
Patrick Uiterwijk |
3f97f6 |
shutil.copyfile(src, file_path)
|
|
Pierre-Yves Chibon |
852918 |
|
|
Patrick Uiterwijk |
3f97f6 |
# Retrieve the list of files that changed
|
|
Patrick Uiterwijk |
3f97f6 |
diff = new_repo.diff()
|
|
Patrick Uiterwijk |
3f97f6 |
files = [patch.new_file_path for patch in diff]
|
|
Pierre-Yves Chibon |
852918 |
|
|
Patrick Uiterwijk |
3f97f6 |
# Add the changes to the index
|
|
Patrick Uiterwijk |
3f97f6 |
index.add(os.path.join("files", filename))
|
|
Patrick Uiterwijk |
3f97f6 |
for filename in files:
|
|
Patrick Uiterwijk |
3f97f6 |
index.add(filename)
|
|
Pierre-Yves Chibon |
5e105c |
|
|
Patrick Uiterwijk |
3f97f6 |
# See if there is a parent to this commit
|
|
Patrick Uiterwijk |
3f97f6 |
parent = None
|
|
Patrick Uiterwijk |
3f97f6 |
try:
|
|
Pierre-Yves Chibon |
29ff0a |
parent = new_repo.head.peel().oid
|
|
Patrick Uiterwijk |
3f97f6 |
except pygit2.GitError:
|
|
Patrick Uiterwijk |
3f97f6 |
pass
|
|
Pierre-Yves Chibon |
5e105c |
|
|
Patrick Uiterwijk |
3f97f6 |
parents = []
|
|
Patrick Uiterwijk |
3f97f6 |
if parent:
|
|
Patrick Uiterwijk |
3f97f6 |
parents.append(parent)
|
|
Patrick Uiterwijk |
3f97f6 |
|
|
Patrick Uiterwijk |
3f97f6 |
# Author/commiter will always be this one
|
|
Patrick Uiterwijk |
3f97f6 |
author = _make_signature(name=user.username, email=user.default_email)
|
|
Patrick Uiterwijk |
3f97f6 |
|
|
Patrick Uiterwijk |
3f97f6 |
# Actually commit
|
|
Patrick Uiterwijk |
3f97f6 |
new_repo.create_commit(
|
|
Patrick Uiterwijk |
3f97f6 |
"refs/heads/master",
|
|
Patrick Uiterwijk |
3f97f6 |
author,
|
|
Patrick Uiterwijk |
3f97f6 |
author,
|
|
Patrick Uiterwijk |
3f97f6 |
"Add file %s to ticket %s: %s"
|
|
Patrick Uiterwijk |
3f97f6 |
% (filename, issue.uid, issue.title),
|
|
Patrick Uiterwijk |
3f97f6 |
new_repo.index.write_tree(),
|
|
Patrick Uiterwijk |
3f97f6 |
parents,
|
|
Patrick Uiterwijk |
3f97f6 |
)
|
|
Patrick Uiterwijk |
3f97f6 |
index.write()
|
|
Pierre-Yves Chibon |
852918 |
|
|
Patrick Uiterwijk |
3f97f6 |
master_ref = new_repo.lookup_reference("HEAD").resolve()
|
|
Patrick Uiterwijk |
03a519 |
tempclone.push(user.username, master_ref.name)
|
|
Patrick Uiterwijk |
0a0334 |
|
|
Patrick Uiterwijk |
3f97f6 |
return os.path.join("files", filename)
|
|
Patrick Uiterwijk |
0a0334 |
|
|
Pierre-Yves Chibon |
774fee |
|
|
Patrick Uiterwijk |
3f97f6 |
class TemporaryClone(object):
|
|
Patrick Uiterwijk |
3f97f6 |
_project = None
|
|
Patrick Uiterwijk |
3f97f6 |
_action = None
|
|
Patrick Uiterwijk |
3f97f6 |
_repotype = None
|
|
Patrick Uiterwijk |
3f97f6 |
_origpath = None
|
|
Pierre-Yves Chibon |
ded1fa |
_origrepopath = None
|
|
Patrick Uiterwijk |
3f97f6 |
repopath = None
|
|
Patrick Uiterwijk |
3f97f6 |
repo = None
|
|
Patrick Uiterwijk |
3f97f6 |
|
|
Pierre-Yves Chibon |
ded1fa |
def __init__(self, project, repotype, action, path=None, parent=None):
|
|
Patrick Uiterwijk |
3f97f6 |
""" Initializes a TempoaryClone instance.
|
|
Patrick Uiterwijk |
3f97f6 |
|
|
Patrick Uiterwijk |
3f97f6 |
Args:
|
|
Patrick Uiterwijk |
3f97f6 |
project (model.Project): A project instance
|
|
Patrick Uiterwijk |
3f97f6 |
repotype (string): The type of repo to clone, one of:
|
|
Patrick Uiterwijk |
3f97f6 |
main, docs, requests, tickets
|
|
Patrick Uiterwijk |
3f97f6 |
action (string): Type of action performing, used in the
|
|
Patrick Uiterwijk |
3f97f6 |
temporary directory name
|
|
Pierre-Yves Chibon |
ded1fa |
path (string or None): the path to clone, allows cloning, for
|
|
Pierre-Yves Chibon |
ded1fa |
example remote git repo for remote PRs instead of the
|
|
Pierre-Yves Chibon |
ded1fa |
default one
|
|
Pierre-Yves Chibon |
ded1fa |
parent (string or None): Adds this directory to the path in
|
|
Pierre-Yves Chibon |
ded1fa |
which the project is cloned
|
|
Pierre-Yves Chibon |
ded1fa |
|
|
Patrick Uiterwijk |
3f97f6 |
"""
|
|
Slavek Kabrda |
0915d0 |
if repotype not in pagure.lib.query.get_repotypes():
|
|
Patrick Uiterwijk |
3f97f6 |
raise NotImplementedError("Repotype %s not known" % repotype)
|
|
Patrick Uiterwijk |
3f97f6 |
|
|
Patrick Uiterwijk |
3f97f6 |
self._project = project
|
|
Patrick Uiterwijk |
3f97f6 |
self._repotype = repotype
|
|
Patrick Uiterwijk |
3f97f6 |
self._action = action
|
|
Pierre-Yves Chibon |
8bced8 |
self._path = path
|
|
Pierre-Yves Chibon |
ded1fa |
self._parent = parent
|
|
Patrick Uiterwijk |
3f97f6 |
|
|
Patrick Uiterwijk |
3f97f6 |
def __enter__(self):
|
|
Patrick Uiterwijk |
3f97f6 |
""" Enter the context manager, creating the clone. """
|
|
Patrick Uiterwijk |
3f97f6 |
self.repopath = tempfile.mkdtemp(prefix="pagure-%s-" % self._action)
|
|
Pierre-Yves Chibon |
ded1fa |
self._origrepopath = self.repopath
|
|
Pierre-Yves Chibon |
ded1fa |
if self._parent:
|
|
Pierre-Yves Chibon |
ded1fa |
self.repopath = os.path.join(self.repopath, self._parent)
|
|
Pierre-Yves Chibon |
ded1fa |
os.makedirs(self.repopath)
|
|
Patrick Uiterwijk |
3f97f6 |
if not self._project.is_on_repospanner:
|
|
Patrick Uiterwijk |
3f97f6 |
# This is the simple case. Just do a local clone
|
|
Pierre-Yves Chibon |
97d19d |
# use either the specified path or the use the path of the
|
|
Pierre-Yves Chibon |
97d19d |
# specified project
|
|
Pierre-Yves Chibon |
8bced8 |
self._origpath = self._path or self._project.repopath(
|
|
Pierre-Yves Chibon |
8bced8 |
self._repotype
|
|
Pierre-Yves Chibon |
8bced8 |
)
|
|
Patrick Uiterwijk |
3f97f6 |
if self._origpath is None:
|
|
Patrick Uiterwijk |
3f97f6 |
# No repository of this type
|
|
Patrick Uiterwijk |
3f97f6 |
# 'main' is already caught and returns an error in repopath()
|
|
Patrick Uiterwijk |
3f97f6 |
return None
|
|
Patrick Uiterwijk |
3f97f6 |
if not os.path.exists(self._origpath):
|
|
Patrick Uiterwijk |
3f97f6 |
return None
|
|
Pierre-Yves Chibon |
a87742 |
PagureRepo.clone(self._origpath, self.repopath)
|
|
Patrick Uiterwijk |
3f97f6 |
# Because for whatever reason, one pygit2.Repository is not
|
|
Patrick Uiterwijk |
3f97f6 |
# equal to another.... The pygit2.Repository returned from
|
|
Patrick Uiterwijk |
3f97f6 |
# pygit2.clone_repository does not have the "branches" attribute.
|
|
Patrick Uiterwijk |
3f97f6 |
self.repo = pygit2.Repository(self.repopath)
|
|
Pierre-Yves Chibon |
c96124 |
self._origrepo = pygit2.Repository(self._origpath)
|
|
Patrick Uiterwijk |
3f97f6 |
else:
|
|
Patrick Uiterwijk |
3f97f6 |
repourl, regioninfo = self._project.repospanner_repo_info(
|
|
Patrick Uiterwijk |
3f97f6 |
self._repotype
|
|
Patrick Uiterwijk |
3f97f6 |
)
|
|
Patrick Uiterwijk |
3f97f6 |
|
|
Patrick Uiterwijk |
3f97f6 |
command = [
|
|
Patrick Uiterwijk |
3f97f6 |
"git",
|
|
Patrick Uiterwijk |
3f97f6 |
"-c",
|
|
Patrick Uiterwijk |
8174a4 |
"protocol.ext.allow=always",
|
|
Patrick Uiterwijk |
3f97f6 |
"clone",
|
|
Patrick Uiterwijk |
8174a4 |
"ext::%s %s"
|
|
Patrick Uiterwijk |
8174a4 |
% (
|
|
Patrick Uiterwijk |
8174a4 |
pagure_config["REPOBRIDGE_BINARY"],
|
|
Patrick Uiterwijk |
8174a4 |
self._project._repospanner_repo_name(self._repotype),
|
|
Patrick Uiterwijk |
8174a4 |
),
|
|
Patrick Uiterwijk |
3f97f6 |
self.repopath,
|
|
Patrick Uiterwijk |
3f97f6 |
]
|
|
Patrick Uiterwijk |
8174a4 |
environ = os.environ.copy()
|
|
Patrick Uiterwijk |
8174a4 |
environ.update(
|
|
Patrick Uiterwijk |
8174a4 |
{
|
|
Patrick Uiterwijk |
8174a4 |
"USER": "pagure",
|
|
Patrick Uiterwijk |
8174a4 |
"REPOBRIDGE_CONFIG": ":environment:",
|
|
Patrick Uiterwijk |
8174a4 |
"REPOBRIDGE_BASEURL": regioninfo["url"],
|
|
Patrick Uiterwijk |
8174a4 |
"REPOBRIDGE_CA": regioninfo["ca"],
|
|
Patrick Uiterwijk |
8174a4 |
"REPOBRIDGE_CERT": regioninfo["push_cert"]["cert"],
|
|
Patrick Uiterwijk |
8174a4 |
"REPOBRIDGE_KEY": regioninfo["push_cert"]["key"],
|
|
Patrick Uiterwijk |
8174a4 |
}
|
|
Patrick Uiterwijk |
8174a4 |
)
|
|
Patrick Uiterwijk |
3f97f6 |
with open(os.devnull, "w") as devnull:
|
|
Patrick Uiterwijk |
3f97f6 |
subprocess.check_call(
|
|
Patrick Uiterwijk |
8174a4 |
command,
|
|
Patrick Uiterwijk |
8174a4 |
stdout=devnull,
|
|
Patrick Uiterwijk |
8174a4 |
stderr=subprocess.STDOUT,
|
|
Patrick Uiterwijk |
8174a4 |
env=environ,
|
|
Patrick Uiterwijk |
3f97f6 |
)
|
|
Patrick Uiterwijk |
3f97f6 |
self.repo = pygit2.Repository(self.repopath)
|
|
Patrick Uiterwijk |
c58901 |
self._origrepo = self.repo
|
|
Patrick Uiterwijk |
3f97f6 |
|
|
Patrick Uiterwijk |
3f97f6 |
# Make sure that all remote refs are mapped to local ones.
|
|
Pierre-Yves Chibon |
dd1ea3 |
headname = None
|
|
Pierre-Yves Chibon |
dd1ea3 |
if not self.repo.is_empty and not self.repo.head_is_unborn:
|
|
Pierre-Yves Chibon |
dd1ea3 |
headname = self.repo.head.shorthand
|
|
Pierre-Yves Chibon |
c96124 |
|
|
Pierre-Yves Chibon |
c96124 |
# Sync up all the references, branches and PR heads
|
|
Pierre-Yves Chibon |
c96124 |
for ref in self._origrepo.listall_references():
|
|
Pierre-Yves Chibon |
c96124 |
if ref.startswith("refs/heads/"):
|
|
Pierre-Yves Chibon |
c96124 |
localname = ref.replace("refs/heads/", "")
|
|
Pierre-Yves Chibon |
c96124 |
if localname in (headname, "HEAD"):
|
|
Pierre-Yves Chibon |
c96124 |
# This gets checked out by default
|
|
Pierre-Yves Chibon |
c96124 |
continue
|
|
Pierre-Yves Chibon |
c96124 |
branch = self.repo.branches.remote.get("origin/%s" % localname)
|
|
Pierre-Yves Chibon |
29ff0a |
self.repo.branches.local.create(localname, branch.peel())
|
|
Pierre-Yves Chibon |
c96124 |
elif ref.startswith("refs/pull/"):
|
|
Pierre-Yves Chibon |
c96124 |
reference = self._origrepo.references.get(ref)
|
|
Pierre-Yves Chibon |
29ff0a |
self.repo.references.create(ref, reference.peel().oid.hex)
|
|
Patrick Uiterwijk |
3f97f6 |
|
|
Patrick Uiterwijk |
3f97f6 |
return self
|
|
Patrick Uiterwijk |
3f97f6 |
|
|
Patrick Uiterwijk |
3f97f6 |
def __exit__(self, exc_type, exc_value, traceback):
|
|
Patrick Uiterwijk |
3f97f6 |
""" Exit the context manager, removing the temorary clone. """
|
|
Patrick Uiterwijk |
3f97f6 |
shutil.rmtree(self.repopath)
|
|
Patrick Uiterwijk |
3f97f6 |
|
|
Slavek Kabrda |
29bdb9 |
def change_project_association(self, new_project):
|
|
Slavek Kabrda |
29bdb9 |
""" Make this instance "belong" to another project.
|
|
Slavek Kabrda |
29bdb9 |
|
|
Slavek Kabrda |
29bdb9 |
This is useful when you want to create TemporaryClone of one project
|
|
Slavek Kabrda |
29bdb9 |
and then push some of its content into a different project just
|
|
Slavek Kabrda |
29bdb9 |
by running ``push`` or ``mirror`` methods.
|
|
Slavek Kabrda |
29bdb9 |
|
|
Slavek Kabrda |
29bdb9 |
Args:
|
|
Slavek Kabrda |
29bdb9 |
new_project (pagure.lib.model.Project): project to associate
|
|
Slavek Kabrda |
29bdb9 |
this TemporaryClone instance with
|
|
Slavek Kabrda |
29bdb9 |
"""
|
|
Slavek Kabrda |
29bdb9 |
self._project = new_project
|
|
Slavek Kabrda |
29bdb9 |
if not new_project.is_on_repospanner:
|
|
Slavek Kabrda |
29bdb9 |
self.repo.remotes.set_push_url(
|
|
Slavek Kabrda |
29bdb9 |
"origin", new_project.repopath("main")
|
|
Slavek Kabrda |
29bdb9 |
)
|
|
Slavek Kabrda |
29bdb9 |
|
|
Slavek Kabrda |
29bdb9 |
def mirror(self, username, force=False, **extra):
|
|
Slavek Kabrda |
29bdb9 |
""" Run ``git push --mirror`` of the repo to its origin.
|
|
Slavek Kabrda |
29bdb9 |
|
|
Slavek Kabrda |
29bdb9 |
Args:
|
|
Slavek Kabrda |
29bdb9 |
username (string): The user on who's account this push is
|
|
Slavek Kabrda |
29bdb9 |
force (bool): whether or not to use ``--force`` when pushing
|
|
Slavek Kabrda |
29bdb9 |
extra (dict): Extra fields passed to the remote side. Either via
|
|
Slavek Kabrda |
29bdb9 |
environment variables, or as X-Extra-<key> HTTP headers.</key>
|
|
Slavek Kabrda |
29bdb9 |
"""
|
|
Slavek Kabrda |
29bdb9 |
# git push --mirror fails if there are no branches
|
|
Slavek Kabrda |
29bdb9 |
if len(list(self.repo.branches)) > 0:
|
|
Slavek Kabrda |
29bdb9 |
self._push(username, "--mirror", force, **extra)
|
|
Slavek Kabrda |
29bdb9 |
|
|
Pierre-Yves Chibon |
da3640 |
def push(self, username, sbranch, tbranch=None, force=False, **extra):
|
|
Patrick Uiterwijk |
3f97f6 |
""" Push the repo back to its origin.
|
|
Patrick Uiterwijk |
3f97f6 |
|
|
Patrick Uiterwijk |
3f97f6 |
Args:
|
|
Patrick Uiterwijk |
03a519 |
username (string): The user on who's account this push is
|
|
Patrick Uiterwijk |
3f97f6 |
sbranch (string): Source branch to push
|
|
Patrick Uiterwijk |
3f97f6 |
tbranch (string): Target branch if different from sbranch
|
|
Slavek Kabrda |
29bdb9 |
force (bool): whether or not to use ``--force`` when pushing
|
|
Patrick Uiterwijk |
03a519 |
extra (dict): Extra fields passed to the remote side. Either via
|
|
Patrick Uiterwijk |
03a519 |
environment variables, or as X-Extra-<key> HTTP headers.</key>
|
|
Patrick Uiterwijk |
3f97f6 |
"""
|
|
Patrick Uiterwijk |
3f97f6 |
pushref = "%s:%s" % (sbranch, tbranch if tbranch else sbranch)
|
|
Slavek Kabrda |
29bdb9 |
self._push(username, pushref, force, **extra)
|
|
Slavek Kabrda |
29bdb9 |
|
|
Slavek Kabrda |
29bdb9 |
def _push(self, username, pushref, force, **extra):
|
|
Slavek Kabrda |
29bdb9 |
""" Push the repo back to its origin.
|
|
Patrick Uiterwijk |
3f97f6 |
|
|
Slavek Kabrda |
29bdb9 |
Args:
|
|
Slavek Kabrda |
29bdb9 |
username (string): The user on who's account this push is
|
|
Slavek Kabrda |
29bdb9 |
pushref(string): either ``<sbranch>:<tbranch>`` or ``--mirror``</tbranch></sbranch>
|
|
Slavek Kabrda |
29bdb9 |
force (bool): whether or not to use ``--force`` when pushing
|
|
Slavek Kabrda |
29bdb9 |
extra (dict): Extra fields passed to the remote side. Either via
|
|
Slavek Kabrda |
29bdb9 |
environment variables, or as X-Extra-<key> HTTP headers.</key>
|
|
Slavek Kabrda |
29bdb9 |
"""
|
|
Patrick Uiterwijk |
03a519 |
if "pull_request" in extra:
|
|
Patrick Uiterwijk |
03a519 |
extra["pull_request_uid"] = extra["pull_request"].uid
|
|
Patrick Uiterwijk |
03a519 |
del extra["pull_request"]
|
|
Patrick Uiterwijk |
03a519 |
|
|
Patrick Uiterwijk |
3f97f6 |
if self._project.is_on_repospanner:
|
|
Patrick Uiterwijk |
3f97f6 |
regioninfo = pagure_config["REPOSPANNER_REGIONS"][
|
|
Patrick Uiterwijk |
3f97f6 |
self._project.repospanner_region
|
|
Patrick Uiterwijk |
3f97f6 |
]
|
|
Patrick Uiterwijk |
d29158 |
|
|
Patrick Uiterwijk |
d29158 |
extra.update(
|
|
Patrick Uiterwijk |
d29158 |
{
|
|
Patrick Uiterwijk |
d29158 |
"username": username,
|
|
Patrick Uiterwijk |
d29158 |
"repotype": self._repotype,
|
|
Patrick Uiterwijk |
d29158 |
"project_name": self._project.name,
|
|
Patrick Uiterwijk |
d29158 |
"project_user": self._project.user.username
|
|
Patrick Uiterwijk |
d29158 |
if self._project.is_fork
|
|
Patrick Uiterwijk |
d29158 |
else "",
|
|
Patrick Uiterwijk |
d29158 |
"project_namespace": self._project.namespace or "",
|
|
Patrick Uiterwijk |
d29158 |
}
|
|
Patrick Uiterwijk |
d29158 |
)
|
|
Patrick Uiterwijk |
8174a4 |
args = []
|
|
Patrick Uiterwijk |
8174a4 |
for opt in extra:
|
|
Patrick Uiterwijk |
8174a4 |
args.extend(["--extra", opt, extra[opt]])
|
|
Patrick Uiterwijk |
8174a4 |
command = [
|
|
Patrick Uiterwijk |
8174a4 |
"git",
|
|
Patrick Uiterwijk |
3f97f6 |
"-c",
|
|
Patrick Uiterwijk |
8174a4 |
"protocol.ext.allow=always",
|
|
Patrick Uiterwijk |
8174a4 |
"push",
|
|
Patrick Uiterwijk |
8174a4 |
"ext::%s %s %s"
|
|
Patrick Uiterwijk |
8174a4 |
% (
|
|
Patrick Uiterwijk |
8174a4 |
pagure_config["REPOBRIDGE_BINARY"],
|
|
Patrick Uiterwijk |
8174a4 |
" ".join(args),
|
|
Patrick Uiterwijk |
8174a4 |
self._project._repospanner_repo_name(self._repotype),
|
|
Patrick Uiterwijk |
8174a4 |
),
|
|
Patrick Uiterwijk |
8174a4 |
"--repo",
|
|
Patrick Uiterwijk |
8174a4 |
self.repopath,
|
|
Patrick Uiterwijk |
3f97f6 |
]
|
|
Patrick Uiterwijk |
8174a4 |
environ = {
|
|
Patrick Uiterwijk |
8174a4 |
"USER": "pagure",
|
|
Patrick Uiterwijk |
8174a4 |
"REPOBRIDGE_CONFIG": ":environment:",
|
|
Patrick Uiterwijk |
8174a4 |
"REPOBRIDGE_BASEURL": regioninfo["url"],
|
|
Patrick Uiterwijk |
8174a4 |
"REPOBRIDGE_CA": regioninfo["ca"],
|
|
Patrick Uiterwijk |
8174a4 |
"REPOBRIDGE_CERT": regioninfo["push_cert"]["cert"],
|
|
Patrick Uiterwijk |
8174a4 |
"REPOBRIDGE_KEY": regioninfo["push_cert"]["key"],
|
|
Patrick Uiterwijk |
8174a4 |
}
|
|
Patrick Uiterwijk |
8174a4 |
else:
|
|
Patrick Uiterwijk |
8174a4 |
command = ["git", "push", "origin"]
|
|
Pierre-Yves Chibon |
da3640 |
if force:
|
|
Pierre-Yves Chibon |
da3640 |
command.append("--force")
|
|
Patrick Uiterwijk |
8174a4 |
environ = {}
|
|
Patrick Uiterwijk |
3f97f6 |
|
|
Slavek Kabrda |
be430b |
command.append("--follow-tags")
|
|
Slavek Kabrda |
be430b |
|
|
Patrick Uiterwijk |
3f97f6 |
try:
|
|
Patrick Uiterwijk |
b2cb9c |
_log.debug(
|
|
Patrick Uiterwijk |
b2cb9c |
"Running a git push of %s to %s"
|
|
Pierre-Yves Chibon |
8bced8 |
% (pushref, self._path or self._project.fullname)
|
|
Patrick Uiterwijk |
b2cb9c |
)
|
|
Patrick Uiterwijk |
03a519 |
env = os.environ.copy()
|
|
Patrick Uiterwijk |
03a519 |
env["GL_USER"] = username
|
|
Pierre-Yves Chibon |
c26740 |
env["GL_BYPASS_ACCESS_CHECKS"] = "1"
|
|
Pierre-Yves Chibon |
00d0c4 |
if pagure_config.get("GITOLITE_HOME"):
|
|
Pierre-Yves Chibon |
00d0c4 |
env["HOME"] = pagure_config["GITOLITE_HOME"]
|
|
Patrick Uiterwijk |
8174a4 |
env.update(environ)
|
|
Patrick Uiterwijk |
03a519 |
env.update(extra)
|
|
Patrick Uiterwijk |
b2cb9c |
out = subprocess.check_output(
|
|
Patrick Uiterwijk |
8174a4 |
command + [pushref],
|
|
Patrick Uiterwijk |
3f97f6 |
cwd=self.repopath,
|
|
Patrick Uiterwijk |
3f97f6 |
stderr=subprocess.STDOUT,
|
|
Patrick Uiterwijk |
03a519 |
env=env,
|
|
Patrick Uiterwijk |
3f97f6 |
)
|
|
Patrick Uiterwijk |
b2cb9c |
_log.debug("Output: %s" % out)
|
|
Patrick Uiterwijk |
3f97f6 |
except subprocess.CalledProcessError as ex:
|
|
Patrick Uiterwijk |
3f97f6 |
# This should never really happen, since we control the repos, but
|
|
Patrick Uiterwijk |
3f97f6 |
# this way, we can be sure to get the output logged
|
|
Patrick Uiterwijk |
b2cb9c |
remotes = []
|
|
Patrick Uiterwijk |
b2cb9c |
for line in ex.output.decode("utf-8").split("\n"):
|
|
Patrick Uiterwijk |
d29158 |
_log.info("Remote line: %s", line)
|
|
Patrick Uiterwijk |
b2cb9c |
if line.startswith("remote: "):
|
|
Patrick Uiterwijk |
b2cb9c |
_log.debug("Remote: %s" % line)
|
|
Patrick Uiterwijk |
b2cb9c |
remotes.append(line[len("remote: ") :].strip())
|
|
Patrick Uiterwijk |
b2cb9c |
if remotes:
|
|
Patrick Uiterwijk |
b2cb9c |
_log.info("Remote rejected with: %s" % remotes)
|
|
Patrick Uiterwijk |
b2cb9c |
raise pagure.exceptions.PagurePushDenied(
|
|
Patrick Uiterwijk |
b2cb9c |
"Remote hook declined the push: %s" % "\n".join(remotes)
|
|
Patrick Uiterwijk |
b2cb9c |
)
|
|
Patrick Uiterwijk |
b2cb9c |
else:
|
|
Patrick Uiterwijk |
b2cb9c |
# Something else happened, pass the original
|
|
Patrick Uiterwijk |
b2cb9c |
_log.exception("Error pushing. Output: %s", ex.output)
|
|
Patrick Uiterwijk |
b2cb9c |
raise
|
|
Patrick Uiterwijk |
3f97f6 |
|
|
Pierre-Yves Chibon |
2ed535 |
|
|
Patrick Uiterwijk |
8cb224 |
def _update_file_in_git(
|
|
Patrick Uiterwijk |
03a519 |
repo, branch, branchto, filename, content, message, user, email
|
|
Pierre-Yves Chibon |
9c2953 |
):
|
|
Pierre-Yves Chibon |
9c2953 |
""" Update a specific file in the specified repository with the content
|
|
Pierre-Yves Chibon |
54335c |
given and commit the change under the user's name.
|
|
Pierre-Yves Chibon |
54335c |
|
|
Pierre-Yves Chibon |
54335c |
:arg repo: the Project object from the database
|
|
Pierre-Yves Chibon |
e59791 |
:arg branch: the branch from which the edit is made
|
|
Pierre-Yves Chibon |
e59791 |
:arg branchto: the name of the branch into which to edit the file
|
|
Pierre-Yves Chibon |
54335c |
:arg filename: the name of the file to save
|
|
Pierre-Yves Chibon |
54335c |
:arg content: the new content of the file
|
|
Pierre-Yves Chibon |
54335c |
:arg message: the message of the git commit
|
|
Pierre-Yves Chibon |
e59791 |
:arg user: the user name, to use in the commit
|
|
Pierre-Yves Chibon |
e59791 |
:arg email: the email of the user, to use in the commit
|
|
Pierre-Yves Chibon |
54335c |
|
|
Pierre-Yves Chibon |
9c2953 |
"""
|
|
Pierre-Yves Chibon |
9c2953 |
_log.info("Updating file: %s in the repo: %s", filename, repo.path)
|
|
Pierre-Yves Chibon |
54335c |
|
|
Patrick Uiterwijk |
3f97f6 |
with TemporaryClone(repo, "main", "edit_file") as tempclone:
|
|
Patrick Uiterwijk |
3f97f6 |
newpath = tempclone.repopath
|
|
Patrick Uiterwijk |
3f97f6 |
new_repo = tempclone.repo
|
|
Patrick Uiterwijk |
3f97f6 |
|
|
Patrick Uiterwijk |
3f97f6 |
new_repo.checkout("refs/heads/%s" % branch)
|
|
Patrick Uiterwijk |
3f97f6 |
|
|
Patrick Uiterwijk |
3f97f6 |
file_path = os.path.join(newpath, filename)
|
|
Patrick Uiterwijk |
3f97f6 |
|
|
Patrick Uiterwijk |
3f97f6 |
# Get the current index
|
|
Patrick Uiterwijk |
3f97f6 |
index = new_repo.index
|
|
Patrick Uiterwijk |
3f97f6 |
|
|
Patrick Uiterwijk |
3f97f6 |
# Write down what changed
|
|
Patrick Uiterwijk |
3f97f6 |
with open(file_path, "wb") as stream:
|
|
Patrick Uiterwijk |
3f97f6 |
stream.write(content.replace("\r", "").encode("utf-8"))
|
|
Patrick Uiterwijk |
3f97f6 |
|
|
Patrick Uiterwijk |
3f97f6 |
# Retrieve the list of files that changed
|
|
Patrick Uiterwijk |
3f97f6 |
diff = new_repo.diff()
|
|
Patrick Uiterwijk |
3f97f6 |
files = []
|
|
Patrick Uiterwijk |
3f97f6 |
for patch in diff:
|
|
Patrick Uiterwijk |
3f97f6 |
files.append(patch.delta.new_file.path)
|
|
Patrick Uiterwijk |
3f97f6 |
|
|
Patrick Uiterwijk |
3f97f6 |
# Add the changes to the index
|
|
Patrick Uiterwijk |
3f97f6 |
added = False
|
|
Patrick Uiterwijk |
3f97f6 |
for filename in files:
|
|
Patrick Uiterwijk |
3f97f6 |
added = True
|
|
Patrick Uiterwijk |
3f97f6 |
index.add(filename)
|
|
Patrick Uiterwijk |
3f97f6 |
|
|
Patrick Uiterwijk |
3f97f6 |
# If not change, return
|
|
Patrick Uiterwijk |
3f97f6 |
if not files and not added:
|
|
Patrick Uiterwijk |
3f97f6 |
return
|
|
Patrick Uiterwijk |
3f97f6 |
|
|
Patrick Uiterwijk |
3f97f6 |
# See if there is a parent to this commit
|
|
Patrick Uiterwijk |
3f97f6 |
branch_ref = get_branch_ref(new_repo, branch)
|
|
Pierre-Yves Chibon |
29ff0a |
parent = branch_ref.peel()
|
|
Patrick Uiterwijk |
3f97f6 |
|
|
Patrick Uiterwijk |
3f97f6 |
# See if we need to create the branch
|
|
Patrick Uiterwijk |
3f97f6 |
nbranch_ref = None
|
|
Patrick Uiterwijk |
3f97f6 |
if branchto not in new_repo.listall_branches():
|
|
Patrick Uiterwijk |
3f97f6 |
nbranch_ref = new_repo.create_branch(branchto, parent)
|
|
Patrick Uiterwijk |
3f97f6 |
|
|
Patrick Uiterwijk |
3f97f6 |
parents = []
|
|
Patrick Uiterwijk |
3f97f6 |
if parent:
|
|
Patrick Uiterwijk |
3f97f6 |
parents.append(parent.hex)
|
|
Patrick Uiterwijk |
3f97f6 |
|
|
Patrick Uiterwijk |
3f97f6 |
# Author/commiter will always be this one
|
|
Patrick Uiterwijk |
3f97f6 |
name = user.fullname or user.username
|
|
Patrick Uiterwijk |
3f97f6 |
author = _make_signature(name=name, email=email)
|
|
Patrick Uiterwijk |
3f97f6 |
|
|
Patrick Uiterwijk |
3f97f6 |
# Actually commit
|
|
Patrick Uiterwijk |
03a519 |
new_repo.create_commit(
|
|
Patrick Uiterwijk |
3f97f6 |
nbranch_ref.name if nbranch_ref else branch_ref.name,
|
|
Patrick Uiterwijk |
3f97f6 |
author,
|
|
Patrick Uiterwijk |
3f97f6 |
author,
|
|
Patrick Uiterwijk |
3f97f6 |
message.strip(),
|
|
Patrick Uiterwijk |
3f97f6 |
new_repo.index.write_tree(),
|
|
Patrick Uiterwijk |
3f97f6 |
parents,
|
|
Pierre-Yves Chibon |
9c2953 |
)
|
|
Patrick Uiterwijk |
3f97f6 |
index.write()
|
|
Pierre-Yves Chibon |
08eaf8 |
|
|
Patrick Uiterwijk |
3f97f6 |
tempclone.push(
|
|
Patrick Uiterwijk |
03a519 |
user.username,
|
|
Patrick Uiterwijk |
03a519 |
nbranch_ref.name if nbranch_ref else branch_ref.name,
|
|
Patrick Uiterwijk |
03a519 |
branchto,
|
|
Pierre-Yves Chibon |
e59791 |
)
|
|
Pierre-Yves Chibon |
e59791 |
|
|
Pierre-Yves Chibon |
9c2953 |
return os.path.join("files", filename)
|
|
Pierre-Yves Chibon |
54335c |
|
|
Pierre-Yves Chibon |
54335c |
|
|
Pierre-Yves Chibon |
86e98d |
def read_output(cmd, abspath, input=None, keepends=False, error=False, **kw):
|
|
Pierre-Yves Chibon |
86e98d |
""" Read the output from the given command to run.
|
|
Pierre-Yves Chibon |
86e98d |
|
|
Pierre-Yves Chibon |
86e98d |
cmd:
|
|
Pierre-Yves Chibon |
86e98d |
The command to run, this is a list with each space separated into an
|
|
Pierre-Yves Chibon |
86e98d |
element of the list.
|
|
Pierre-Yves Chibon |
86e98d |
abspath:
|
|
Pierre-Yves Chibon |
86e98d |
The absolute path where the command should be ran.
|
|
Pierre-Yves Chibon |
86e98d |
input:
|
|
Pierre-Yves Chibon |
86e98d |
Whether the command should take input from stdin or not.
|
|
Pierre-Yves Chibon |
86e98d |
(Defaults to False)
|
|
Pierre-Yves Chibon |
86e98d |
keepends:
|
|
Pierre-Yves Chibon |
86e98d |
Whether to strip the newline characters at the end of the standard
|
|
Pierre-Yves Chibon |
86e98d |
output or not.
|
|
Pierre-Yves Chibon |
86e98d |
error:
|
|
Pierre-Yves Chibon |
86e98d |
Whether to return both the standard output and the standard error,
|
|
Pierre-Yves Chibon |
86e98d |
or just the standard output.
|
|
Pierre-Yves Chibon |
86e98d |
(Defaults to False).
|
|
Pierre-Yves Chibon |
86e98d |
kw*:
|
|
Pierre-Yves Chibon |
86e98d |
Any other arguments to be passed onto the subprocess.Popen command,
|
|
Pierre-Yves Chibon |
86e98d |
such as env, shell, executable...
|
|
Pierre-Yves Chibon |
86e98d |
|
|
Pierre-Yves Chibon |
86e98d |
"""
|
|
Pierre-Yves Chibon |
2ed535 |
if input:
|
|
Pierre-Yves Chibon |
2ed535 |
stdin = subprocess.PIPE
|
|
Pierre-Yves Chibon |
2ed535 |
else:
|
|
Pierre-Yves Chibon |
2ed535 |
stdin = None
|
|
Pierre-Yves Chibon |
164a57 |
procs = subprocess.Popen(
|
|
Pierre-Yves Chibon |
2ed535 |
cmd,
|
|
Pierre-Yves Chibon |
2ed535 |
stdin=stdin,
|
|
Pierre-Yves Chibon |
2ed535 |
stdout=subprocess.PIPE,
|
|
Pierre-Yves Chibon |
2ed535 |
stderr=subprocess.PIPE,
|
|
Pierre-Yves Chibon |
2ed535 |
cwd=abspath,
|
|
Pierre-Yves Chibon |
9c2953 |
**kw
|
|
Pierre-Yves Chibon |
9c2953 |
)
|
|
Pierre-Yves Chibon |
164a57 |
retcode = procs.wait()
|
|
Pierre-Yves Chibon |
227f4c |
(out, err) = procs.communicate(input)
|
|
Pierre-Yves Chibon |
6e566a |
if isinstance(out, six.binary_type):
|
|
Pierre-Yves Chibon |
227f4c |
out = out.decode("utf-8")
|
|
Pierre-Yves Chibon |
6e566a |
if isinstance(err, six.binary_type):
|
|
Pierre-Yves Chibon |
227f4c |
err = err.decode("utf-8")
|
|
Pierre-Yves Chibon |
2ed535 |
if retcode:
|
|
Pierre-Yves Chibon |
9c2953 |
print("ERROR: %s =-- %s" % (cmd, retcode))
|
|
Aurélien Bompard |
831553 |
print(out)
|
|
Aurélien Bompard |
831553 |
print(err)
|
|
Pierre-Yves Chibon |
2ed535 |
if not keepends:
|
|
Pierre-Yves Chibon |
7943c2 |
out = out.rstrip("\n\r")
|
|
Pierre-Yves Chibon |
86e98d |
|
|
Pierre-Yves Chibon |
86e98d |
if error:
|
|
Pierre-Yves Chibon |
86e98d |
return (out, err)
|
|
Pierre-Yves Chibon |
86e98d |
else:
|
|
Pierre-Yves Chibon |
86e98d |
return out
|
|
Pierre-Yves Chibon |
2ed535 |
|
|
Pierre-Yves Chibon |
2ed535 |
|
|
Pierre-Yves Chibon |
86e98d |
def read_git_output(
|
|
Pierre-Yves Chibon |
9c2953 |
args, abspath, input=None, keepends=False, error=False, **kw
|
|
Pierre-Yves Chibon |
9c2953 |
):
|
|
Pierre-Yves Chibon |
2ed535 |
"""Read the output of a Git command."""
|
|
Pierre-Yves Chibon |
2ed535 |
|
|
Pierre-Yves Chibon |
432e7d |
return read_output(
|
|
Pierre-Yves Chibon |
9c2953 |
["git"] + args,
|
|
Pierre-Yves Chibon |
9c2953 |
abspath,
|
|
Pierre-Yves Chibon |
9c2953 |
input=input,
|
|
Pierre-Yves Chibon |
9c2953 |
keepends=keepends,
|
|
Pierre-Yves Chibon |
9c2953 |
error=error,
|
|
Pierre-Yves Chibon |
9c2953 |
**kw
|
|
Pierre-Yves Chibon |
9c2953 |
)
|
|
Pierre-Yves Chibon |
2ed535 |
|
|
Pierre-Yves Chibon |
2ed535 |
|
|
Pierre-Yves Chibon |
86e98d |
def read_git_lines(args, abspath, keepends=False, error=False, **kw):
|
|
Pierre-Yves Chibon |
2ed535 |
"""Return the lines output by Git command.
|
|
Pierre-Yves Chibon |
2ed535 |
|
|
Pierre-Yves Chibon |
2ed535 |
Return as single lines, with newlines stripped off."""
|
|
Pierre-Yves Chibon |
2ed535 |
|
|
Pierre-Yves Chibon |
86e98d |
if error:
|
|
Pierre-Yves Chibon |
86e98d |
return read_git_output(
|
|
Pierre-Yves Chibon |
86e98d |
args, abspath, keepends=keepends, error=error, **kw
|
|
Pierre-Yves Chibon |
86e98d |
)
|
|
Pierre-Yves Chibon |
86e98d |
else:
|
|
Pierre-Yves Chibon |
86e98d |
return read_git_output(
|
|
Pierre-Yves Chibon |
86e98d |
args, abspath, keepends=keepends, **kw
|
|
Pierre-Yves Chibon |
86e98d |
).splitlines(keepends)
|
|
Pierre-Yves Chibon |
2ed535 |
|
|
Pierre-Yves Chibon |
2ed535 |
|
|
Clement Verna |
f202e4 |
def get_revs_between(oldrev, newrev, abspath, refname, forced=False):
|
|
Pierre-Yves Chibon |
2ed535 |
""" Yield revisions between HEAD and BASE. """
|
|
Pierre-Yves Chibon |
2ed535 |
|
|
Pierre-Yves Chibon |
9c2953 |
cmd = ["rev-list", "%s...%s" % (oldrev, newrev)]
|
|
Pierre-Yves Chibon |
72398f |
if forced:
|
|
Pierre-Yves Chibon |
72398f |
head = get_default_branch(abspath)
|
|
Pierre-Yves Chibon |
9c2953 |
cmd.append("^%s" % head)
|
|
Pierre-Yves Chibon |
9c2953 |
if set(newrev) == set("0"):
|
|
Pierre-Yves Chibon |
9c2953 |
cmd = ["rev-list", "%s" % oldrev]
|
|
Pierre-Yves Chibon |
9c2953 |
elif set(oldrev) == set("0") or set(oldrev) == set("^0"):
|
|
Pierre-Yves Chibon |
75a9b6 |
head = get_default_branch(abspath)
|
|
Pierre-Yves Chibon |
9c2953 |
cmd = ["rev-list", "%s" % newrev, "^%s" % head]
|
|
Clement Verna |
f202e4 |
if head in refname:
|
|
Pierre-Yves Chibon |
9c2953 |
cmd = ["rev-list", "%s" % newrev]
|
|
Pierre-Yves Chibon |
432e7d |
return pagure.lib.git.read_git_lines(cmd, abspath)
|
|
Pierre-Yves Chibon |
2ed535 |
|
|
Pierre-Yves Chibon |
2ed535 |
|
|
Pierre-Yves Chibon |
b1f2a1 |
def is_forced_push(oldrev, newrev, abspath):
|
|
Abhijeet Kasurde |
a6221b |
""" Returns whether there was a force push between HEAD and BASE.
|
|
Pierre-Yves Chibon |
b1f2a1 |
Doc: http://stackoverflow.com/a/12258773
|
|
Pierre-Yves Chibon |
b1f2a1 |
"""
|
|
Pierre-Yves Chibon |
599a9d |
|
|
Pierre-Yves Chibon |
9c2953 |
if set(oldrev) == set("0"):
|
|
Slavek Kabrda |
595b6f |
# This is a push that's creating a new branch => certainly ok
|
|
Slavek Kabrda |
595b6f |
return False
|
|
Pierre-Yves Chibon |
599a9d |
# Returns if there was any commits deleted in the changeset
|
|
Pierre-Yves Chibon |
9c2953 |
cmd = ["rev-list", "%s" % oldrev, "^%s" % newrev]
|
|
Pierre-Yves Chibon |
599a9d |
out = pagure.lib.git.read_git_lines(cmd, abspath)
|
|
Pierre-Yves Chibon |
599a9d |
return len(out) > 0
|
|
Pierre-Yves Chibon |
599a9d |
|
|
Pierre-Yves Chibon |
599a9d |
|
|
Pierre-Yves Chibon |
20364a |
def get_base_revision(torev, fromrev, abspath):
|
|
Pierre-Yves Chibon |
20364a |
""" Return the base revision between HEAD and BASE.
|
|
Pierre-Yves Chibon |
20364a |
This is useful in case of force-push.
|
|
Pierre-Yves Chibon |
20364a |
"""
|
|
Pierre-Yves Chibon |
9c2953 |
cmd = ["merge-base", fromrev, torev]
|
|
Pierre-Yves Chibon |
20364a |
return pagure.lib.git.read_git_lines(cmd, abspath)
|
|
Pierre-Yves Chibon |
20364a |
|
|
Pierre-Yves Chibon |
20364a |
|
|
Pierre-Yves Chibon |
2a5cba |
def get_default_branch(abspath):
|
|
Pierre-Yves Chibon |
2a5cba |
""" Return the default branch of a repo. """
|
|
Pierre-Yves Chibon |
9c2953 |
cmd = ["rev-parse", "--abbrev-ref", "HEAD"]
|
|
Pierre-Yves Chibon |
2a5cba |
out = pagure.lib.git.read_git_lines(cmd, abspath)
|
|
Pierre-Yves Chibon |
2a5cba |
if out:
|
|
Pierre-Yves Chibon |
2a5cba |
return out[0]
|
|
Pierre-Yves Chibon |
2a5cba |
else:
|
|
Pierre-Yves Chibon |
9c2953 |
return "master"
|
|
Pierre-Yves Chibon |
2a5cba |
|
|
Pierre-Yves Chibon |
2a5cba |
|
|
Pierre-Yves Chibon |
00d774 |
def get_author(commit, abspath):
|
|
Pierre-Yves Chibon |
9c2953 |
""" Return the name of the person that authored the commit. """
|
|
Pierre-Yves Chibon |
2ed535 |
user = pagure.lib.git.read_git_lines(
|
|
Pierre-Yves Chibon |
9c2953 |
["log", "-1", '--pretty=format:"%an"', commit], abspath
|
|
Pierre-Yves Chibon |
9c2953 |
)[0].replace('"', "")
|
|
Pierre-Yves Chibon |
2ed535 |
return user
|
|
Pierre-Yves Chibon |
2ed535 |
|
|
Pierre-Yves Chibon |
2ed535 |
|
|
Pierre-Yves Chibon |
00d774 |
def get_author_email(commit, abspath):
|
|
Pierre-Yves Chibon |
9c2953 |
""" Return the email of the person that authored the commit. """
|
|
Pierre-Yves Chibon |
2ed535 |
user = pagure.lib.git.read_git_lines(
|
|
Pierre-Yves Chibon |
9c2953 |
["log", "-1", '--pretty=format:"%ae"', commit], abspath
|
|
Pierre-Yves Chibon |
9c2953 |
)[0].replace('"', "")
|
|
Pierre-Yves Chibon |
2ed535 |
return user
|
|
Pierre-Yves Chibon |
432e7d |
|
|
Pierre-Yves Chibon |
432e7d |
|
|
Matt Prahl |
b49f93 |
def get_commit_subject(commit, abspath):
|
|
Pierre-Yves Chibon |
9c2953 |
""" Return the subject of the commit. """
|
|
Matt Prahl |
b49f93 |
subject = pagure.lib.git.read_git_lines(
|
|
Pierre-Yves Chibon |
9c2953 |
["log", "-1", '--pretty=format:"%s"', commit], abspath
|
|
Pierre-Yves Chibon |
9c2953 |
)[0].replace('"', "")
|
|
Matt Prahl |
b49f93 |
return subject
|
|
Matt Prahl |
b49f93 |
|
|
Matt Prahl |
b49f93 |
|
|
Patrick Uiterwijk |
7b7c23 |
def get_repo_info_from_path(gitdir, hide_notfound=False):
|
|
Patrick Uiterwijk |
4012dc |
""" Returns the name, username, namespace and type of a git directory
|
|
Pierre-Yves Chibon |
432e7d |
|
|
Patrick Uiterwijk |
4012dc |
This gets computed based on the *_FOLDER's in the config file,
|
|
Patrick Uiterwijk |
4012dc |
and as such only works for the central file-based repositories.
|
|
Pierre-Yves Chibon |
432e7d |
|
|
Patrick Uiterwijk |
4012dc |
Args:
|
|
Patrick Uiterwijk |
4012dc |
gitdir (string): Path of the canonical git repository
|
|
Patrick Uiterwijk |
7b7c23 |
hide_notfound (bool): Whether to return a tuple with None's instead of
|
|
Patrick Uiterwijk |
7b7c23 |
raising an error if the regenerated repo didn't exist.
|
|
Patrick Uiterwijk |
7b7c23 |
Can be used to hide the difference between no project access vs not
|
|
Patrick Uiterwijk |
7b7c23 |
existing when looking up private repos.
|
|
Patrick Uiterwijk |
4012dc |
Return: (tuple): Tuple with (repotype, username, namespace, repo)
|
|
Patrick Uiterwijk |
4012dc |
Some of these elements may be None if not applicable.
|
|
Pierre-Yves Chibon |
9c2953 |
"""
|
|
Patrick Uiterwijk |
4012dc |
if not os.path.isabs(gitdir):
|
|
Patrick Uiterwijk |
4012dc |
raise ValueError("Tried to locate non-absolute gitdir %s" % gitdir)
|
|
Patrick Uiterwijk |
4012dc |
gitdir = os.path.normpath(gitdir)
|
|
Patrick Uiterwijk |
4012dc |
|
|
Patrick Uiterwijk |
4012dc |
types = {
|
|
Patrick Uiterwijk |
d75948 |
"main": pagure_config["GIT_FOLDER"],
|
|
Patrick Uiterwijk |
d75948 |
"docs": pagure_config["DOCS_FOLDER"],
|
|
Patrick Uiterwijk |
d75948 |
"tickets": pagure_config["TICKETS_FOLDER"],
|
|
Patrick Uiterwijk |
d75948 |
"requests": pagure_config["REQUESTS_FOLDER"],
|
|
Patrick Uiterwijk |
4012dc |
}
|
|
Patrick Uiterwijk |
4012dc |
|
|
Patrick Uiterwijk |
4012dc |
match = None
|
|
Patrick Uiterwijk |
4012dc |
matchlen = None
|
|
Patrick Uiterwijk |
4012dc |
|
|
Patrick Uiterwijk |
4012dc |
# First find the longest match in types. This makes sure that even if the
|
|
Patrick Uiterwijk |
4012dc |
# non-main repos are in a subdir of main (i.e. repos/ and repos/tickets/),
|
|
Patrick Uiterwijk |
4012dc |
# we find the correct type.
|
|
Patrick Uiterwijk |
4012dc |
for typename in types:
|
|
Patrick Uiterwijk |
d75948 |
if not types[typename]:
|
|
Patrick Uiterwijk |
d75948 |
continue
|
|
Patrick Uiterwijk |
d75948 |
types[typename] = os.path.abspath(types[typename])
|
|
Patrick Uiterwijk |
4012dc |
path = types[typename] + "/"
|
|
Patrick Uiterwijk |
4012dc |
if gitdir.startswith(path) and (
|
|
Patrick Uiterwijk |
4012dc |
matchlen is None or len(path) > matchlen
|
|
Patrick Uiterwijk |
4012dc |
):
|
|
Patrick Uiterwijk |
4012dc |
match = typename
|
|
Patrick Uiterwijk |
4012dc |
matchlen = len(path)
|
|
Patrick Uiterwijk |
4012dc |
|
|
Patrick Uiterwijk |
4012dc |
if match is None:
|
|
Pierre-Yves Chibon |
4cc343 |
raise ValueError("Gitdir %s could not be located" % gitdir)
|
|
Patrick Uiterwijk |
4012dc |
|
|
Patrick Uiterwijk |
4012dc |
typepath = types[match]
|
|
Patrick Uiterwijk |
4012dc |
guesspath = gitdir[len(typepath) + 1 :]
|
|
Patrick Uiterwijk |
4012dc |
if len(guesspath) < 5:
|
|
Patrick Uiterwijk |
4012dc |
# At least 4 characters for ".git" is required plus one for project
|
|
Patrick Uiterwijk |
4012dc |
# name
|
|
Patrick Uiterwijk |
4012dc |
raise ValueError("Invalid gitdir %s located" % gitdir)
|
|
Patrick Uiterwijk |
4012dc |
|
|
Patrick Uiterwijk |
4012dc |
# Just in the case we run on a non-*nix system...
|
|
Patrick Uiterwijk |
4012dc |
guesspath = guesspath.replace("\\", "/")
|
|
Patrick Uiterwijk |
4012dc |
|
|
Patrick Uiterwijk |
4012dc |
# Now guesspath should be one of:
|
|
Patrick Uiterwijk |
4012dc |
# - reponame.git
|
|
Patrick Uiterwijk |
4012dc |
# - namespace/reponame.git
|
|
Patrick Uiterwijk |
4012dc |
# - forks/username/reponame.git
|
|
Patrick Uiterwijk |
4012dc |
# - forks/username/namespace/reponame.git
|
|
Patrick Uiterwijk |
4012dc |
repotype = match
|
|
Patrick Uiterwijk |
4012dc |
username = None
|
|
Pierre-Yves Chibon |
a4db36 |
namespace = None
|
|
Patrick Uiterwijk |
4012dc |
repo = None
|
|
Pierre-Yves Chibon |
a4db36 |
|
|
Patrick Uiterwijk |
4012dc |
guesspath, repo = os.path.split(guesspath)
|
|
Patrick Uiterwijk |
4012dc |
if not repo.endswith(".git"):
|
|
Patrick Uiterwijk |
4012dc |
raise ValueError("Git dir looks to not be a bare repo")
|
|
Patrick Uiterwijk |
4012dc |
repo = repo[: -len(".git")]
|
|
Patrick Uiterwijk |
4012dc |
if not repo:
|
|
Patrick Uiterwijk |
4012dc |
raise ValueError("Gitdir %s seems to not be a bare repo" % gitdir)
|
|
Patrick Uiterwijk |
4012dc |
|
|
Patrick Uiterwijk |
4012dc |
# Split the guesspath up, throwing out any empty strings
|
|
Patrick Uiterwijk |
4012dc |
splitguess = [part for part in guesspath.split("/") if part]
|
|
Patrick Uiterwijk |
4012dc |
if splitguess and splitguess[0] == "forks":
|
|
Patrick Uiterwijk |
4012dc |
if len(splitguess) < 2:
|
|
Patrick Uiterwijk |
4012dc |
raise ValueError("Invalid gitdir %s" % gitdir)
|
|
Patrick Uiterwijk |
4012dc |
username = splitguess[1]
|
|
Patrick Uiterwijk |
4012dc |
splitguess = splitguess[2:]
|
|
Patrick Uiterwijk |
4012dc |
|
|
Patrick Uiterwijk |
4012dc |
if splitguess:
|
|
Patrick Uiterwijk |
4012dc |
# At this point, we've cut off the repo name at the end, and any forks/
|
|
Patrick Uiterwijk |
4012dc |
# indicators and their usernames are also removed, so remains just the
|
|
Patrick Uiterwijk |
4012dc |
# namespace
|
|
Patrick Uiterwijk |
4012dc |
namespace = os.path.join(*splitguess)
|
|
Patrick Uiterwijk |
4012dc |
|
|
Patrick Uiterwijk |
4012dc |
# Okay, we think we have everything. Let's make doubly sure the path is
|
|
Patrick Uiterwijk |
4012dc |
# correct and exists
|
|
Patrick Uiterwijk |
4012dc |
rebuiltpath = os.path.join(
|
|
Patrick Uiterwijk |
4012dc |
typepath,
|
|
Patrick Uiterwijk |
4012dc |
"forks/" if username else "",
|
|
Patrick Uiterwijk |
4012dc |
username if username else "",
|
|
Patrick Uiterwijk |
4012dc |
namespace if namespace else "",
|
|
Patrick Uiterwijk |
4012dc |
repo + ".git",
|
|
Pierre-Yves Chibon |
9c2953 |
)
|
|
Patrick Uiterwijk |
4012dc |
if os.path.normpath(rebuiltpath) != gitdir:
|
|
Patrick Uiterwijk |
4012dc |
raise ValueError(
|
|
Patrick Uiterwijk |
4012dc |
"Rebuilt %s path not identical to gitdir %s"
|
|
Patrick Uiterwijk |
4012dc |
% (rebuiltpath, gitdir)
|
|
Patrick Uiterwijk |
4012dc |
)
|
|
Patrick Uiterwijk |
d75948 |
if not os.path.exists(rebuiltpath) and not hide_notfound:
|
|
Patrick Uiterwijk |
d75948 |
raise ValueError("Splitting gitdir %s failed" % gitdir)
|
|
Patrick Uiterwijk |
4012dc |
|
|
Patrick Uiterwijk |
4012dc |
return (repotype, username, namespace, repo)
|
|
Pierre-Yves Chibon |
09d70b |
|
|
Pierre-Yves Chibon |
09d70b |
|
|
Patrick Uiterwijk |
4012dc |
def get_repo_name(abspath):
|
|
Patrick Uiterwijk |
4012dc |
""" Return the name of the git repo based on its path.
|
|
Patrick Uiterwijk |
4012dc |
"""
|
|
Patrick Uiterwijk |
4012dc |
_, _, _, name = get_repo_info_from_path(abspath)
|
|
Patrick Uiterwijk |
4012dc |
return name
|
|
Pierre-Yves Chibon |
a4db36 |
|
|
Patrick Uiterwijk |
4012dc |
|
|
Patrick Uiterwijk |
4012dc |
def get_repo_namespace(abspath, gitfolder=None):
|
|
Patrick Uiterwijk |
4012dc |
""" Return the name of the git repo based on its path.
|
|
Patrick Uiterwijk |
4012dc |
"""
|
|
Patrick Uiterwijk |
4012dc |
_, _, namespace, _ = get_repo_info_from_path(abspath)
|
|
Pierre-Yves Chibon |
a4db36 |
return namespace
|
|
Pierre-Yves Chibon |
a4db36 |
|
|
Pierre-Yves Chibon |
a4db36 |
|
|
Pierre-Yves Chibon |
432e7d |
def get_username(abspath):
|
|
Pierre-Yves Chibon |
9c2953 |
""" Return the username of the git repo based on its path.
|
|
Pierre-Yves Chibon |
9c2953 |
"""
|
|
Patrick Uiterwijk |
4012dc |
_, username, _, _ = get_repo_info_from_path(abspath)
|
|
Pierre-Yves Chibon |
432e7d |
return username
|
|
Pierre-Yves Chibon |
0aaeb1 |
|
|
Pierre-Yves Chibon |
0aaeb1 |
|
|
Pierre-Yves Chibon |
c57267 |
def get_branch_ref(repo, branchname):
|
|
Pierre-Yves Chibon |
9c2953 |
""" Return the reference to the specified branch or raises an exception.
|
|
Pierre-Yves Chibon |
9c2953 |
"""
|
|
Pierre-Yves Chibon |
9126bb |
location = pygit2.GIT_BRANCH_LOCAL
|
|
Pierre-Yves Chibon |
9126bb |
if branchname not in repo.listall_branches():
|
|
Pierre-Yves Chibon |
9c2953 |
branchname = "origin/%s" % branchname
|
|
Pierre-Yves Chibon |
9126bb |
location = pygit2.GIT_BRANCH_REMOTE
|
|
Pierre-Yves Chibon |
e30013 |
branch_ref = repo.lookup_branch(branchname, location)
|
|
Pierre-Yves Chibon |
9126bb |
|
|
Pierre-Yves Chibon |
e30013 |
if not branch_ref or not branch_ref.resolve():
|
|
Pierre-Yves Chibon |
c57267 |
raise pagure.exceptions.PagureException(
|
|
Pierre-Yves Chibon |
9c2953 |
"No refs found for %s" % branchname
|
|
Pierre-Yves Chibon |
9c2953 |
)
|
|
Pierre-Yves Chibon |
e30013 |
return branch_ref.resolve()
|
|
Pierre-Yves Chibon |
c57267 |
|
|
Pierre-Yves Chibon |
c57267 |
|
|
Patrick Uiterwijk |
3f97f6 |
def merge_pull_request(session, request, username, domerge=True):
|
|
Pierre-Yves Chibon |
9c2953 |
""" Merge the specified pull-request.
|
|
Pierre-Yves Chibon |
9c2953 |
"""
|
|
Pierre-Yves Chibon |
b73de8 |
if domerge:
|
|
Pierre-Yves Chibon |
9c2953 |
_log.info("%s asked to merge the pull-request: %s", username, request)
|
|
Pierre-Yves Chibon |
b73de8 |
else:
|
|
Pierre-Yves Chibon |
9c2953 |
_log.info("%s asked to diff the pull-request: %s", username, request)
|
|
Pierre-Yves Chibon |
b73de8 |
|
|
Pierre-Yves Chibon |
c96124 |
repopath = None
|
|
Pierre-Yves Chibon |
28fa3d |
if request.remote:
|
|
Pierre-Yves Chibon |
28fa3d |
# Get the fork
|
|
Pierre-Yves Chibon |
b130e5 |
repopath = pagure.utils.get_remote_repo_path(
|
|
Pierre-Yves Chibon |
9c2953 |
request.remote_git, request.branch_from
|
|
Pierre-Yves Chibon |
9c2953 |
)
|
|
Pierre-Yves Chibon |
59f36c |
elif request.project_from:
|
|
Pierre-Yves Chibon |
28fa3d |
# Get the fork
|
|
Pierre-Yves Chibon |
b130e5 |
repopath = pagure.utils.get_repo_path(request.project_from)
|
|
Pierre-Yves Chibon |
0aaeb1 |
|
|
Pierre-Yves Chibon |
c96124 |
fork_obj = None
|
|
Pierre-Yves Chibon |
c96124 |
if repopath:
|
|
Pierre-Yves Chibon |
c96124 |
fork_obj = PagureRepo(repopath)
|
|
Pierre-Yves Chibon |
0aaeb1 |
|
|
Patrick Uiterwijk |
3f97f6 |
with TemporaryClone(request.project, "main", "merge_pr") as tempclone:
|
|
Patrick Uiterwijk |
3f97f6 |
new_repo = tempclone.repo
|
|
Pierre-Yves Chibon |
d10db0 |
|
|
Patrick Uiterwijk |
3f97f6 |
# Update the start and stop commits in the DB, one last time
|
|
Patrick Uiterwijk |
3f97f6 |
diff_commits = diff_pull_request(
|
|
Pierre-Yves Chibon |
b983f9 |
session,
|
|
Pierre-Yves Chibon |
b983f9 |
request,
|
|
Pierre-Yves Chibon |
b983f9 |
fork_obj,
|
|
Pierre-Yves Chibon |
b983f9 |
new_repo,
|
|
Pierre-Yves Chibon |
b983f9 |
with_diff=False,
|
|
Pierre-Yves Chibon |
b983f9 |
username=username,
|
|
Pierre-Yves Chibon |
9c2953 |
)
|
|
Patrick Uiterwijk |
3f97f6 |
_log.info(" %s commit to merge", len(diff_commits))
|
|
Pierre-Yves Chibon |
bef1de |
|
|
Patrick Uiterwijk |
3f97f6 |
if request.project.settings.get(
|
|
Patrick Uiterwijk |
3f97f6 |
"Enforce_signed-off_commits_in_pull-request", False
|
|
Patrick Uiterwijk |
3f97f6 |
):
|
|
Patrick Uiterwijk |
3f97f6 |
for commit in diff_commits:
|
|
Patrick Uiterwijk |
3f97f6 |
if "signed-off-by" not in commit.message.lower():
|
|
Patrick Uiterwijk |
3f97f6 |
_log.info(" Missing a required: signed-off-by: Bailing")
|
|
Patrick Uiterwijk |
3f97f6 |
raise pagure.exceptions.PagureException(
|
|
Patrick Uiterwijk |
3f97f6 |
"This repo enforces that all commits are "
|
|
Patrick Uiterwijk |
3f97f6 |
"signed off by their author. "
|
|
Patrick Uiterwijk |
3f97f6 |
)
|
|
Pierre-Yves Chibon |
28fa3d |
|
|
Pierre-Yves Chibon |
c96124 |
if not new_repo.is_empty and not new_repo.head_is_unborn:
|
|
Pierre-Yves Chibon |
c96124 |
try:
|
|
Pierre-Yves Chibon |
c96124 |
branch_ref = get_branch_ref(new_repo, request.branch)
|
|
Pierre-Yves Chibon |
c96124 |
except pagure.exceptions.PagureException:
|
|
Pierre-Yves Chibon |
c96124 |
branch_ref = None
|
|
Pierre-Yves Chibon |
c96124 |
if not branch_ref:
|
|
Pierre-Yves Chibon |
c96124 |
_log.info(" Target branch could not be found")
|
|
Pierre-Yves Chibon |
c96124 |
raise pagure.exceptions.BranchNotFoundException(
|
|
Pierre-Yves Chibon |
c96124 |
"Branch %s could not be found in the repo %s"
|
|
Pierre-Yves Chibon |
c96124 |
% (request.branch, request.project.fullname)
|
|
Pierre-Yves Chibon |
c96124 |
)
|
|
Pierre-Yves Chibon |
c96124 |
|
|
Pierre-Yves Chibon |
c96124 |
new_repo.checkout(branch_ref)
|
|
Pierre-Yves Chibon |
c96124 |
|
|
Pierre-Yves Chibon |
c96124 |
if fork_obj:
|
|
Pierre-Yves Chibon |
c96124 |
# Check/Get the branch from
|
|
Patrick Uiterwijk |
3f97f6 |
branch = None
|
|
Pierre-Yves Chibon |
c96124 |
try:
|
|
Pierre-Yves Chibon |
c96124 |
branch = get_branch_ref(fork_obj, request.branch_from)
|
|
Pierre-Yves Chibon |
c96124 |
except pagure.exceptions.PagureException:
|
|
Pierre-Yves Chibon |
c96124 |
pass
|
|
Pierre-Yves Chibon |
c96124 |
if not branch:
|
|
Pierre-Yves Chibon |
c96124 |
_log.info(" Branch of origin could not be found")
|
|
Pierre-Yves Chibon |
c96124 |
raise pagure.exceptions.BranchNotFoundException(
|
|
Pierre-Yves Chibon |
c96124 |
"Branch %s could not be found in the repo %s"
|
|
Pierre-Yves Chibon |
c96124 |
% (
|
|
Pierre-Yves Chibon |
c96124 |
request.branch_from,
|
|
Pierre-Yves Chibon |
c96124 |
request.project_from.fullname
|
|
Pierre-Yves Chibon |
c96124 |
if request.project_from
|
|
Pierre-Yves Chibon |
c96124 |
else request.remote_git,
|
|
Pierre-Yves Chibon |
c96124 |
)
|
|
Patrick Uiterwijk |
3f97f6 |
)
|
|
Pierre-Yves Chibon |
c96124 |
|
|
Pierre-Yves Chibon |
c96124 |
# Add the fork as remote repo
|
|
Pierre-Yves Chibon |
c96124 |
reponame = "%s_%s" % (request.user.user, request.uid)
|
|
Pierre-Yves Chibon |
c96124 |
|
|
Pierre-Yves Chibon |
c96124 |
_log.info(
|
|
Pierre-Yves Chibon |
c96124 |
" Adding remote: %s pointing to: %s", reponame, repopath
|
|
Patrick Uiterwijk |
3f97f6 |
)
|
|
Pierre-Yves Chibon |
c96124 |
remote = new_repo.create_remote(reponame, repopath)
|
|
Pierre-Yves Chibon |
0aaeb1 |
|
|
Pierre-Yves Chibon |
c96124 |
# Fetch the commits
|
|
Pierre-Yves Chibon |
c96124 |
remote.fetch()
|
|
Pierre-Yves Chibon |
0aaeb1 |
|
|
Pierre-Yves Chibon |
29ff0a |
# repo_commit = fork_obj[branch.peel().hex]
|
|
Pierre-Yves Chibon |
29ff0a |
repo_commit = new_repo[branch.peel().hex]
|
|
Pierre-Yves Chibon |
59f36c |
|
|
Pierre-Yves Chibon |
c96124 |
# Checkout the correct branch
|
|
Pierre-Yves Chibon |
c96124 |
if new_repo.is_empty or new_repo.head_is_unborn:
|
|
Pierre-Yves Chibon |
c96124 |
_log.debug(
|
|
Pierre-Yves Chibon |
c96124 |
" target repo is empty, so PR can be merged using "
|
|
Pierre-Yves Chibon |
c96124 |
"fast-forward, reporting it"
|
|
Pierre-Yves Chibon |
c96124 |
)
|
|
Pierre-Yves Chibon |
59f36c |
|
|
Pierre-Yves Chibon |
c96124 |
if domerge:
|
|
Pierre-Yves Chibon |
c96124 |
_log.info(" PR merged using fast-forward")
|
|
Pierre-Yves Chibon |
c96124 |
if not request.project.settings.get("always_merge", False):
|
|
Pierre-Yves Chibon |
c96124 |
new_repo.create_branch(request.branch, repo_commit)
|
|
Pierre-Yves Chibon |
c96124 |
commit = repo_commit.oid.hex
|
|
Pierre-Yves Chibon |
c96124 |
else:
|
|
Pierre-Yves Chibon |
c96124 |
tree = new_repo.index.write_tree()
|
|
Pierre-Yves Chibon |
c96124 |
user_obj = pagure.lib.query.get_user(session, username)
|
|
Pierre-Yves Chibon |
c96124 |
commitname = user_obj.fullname or user_obj.user
|
|
Pierre-Yves Chibon |
c96124 |
author = _make_signature(
|
|
Pierre-Yves Chibon |
c96124 |
commitname, user_obj.default_email
|
|
Pierre-Yves Chibon |
c96124 |
)
|
|
Pierre-Yves Chibon |
c96124 |
commit = new_repo.create_commit(
|
|
Pierre-Yves Chibon |
c96124 |
"refs/heads/%s" % request.branch,
|
|
Pierre-Yves Chibon |
c96124 |
author,
|
|
Pierre-Yves Chibon |
c96124 |
author,
|
|
Pierre-Yves Chibon |
c96124 |
"Merge #%s `%s`" % (request.id, request.title),
|
|
Pierre-Yves Chibon |
c96124 |
tree,
|
|
Pierre-Yves Chibon |
c96124 |
[repo_commit.oid.hex],
|
|
Pierre-Yves Chibon |
c96124 |
)
|
|
Patrick Uiterwijk |
3f97f6 |
|
|
Pierre-Yves Chibon |
c96124 |
_log.info(" New head: %s", commit)
|
|
Pierre-Yves Chibon |
c96124 |
tempclone.push(
|
|
Pierre-Yves Chibon |
c96124 |
username,
|
|
Pierre-Yves Chibon |
c96124 |
request.branch,
|
|
Pierre-Yves Chibon |
c96124 |
request.branch,
|
|
Pierre-Yves Chibon |
c96124 |
pull_request=request,
|
|
Patrick Uiterwijk |
3f97f6 |
)
|
|
Pierre-Yves Chibon |
59f36c |
|
|
Pierre-Yves Chibon |
c96124 |
# Update status
|
|
Pierre-Yves Chibon |
c96124 |
_log.info(" Closing the PR in the DB")
|
|
Pierre-Yves Chibon |
c96124 |
pagure.lib.query.close_pull_request(
|
|
Pierre-Yves Chibon |
c96124 |
session, request, username
|
|
Pierre-Yves Chibon |
c96124 |
)
|
|
Pierre-Yves Chibon |
59f36c |
|
|
Pierre-Yves Chibon |
c96124 |
return "Changes merged!"
|
|
Pierre-Yves Chibon |
c96124 |
else:
|
|
Pierre-Yves Chibon |
c96124 |
_log.info(
|
|
Pierre-Yves Chibon |
c96124 |
" PR can be merged using fast-forward, reporting it"
|
|
Pierre-Yves Chibon |
c96124 |
)
|
|
Pierre-Yves Chibon |
c96124 |
request.merge_status = "FFORWARD"
|
|
Pierre-Yves Chibon |
c96124 |
session.commit()
|
|
Pierre-Yves Chibon |
c96124 |
return "FFORWARD"
|
|
Pierre-Yves Chibon |
59f36c |
|
|
Pierre-Yves Chibon |
c96124 |
else:
|
|
Pierre-Yves Chibon |
c96124 |
try:
|
|
Pierre-Yves Chibon |
c96124 |
ref = new_repo.lookup_reference(
|
|
Pierre-Yves Chibon |
c96124 |
"refs/pull/%s/head" % request.id
|
|
Pierre-Yves Chibon |
97d19d |
)
|
|
Pierre-Yves Chibon |
c96124 |
repo_commit = new_repo[ref.target.hex]
|
|
Pierre-Yves Chibon |
c96124 |
except KeyError:
|
|
Pierre-Yves Chibon |
c96124 |
pass
|
|
Pierre-Yves Chibon |
99d493 |
|
|
Patrick Uiterwijk |
3f97f6 |
merge = new_repo.merge(repo_commit.oid)
|
|
Patrick Uiterwijk |
3f97f6 |
_log.debug(" Merge: %s", merge)
|
|
Patrick Uiterwijk |
3f97f6 |
if merge is None:
|
|
Patrick Uiterwijk |
3f97f6 |
mergecode = new_repo.merge_analysis(repo_commit.oid)[0]
|
|
Patrick Uiterwijk |
3f97f6 |
_log.debug(" Mergecode: %s", mergecode)
|
|
Pierre-Yves Chibon |
a19f20 |
|
|
Patrick Uiterwijk |
3f97f6 |
# Wait until the last minute then check if the PR was already closed
|
|
Patrick Uiterwijk |
3f97f6 |
# by someone else in the mean while and if so, just bail
|
|
Patrick Uiterwijk |
3f97f6 |
if request.status != "Open":
|
|
Patrick Uiterwijk |
3f97f6 |
_log.info(
|
|
Patrick Uiterwijk |
3f97f6 |
" This pull-request has already been merged or closed by %s "
|
|
Patrick Uiterwijk |
3f97f6 |
"on %s" % (request.closed_by.user, request.closed_at)
|
|
Pierre-Yves Chibon |
9c2953 |
)
|
|
Pierre-Yves Chibon |
0aaeb1 |
raise pagure.exceptions.PagureException(
|
|
Patrick Uiterwijk |
3f97f6 |
"This pull-request was merged or closed by %s"
|
|
Patrick Uiterwijk |
3f97f6 |
% request.closed_by.user
|
|
Pierre-Yves Chibon |
9c2953 |
)
|
|
Patrick Uiterwijk |
3f97f6 |
|
|
Patrick Uiterwijk |
3f97f6 |
if (merge is not None and merge.is_uptodate) or ( # noqa
|
|
Patrick Uiterwijk |
3f97f6 |
merge is None and mergecode & pygit2.GIT_MERGE_ANALYSIS_UP_TO_DATE
|
|
Patrick Uiterwijk |
3f97f6 |
):
|
|
Patrick Uiterwijk |
3f97f6 |
|
|
Patrick Uiterwijk |
3f97f6 |
if domerge:
|
|
Patrick Uiterwijk |
3f97f6 |
_log.info(" PR up to date, closing it")
|
|
Pierre-Yves Chibon |
930073 |
pagure.lib.query.close_pull_request(session, request, username)
|
|
Patrick Uiterwijk |
3f97f6 |
try:
|
|
Patrick Uiterwijk |
3f97f6 |
session.commit()
|
|
Karsten Hopp |
3b333e |
except SQLAlchemyError: # pragma: no cover
|
|
Patrick Uiterwijk |
3f97f6 |
session.rollback()
|
|
Patrick Uiterwijk |
3f97f6 |
_log.exception(" Could not merge the PR in the DB")
|
|
Patrick Uiterwijk |
3f97f6 |
raise pagure.exceptions.PagureException(
|
|
Patrick Uiterwijk |
3f97f6 |
"Could not close this pull-request"
|
|
Patrick Uiterwijk |
3f97f6 |
)
|
|
Patrick Uiterwijk |
3f97f6 |
raise pagure.exceptions.PagureException(
|
|
Patrick Uiterwijk |
3f97f6 |
"Nothing to do, changes were already merged"
|
|
Patrick Uiterwijk |
3f97f6 |
)
|
|
Patrick Uiterwijk |
3f97f6 |
else:
|
|
Patrick Uiterwijk |
3f97f6 |
_log.info(" PR up to date, reporting it")
|
|
Patrick Uiterwijk |
3f97f6 |
request.merge_status = "NO_CHANGE"
|
|
Patrick Uiterwijk |
3f97f6 |
session.commit()
|
|
Patrick Uiterwijk |
3f97f6 |
return "NO_CHANGE"
|
|
Patrick Uiterwijk |
3f97f6 |
|
|
Patrick Uiterwijk |
3f97f6 |
elif (merge is not None and merge.is_fastforward) or ( # noqa
|
|
Patrick Uiterwijk |
3f97f6 |
merge is None and mergecode & pygit2.GIT_MERGE_ANALYSIS_FASTFORWARD
|
|
Patrick Uiterwijk |
3f97f6 |
):
|
|
Patrick Uiterwijk |
3f97f6 |
|
|
Patrick Uiterwijk |
3f97f6 |
if domerge:
|
|
Patrick Uiterwijk |
3f97f6 |
_log.info(" PR merged using fast-forward")
|
|
Pierre-Yves Chibon |
29ff0a |
head = new_repo.lookup_reference("HEAD").peel()
|
|
Patrick Uiterwijk |
3f97f6 |
if not request.project.settings.get("always_merge", False):
|
|
Patrick Uiterwijk |
3f97f6 |
if merge is not None:
|
|
Patrick Uiterwijk |
3f97f6 |
# This is depending on the pygit2 version
|
|
Patrick Uiterwijk |
3f97f6 |
branch_ref.target = merge.fastforward_oid
|
|
Patrick Uiterwijk |
3f97f6 |
elif merge is None and mergecode is not None:
|
|
Patrick Uiterwijk |
3f97f6 |
branch_ref.set_target(repo_commit.oid.hex)
|
|
Patrick Uiterwijk |
3f97f6 |
commit = repo_commit.oid.hex
|
|
Patrick Uiterwijk |
3f97f6 |
else:
|
|
Patrick Uiterwijk |
3f97f6 |
tree = new_repo.index.write_tree()
|
|
Pierre-Yves Chibon |
930073 |
user_obj = pagure.lib.query.get_user(session, username)
|
|
Patrick Uiterwijk |
3f97f6 |
commitname = user_obj.fullname or user_obj.user
|
|
Patrick Uiterwijk |
3f97f6 |
author = _make_signature(
|
|
Patrick Uiterwijk |
3f97f6 |
commitname, user_obj.default_email
|
|
Patrick Uiterwijk |
3f97f6 |
)
|
|
Pierre-Yves Chibon |
707873 |
|
|
Pierre-Yves Chibon |
707873 |
commit_message = "Merge #%s `%s`" % (
|
|
Pierre-Yves Chibon |
707873 |
request.id,
|
|
Pierre-Yves Chibon |
707873 |
request.title,
|
|
Pierre-Yves Chibon |
707873 |
)
|
|
Pierre-Yves Chibon |
707873 |
if request.project.settings.get(
|
|
Pierre-Yves Chibon |
707873 |
"Enforce_signed-off_commits_in_pull-request", False
|
|
Pierre-Yves Chibon |
707873 |
):
|
|
Pierre-Yves Chibon |
7bf987 |
commit_message += "\n\nSigned-off-by: %s <%s>" % (
|
|
Pierre-Yves Chibon |
707873 |
commitname,
|
|
Pierre-Yves Chibon |
707873 |
user_obj.default_email,
|
|
Pierre-Yves Chibon |
707873 |
)
|
|
Pierre-Yves Chibon |
707873 |
|
|
Patrick Uiterwijk |
3f97f6 |
commit = new_repo.create_commit(
|
|
Patrick Uiterwijk |
3f97f6 |
"refs/heads/%s" % request.branch,
|
|
Patrick Uiterwijk |
3f97f6 |
author,
|
|
Patrick Uiterwijk |
3f97f6 |
author,
|
|
Pierre-Yves Chibon |
707873 |
commit_message,
|
|
Patrick Uiterwijk |
3f97f6 |
tree,
|
|
Patrick Uiterwijk |
3f97f6 |
[head.hex, repo_commit.oid.hex],
|
|
Patrick Uiterwijk |
3f97f6 |
)
|
|
Patrick Uiterwijk |
3f97f6 |
|
|
Patrick Uiterwijk |
3f97f6 |
_log.info(" New head: %s", commit)
|
|
Patrick Uiterwijk |
03a519 |
tempclone.push(
|
|
Patrick Uiterwijk |
03a519 |
username,
|
|
Patrick Uiterwijk |
03a519 |
branch_ref.name,
|
|
Patrick Uiterwijk |
03a519 |
request.branch,
|
|
Patrick Uiterwijk |
03a519 |
pull_request=request,
|
|
Patrick Uiterwijk |
03a519 |
)
|
|
Pierre-Yves Chibon |
ccc85e |
else:
|
|
Pierre-Yves Chibon |
97d19d |
_log.info(
|
|
Pierre-Yves Chibon |
97d19d |
" PR can be merged using fast-forward, reporting it"
|
|
Pierre-Yves Chibon |
97d19d |
)
|
|
Patrick Uiterwijk |
3f97f6 |
request.merge_status = "FFORWARD"
|
|
Patrick Uiterwijk |
3f97f6 |
session.commit()
|
|
Patrick Uiterwijk |
3f97f6 |
return "FFORWARD"
|
|
Patrick Uiterwijk |
3f97f6 |
|
|
Patrick Uiterwijk |
3f97f6 |
else:
|
|
Patrick Uiterwijk |
3f97f6 |
tree = None
|
|
Patrick Uiterwijk |
3f97f6 |
try:
|
|
Pierre-Yves Chibon |
ccc85e |
tree = new_repo.index.write_tree()
|
|
Patrick Uiterwijk |
3f97f6 |
except pygit2.GitError as err:
|
|
Patrick Uiterwijk |
3f97f6 |
_log.debug(
|
|
Patrick Uiterwijk |
3f97f6 |
" Could not write down the new tree: " "merge conflicts"
|
|
Patrick Uiterwijk |
3f97f6 |
)
|
|
Patrick Uiterwijk |
3f97f6 |
_log.debug(err)
|
|
Patrick Uiterwijk |
3f97f6 |
if domerge:
|
|
Patrick Uiterwijk |
3f97f6 |
_log.info(" Merge conflict: Bailing")
|
|
Patrick Uiterwijk |
3f97f6 |
raise pagure.exceptions.PagureException("Merge conflicts!")
|
|
Patrick Uiterwijk |
3f97f6 |
else:
|
|
Patrick Uiterwijk |
3f97f6 |
_log.info(" Merge conflict, reporting it")
|
|
Patrick Uiterwijk |
3f97f6 |
request.merge_status = "CONFLICTS"
|
|
Patrick Uiterwijk |
3f97f6 |
session.commit()
|
|
Patrick Uiterwijk |
3f97f6 |
return "CONFLICTS"
|
|
Patrick Uiterwijk |
3f97f6 |
|
|
Patrick Uiterwijk |
3f97f6 |
if domerge:
|
|
Slavek Kabrda |
cdb053 |
if request.project.settings.get(
|
|
Slavek Kabrda |
cdb053 |
"disable_non_fast-forward_merges", False
|
|
Slavek Kabrda |
cdb053 |
):
|
|
Slavek Kabrda |
cdb053 |
_log.info(" Merge non-FF PR is disabled for this project")
|
|
Slavek Kabrda |
cdb053 |
return "MERGE"
|
|
Patrick Uiterwijk |
3f97f6 |
_log.info(" Writing down merge commit")
|
|
Pierre-Yves Chibon |
29ff0a |
head = new_repo.lookup_reference("HEAD").peel()
|
|
Patrick Uiterwijk |
3f97f6 |
_log.info(
|
|
Patrick Uiterwijk |
3f97f6 |
" Basing on: %s - %s", head.hex, repo_commit.oid.hex
|
|
Patrick Uiterwijk |
3f97f6 |
)
|
|
Pierre-Yves Chibon |
930073 |
user_obj = pagure.lib.query.get_user(session, username)
|
|
Pierre-Yves Chibon |
157c26 |
commitname = user_obj.fullname or user_obj.user
|
|
Pierre-Yves Chibon |
9c2953 |
author = _make_signature(commitname, user_obj.default_email)
|
|
Pierre-Yves Chibon |
707873 |
|
|
Pierre-Yves Chibon |
707873 |
commit_message = "Merge #%s `%s`" % (request.id, request.title)
|
|
Pierre-Yves Chibon |
707873 |
if request.project.settings.get(
|
|
Pierre-Yves Chibon |
707873 |
"Enforce_signed-off_commits_in_pull-request", False
|
|
Pierre-Yves Chibon |
707873 |
):
|
|
Pierre-Yves Chibon |
7bf987 |
commit_message += "\n\nSigned-off-by: %s <%s>" % (
|
|
Pierre-Yves Chibon |
707873 |
commitname,
|
|
Pierre-Yves Chibon |
707873 |
user_obj.default_email,
|
|
Pierre-Yves Chibon |
707873 |
)
|
|
Pierre-Yves Chibon |
707873 |
|
|
Pierre-Yves Chibon |
5a8c6a |
commit = new_repo.create_commit(
|
|
Pierre-Yves Chibon |
9c2953 |
"refs/heads/%s" % request.branch,
|
|
Pierre-Yves Chibon |
ccc85e |
author,
|
|
Pierre-Yves Chibon |
ccc85e |
author,
|
|
Pierre-Yves Chibon |
707873 |
commit_message,
|
|
Pierre-Yves Chibon |
ccc85e |
tree,
|
|
Pierre-Yves Chibon |
9c2953 |
[head.hex, repo_commit.oid.hex],
|
|
Pierre-Yves Chibon |
9c2953 |
)
|
|
Pierre-Yves Chibon |
a19f20 |
|
|
Patrick Uiterwijk |
3f97f6 |
_log.info(" New head: %s", commit)
|
|
Patrick Uiterwijk |
3f97f6 |
local_ref = "refs/heads/_pagure_topush"
|
|
Patrick Uiterwijk |
3f97f6 |
new_repo.create_reference(local_ref, commit)
|
|
Patrick Uiterwijk |
03a519 |
tempclone.push(
|
|
Patrick Uiterwijk |
03a519 |
username, local_ref, request.branch, pull_request=request
|
|
Patrick Uiterwijk |
3f97f6 |
)
|
|
Pierre-Yves Chibon |
0aaeb1 |
|
|
Pierre-Yves Chibon |
a19f20 |
else:
|
|
Patrick Uiterwijk |
3f97f6 |
_log.info(
|
|
Patrick Uiterwijk |
3f97f6 |
" PR can be merged with a merge commit, " "reporting it"
|
|
Patrick Uiterwijk |
3f97f6 |
)
|
|
Patrick Uiterwijk |
3f97f6 |
request.merge_status = "MERGE"
|
|
Pierre-Yves Chibon |
a19f20 |
session.commit()
|
|
Patrick Uiterwijk |
3f97f6 |
return "MERGE"
|
|
Pierre-Yves Chibon |
0aaeb1 |
|
|
Pierre-Yves Chibon |
0aaeb1 |
# Update status
|
|
Pierre-Yves Chibon |
9c2953 |
_log.info(" Closing the PR in the DB")
|
|
Pierre-Yves Chibon |
930073 |
pagure.lib.query.close_pull_request(session, request, username)
|
|
Pierre-Yves Chibon |
0aaeb1 |
|
|
Pierre-Yves Chibon |
9c2953 |
return "Changes merged!"
|
|
Pierre-Yves Chibon |
dbf3e1 |
|
|
Pierre-Yves Chibon |
dbf3e1 |
|
|
Pierre-Yves Chibon |
011b16 |
def rebase_pull_request(session, request, username):
|
|
Pierre-Yves Chibon |
9b2a96 |
""" Rebase the specified pull-request.
|
|
Pierre-Yves Chibon |
9b2a96 |
|
|
Pierre-Yves Chibon |
9b2a96 |
Args:
|
|
Pierre-Yves Chibon |
9b2a96 |
session (sqlalchemy): the session to connect to the database with
|
|
Pierre-Yves Chibon |
9b2a96 |
request (pagure.lib.model.PullRequest): the database object
|
|
Pierre-Yves Chibon |
9b2a96 |
corresponding to the pull-request to rebase
|
|
Pierre-Yves Chibon |
9b2a96 |
username (string): the name of the user asking for the pull-request
|
|
Pierre-Yves Chibon |
9b2a96 |
to be rebased
|
|
Pierre-Yves Chibon |
9b2a96 |
|
|
Pierre-Yves Chibon |
9b2a96 |
Returns: (string or None): Pull-request rebased
|
|
Pierre-Yves Chibon |
9b2a96 |
Raises: pagure.exceptions.PagureException
|
|
Pierre-Yves Chibon |
9b2a96 |
|
|
Pierre-Yves Chibon |
9b2a96 |
"""
|
|
Pierre-Yves Chibon |
0b785c |
_log.info("%s asked to rebase the pull-request: %s", username, request)
|
|
Pierre-Yves Chibon |
011b16 |
user = pagure.lib.query.get_user(session, username)
|
|
Pierre-Yves Chibon |
9b2a96 |
|
|
Pierre-Yves Chibon |
9b2a96 |
if request.remote:
|
|
Pierre-Yves Chibon |
9b2a96 |
# Get the fork
|
|
Pierre-Yves Chibon |
9b2a96 |
repopath = pagure.utils.get_remote_repo_path(
|
|
Pierre-Yves Chibon |
9b2a96 |
request.remote_git, request.branch_from
|
|
Pierre-Yves Chibon |
9b2a96 |
)
|
|
Pierre-Yves Chibon |
9b2a96 |
elif request.project_from:
|
|
Pierre-Yves Chibon |
9b2a96 |
# Get the fork
|
|
Pierre-Yves Chibon |
9b2a96 |
repopath = pagure.utils.get_repo_path(request.project_from)
|
|
Pierre-Yves Chibon |
9b2a96 |
else:
|
|
Pierre-Yves Chibon |
d91c53 |
_log.info(
|
|
Pierre-Yves Chibon |
d91c53 |
"PR is neither from a remote git repo or an existing local "
|
|
Pierre-Yves Chibon |
accad9 |
"repo, bailing"
|
|
Pierre-Yves Chibon |
accad9 |
)
|
|
Pierre-Yves Chibon |
9b2a96 |
return
|
|
Pierre-Yves Chibon |
9b2a96 |
|
|
Pierre-Yves Chibon |
9b2a96 |
if not request.project or not os.path.exists(
|
|
Pierre-Yves Chibon |
9b2a96 |
pagure.utils.get_repo_path(request.project)
|
|
Pierre-Yves Chibon |
9b2a96 |
):
|
|
Pierre-Yves Chibon |
d91c53 |
_log.info(
|
|
Pierre-Yves Chibon |
d91c53 |
"Could not find the targeted git repository for %s",
|
|
Pierre-Yves Chibon |
accad9 |
request.project.fullname,
|
|
Pierre-Yves Chibon |
accad9 |
)
|
|
Pierre-Yves Chibon |
9b2a96 |
raise pagure.exceptions.PagureException(
|
|
Pierre-Yves Chibon |
9b2a96 |
"Could not find the targeted git repository for %s"
|
|
Pierre-Yves Chibon |
9b2a96 |
% request.project.fullname
|
|
Pierre-Yves Chibon |
9b2a96 |
)
|
|
Pierre-Yves Chibon |
9b2a96 |
|
|
Pierre-Yves Chibon |
9b2a96 |
with TemporaryClone(
|
|
Pierre-Yves Chibon |
9b2a96 |
project=request.project,
|
|
Pierre-Yves Chibon |
9b2a96 |
repotype="main",
|
|
Pierre-Yves Chibon |
9b2a96 |
action="rebase_pr",
|
|
Pierre-Yves Chibon |
9b2a96 |
path=repopath,
|
|
Pierre-Yves Chibon |
9b2a96 |
) as tempclone:
|
|
Pierre-Yves Chibon |
9b2a96 |
new_repo = tempclone.repo
|
|
Pierre-Yves Chibon |
9b2a96 |
new_repo.checkout("refs/heads/%s" % request.branch_from)
|
|
Pierre-Yves Chibon |
9b2a96 |
|
|
Pierre-Yves Chibon |
9b2a96 |
# Add the upstream repo as remote
|
|
Pierre-Yves Chibon |
9b2a96 |
upstream = "%s_%s" % (request.user.user, request.uid)
|
|
Pierre-Yves Chibon |
9b2a96 |
upstream_path = pagure.utils.get_repo_path(request.project)
|
|
Pierre-Yves Chibon |
9b2a96 |
_log.info(
|
|
Pierre-Yves Chibon |
9b2a96 |
" Adding remote: %s pointing to: %s", upstream, upstream_path
|
|
Pierre-Yves Chibon |
9b2a96 |
)
|
|
Pierre-Yves Chibon |
9b2a96 |
remote = new_repo.create_remote(upstream, upstream_path)
|
|
Pierre-Yves Chibon |
9b2a96 |
|
|
Pierre-Yves Chibon |
9b2a96 |
# Fetch the commits
|
|
Pierre-Yves Chibon |
9b2a96 |
remote.fetch()
|
|
Pierre-Yves Chibon |
9b2a96 |
|
|
Pierre-Yves Chibon |
9b2a96 |
def _run_command(command):
|
|
Pierre-Yves Chibon |
d91c53 |
_log.info("Running command: %s", command)
|
|
Pierre-Yves Chibon |
9b2a96 |
try:
|
|
Pierre-Yves Chibon |
9b2a96 |
out = subprocess.check_output(
|
|
Pierre-Yves Chibon |
9b2a96 |
command, cwd=tempclone.repopath, stderr=subprocess.STDOUT
|
|
Pierre-Yves Chibon |
9b2a96 |
)
|
|
Pierre-Yves Chibon |
d91c53 |
_log.info(" command ran successfully")
|
|
Pierre-Yves Chibon |
9b2a96 |
_log.debug("Output: %s" % out)
|
|
Pierre-Yves Chibon |
9b2a96 |
except subprocess.CalledProcessError as err:
|
|
Pierre-Yves Chibon |
9b2a96 |
_log.debug(
|
|
Pierre-Yves Chibon |
9b2a96 |
"Rebase FAILED: {cmd} returned code {code} with the "
|
|
Pierre-Yves Chibon |
9b2a96 |
"following output: {output}".format(
|
|
Pierre-Yves Chibon |
9b2a96 |
cmd=err.cmd, code=err.returncode, output=err.output
|
|
Pierre-Yves Chibon |
9b2a96 |
)
|
|
Pierre-Yves Chibon |
9b2a96 |
)
|
|
Pierre-Yves Chibon |
9b2a96 |
raise pagure.exceptions.PagureException(
|
|
Pierre-Yves Chibon |
9b2a96 |
"Did not manage to rebase this pull-request"
|
|
Pierre-Yves Chibon |
9b2a96 |
)
|
|
Pierre-Yves Chibon |
9b2a96 |
|
|
Pierre-Yves Chibon |
9b2a96 |
# Configure git for that user
|
|
Pierre-Yves Chibon |
9b2a96 |
command = ["git", "config", "user.name", username]
|
|
Pierre-Yves Chibon |
9b2a96 |
_run_command(command)
|
|
Pierre-Yves Chibon |
011b16 |
command = ["git", "config", "user.email", user.default_email]
|
|
Pierre-Yves Chibon |
9b2a96 |
_run_command(command)
|
|
Pierre-Yves Chibon |
9b2a96 |
|
|
Pierre-Yves Chibon |
9b2a96 |
# Do the rebase
|
|
Pierre-Yves Chibon |
9b2a96 |
command = ["git", "pull", "--rebase", upstream, request.branch]
|
|
Pierre-Yves Chibon |
9b2a96 |
_run_command(command)
|
|
Pierre-Yves Chibon |
9b2a96 |
|
|
Pierre-Yves Chibon |
9b2a96 |
# Retrieve the reference of the branch we're working on
|
|
Pierre-Yves Chibon |
9b2a96 |
try:
|
|
Pierre-Yves Chibon |
9b2a96 |
branch_ref = get_branch_ref(new_repo, request.branch_from)
|
|
Pierre-Yves Chibon |
9b2a96 |
except pagure.exceptions.PagureException:
|
|
Pierre-Yves Chibon |
9b2a96 |
branch_ref = None
|
|
Pierre-Yves Chibon |
9b2a96 |
if not branch_ref:
|
|
Pierre-Yves Chibon |
9b2a96 |
_log.debug(" Target branch could not be found")
|
|
Pierre-Yves Chibon |
9b2a96 |
raise pagure.exceptions.BranchNotFoundException(
|
|
Pierre-Yves Chibon |
9b2a96 |
"Branch %s could not be found in the repo %s"
|
|
Pierre-Yves Chibon |
9b2a96 |
% (request.branch, request.project.fullname)
|
|
Pierre-Yves Chibon |
9b2a96 |
)
|
|
Pierre-Yves Chibon |
9b2a96 |
|
|
Pierre-Yves Chibon |
9b2a96 |
# Push the changes
|
|
Pierre-Yves Chibon |
9b2a96 |
_log.info("Pushing %s to %s", branch_ref.name, request.branch_from)
|
|
Pierre-Yves Chibon |
9b2a96 |
try:
|
|
Pierre-Yves Chibon |
e180e7 |
if request.allow_rebase:
|
|
Pierre-Yves Chibon |
e180e7 |
tempclone.push(
|
|
Pierre-Yves Chibon |
e180e7 |
username,
|
|
Pierre-Yves Chibon |
e180e7 |
branch_ref.name,
|
|
Pierre-Yves Chibon |
e180e7 |
request.branch_from,
|
|
Pierre-Yves Chibon |
e180e7 |
pull_request=request,
|
|
Pierre-Yves Chibon |
e180e7 |
force=True,
|
|
Pierre-Yves Chibon |
e180e7 |
internal="yes",
|
|
Pierre-Yves Chibon |
e180e7 |
)
|
|
Pierre-Yves Chibon |
e180e7 |
else:
|
|
Pierre-Yves Chibon |
e180e7 |
tempclone.push(
|
|
Pierre-Yves Chibon |
e180e7 |
username,
|
|
Pierre-Yves Chibon |
e180e7 |
branch_ref.name,
|
|
Pierre-Yves Chibon |
e180e7 |
request.branch_from,
|
|
Pierre-Yves Chibon |
e180e7 |
pull_request=request,
|
|
Pierre-Yves Chibon |
e180e7 |
force=True,
|
|
Pierre-Yves Chibon |
e180e7 |
)
|
|
Pierre-Yves Chibon |
9b2a96 |
except subprocess.CalledProcessError as err:
|
|
Pierre-Yves Chibon |
9b2a96 |
_log.debug(
|
|
Pierre-Yves Chibon |
9b2a96 |
"Rebase FAILED: {cmd} returned code {code} with the "
|
|
Pierre-Yves Chibon |
9b2a96 |
"following output: {output}".format(
|
|
Pierre-Yves Chibon |
9b2a96 |
cmd=err.cmd, code=err.returncode, output=err.output
|
|
Pierre-Yves Chibon |
9b2a96 |
)
|
|
Pierre-Yves Chibon |
9b2a96 |
)
|
|
Pierre-Yves Chibon |
9b2a96 |
raise pagure.exceptions.PagureException(
|
|
Pierre-Yves Chibon |
9b2a96 |
"Did not manage to rebase this pull-request"
|
|
Pierre-Yves Chibon |
9b2a96 |
)
|
|
Pierre-Yves Chibon |
9b2a96 |
|
|
Pierre-Yves Chibon |
9b2a96 |
return "Pull-request rebased"
|
|
Pierre-Yves Chibon |
9b2a96 |
|
|
Pierre-Yves Chibon |
9b2a96 |
|
|
Pierre-Yves Chibon |
ff9832 |
def get_diff_info(repo_obj, orig_repo, branch_from, branch_to, prid=None):
|
|
Pierre-Yves Chibon |
9c2953 |
""" Return the info needed to see a diff or make a Pull-Request between
|
|
Pierre-Yves Chibon |
875a08 |
the two specified repo.
|
|
Pierre-Yves Chibon |
dbf3e1 |
|
|
Pierre-Yves Chibon |
875a08 |
:arg repo_obj: The pygit2.Repository object of the first git repo
|
|
Pierre-Yves Chibon |
875a08 |
:arg orig_repo: The pygit2.Repository object of the second git repo
|
|
Pierre-Yves Chibon |
875a08 |
:arg branch_from: the name of the branch having the changes, in the
|
|
Pierre-Yves Chibon |
875a08 |
first git repo
|
|
Pierre-Yves Chibon |
41dbac |
:arg branch_to: the name of the branch in which we want to merge the
|
|
Pierre-Yves Chibon |
875a08 |
changes in the second git repo
|
|
Pierre-Yves Chibon |
ff9832 |
:kwarg prid: the identifier of the pull-request to
|
|
Pierre-Yves Chibon |
dbf3e1 |
|
|
Pierre-Yves Chibon |
9c2953 |
"""
|
|
Pierre-Yves Chibon |
e3d601 |
try:
|
|
Pierre-Yves Chibon |
e3d601 |
frombranch = repo_obj.lookup_branch(branch_from)
|
|
Pierre-Yves Chibon |
e3d601 |
except ValueError:
|
|
Pierre-Yves Chibon |
e3d601 |
raise pagure.exceptions.BranchNotFoundException(
|
|
Pierre-Yves Chibon |
9c2953 |
"Branch %s does not exist" % branch_from
|
|
Pierre-Yves Chibon |
e3d601 |
)
|
|
Pierre-Yves Chibon |
c96124 |
except AttributeError:
|
|
Pierre-Yves Chibon |
c96124 |
frombranch = None
|
|
Pierre-Yves Chibon |
c96124 |
if not frombranch and prid is None and repo_obj and not repo_obj.is_empty:
|
|
Pierre-Yves Chibon |
875a08 |
raise pagure.exceptions.BranchNotFoundException(
|
|
Pierre-Yves Chibon |
9c2953 |
"Branch %s does not exist" % branch_from
|
|
Stanislav Laznicka |
14c8c3 |
)
|
|
Pierre-Yves Chibon |
0bc5ac |
|
|
Pierre-Yves Chibon |
875a08 |
branch = None
|
|
Pierre-Yves Chibon |
875a08 |
if branch_to:
|
|
Pierre-Yves Chibon |
e3d601 |
try:
|
|
Pierre-Yves Chibon |
e3d601 |
branch = orig_repo.lookup_branch(branch_to)
|
|
Pierre-Yves Chibon |
e3d601 |
except ValueError:
|
|
Pierre-Yves Chibon |
e3d601 |
raise pagure.exceptions.BranchNotFoundException(
|
|
Pierre-Yves Chibon |
9c2953 |
"Branch %s does not exist" % branch_to
|
|
Pierre-Yves Chibon |
e3d601 |
)
|
|
Pierre-Yves Chibon |
189430 |
local_branches = orig_repo.listall_branches(pygit2.GIT_BRANCH_LOCAL)
|
|
Pierre-Yves Chibon |
189430 |
if not branch and local_branches:
|
|
Pierre-Yves Chibon |
875a08 |
raise pagure.exceptions.BranchNotFoundException(
|
|
Pierre-Yves Chibon |
9c2953 |
"Branch %s could not be found in the target repo" % branch_to
|
|
Pierre-Yves Chibon |
875a08 |
)
|
|
Pierre-Yves Chibon |
5e3931 |
|
|
Pierre-Yves Chibon |
875a08 |
commitid = None
|
|
Pierre-Yves Chibon |
875a08 |
if frombranch:
|
|
Pierre-Yves Chibon |
29ff0a |
commitid = frombranch.peel().hex
|
|
Pierre-Yves Chibon |
ff9832 |
elif prid is not None:
|
|
Pierre-Yves Chibon |
ff9832 |
# If there is not branch found but there is a PR open, use the ref
|
|
Pierre-Yves Chibon |
ff9832 |
# of that PR in the main repo
|
|
Pierre-Yves Chibon |
ff9832 |
try:
|
|
Pierre-Yves Chibon |
ff9832 |
ref = orig_repo.lookup_reference("refs/pull/%s/head" % prid)
|
|
Pierre-Yves Chibon |
ff9832 |
commitid = ref.target.hex
|
|
Pierre-Yves Chibon |
0f7101 |
except KeyError:
|
|
Pierre-Yves Chibon |
ff9832 |
pass
|
|
Pierre-Yves Chibon |
875a08 |
|
|
Pierre-Yves Chibon |
c96124 |
if not commitid and repo_obj and not repo_obj.is_empty:
|
|
Pierre-Yves Chibon |
8ffbe4 |
raise pagure.exceptions.PagureException(
|
|
Pierre-Yves Chibon |
9c2953 |
"No branch from which to pull or local PR reference were found"
|
|
Pierre-Yves Chibon |
8ffbe4 |
)
|
|
Pierre-Yves Chibon |
8ffbe4 |
|
|
Pierre-Yves Chibon |
875a08 |
diff_commits = []
|
|
Pierre-Yves Chibon |
875a08 |
diff = None
|
|
Pierre-Yves Chibon |
875a08 |
orig_commit = None
|
|
Pierre-Yves Chibon |
ff9832 |
|
|
Pierre-Yves Chibon |
ff9832 |
# If the fork is empty but there is a PR open, use the main repo
|
|
Pierre-Yves Chibon |
c96124 |
if (not repo_obj or repo_obj.is_empty) and prid is not None:
|
|
Pierre-Yves Chibon |
ff9832 |
repo_obj = orig_repo
|
|
Pierre-Yves Chibon |
ff9832 |
|
|
Pierre-Yves Chibon |
dbf3e1 |
if not repo_obj.is_empty and not orig_repo.is_empty:
|
|
Pierre-Yves Chibon |
6bd26b |
_log.info(
|
|
Pierre-Yves Chibon |
6bd26b |
"pagure.lib.git.get_diff_info: Pulling into a non-empty repo"
|
|
Pierre-Yves Chibon |
6bd26b |
)
|
|
Pierre-Yves Chibon |
875a08 |
if branch:
|
|
Pierre-Yves Chibon |
29ff0a |
orig_commit = orig_repo[branch.peel().hex]
|
|
Pierre-Yves Chibon |
875a08 |
main_walker = orig_repo.walk(
|
|
Slavek Kabrda |
0dd0cd |
orig_commit.oid.hex, pygit2.GIT_SORT_NONE
|
|
Pierre-Yves Chibon |
9c2953 |
)
|
|
Pierre-Yves Chibon |
875a08 |
|
|
Pierre-Yves Chibon |
875a08 |
repo_commit = repo_obj[commitid]
|
|
Pierre-Yves Chibon |
875a08 |
branch_walker = repo_obj.walk(
|
|
Slavek Kabrda |
0dd0cd |
repo_commit.oid.hex, pygit2.GIT_SORT_NONE
|
|
Pierre-Yves Chibon |
9c2953 |
)
|
|
Pierre-Yves Chibon |
38062e |
|
|
Pierre-Yves Chibon |
38062e |
main_commits = set()
|
|
Pierre-Yves Chibon |
38062e |
branch_commits = set()
|
|
Pierre-Yves Chibon |
38062e |
|
|
Pierre-Yves Chibon |
38062e |
while 1:
|
|
Pierre-Yves Chibon |
875a08 |
com = None
|
|
Pierre-Yves Chibon |
875a08 |
if branch:
|
|
Pierre-Yves Chibon |
875a08 |
try:
|
|
Aurélien Bompard |
831553 |
com = next(main_walker)
|
|
Pierre-Yves Chibon |
875a08 |
main_commits.add(com.oid.hex)
|
|
Pierre-Yves Chibon |
875a08 |
except StopIteration:
|
|
Pierre-Yves Chibon |
875a08 |
com = None
|
|
Pierre-Yves Chibon |
de491b |
|
|
Pierre-Yves Chibon |
38062e |
try:
|
|
Aurélien Bompard |
831553 |
branch_commit = next(branch_walker)
|
|
Pierre-Yves Chibon |
38062e |
except StopIteration:
|
|
Pierre-Yves Chibon |
38062e |
branch_commit = None
|
|
Pierre-Yves Chibon |
38062e |
|
|
Pierre-Yves Chibon |
de491b |
# We sure never end up here but better safe than sorry
|
|
Pierre-Yves Chibon |
de491b |
if com is None and branch_commit is None:
|
|
Pierre-Yves Chibon |
de491b |
break
|
|
Pierre-Yves Chibon |
de491b |
|
|
Pierre-Yves Chibon |
de491b |
if branch_commit:
|
|
Pierre-Yves Chibon |
de491b |
branch_commits.add(branch_commit.oid.hex)
|
|
Pierre-Yves Chibon |
fbb684 |
diff_commits.append(branch_commit)
|
|
Pierre-Yves Chibon |
38062e |
if main_commits.intersection(branch_commits):
|
|
Pierre-Yves Chibon |
dbf3e1 |
break
|
|
Pierre-Yves Chibon |
38062e |
|
|
Pierre-Yves Chibon |
f556c2 |
# If master is ahead of branch, we need to remove the commits
|
|
Pierre-Yves Chibon |
fbb684 |
# that are after the first one found in master
|
|
Pierre-Yves Chibon |
fbb684 |
i = 0
|
|
Pierre-Yves Chibon |
875a08 |
if diff_commits and main_commits:
|
|
Pierre-Yves Chibon |
875a08 |
for i in range(len(diff_commits)):
|
|
Pierre-Yves Chibon |
875a08 |
if diff_commits[i].oid.hex in main_commits:
|
|
Pierre-Yves Chibon |
875a08 |
break
|
|
Pierre-Yves Chibon |
875a08 |
diff_commits = diff_commits[:i]
|
|
Pierre-Yves Chibon |
f556c2 |
|
|
Slavek Kabrda |
94599b |
_log.debug("Diff commits: %s", diff_commits)
|
|
Pierre-Yves Chibon |
875a08 |
if diff_commits:
|
|
Pierre-Yves Chibon |
d9d77c |
first_commit = repo_obj[diff_commits[-1].oid.hex]
|
|
Pierre-Yves Chibon |
875a08 |
if len(first_commit.parents) > 0:
|
|
Pierre-Yves Chibon |
875a08 |
diff = repo_obj.diff(
|
|
Pierre-Yves Chibon |
875a08 |
repo_obj.revparse_single(first_commit.parents[0].oid.hex),
|
|
Pierre-Yves Chibon |
9c2953 |
repo_obj.revparse_single(diff_commits[0].oid.hex),
|
|
Pierre-Yves Chibon |
fa1dee |
)
|
|
Pierre-Yves Chibon |
59f36c |
elif first_commit.oid.hex == diff_commits[0].oid.hex:
|
|
Pierre-Yves Chibon |
83bb93 |
_log.info(
|
|
Pierre-Yves Chibon |
6bd26b |
"pagure.lib.git.get_diff_info: First commit is also the "
|
|
Pierre-Yves Chibon |
6bd26b |
"last commit"
|
|
Pierre-Yves Chibon |
9c2953 |
)
|
|
Pierre-Yves Chibon |
59f36c |
diff = diff_commits[0].tree.diff_to_tree(swap=True)
|
|
Pierre-Yves Chibon |
59f36c |
|
|
Pierre-Yves Chibon |
c96124 |
elif orig_repo.is_empty and repo_obj and not repo_obj.is_empty:
|
|
Pierre-Yves Chibon |
6bd26b |
_log.info("pagure.lib.git.get_diff_info: Pulling into an empty repo")
|
|
Pierre-Yves Chibon |
9c2953 |
if "master" in repo_obj.listall_branches():
|
|
Pierre-Yves Chibon |
875a08 |
repo_commit = repo_obj[repo_obj.head.target]
|
|
Pierre-Yves Chibon |
875a08 |
else:
|
|
Pierre-Yves Chibon |
875a08 |
branch = repo_obj.lookup_branch(branch_from)
|
|
Pierre-Yves Chibon |
29ff0a |
repo_commit = branch.peel()
|
|
Pierre-Yves Chibon |
875a08 |
|
|
Slavek Kabrda |
0dd0cd |
for commit in repo_obj.walk(repo_commit.oid.hex, pygit2.GIT_SORT_NONE):
|
|
Pierre-Yves Chibon |
dbf3e1 |
diff_commits.append(commit)
|
|
Pierre-Yves Chibon |
dbf3e1 |
|
|
Slavek Kabrda |
94599b |
_log.debug("Diff commits: %s", diff_commits)
|
|
Pierre-Yves Chibon |
875a08 |
diff = repo_commit.tree.diff_to_tree(swap=True)
|
|
Pierre-Yves Chibon |
875a08 |
else:
|
|
Pierre-Yves Chibon |
875a08 |
raise pagure.exceptions.PagureException(
|
|
Pierre-Yves Chibon |
9c2953 |
"Fork is empty, there are no commits to create a pull "
|
|
Pierre-Yves Chibon |
9c2953 |
"request with"
|
|
Pierre-Yves Chibon |
875a08 |
)
|
|
Pierre-Yves Chibon |
875a08 |
|
|
Pierre-Yves Chibon |
83bb93 |
_log.info(
|
|
Pierre-Yves Chibon |
6bd26b |
"pagure.lib.git.get_diff_info: diff_commits length: %s",
|
|
Pierre-Yves Chibon |
6bd26b |
len(diff_commits),
|
|
Pierre-Yves Chibon |
9c2953 |
)
|
|
Pierre-Yves Chibon |
6bd26b |
_log.info("pagure.lib.git.get_diff_info: original commit: %s", orig_commit)
|
|
Pierre-Yves Chibon |
83bb93 |
|
|
Pierre-Yves Chibon |
9c2953 |
return (diff, diff_commits, orig_commit)
|
|
Pierre-Yves Chibon |
875a08 |
|
|
Pierre-Yves Chibon |
875a08 |
|
|
Pierre-Yves Chibon |
35fe76 |
def diff_pull_request(
|
|
Pierre-Yves Chibon |
b983f9 |
session,
|
|
Pierre-Yves Chibon |
b983f9 |
request,
|
|
Pierre-Yves Chibon |
b983f9 |
repo_obj,
|
|
Pierre-Yves Chibon |
b983f9 |
orig_repo,
|
|
Pierre-Yves Chibon |
b983f9 |
with_diff=True,
|
|
Pierre-Yves Chibon |
b983f9 |
notify=True,
|
|
Pierre-Yves Chibon |
b983f9 |
username=None,
|
|
Pierre-Yves Chibon |
433e5e |
):
|
|
Pierre-Yves Chibon |
875a08 |
""" Returns the diff and the list of commits between the two git repos
|
|
Pierre-Yves Chibon |
875a08 |
mentionned in the given pull-request.
|
|
Pierre-Yves Chibon |
dbf3e1 |
|
|
Pierre-Yves Chibon |
875a08 |
:arg session: The sqlalchemy session to connect to the database
|
|
Pierre-Yves Chibon |
875a08 |
:arg request: The pagure.lib.model.PullRequest object of the pull-request
|
|
Pierre-Yves Chibon |
875a08 |
to look into
|
|
Pierre-Yves Chibon |
875a08 |
:arg repo_obj: The pygit2.Repository object of the first git repo
|
|
Pierre-Yves Chibon |
875a08 |
:arg orig_repo: The pygit2.Repository object of the second git repo
|
|
Pierre-Yves Chibon |
875a08 |
:arg with_diff: A boolean on whether to return the diff with the list
|
|
Pierre-Yves Chibon |
875a08 |
of commits (or just the list of commits)
|
|
Pierre-Yves Chibon |
b983f9 |
:arg username: The username of the user diffing the pull-request
|
|
Pierre-Yves Chibon |
875a08 |
|
|
Pierre-Yves Chibon |
875a08 |
"""
|
|
Pierre-Yves Chibon |
875a08 |
|
|
Pierre-Yves Chibon |
b983f9 |
_log.debug("pagure.lib.git.diff_pull_request, started")
|
|
Pierre-Yves Chibon |
875a08 |
diff = None
|
|
Pierre-Yves Chibon |
875a08 |
diff_commits = []
|
|
Pierre-Yves Chibon |
875a08 |
diff, diff_commits, _ = get_diff_info(
|
|
Pierre-Yves Chibon |
9c2953 |
repo_obj,
|
|
Pierre-Yves Chibon |
9c2953 |
orig_repo,
|
|
Pierre-Yves Chibon |
9c2953 |
request.branch_from,
|
|
Pierre-Yves Chibon |
9c2953 |
request.branch,
|
|
Pierre-Yves Chibon |
9c2953 |
prid=request.id,
|
|
Pierre-Yves Chibon |
9c2953 |
)
|
|
Pierre-Yves Chibon |
b983f9 |
_log.debug("pagure.lib.git.diff_pull_request, diff done")
|
|
Pierre-Yves Chibon |
875a08 |
|
|
Pierre-Yves Chibon |
9c2953 |
if request.status == "Open" and diff_commits:
|
|
Pierre-Yves Chibon |
b983f9 |
_log.debug("pagure.lib.git.diff_pull_request, PR open and with a diff")
|
|
Pierre-Yves Chibon |
c96124 |
first_commit = diff_commits[-1]
|
|
Pierre-Yves Chibon |
875a08 |
# Check if we can still rely on the merge_status
|
|
Pierre-Yves Chibon |
875a08 |
commenttext = None
|
|
Pierre-Yves Chibon |
9c2953 |
if (
|
|
Pierre-Yves Chibon |
9c2953 |
request.commit_start != first_commit.oid.hex
|
|
Pierre-Yves Chibon |
9c2953 |
or request.commit_stop != diff_commits[0].oid.hex
|
|
Pierre-Yves Chibon |
9c2953 |
):
|
|
Pierre-Yves Chibon |
875a08 |
request.merge_status = None
|
|
Pierre-Yves Chibon |
875a08 |
if request.commit_start:
|
|
Pierre-Yves Chibon |
f39c35 |
pr_action = "updated"
|
|
Pierre-Yves Chibon |
875a08 |
new_commits_count = 0
|
|
Pierre-Yves Chibon |
875a08 |
commenttext = ""
|
|
Pierre-Yves Chibon |
875a08 |
for i in diff_commits:
|
|
Pierre-Yves Chibon |
875a08 |
if i.oid.hex == request.commit_stop:
|
|
Pierre-Yves Chibon |
875a08 |
break
|
|
Pierre-Yves Chibon |
875a08 |
new_commits_count = new_commits_count + 1
|
|
Pierre-Yves Chibon |
9c2953 |
commenttext = "%s * ``%s``\n" % (
|
|
Pierre-Yves Chibon |
9c2953 |
commenttext,
|
|
Pierre-Yves Chibon |
9c2953 |
i.message.strip().split("\n")[0],
|
|
Pierre-Yves Chibon |
9c2953 |
)
|
|
Pierre-Yves Chibon |
875a08 |
if new_commits_count == 1:
|
|
Pierre-Yves Chibon |
875a08 |
commenttext = "**%d new commit added**\n\n%s" % (
|
|
Pierre-Yves Chibon |
9c2953 |
new_commits_count,
|
|
Pierre-Yves Chibon |
9c2953 |
commenttext,
|
|
Pierre-Yves Chibon |
9c2953 |
)
|
|
Pierre-Yves Chibon |
875a08 |
else:
|
|
Pierre-Yves Chibon |
875a08 |
commenttext = "**%d new commits added**\n\n%s" % (
|
|
Pierre-Yves Chibon |
9c2953 |
new_commits_count,
|
|
Pierre-Yves Chibon |
9c2953 |
commenttext,
|
|
Pierre-Yves Chibon |
9c2953 |
)
|
|
Pierre-Yves Chibon |
9c2953 |
if (
|
|
Pierre-Yves Chibon |
9c2953 |
request.commit_start
|
|
Pierre-Yves Chibon |
9c2953 |
and request.commit_start != first_commit.oid.hex
|
|
Pierre-Yves Chibon |
9c2953 |
):
|
|
Pierre-Yves Chibon |
f39c35 |
pr_action = "rebased"
|
|
Pierre-Yves Chibon |
9c2953 |
commenttext = "rebased onto %s" % first_commit.oid.hex
|
|
Pierre-Yves Chibon |
875a08 |
request.commit_start = first_commit.oid.hex
|
|
Pierre-Yves Chibon |
875a08 |
request.commit_stop = diff_commits[0].oid.hex
|
|
Pierre-Yves Chibon |
875a08 |
session.add(request)
|
|
Pierre-Yves Chibon |
875a08 |
session.commit()
|
|
Pierre-Yves Chibon |
b983f9 |
_log.debug(
|
|
Pierre-Yves Chibon |
b983f9 |
"pagure.lib.git.diff_pull_request, commenttext: %s", commenttext
|
|
Pierre-Yves Chibon |
b983f9 |
)
|
|
Pierre-Yves Chibon |
acd3eb |
|
|
Pierre-Yves Chibon |
eb5f49 |
pagure.lib.tasks.sync_pull_ref.delay(
|
|
Pierre-Yves Chibon |
acd3eb |
request.project.name,
|
|
Pierre-Yves Chibon |
acd3eb |
request.project.namespace,
|
|
Pierre-Yves Chibon |
acd3eb |
request.project.user.username if request.project.is_fork else None,
|
|
Pierre-Yves Chibon |
9c2953 |
request.id,
|
|
Pierre-Yves Chibon |
acd3eb |
)
|
|
Pierre-Yves Chibon |
acd3eb |
|
|
Pierre-Yves Chibon |
875a08 |
if commenttext:
|
|
Pierre-Yves Chibon |
eb5f49 |
pagure.lib.tasks.link_pr_to_ticket.delay(request.uid)
|
|
Pierre-Yves Chibon |
35fe76 |
if notify:
|
|
Pierre-Yves Chibon |
f39c35 |
if pr_action:
|
|
Pierre-Yves Chibon |
f39c35 |
pagure.lib.notify.log(
|
|
Pierre-Yves Chibon |
f39c35 |
request.project,
|
|
Pierre-Yves Chibon |
f39c35 |
topic="pull-request.%s" % pr_action,
|
|
Pierre-Yves Chibon |
f39c35 |
msg=dict(
|
|
Pierre-Yves Chibon |
f39c35 |
pullrequest=request.to_json(
|
|
Pierre-Yves Chibon |
97d19d |
with_comments=False, public=True
|
|
Pierre-Yves Chibon |
97d19d |
),
|
|
Pierre-Yves Chibon |
97d19d |
agent="pagure",
|
|
Pierre-Yves Chibon |
f39c35 |
),
|
|
Pierre-Yves Chibon |
f39c35 |
)
|
|
Pierre-Yves Chibon |
b983f9 |
_log.debug(
|
|
Pierre-Yves Chibon |
b983f9 |
"pagure.lib.git.diff_pull_request: adding notification: %s"
|
|
Pierre-Yves Chibon |
b983f9 |
"as user: %s",
|
|
Pierre-Yves Chibon |
b983f9 |
commenttext,
|
|
Pierre-Yves Chibon |
b983f9 |
username or request.user.username,
|
|
Pierre-Yves Chibon |
b983f9 |
)
|
|
Pierre-Yves Chibon |
930073 |
pagure.lib.query.add_pull_request_comment(
|
|
Pierre-Yves Chibon |
35fe76 |
session,
|
|
Pierre-Yves Chibon |
35fe76 |
request,
|
|
Pierre-Yves Chibon |
35fe76 |
commit=None,
|
|
Pierre-Yves Chibon |
35fe76 |
tree_id=None,
|
|
Pierre-Yves Chibon |
35fe76 |
filename=None,
|
|
Pierre-Yves Chibon |
35fe76 |
row=None,
|
|
Pierre-Yves Chibon |
35fe76 |
comment="%s" % commenttext,
|
|
Pierre-Yves Chibon |
b983f9 |
user=username or request.user.username,
|
|
Pierre-Yves Chibon |
35fe76 |
notify=False,
|
|
Pierre-Yves Chibon |
35fe76 |
notification=True,
|
|
Pierre-Yves Chibon |
35fe76 |
)
|
|
Pierre-Yves Chibon |
35fe76 |
session.commit()
|
|
Pierre-Yves Chibon |
9542ad |
else:
|
|
Pierre-Yves Chibon |
9542ad |
pagure.lib.git.update_git(request, repo=request.project)
|
|
Pierre-Yves Chibon |
875a08 |
|
|
Pierre-Yves Chibon |
875a08 |
if with_diff:
|
|
Pierre-Yves Chibon |
875a08 |
return (diff_commits, diff)
|
|
Pierre-Yves Chibon |
875a08 |
else:
|
|
Pierre-Yves Chibon |
bcb5c1 |
return diff_commits
|
|
Pierre-Yves Chibon |
04f59d |
|
|
Pierre-Yves Chibon |
04f59d |
|
|
Pierre-Yves Chibon |
acd3eb |
def update_pull_ref(request, repo):
|
|
Pierre-Yves Chibon |
acd3eb |
""" Create or update the refs/pull/ reference in the git repo.
|
|
Pierre-Yves Chibon |
acd3eb |
"""
|
|
Pierre-Yves Chibon |
acd3eb |
|
|
Pierre-Yves Chibon |
b130e5 |
repopath = pagure.utils.get_repo_path(request.project)
|
|
Pierre-Yves Chibon |
9c2953 |
reponame = "%s_%s" % (request.user.user, request.uid)
|
|
Pierre-Yves Chibon |
acd3eb |
|
|
Pierre-Yves Chibon |
9c2953 |
_log.info(" Adding remote: %s pointing to: %s", reponame, repopath)
|
|
Pierre-Yves Chibon |
acd3eb |
rc = RemoteCollection(repo)
|
|
Slavek Kabrda |
197fa2 |
|
|
Slavek Kabrda |
197fa2 |
try:
|
|
Slavek Kabrda |
197fa2 |
# we do rc.delete(reponame) both here and in the finally block below:
|
|
Slavek Kabrda |
197fa2 |
# * here: it's useful for cases when worker was interrupted
|
|
Slavek Kabrda |
197fa2 |
# on the previous execution of this function and didn't manage
|
|
Slavek Kabrda |
197fa2 |
# to remove the ref
|
|
Slavek Kabrda |
197fa2 |
# * in the finally clause: to remove the ref so that it doesn't stay
|
|
Slavek Kabrda |
197fa2 |
# in the fork forever (as noted above, it might still stay there
|
|
Slavek Kabrda |
197fa2 |
# if the worker gets interrupted, but that's not a huge deal)
|
|
Slavek Kabrda |
197fa2 |
rc[reponame]
|
|
Slavek Kabrda |
197fa2 |
rc.delete(reponame)
|
|
Slavek Kabrda |
197fa2 |
except KeyError:
|
|
Slavek Kabrda |
197fa2 |
pass
|
|
Slavek Kabrda |
197fa2 |
|
|
Pierre-Yves Chibon |
acd3eb |
remote = rc.create(reponame, repopath)
|
|
Pierre-Yves Chibon |
acd3eb |
try:
|
|
Pierre-Yves Chibon |
acd3eb |
_log.info(
|
|
Pierre-Yves Chibon |
9c2953 |
" Pushing refs/heads/%s to refs/pull/%s/head",
|
|
Pierre-Yves Chibon |
9c2953 |
request.branch_from,
|
|
Pierre-Yves Chibon |
9c2953 |
request.id,
|
|
Pierre-Yves Chibon |
9c2953 |
)
|
|
Pierre-Yves Chibon |
9c2953 |
refname = "+refs/heads/%s:refs/pull/%s/head" % (
|
|
Pierre-Yves Chibon |
9c2953 |
request.branch_from,
|
|
Pierre-Yves Chibon |
9c2953 |
request.id,
|
|
Pierre-Yves Chibon |
9c2953 |
)
|
|
Pierre-Yves Chibon |
acd3eb |
PagureRepo.push(remote, refname)
|
|
Pierre-Yves Chibon |
acd3eb |
finally:
|
|
Pierre-Yves Chibon |
acd3eb |
rc.delete(reponame)
|
|
Pierre-Yves Chibon |
acd3eb |
|
|
Pierre-Yves Chibon |
acd3eb |
|
|
Pierre-Yves Chibon |
06f5ad |
def get_git_tags(project, with_commits=False):
|
|
Pierre-Yves Chibon |
04f59d |
""" Returns the list of tags created in the git repositorie of the
|
|
Pierre-Yves Chibon |
04f59d |
specified project.
|
|
Pierre-Yves Chibon |
04f59d |
"""
|
|
Pierre-Yves Chibon |
b130e5 |
repopath = pagure.utils.get_repo_path(project)
|
|
Pierre-Yves Chibon |
609965 |
repo_obj = PagureRepo(repopath)
|
|
Pierre-Yves Chibon |
4230af |
|
|
Pierre-Yves Chibon |
06f5ad |
if with_commits:
|
|
Pierre-Yves Chibon |
06f5ad |
tags = {}
|
|
Pierre-Yves Chibon |
06f5ad |
for tag in repo_obj.listall_references():
|
|
Pierre-Yves Chibon |
9c2953 |
if tag.startswith("refs/tags/"):
|
|
Pierre-Yves Chibon |
06f5ad |
ref = repo_obj.lookup_reference(tag)
|
|
Pierre-Yves Chibon |
06f5ad |
if ref:
|
|
Pierre-Yves Chibon |
29ff0a |
com = ref.peel()
|
|
Pierre-Yves Chibon |
06f5ad |
if com:
|
|
Pierre-Yves Chibon |
9c2953 |
tags[tag.split("refs/tags/")[1]] = com.oid.hex
|
|
Pierre-Yves Chibon |
06f5ad |
else:
|
|
Pierre-Yves Chibon |
06f5ad |
tags = [
|
|
Pierre-Yves Chibon |
9c2953 |
tag.split("refs/tags/")[1]
|
|
Pierre-Yves Chibon |
06f5ad |
for tag in repo_obj.listall_references()
|
|
Pierre-Yves Chibon |
9c2953 |
if tag.startswith("refs/tags/")
|
|
Pierre-Yves Chibon |
06f5ad |
]
|
|
Pierre-Yves Chibon |
4230af |
|
|
Pierre-Yves Chibon |
04f59d |
return tags
|
|
Pierre-Yves Chibon |
49f980 |
|
|
Pierre-Yves Chibon |
49f980 |
|
|
Pierre-Yves Chibon |
49f980 |
def get_git_tags_objects(project):
|
|
Pierre-Yves Chibon |
49f980 |
""" Returns the list of references of the tags created in the git
|
|
Pierre-Yves Chibon |
49f980 |
repositorie the specified project.
|
|
Clement Verna |
d76ad6 |
The list is sorted using the time of the commit associated to the tag """
|
|
Pierre-Yves Chibon |
b130e5 |
repopath = pagure.utils.get_repo_path(project)
|
|
Pierre-Yves Chibon |
609965 |
repo_obj = PagureRepo(repopath)
|
|
Ryan Lerch |
fe67e4 |
tags = {}
|
|
Ryan Lerch |
fe67e4 |
for tag in repo_obj.listall_references():
|
|
Pierre-Yves Chibon |
9c2953 |
if "refs/tags/" in tag and repo_obj.lookup_reference(tag):
|
|
Pierre-Yves Chibon |
616641 |
commit_time = None
|
|
Pierre-Yves Chibon |
616641 |
try:
|
|
Pierre-Yves Chibon |
616641 |
theobject = repo_obj[repo_obj.lookup_reference(tag).target]
|
|
Pierre-Yves Chibon |
616641 |
except ValueError:
|
|
Pierre-Yves Chibon |
616641 |
theobject = None
|
|
Ryan Lerch |
fe67e4 |
objecttype = ""
|
|
Ryan Lerch |
fe67e4 |
if isinstance(theobject, pygit2.Tag):
|
|
Pierre-Yves Chibon |
29ff0a |
underlying_obj = theobject.peel(pygit2.Commit)
|
|
Pierre-Yves Chibon |
0d3c39 |
commit_time = underlying_obj.commit_time
|
|
Ryan Lerch |
fe67e4 |
objecttype = "tag"
|
|
Ryan Lerch |
9aecfd |
elif isinstance(theobject, pygit2.Commit):
|
|
Ryan Lerch |
fe67e4 |
commit_time = theobject.commit_time
|
|
Ryan Lerch |
fe67e4 |
objecttype = "commit"
|
|
Ryan Lerch |
fe67e4 |
|
|
Ryan Lerch |
fe67e4 |
tags[commit_time] = {
|
|
Pierre-Yves Chibon |
616641 |
"object": theobject,
|
|
Pierre-Yves Chibon |
c70df4 |
"tagname": tag.replace("refs/tags/", ""),
|
|
Pierre-Yves Chibon |
0f5e8f |
"date": commit_time,
|
|
Pierre-Yves Chibon |
0f5e8f |
"objecttype": objecttype,
|
|
Pierre-Yves Chibon |
0f5e8f |
"head_msg": None,
|
|
Pierre-Yves Chibon |
0f5e8f |
"body_msg": None,
|
|
Pierre-Yves Chibon |
0f5e8f |
}
|
|
Pierre-Yves Chibon |
9c2953 |
if objecttype == "tag":
|
|
Pierre-Yves Chibon |
0f5e8f |
head_msg, _, body_msg = tags[commit_time][
|
|
Pierre-Yves Chibon |
9c2953 |
"object"
|
|
Pierre-Yves Chibon |
9c2953 |
].message.partition("\n")
|
|
Pierre-Yves Chibon |
9c2953 |
if body_msg.strip().endswith("\n-----END PGP SIGNATURE-----"):
|
|
Pierre-Yves Chibon |
cc2fc7 |
body_msg = body_msg.rsplit(
|
|
Pierre-Yves Chibon |
9c2953 |
"-----BEGIN PGP SIGNATURE-----", 1
|
|
Pierre-Yves Chibon |
9c2953 |
)[0].strip()
|
|
Pierre-Yves Chibon |
0f5e8f |
tags[commit_time]["head_msg"] = head_msg
|
|
Pierre-Yves Chibon |
0f5e8f |
tags[commit_time]["body_msg"] = body_msg
|
|
Clement Verna |
c99c18 |
sorted_tags = []
|
|
Clement Verna |
c99c18 |
|
|
Ryan Lerch |
fe67e4 |
for tag in sorted(tags, reverse=True):
|
|
Ryan Lerch |
fe67e4 |
sorted_tags.append(tags[tag])
|
|
Clement Verna |
c99c18 |
|
|
Clement Verna |
c99c18 |
return sorted_tags
|
|
Pierre-Yves Chibon |
7772c6 |
|
|
Pierre-Yves Chibon |
7772c6 |
|
|
Pierre-Yves Chibon |
7772c6 |
def log_commits_to_db(session, project, commits, gitdir):
|
|
Pierre-Yves Chibon |
7772c6 |
""" Log the given commits to the DB. """
|
|
Pierre-Yves Chibon |
7772c6 |
repo_obj = PagureRepo(gitdir)
|
|
Pierre-Yves Chibon |
7772c6 |
|
|
Pierre-Yves Chibon |
801150 |
for commitid in commits:
|
|
Pierre-Yves Chibon |
7772c6 |
try:
|
|
Pierre-Yves Chibon |
801150 |
commit = repo_obj[commitid]
|
|
Pierre-Yves Chibon |
7772c6 |
except ValueError:
|
|
Pierre-Yves Chibon |
7772c6 |
continue
|
|
Pierre-Yves Chibon |
7772c6 |
|
|
Pierre-Yves Chibon |
7772c6 |
try:
|
|
Pierre-Yves Chibon |
930073 |
author_obj = pagure.lib.query.get_user(
|
|
Pierre-Yves Chibon |
930073 |
session, commit.author.email
|
|
Pierre-Yves Chibon |
930073 |
)
|
|
Pierre-Yves Chibon |
7772c6 |
except pagure.exceptions.PagureException:
|
|
Pierre-Yves Chibon |
7772c6 |
author_obj = None
|
|
Pierre-Yves Chibon |
7772c6 |
|
|
Pierre-Yves Chibon |
7772c6 |
date_created = arrow.get(commit.commit_time)
|
|
Pierre-Yves Chibon |
7772c6 |
|
|
Pierre-Yves Chibon |
7772c6 |
log = model.PagureLog(
|
|
Pierre-Yves Chibon |
7772c6 |
user_id=author_obj.id if author_obj else None,
|
|
Pierre-Yves Chibon |
7772c6 |
user_email=commit.author.email if not author_obj else None,
|
|
Pierre-Yves Chibon |
7772c6 |
project_id=project.id,
|
|
Pierre-Yves Chibon |
9c2953 |
log_type="committed",
|
|
Pierre-Yves Chibon |
3fa4ec |
ref_id=commit.oid.hex,
|
|
Pierre-Yves Chibon |
7772c6 |
date=date_created.date(),
|
|
Pierre-Yves Chibon |
9c2953 |
date_created=date_created.datetime,
|
|
Pierre-Yves Chibon |
7772c6 |
)
|
|
Pierre-Yves Chibon |
7772c6 |
session.add(log)
|
|
Vivek Anand |
8ced04 |
|
|
Vivek Anand |
8ced04 |
|
|
Vivek Anand |
8ced04 |
def reinit_git(project, repofolder):
|
|
Pierre-Yves Chibon |
9c2953 |
""" Delete and recreate a git folder
|
|
Vivek Anand |
8ced04 |
:args project: SQLAlchemy object of the project
|
|
Vivek Anand |
8ced04 |
:args folder: The folder which contains the git repos
|
|
Vivek Anand |
8ced04 |
like TICKETS_FOLDER for tickets and REQUESTS_FOLDER for
|
|
Vivek Anand |
8ced04 |
pull requests
|
|
Pierre-Yves Chibon |
9c2953 |
"""
|
|
Vivek Anand |
8ced04 |
|
|
Vivek Anand |
8ced04 |
repo_path = os.path.join(repofolder, project.path)
|
|
Vivek Anand |
8ced04 |
if not os.path.exists(repo_path):
|
|
Vivek Anand |
8ced04 |
return
|
|
Vivek Anand |
8ced04 |
|
|
Vivek Anand |
8ced04 |
# delete that repo
|
|
Vivek Anand |
8ced04 |
shutil.rmtree(repo_path)
|
|
Vivek Anand |
8ced04 |
|
|
Vivek Anand |
8ced04 |
# create it again
|
|
Vivek Anand |
8ced04 |
pygit2.init_repository(
|
|
Pierre-Yves Chibon |
9c2953 |
repo_path, bare=True, mode=pygit2.C.GIT_REPOSITORY_INIT_SHARED_GROUP
|
|
Vivek Anand |
8ced04 |
)
|
|
Matt Prahl |
cd940d |
|
|
Matt Prahl |
cd940d |
|
|
Brian Stinson |
4f81f7 |
def get_git_branches(project, with_commits=False):
|
|
Pierre-Yves Chibon |
9c2953 |
""" Return a list of branches for the project
|
|
Matt Prahl |
cd940d |
:arg project: The Project instance to get the branches for
|
|
Julen Landa Alustiza |
f499a7 |
:arg with_commits: Whether we should return branch head commits or not
|
|
Pierre-Yves Chibon |
9c2953 |
"""
|
|
Pierre-Yves Chibon |
b130e5 |
repo_path = pagure.utils.get_repo_path(project)
|
|
Brian Stinson |
4f81f7 |
repo_obj = PagureRepo(repo_path)
|
|
Brian Stinson |
4f81f7 |
|
|
Brian Stinson |
4f81f7 |
if with_commits:
|
|
Brian Stinson |
4f81f7 |
branches = {}
|
|
Brian Stinson |
4f81f7 |
|
|
Brian Stinson |
4f81f7 |
for branch in repo_obj.listall_branches():
|
|
Brian Stinson |
4f81f7 |
resolved_branch = repo_obj.lookup_branch(branch).resolve()
|
|
Brian Stinson |
4f81f7 |
com = resolved_branch.peel()
|
|
Brian Stinson |
4f81f7 |
if com:
|
|
Brian Stinson |
4f81f7 |
branches[branch] = com.oid.hex
|
|
Brian Stinson |
4f81f7 |
else:
|
|
Brian Stinson |
4f81f7 |
branches = repo_obj.listall_branches()
|
|
Brian Stinson |
4f81f7 |
|
|
Brian Stinson |
4f81f7 |
return branches
|
|
mprahl |
7d811e |
|
|
mprahl |
7d811e |
|
|
Patrick Uiterwijk |
03a519 |
def new_git_branch(
|
|
Patrick Uiterwijk |
03a519 |
username, project, branch, from_branch=None, from_commit=None
|
|
Patrick Uiterwijk |
03a519 |
):
|
|
Pierre-Yves Chibon |
9c2953 |
""" Create a new git branch on the project
|
|
mprahl |
7d811e |
:arg project: The Project instance to get the branches for
|
|
mprahl |
7d811e |
:arg from_branch: The branch to branch off of
|
|
Pierre-Yves Chibon |
9c2953 |
"""
|
|
Patrick Uiterwijk |
3f97f6 |
with TemporaryClone(project, "main", "new_branch") as tempclone:
|
|
Patrick Uiterwijk |
3f97f6 |
repo_obj = tempclone.repo
|
|
Patrick Uiterwijk |
3f97f6 |
|
|
Patrick Uiterwijk |
3f97f6 |
if not from_branch and not from_commit:
|
|
Patrick Uiterwijk |
3f97f6 |
from_branch = "master"
|
|
Patrick Uiterwijk |
3f97f6 |
branches = repo_obj.listall_branches()
|
|
Patrick Uiterwijk |
3f97f6 |
|
|
Patrick Uiterwijk |
3f97f6 |
if from_branch:
|
|
Patrick Uiterwijk |
3f97f6 |
if from_branch not in branches:
|
|
Patrick Uiterwijk |
3f97f6 |
raise pagure.exceptions.PagureException(
|
|
Patrick Uiterwijk |
3f97f6 |
'The "{0}" branch does not exist'.format(from_branch)
|
|
Patrick Uiterwijk |
3f97f6 |
)
|
|
Pierre-Yves Chibon |
29ff0a |
parent = get_branch_ref(repo_obj, from_branch).peel()
|
|
Patrick Uiterwijk |
3f97f6 |
else:
|
|
Patrick Uiterwijk |
3f97f6 |
if from_commit not in repo_obj:
|
|
Patrick Uiterwijk |
3f97f6 |
raise pagure.exceptions.PagureException(
|
|
Patrick Uiterwijk |
3f97f6 |
'The commit "{0}" does not exist'.format(from_commit)
|
|
Patrick Uiterwijk |
3f97f6 |
)
|
|
Patrick Uiterwijk |
3f97f6 |
parent = repo_obj[from_commit]
|
|
mprahl |
7d811e |
|
|
Patrick Uiterwijk |
3f97f6 |
if branch not in branches:
|
|
Patrick Uiterwijk |
3f97f6 |
repo_obj.create_branch(branch, parent)
|
|
Patrick Uiterwijk |
3f97f6 |
else:
|
|
mprahl |
7d811e |
raise pagure.exceptions.PagureException(
|
|
Patrick Uiterwijk |
3f97f6 |
'The branch "{0}" already exists'.format(branch)
|
|
Pierre-Yves Chibon |
9c2953 |
)
|
|
Patrick Uiterwijk |
3f97f6 |
|
|
Patrick Uiterwijk |
03a519 |
tempclone.push(username, branch, branch)
|
|
Patrick Uiterwijk |
3f97f6 |
|
|
Patrick Uiterwijk |
3f97f6 |
|
|
Patrick Uiterwijk |
3f97f6 |
def delete_project_repos(project):
|
|
Patrick Uiterwijk |
3f97f6 |
""" Deletes the actual git repositories on disk or repoSpanner
|
|
Patrick Uiterwijk |
3f97f6 |
|
|
Patrick Uiterwijk |
3f97f6 |
Args:
|
|
Patrick Uiterwijk |
3f97f6 |
project (Project): Project to delete repos for
|
|
Patrick Uiterwijk |
3f97f6 |
"""
|
|
Slavek Kabrda |
0915d0 |
for repotype in pagure.lib.query.get_repotypes():
|
|
Patrick Uiterwijk |
3f97f6 |
if project.is_on_repospanner:
|
|
Patrick Uiterwijk |
3f97f6 |
_, regioninfo = project.repospanner_repo_info(repotype)
|
|
Patrick Uiterwijk |
3f97f6 |
|
|
Patrick Uiterwijk |
3f97f6 |
_log.debug("Deleting repotype %s", repotype)
|
|
Patrick Uiterwijk |
3f97f6 |
data = {
|
|
Patrick Uiterwijk |
3f97f6 |
"Reponame": project._repospanner_repo_name(
|
|
Patrick Uiterwijk |
3f97f6 |
repotype, project.repospanner_region
|
|
Patrick Uiterwijk |
3f97f6 |
)
|
|
Patrick Uiterwijk |
3f97f6 |
}
|
|
Patrick Uiterwijk |
3f97f6 |
resp = requests.post(
|
|
Patrick Uiterwijk |
3f97f6 |
"%s/admin/deleterepo" % regioninfo["url"],
|
|
Patrick Uiterwijk |
3f97f6 |
json=data,
|
|
Patrick Uiterwijk |
3f97f6 |
verify=regioninfo["ca"],
|
|
Patrick Uiterwijk |
3f97f6 |
cert=(
|
|
Patrick Uiterwijk |
3f97f6 |
regioninfo["admin_cert"]["cert"],
|
|
Patrick Uiterwijk |
3f97f6 |
regioninfo["admin_cert"]["key"],
|
|
Patrick Uiterwijk |
3f97f6 |
),
|
|
Pierre-Yves Chibon |
9c2953 |
)
|
|
Patrick Uiterwijk |
3f97f6 |
resp.raise_for_status()
|
|
Patrick Uiterwijk |
3f97f6 |
resp = resp.json()
|
|
Patrick Uiterwijk |
3f97f6 |
_log.debug("Response json: %s", resp)
|
|
Patrick Uiterwijk |
3f97f6 |
if not resp["Success"]:
|
|
Patrick Uiterwijk |
3f97f6 |
raise Exception(
|
|
Patrick Uiterwijk |
3f97f6 |
"Error in repoSpanner API call: %s" % resp["Error"]
|
|
Patrick Uiterwijk |
3f97f6 |
)
|
|
mprahl |
7d811e |
|
|
Patrick Uiterwijk |
3f97f6 |
else:
|
|
Patrick Uiterwijk |
3f97f6 |
repopath = project.repopath(repotype)
|
|
Patrick Uiterwijk |
3f97f6 |
if repopath is None:
|
|
Patrick Uiterwijk |
3f97f6 |
continue
|
|
Patrick Uiterwijk |
3f97f6 |
|
|
Patrick Uiterwijk |
3f97f6 |
try:
|
|
Patrick Uiterwijk |
3f97f6 |
shutil.rmtree(repopath)
|
|
Patrick Uiterwijk |
3f97f6 |
except Exception:
|
|
Patrick Uiterwijk |
3f97f6 |
_log.exception(
|
|
Patrick Uiterwijk |
3f97f6 |
"Failed to remove repotype %s for %s",
|
|
Patrick Uiterwijk |
3f97f6 |
repotype,
|
|
Patrick Uiterwijk |
3f97f6 |
project.fullname,
|
|
Patrick Uiterwijk |
3f97f6 |
)
|
|
Patrick Uiterwijk |
3f97f6 |
|
|
Patrick Uiterwijk |
3f97f6 |
|
|
Patrick Uiterwijk |
d29158 |
def set_up_project_hooks(project, region, hook=None):
|
|
Patrick Uiterwijk |
d29158 |
""" Makes sure the git repositories for a project have their hooks setup.
|
|
Patrick Uiterwijk |
d29158 |
|
|
Patrick Uiterwijk |
d29158 |
Args:
|
|
Patrick Uiterwijk |
d29158 |
project (model.Project): Project to set up hooks for
|
|
Patrick Uiterwijk |
d29158 |
region (string or None): repoSpanner region to set hooks up for
|
|
Patrick Uiterwijk |
d29158 |
hook (string): The hook ID to set up in repoSpanner (tests only)
|
|
Patrick Uiterwijk |
d29158 |
"""
|
|
Patrick Uiterwijk |
d29158 |
if region is None:
|
|
Patrick Uiterwijk |
d29158 |
# This repo is not on repoSpanner, create hooks locally
|
|
Patrick Uiterwijk |
d29158 |
pagure.hooks.BaseHook.set_up(project)
|
|
Patrick Uiterwijk |
d29158 |
else:
|
|
Patrick Uiterwijk |
d29158 |
regioninfo = pagure_config["REPOSPANNER_REGIONS"].get(region)
|
|
Patrick Uiterwijk |
d29158 |
if not regioninfo:
|
|
Patrick Uiterwijk |
d29158 |
raise ValueError(
|
|
Patrick Uiterwijk |
d29158 |
"Invalid repoSpanner region %s looked up" % region
|
|
Patrick Uiterwijk |
d29158 |
)
|
|
Patrick Uiterwijk |
d29158 |
if not hook:
|
|
Patrick Uiterwijk |
d29158 |
hook = regioninfo["hook"]
|
|
Patrick Uiterwijk |
d29158 |
if not hook:
|
|
Patrick Uiterwijk |
d29158 |
# No hooks to set up for this region
|
|
Patrick Uiterwijk |
d29158 |
return
|
|
Patrick Uiterwijk |
d29158 |
|
|
Slavek Kabrda |
0915d0 |
for repotype in pagure.lib.query.get_repotypes():
|
|
Patrick Uiterwijk |
d29158 |
data = {
|
|
Patrick Uiterwijk |
d29158 |
"Reponame": project._repospanner_repo_name(repotype, region),
|
|
Patrick Uiterwijk |
d29158 |
"UpdateRequest": {
|
|
Patrick Uiterwijk |
d29158 |
"hook-prereceive": hook,
|
|
Patrick Uiterwijk |
d29158 |
"hook-update": hook,
|
|
Patrick Uiterwijk |
d29158 |
"hook-postreceive": hook,
|
|
Patrick Uiterwijk |
d29158 |
},
|
|
Patrick Uiterwijk |
d29158 |
}
|
|
Patrick Uiterwijk |
d29158 |
resp = requests.post(
|
|
Patrick Uiterwijk |
d29158 |
"%s/admin/editrepo" % regioninfo["url"],
|
|
Patrick Uiterwijk |
d29158 |
json=data,
|
|
Patrick Uiterwijk |
d29158 |
verify=regioninfo["ca"],
|
|
Patrick Uiterwijk |
d29158 |
cert=(
|
|
Patrick Uiterwijk |
d29158 |
regioninfo["admin_cert"]["cert"],
|
|
Patrick Uiterwijk |
d29158 |
regioninfo["admin_cert"]["key"],
|
|
Patrick Uiterwijk |
d29158 |
),
|
|
Patrick Uiterwijk |
d29158 |
)
|
|
Patrick Uiterwijk |
d29158 |
resp.raise_for_status()
|
|
Patrick Uiterwijk |
d29158 |
resp = resp.json()
|
|
Patrick Uiterwijk |
d29158 |
_log.debug("Response json: %s", resp)
|
|
Patrick Uiterwijk |
d29158 |
if not resp["Success"]:
|
|
Patrick Uiterwijk |
d29158 |
raise Exception(
|
|
Patrick Uiterwijk |
d29158 |
"Error in repoSpanner API call: %s" % resp["Error"]
|
|
Patrick Uiterwijk |
d29158 |
)
|
|
Patrick Uiterwijk |
d29158 |
|
|
Patrick Uiterwijk |
d29158 |
|
|
Patrick Uiterwijk |
3f97f6 |
def _create_project_repo(project, region, templ, ignore_existing, repotype):
|
|
Patrick Uiterwijk |
3f97f6 |
""" Creates a single specific git repository on disk or repoSpanner
|
|
Patrick Uiterwijk |
3f97f6 |
|
|
Patrick Uiterwijk |
3f97f6 |
Args:
|
|
Patrick Uiterwijk |
3f97f6 |
project (Project): Project to create repos for
|
|
Patrick Uiterwijk |
3f97f6 |
region (string or None): repoSpanner region to create the repos in
|
|
Patrick Uiterwijk |
3f97f6 |
templ (string): Template directory, only valid for non-repoSpanner
|
|
Patrick Uiterwijk |
3f97f6 |
ignore_existing (bool): Whether a repo already existing is fatal
|
|
Patrick Uiterwijk |
3f97f6 |
repotype (string): Repotype to create
|
|
Patrick Uiterwijk |
3f97f6 |
Returns: (string or None): Directory created
|
|
Patrick Uiterwijk |
3f97f6 |
"""
|
|
Patrick Uiterwijk |
3f97f6 |
if region:
|
|
Patrick Uiterwijk |
3f97f6 |
# repoSpanner creation
|
|
Patrick Uiterwijk |
3f97f6 |
regioninfo = pagure_config["REPOSPANNER_REGIONS"][region]
|
|
Patrick Uiterwijk |
3f97f6 |
# First create the repository on the repoSpanner region
|
|
Patrick Uiterwijk |
3f97f6 |
_log.debug("Creating repotype %s", repotype)
|
|
Patrick Uiterwijk |
3f97f6 |
data = {
|
|
Patrick Uiterwijk |
3f97f6 |
"Reponame": project._repospanner_repo_name(repotype, region),
|
|
Patrick Uiterwijk |
3f97f6 |
"Public": False,
|
|
Patrick Uiterwijk |
3f97f6 |
}
|
|
Patrick Uiterwijk |
3f97f6 |
resp = requests.post(
|
|
Patrick Uiterwijk |
3f97f6 |
"%s/admin/createrepo" % regioninfo["url"],
|
|
Patrick Uiterwijk |
3f97f6 |
json=data,
|
|
Patrick Uiterwijk |
3f97f6 |
verify=regioninfo["ca"],
|
|
Patrick Uiterwijk |
3f97f6 |
cert=(
|
|
Patrick Uiterwijk |
3f97f6 |
regioninfo["admin_cert"]["cert"],
|
|
Patrick Uiterwijk |
3f97f6 |
regioninfo["admin_cert"]["key"],
|
|
Patrick Uiterwijk |
3f97f6 |
),
|
|
Pierre-Yves Chibon |
9c2953 |
)
|
|
Patrick Uiterwijk |
3f97f6 |
resp.raise_for_status()
|
|
Patrick Uiterwijk |
3f97f6 |
resp = resp.json()
|
|
Patrick Uiterwijk |
3f97f6 |
_log.debug("Response json: %s", resp)
|
|
Patrick Uiterwijk |
3f97f6 |
if not resp["Success"]:
|
|
Patrick Uiterwijk |
6876a8 |
if "already exists" in resp["Error"]:
|
|
Patrick Uiterwijk |
6876a8 |
if ignore_existing:
|
|
Patrick Uiterwijk |
6876a8 |
return None
|
|
Patrick Uiterwijk |
6876a8 |
else:
|
|
Patrick Uiterwijk |
6876a8 |
raise pagure.exceptions.RepoExistsException(resp["Error"])
|
|
Patrick Uiterwijk |
3f97f6 |
raise Exception(
|
|
Patrick Uiterwijk |
3f97f6 |
"Error in repoSpanner API call: %s" % resp["Error"]
|
|
Patrick Uiterwijk |
3f97f6 |
)
|
|
Patrick Uiterwijk |
3f97f6 |
|
|
Patrick Uiterwijk |
3f97f6 |
return None
|
|
Patrick Uiterwijk |
3f97f6 |
|
|
Patrick Uiterwijk |
3f97f6 |
else:
|
|
Patrick Uiterwijk |
3f97f6 |
# local repo
|
|
Patrick Uiterwijk |
3f97f6 |
repodir = project.repopath(repotype)
|
|
Patrick Uiterwijk |
3f97f6 |
if repodir is None:
|
|
Patrick Uiterwijk |
3f97f6 |
# This repo type is disabled
|
|
Patrick Uiterwijk |
3f97f6 |
return None
|
|
Patrick Uiterwijk |
ac10ea |
if os.path.exists(repodir):
|
|
Patrick Uiterwijk |
ac10ea |
if not ignore_existing:
|
|
Patrick Uiterwijk |
ac10ea |
raise pagure.exceptions.RepoExistsException(
|
|
Patrick Uiterwijk |
ac10ea |
"The %s repo %s already exists" % (repotype, project.path)
|
|
Patrick Uiterwijk |
ac10ea |
)
|
|
Patrick Uiterwijk |
ac10ea |
else:
|
|
Patrick Uiterwijk |
ac10ea |
return None
|
|
Patrick Uiterwijk |
3f97f6 |
|
|
Patrick Uiterwijk |
3f97f6 |
if repotype == "main":
|
|
Patrick Uiterwijk |
3f97f6 |
pygit2.init_repository(repodir, bare=True, template_path=templ)
|
|
Patrick Uiterwijk |
3f97f6 |
|
|
Patrick Uiterwijk |
3f97f6 |
if not project.private:
|
|
Patrick Uiterwijk |
3f97f6 |
# Make the repo exportable via apache
|
|
Patrick Uiterwijk |
3f97f6 |
http_clone_file = os.path.join(repodir, "git-daemon-export-ok")
|
|
Patrick Uiterwijk |
3f97f6 |
if not os.path.exists(http_clone_file):
|
|
Patrick Uiterwijk |
3f97f6 |
with open(http_clone_file, "w"):
|
|
Patrick Uiterwijk |
3f97f6 |
pass
|
|
Patrick Uiterwijk |
3f97f6 |
else:
|
|
Patrick Uiterwijk |
3f97f6 |
pygit2.init_repository(
|
|
Patrick Uiterwijk |
3f97f6 |
repodir,
|
|
Patrick Uiterwijk |
3f97f6 |
bare=True,
|
|
Patrick Uiterwijk |
3f97f6 |
mode=pygit2.C.GIT_REPOSITORY_INIT_SHARED_GROUP,
|
|
Patrick Uiterwijk |
3f97f6 |
)
|
|
Patrick Uiterwijk |
3f97f6 |
|
|
Patrick Uiterwijk |
3f97f6 |
return repodir
|
|
Patrick Uiterwijk |
3f97f6 |
|
|
Patrick Uiterwijk |
3f97f6 |
|
|
Patrick Uiterwijk |
3f97f6 |
def create_project_repos(project, region, templ, ignore_existing):
|
|
Patrick Uiterwijk |
3f97f6 |
""" Creates the actual git repositories on disk or repoSpanner
|
|
Patrick Uiterwijk |
3f97f6 |
|
|
Patrick Uiterwijk |
3f97f6 |
Args:
|
|
Patrick Uiterwijk |
3f97f6 |
project (Project): Project to create repos for
|
|
Patrick Uiterwijk |
3f97f6 |
region (string or None): repoSpanner region to create the repos in
|
|
Patrick Uiterwijk |
3f97f6 |
templ (string): Template directory, only valid for non-repoSpanner
|
|
Patrick Uiterwijk |
3f97f6 |
ignore_existing (bool): Whether a repo already existing is fatal
|
|
Patrick Uiterwijk |
3f97f6 |
"""
|
|
Patrick Uiterwijk |
3f97f6 |
if region and templ:
|
|
Patrick Uiterwijk |
3f97f6 |
raise Exception("repoSpanner is incompatible with template directory")
|
|
Patrick Uiterwijk |
3f97f6 |
|
|
Patrick Uiterwijk |
3f97f6 |
created_dirs = []
|
|
Patrick Uiterwijk |
3f97f6 |
|
|
Patrick Uiterwijk |
3f97f6 |
try:
|
|
Slavek Kabrda |
0915d0 |
for repotype in pagure.lib.query.get_repotypes():
|
|
Patrick Uiterwijk |
3f97f6 |
created = _create_project_repo(
|
|
Patrick Uiterwijk |
3f97f6 |
project, region, templ, ignore_existing, repotype
|
|
Patrick Uiterwijk |
3f97f6 |
)
|
|
Patrick Uiterwijk |
3f97f6 |
if created:
|
|
Patrick Uiterwijk |
3f97f6 |
created_dirs.append(created)
|
|
Patrick Uiterwijk |
3f97f6 |
except Exception:
|
|
Patrick Uiterwijk |
3f97f6 |
for created in created_dirs:
|
|
Patrick Uiterwijk |
3f97f6 |
shutil.rmtree(created)
|
|
Patrick Uiterwijk |
3f97f6 |
raise
|
|
Patrick Uiterwijk |
d29158 |
|
|
Patrick Uiterwijk |
d29158 |
set_up_project_hooks(project, region)
|
|
Pierre-Yves Chibon |
f6a6e0 |
|
|
Pierre-Yves Chibon |
f6a6e0 |
|
|
Pierre-Yves Chibon |
f6a6e0 |
def get_stats_patch(patch):
|
|
Pierre-Yves Chibon |
f6a6e0 |
""" Returns some statistics about a given patch.
|
|
Pierre-Yves Chibon |
f6a6e0 |
|
|
Pierre-Yves Chibon |
f6a6e0 |
These stats include:
|
|
Pierre-Yves Chibon |
f6a6e0 |
status: if the file was added (A), deleted (D), modified (M) or
|
|
Pierre-Yves Chibon |
f6a6e0 |
renamed (R)
|
|
Pierre-Yves Chibon |
f6a6e0 |
old_path: the path to the old file
|
|
Pierre-Yves Chibon |
f6a6e0 |
new_path: the path to the new file
|
|
Pierre-Yves Chibon |
f6a6e0 |
lines_added: the number of lines added in this patch
|
|
Pierre-Yves Chibon |
f6a6e0 |
lines_removed: the number of lines removed in this patch
|
|
Pierre-Yves Chibon |
f6a6e0 |
|
|
Pierre-Yves Chibon |
f6a6e0 |
All these information are returned in a dict.
|
|
Pierre-Yves Chibon |
f6a6e0 |
|
|
Pierre-Yves Chibon |
f6a6e0 |
Args:
|
|
Pierre-Yves Chibon |
f6a6e0 |
patch (pygit2.Patch): the patch object to get stats on
|
|
Pierre-Yves Chibon |
f6a6e0 |
Returns: a dict with the stats described above
|
|
Pierre-Yves Chibon |
f6a6e0 |
Raises (pagure.exceptions.PagureException): if for some reason (likely
|
|
Pierre-Yves Chibon |
f6a6e0 |
a change in pygit2's API) this function does not manage to gather
|
|
Pierre-Yves Chibon |
f6a6e0 |
all the stats it should
|
|
Pierre-Yves Chibon |
f6a6e0 |
|
|
Pierre-Yves Chibon |
f6a6e0 |
"""
|
|
Pierre-Yves Chibon |
f6a6e0 |
|
|
Pierre-Yves Chibon |
f6a6e0 |
output = {
|
|
Pierre-Yves Chibon |
f6a6e0 |
"lines_added": patch.line_stats[1],
|
|
Pierre-Yves Chibon |
f6a6e0 |
"lines_removed": patch.line_stats[2],
|
|
Pierre-Yves Chibon |
f6a6e0 |
"new_path": None,
|
|
Pierre-Yves Chibon |
f6a6e0 |
"old_path": None,
|
|
Pierre-Yves Chibon |
f6a6e0 |
"status": None,
|
|
Pierre-Yves Chibon |
f6a6e0 |
"new_id": None,
|
|
Pierre-Yves Chibon |
f6a6e0 |
"old_id": None,
|
|
Pierre-Yves Chibon |
f6a6e0 |
}
|
|
Pierre-Yves Chibon |
f6a6e0 |
if hasattr(patch, "new_file_path"):
|
|
Pierre-Yves Chibon |
f6a6e0 |
# Older pygit2
|
|
Pierre-Yves Chibon |
f6a6e0 |
status = patch.status
|
|
Pierre-Yves Chibon |
f6a6e0 |
if patch.new_file_path != patch.old_file_path:
|
|
Pierre-Yves Chibon |
f6a6e0 |
status = "R"
|
|
Pierre-Yves Chibon |
f6a6e0 |
output["status"] = status
|
|
Pierre-Yves Chibon |
f6a6e0 |
output["new_path"] = patch.new_file_path
|
|
Pierre-Yves Chibon |
f6a6e0 |
output["old_path"] = patch.old_file_path
|
|
Pierre-Yves Chibon |
f6a6e0 |
output["new_id"] = str(patch.new_id)
|
|
Pierre-Yves Chibon |
f6a6e0 |
output["old_id"] = str(patch.old_id)
|
|
Pierre-Yves Chibon |
f6a6e0 |
elif hasattr(patch, "delta"):
|
|
Pierre-Yves Chibon |
70eb4b |
status = None
|
|
Pierre-Yves Chibon |
f6a6e0 |
# Newer pygit2
|
|
Slavek Kabrda |
dade63 |
# we recognize non-executable file, executable file and symlink
|
|
Slavek Kabrda |
dade63 |
expected_modes = [33188, 33261, 40960]
|
|
Slavek Kabrda |
dade63 |
if (
|
|
Slavek Kabrda |
dade63 |
patch.delta.new_file.mode == 0
|
|
Slavek Kabrda |
dade63 |
and patch.delta.old_file.mode in expected_modes
|
|
Slavek Kabrda |
dade63 |
):
|
|
Pierre-Yves Chibon |
f6a6e0 |
status = "D"
|
|
Pierre-Yves Chibon |
f6a6e0 |
elif (
|
|
Slavek Kabrda |
dade63 |
patch.delta.new_file.mode in expected_modes
|
|
Pierre-Yves Chibon |
f6a6e0 |
and patch.delta.old_file.mode == 0
|
|
Pierre-Yves Chibon |
f6a6e0 |
):
|
|
Pierre-Yves Chibon |
f6a6e0 |
status = "A"
|
|
Slavek Kabrda |
dade63 |
elif (
|
|
Slavek Kabrda |
dade63 |
patch.delta.new_file.mode in expected_modes
|
|
Slavek Kabrda |
dade63 |
and patch.delta.old_file.mode in expected_modes
|
|
Slavek Kabrda |
dade63 |
):
|
|
Pierre-Yves Chibon |
f6a6e0 |
status = "M"
|
|
Pierre-Yves Chibon |
f6a6e0 |
if patch.delta.new_file.path != patch.delta.old_file.path:
|
|
Pierre-Yves Chibon |
f6a6e0 |
status = "R"
|
|
Pierre-Yves Chibon |
f6a6e0 |
|
|
Pierre-Yves Chibon |
f6a6e0 |
output["status"] = status
|
|
Pierre-Yves Chibon |
f6a6e0 |
output["new_path"] = patch.delta.new_file.path
|
|
Pierre-Yves Chibon |
f6a6e0 |
output["new_id"] = str(patch.delta.new_file.id)
|
|
Pierre-Yves Chibon |
f6a6e0 |
output["old_path"] = patch.delta.old_file.path
|
|
Pierre-Yves Chibon |
f6a6e0 |
output["old_id"] = str(patch.delta.old_file.id)
|
|
Pierre-Yves Chibon |
f6a6e0 |
|
|
Pierre-Yves Chibon |
f6a6e0 |
if None in output.values(): # pragma: no-cover
|
|
Pierre-Yves Chibon |
f6a6e0 |
raise pagure.exceptions.PagureException(
|
|
Pierre-Yves Chibon |
f6a6e0 |
"Unable to properly retrieve the stats for this patch"
|
|
Pierre-Yves Chibon |
f6a6e0 |
)
|
|
Pierre-Yves Chibon |
f6a6e0 |
|
|
Pierre-Yves Chibon |
f6a6e0 |
return output
|
|
Pierre-Yves Chibon |
ded1fa |
|
|
Pierre-Yves Chibon |
ded1fa |
|
|
Pierre-Yves Chibon |
ded1fa |
def generate_archive(project, commit, tag, name, archive_fmt):
|
|
Pierre-Yves Chibon |
ded1fa |
""" Generate the desired archive of the specified project for the
|
|
Pierre-Yves Chibon |
ded1fa |
specified commit with the given name and archive format.
|
|
Pierre-Yves Chibon |
ded1fa |
|
|
Pierre-Yves Chibon |
ded1fa |
Args:
|
|
Pierre-Yves Chibon |
ded1fa |
project (pagure.lib.model.Project): the project's repository from
|
|
Pierre-Yves Chibon |
ded1fa |
which to generate the archive
|
|
Pierre-Yves Chibon |
ded1fa |
commit (str): the commit hash to generate the archive of
|
|
Pierre-Yves Chibon |
ded1fa |
name (str): the name to give to the archive
|
|
Pierre-Yves Chibon |
ded1fa |
archive_fmt (str): the format of the archive to generate, can be
|
|
Pierre-Yves Chibon |
ded1fa |
either gzip or tag or tar.gz
|
|
Pierre-Yves Chibon |
ded1fa |
Returns: None
|
|
Pierre-Yves Chibon |
ded1fa |
Raises (pagure.exceptions.PagureException): if an un-supported archive
|
|
Pierre-Yves Chibon |
ded1fa |
format is specified
|
|
Pierre-Yves Chibon |
ded1fa |
|
|
Pierre-Yves Chibon |
ded1fa |
"""
|
|
Pierre-Yves Chibon |
ded1fa |
|
|
Pierre-Yves Chibon |
ded1fa |
def _exclude_git(filename):
|
|
Pierre-Yves Chibon |
ded1fa |
return ".git" in filename
|
|
Pierre-Yves Chibon |
ded1fa |
|
|
Pierre-Yves Chibon |
ded1fa |
with TemporaryClone(project, "main", "archive", parent=name) as tempclone:
|
|
Pierre-Yves Chibon |
ded1fa |
repo_obj = tempclone.repo
|
|
Pierre-Yves Chibon |
ded1fa |
commit_obj = repo_obj[commit]
|
|
Pierre-Yves Chibon |
ded1fa |
repo_obj.checkout_tree(commit_obj.tree)
|
|
Pierre-Yves Chibon |
ded1fa |
archive_folder = pagure_config.get("ARCHIVE_FOLDER")
|
|
Pierre-Yves Chibon |
ded1fa |
|
|
Pierre-Yves Chibon |
ded1fa |
tag_path = ""
|
|
Pierre-Yves Chibon |
ded1fa |
if tag:
|
|
Pierre-Yves Chibon |
ded1fa |
tag_path = os.path.join("tags", tag)
|
|
Pierre-Yves Chibon |
ded1fa |
target_path = os.path.join(
|
|
Pierre-Yves Chibon |
ded1fa |
archive_folder, project.fullname, tag_path, commit
|
|
Pierre-Yves Chibon |
ded1fa |
)
|
|
Pierre-Yves Chibon |
ded1fa |
if not os.path.exists(target_path):
|
|
Pierre-Yves Chibon |
7c59e9 |
_log.info("Creating folder: %s", target_path)
|
|
Pierre-Yves Chibon |
ded1fa |
os.makedirs(target_path)
|
|
Pierre-Yves Chibon |
ded1fa |
fullpath = os.path.join(target_path, name)
|
|
Pierre-Yves Chibon |
ded1fa |
|
|
Pierre-Yves Chibon |
ded1fa |
if archive_fmt == "tar":
|
|
Pierre-Yves Chibon |
ded1fa |
with tarfile.open(name=fullpath + ".tar", mode="w") as tar:
|
|
Pierre-Yves Chibon |
ded1fa |
tar.add(
|
|
Pierre-Yves Chibon |
ded1fa |
name=tempclone.repopath, exclude=_exclude_git, arcname=name
|
|
Pierre-Yves Chibon |
ded1fa |
)
|
|
Pierre-Yves Chibon |
ded1fa |
elif archive_fmt == "tar.gz":
|
|
Pierre-Yves Chibon |
ded1fa |
with tarfile.open(name=fullpath + ".tar.gz", mode="w:gz") as tar:
|
|
Pierre-Yves Chibon |
ded1fa |
tar.add(
|
|
Pierre-Yves Chibon |
ded1fa |
name=tempclone.repopath, exclude=_exclude_git, arcname=name
|
|
Pierre-Yves Chibon |
ded1fa |
)
|
|
Pierre-Yves Chibon |
ded1fa |
elif archive_fmt == "zip":
|
|
Pierre-Yves Chibon |
ded1fa |
# Code from /usr/lib64/python2.7/zipfile.py adjusted for our
|
|
Pierre-Yves Chibon |
ded1fa |
# needs
|
|
Pierre-Yves Chibon |
ded1fa |
def addToZip(zf, path, zippath):
|
|
Pierre-Yves Chibon |
ded1fa |
if _exclude_git(path):
|
|
Pierre-Yves Chibon |
ded1fa |
return
|
|
Pierre-Yves Chibon |
ded1fa |
if os.path.isfile(path):
|
|
Pierre-Yves Chibon |
ded1fa |
zf.write(path, zippath, zipfile.ZIP_DEFLATED)
|
|
Pierre-Yves Chibon |
ded1fa |
elif os.path.isdir(path):
|
|
Pierre-Yves Chibon |
ded1fa |
if zippath:
|
|
Pierre-Yves Chibon |
ded1fa |
zf.write(path, zippath)
|
|
Pierre-Yves Chibon |
ded1fa |
for nm in os.listdir(path):
|
|
Pierre-Yves Chibon |
ded1fa |
if _exclude_git(path):
|
|
Pierre-Yves Chibon |
ded1fa |
continue
|
|
Pierre-Yves Chibon |
ded1fa |
addToZip(
|
|
Pierre-Yves Chibon |
ded1fa |
zf,
|
|
Pierre-Yves Chibon |
ded1fa |
os.path.join(path, nm),
|
|
Pierre-Yves Chibon |
ded1fa |
os.path.join(zippath, nm),
|
|
Pierre-Yves Chibon |
ded1fa |
)
|
|
Pierre-Yves Chibon |
ded1fa |
|
|
Pierre-Yves Chibon |
ded1fa |
with zipfile.ZipFile(fullpath + ".zip", "w") as zipstream:
|
|
Pierre-Yves Chibon |
ded1fa |
addToZip(zipstream, tempclone.repopath, name)
|
|
Pierre-Yves Chibon |
ded1fa |
else:
|
|
Pierre-Yves Chibon |
ded1fa |
raise pagure.exceptions.PagureException(
|
|
Pierre-Yves Chibon |
ded1fa |
"Un-support archive format requested: %s", archive_fmt
|
|
Pierre-Yves Chibon |
ded1fa |
)
|
|
Pierre-Yves Chibon |
227f4c |
|
|
Pierre-Yves Chibon |
227f4c |
|
|
Pierre-Yves Chibon |
227f4c |
def mirror_pull_project(session, project, debug=False):
|
|
Pierre-Yves Chibon |
227f4c |
""" Mirror locally a project from a remote URL. """
|
|
Pierre-Yves Chibon |
227f4c |
remote = project.mirrored_from
|
|
Pierre-Yves Chibon |
cea8e2 |
if not remote:
|
|
Pierre-Yves Chibon |
cea8e2 |
_log.info("No remote found, ignoring")
|
|
Pierre-Yves Chibon |
cea8e2 |
return
|
|
Pierre-Yves Chibon |
227f4c |
repopath = tempfile.mkdtemp(prefix="pagure-mirror_in-")
|
|
Pierre-Yves Chibon |
227f4c |
lclrepopath = pagure.utils.get_repo_path(project)
|
|
Pierre-Yves Chibon |
227f4c |
|
|
Pierre-Yves Chibon |
227f4c |
def _run_command(command, logs):
|
|
Pierre-Yves Chibon |
227f4c |
_log.info("Running the command: %s" % command)
|
|
Pierre-Yves Chibon |
227f4c |
if debug:
|
|
Pierre-Yves Chibon |
227f4c |
print("Running the command: %s" % command)
|
|
Pierre-Yves Chibon |
227f4c |
print(" Running in: %s" % repopath)
|
|
Pierre-Yves Chibon |
227f4c |
(stdout, stderr) = pagure.lib.git.read_git_lines(
|
|
Pierre-Yves Chibon |
227f4c |
command, abspath=repopath, error=True
|
|
Pierre-Yves Chibon |
227f4c |
)
|
|
Pierre-Yves Chibon |
227f4c |
log = "Output from %s:\n stdout: %s\n stderr: %s" % (
|
|
Pierre-Yves Chibon |
227f4c |
command,
|
|
Pierre-Yves Chibon |
227f4c |
stdout,
|
|
Pierre-Yves Chibon |
227f4c |
stderr,
|
|
Pierre-Yves Chibon |
227f4c |
)
|
|
Pierre-Yves Chibon |
227f4c |
logs.append(log)
|
|
Pierre-Yves Chibon |
227f4c |
if debug:
|
|
Pierre-Yves Chibon |
227f4c |
print(log)
|
|
Pierre-Yves Chibon |
227f4c |
return logs
|
|
Pierre-Yves Chibon |
227f4c |
|
|
Pierre-Yves Chibon |
227f4c |
try:
|
|
Pierre-Yves Chibon |
227f4c |
# Pull
|
|
Pierre-Yves Chibon |
227f4c |
logs = []
|
|
Pierre-Yves Chibon |
227f4c |
logs = _run_command(["clone", "--mirror", remote, "."], logs)
|
|
Pierre-Yves Chibon |
227f4c |
logs = _run_command(["remote", "add", "local", lclrepopath], logs)
|
|
Pierre-Yves Chibon |
227f4c |
|
|
Pierre-Yves Chibon |
227f4c |
# Push the changes
|
|
Pierre-Yves Chibon |
227f4c |
_log.info("Pushing")
|
|
Pierre-Yves Chibon |
227f4c |
if debug:
|
|
Pierre-Yves Chibon |
227f4c |
print("Pushing to the local git repo")
|
|
Pierre-Yves Chibon |
227f4c |
extra = {}
|
|
Pierre-Yves Chibon |
227f4c |
if project.is_on_repospanner:
|
|
Pierre-Yves Chibon |
227f4c |
regioninfo = pagure_config["REPOSPANNER_REGIONS"][
|
|
Pierre-Yves Chibon |
227f4c |
project.repospanner_region
|
|
Pierre-Yves Chibon |
227f4c |
]
|
|
Pierre-Yves Chibon |
227f4c |
|
|
Pierre-Yves Chibon |
227f4c |
extra.update(
|
|
Pierre-Yves Chibon |
227f4c |
{
|
|
Pierre-Yves Chibon |
227f4c |
"username": "pagure",
|
|
Pierre-Yves Chibon |
227f4c |
"repotype": "main",
|
|
Pierre-Yves Chibon |
227f4c |
"project_name": project.name,
|
|
Pierre-Yves Chibon |
227f4c |
"project_user": project.user.username
|
|
Pierre-Yves Chibon |
227f4c |
if project.is_fork
|
|
Pierre-Yves Chibon |
227f4c |
else "",
|
|
Pierre-Yves Chibon |
227f4c |
"project_namespace": project.namespace or "",
|
|
Pierre-Yves Chibon |
227f4c |
}
|
|
Pierre-Yves Chibon |
227f4c |
)
|
|
Pierre-Yves Chibon |
227f4c |
args = []
|
|
Pierre-Yves Chibon |
227f4c |
for opt in extra:
|
|
Pierre-Yves Chibon |
227f4c |
args.extend(["--extra", opt, extra[opt]])
|
|
Pierre-Yves Chibon |
227f4c |
command = [
|
|
Pierre-Yves Chibon |
227f4c |
"git",
|
|
Pierre-Yves Chibon |
227f4c |
"-c",
|
|
Pierre-Yves Chibon |
227f4c |
"protocol.ext.allow=always",
|
|
Pierre-Yves Chibon |
227f4c |
"push",
|
|
Pierre-Yves Chibon |
227f4c |
"ext::%s %s %s"
|
|
Pierre-Yves Chibon |
227f4c |
% (
|
|
Pierre-Yves Chibon |
227f4c |
pagure_config["REPOBRIDGE_BINARY"],
|
|
Pierre-Yves Chibon |
227f4c |
" ".join(args),
|
|
Pierre-Yves Chibon |
227f4c |
project._repospanner_repo_name("main"),
|
|
Pierre-Yves Chibon |
227f4c |
),
|
|
Pierre-Yves Chibon |
227f4c |
"--repo",
|
|
Pierre-Yves Chibon |
227f4c |
repopath,
|
|
Pierre-Yves Chibon |
227f4c |
]
|
|
Pierre-Yves Chibon |
227f4c |
environ = {
|
|
Pierre-Yves Chibon |
227f4c |
"USER": "pagure",
|
|
Pierre-Yves Chibon |
227f4c |
"REPOBRIDGE_CONFIG": ":environment:",
|
|
Pierre-Yves Chibon |
227f4c |
"REPOBRIDGE_BASEURL": regioninfo["url"],
|
|
Pierre-Yves Chibon |
227f4c |
"REPOBRIDGE_CA": regioninfo["ca"],
|
|
Pierre-Yves Chibon |
227f4c |
"REPOBRIDGE_CERT": regioninfo["push_cert"]["cert"],
|
|
Pierre-Yves Chibon |
227f4c |
"REPOBRIDGE_KEY": regioninfo["push_cert"]["key"],
|
|
Pierre-Yves Chibon |
227f4c |
}
|
|
Pierre-Yves Chibon |
227f4c |
else:
|
|
Pierre-Yves Chibon |
227f4c |
command = ["git", "push", "local", "--mirror"]
|
|
Pierre-Yves Chibon |
227f4c |
environ = {}
|
|
Pierre-Yves Chibon |
227f4c |
|
|
Pierre-Yves Chibon |
227f4c |
_log.debug("Running a git push to %s", project.fullname)
|
|
Pierre-Yves Chibon |
227f4c |
env = os.environ.copy()
|
|
Pierre-Yves Chibon |
227f4c |
env["GL_USER"] = "pagure"
|
|
Pierre-Yves Chibon |
227f4c |
env["GL_BYPASS_ACCESS_CHECKS"] = "1"
|
|
Pierre-Yves Chibon |
227f4c |
if pagure_config.get("GITOLITE_HOME"):
|
|
Pierre-Yves Chibon |
227f4c |
env["HOME"] = pagure_config["GITOLITE_HOME"]
|
|
Pierre-Yves Chibon |
227f4c |
env.update(environ)
|
|
Pierre-Yves Chibon |
227f4c |
env.update(extra)
|
|
Pierre-Yves Chibon |
227f4c |
out = subprocess.check_output(
|
|
Pierre-Yves Chibon |
227f4c |
command, cwd=repopath, stderr=subprocess.STDOUT, env=env
|
|
Pierre-Yves Chibon |
227f4c |
)
|
|
Pierre-Yves Chibon |
227f4c |
log = "Output from %s:" % command
|
|
Pierre-Yves Chibon |
227f4c |
logs.append(log)
|
|
Pierre-Yves Chibon |
227f4c |
logs.append(out)
|
|
Pierre-Yves Chibon |
227f4c |
_log.debug("Output: %s" % out)
|
|
Pierre-Yves Chibon |
227f4c |
|
|
Pierre-Yves Chibon |
227f4c |
project.mirrored_from_last_log = "\n".join(logs)
|
|
Pierre-Yves Chibon |
227f4c |
session.add(project)
|
|
Pierre-Yves Chibon |
227f4c |
session.commit()
|
|
Pierre-Yves Chibon |
227f4c |
_log.info("\n".join(logs))
|
|
Pierre-Yves Chibon |
227f4c |
except subprocess.CalledProcessError as err:
|
|
Pierre-Yves Chibon |
227f4c |
_log.debug(
|
|
Pierre-Yves Chibon |
227f4c |
"Rebase FAILED: {cmd} returned code {code} with the "
|
|
Pierre-Yves Chibon |
227f4c |
"following output: {output}".format(
|
|
Pierre-Yves Chibon |
227f4c |
cmd=err.cmd, code=err.returncode, output=err.output
|
|
Pierre-Yves Chibon |
227f4c |
)
|
|
Pierre-Yves Chibon |
227f4c |
)
|
|
Pierre-Yves Chibon |
227f4c |
# This should never really happen, since we control the repos, but
|
|
Pierre-Yves Chibon |
227f4c |
# this way, we can be sure to get the output logged
|
|
Pierre-Yves Chibon |
227f4c |
remotes = []
|
|
Pierre-Yves Chibon |
227f4c |
for line in err.output.decode("utf-8").split("\n"):
|
|
Pierre-Yves Chibon |
227f4c |
_log.info("Remote line: %s", line)
|
|
Pierre-Yves Chibon |
227f4c |
if line.startswith("remote: "):
|
|
Pierre-Yves Chibon |
227f4c |
_log.debug("Remote: %s" % line)
|
|
Pierre-Yves Chibon |
227f4c |
remotes.append(line[len("remote: ") :].strip())
|
|
Pierre-Yves Chibon |
227f4c |
if remotes:
|
|
Pierre-Yves Chibon |
227f4c |
_log.info("Remote rejected with: %s" % remotes)
|
|
Pierre-Yves Chibon |
227f4c |
raise pagure.exceptions.PagurePushDenied(
|
|
Pierre-Yves Chibon |
227f4c |
"Remote hook declined the push: %s" % "\n".join(remotes)
|
|
Pierre-Yves Chibon |
227f4c |
)
|
|
Pierre-Yves Chibon |
227f4c |
else:
|
|
Pierre-Yves Chibon |
227f4c |
# Something else happened, pass the original
|
|
Pierre-Yves Chibon |
227f4c |
_log.exception("Error pushing. Output: %s", err.output)
|
|
Pierre-Yves Chibon |
227f4c |
raise
|
|
Pierre-Yves Chibon |
227f4c |
finally:
|
|
Pierre-Yves Chibon |
227f4c |
shutil.rmtree(repopath)
|