aurweb/aurweb/testing/git.py
Kevin Morris 30e72d2db5 feat: archive git repository (experimental)
See doc/git-archive.md for general Git archive specifications
See doc/repos/metadata-repo.md for info and direction related to the new Git metadata archive
2022-09-24 16:51:25 +00:00

105 lines
3.8 KiB
Python

import os
from typing import Tuple
import py
from aurweb.models import Package
from aurweb.templates import base_template
from aurweb.testing.filelock import FileLock
from aurweb.util import shell_exec
class GitRepository:
"""
A Git repository class to be used for testing.
Expects a `tmpdir` fixture on construction, which an 'aur.git'
git repository will be created in. After this class is constructed,
users can call GitRepository.exec for git repository operations.
"""
def __init__(self, tmpdir: py.path.local):
self.file_lock = FileLock(tmpdir, "aur.git")
self.file_lock.lock(on_create=self._setup)
def _exec(self, cmdline: str, cwd: str) -> Tuple[int, str, str]:
return shell_exec(cmdline, cwd)
def _exec_repository(self, cmdline: str) -> Tuple[int, str, str]:
return self._exec(cmdline, cwd=str(self.file_lock.path))
def exec(self, cmdline: str) -> Tuple[int, str, str]:
return self._exec_repository(cmdline)
def _setup(self, path: str) -> None:
"""
Setup the git repository from scratch.
Create the `path` directory and run the INSTALL recommended
git initialization commands inside of it. Additionally, install
aurweb.git.update to {path}/hooks/update.
:param path: Repository path not yet created
"""
os.makedirs(path)
commands = [
"git init -q",
"git config --local transfer.hideRefs '^refs/'",
"git config --local --add transfer.hideRefs '!refs/'",
"git config --local --add transfer.hideRefs '!HEAD'",
"git config --local commit.gpgsign false",
"git config --local user.name 'Test User'",
"git config --local user.email 'test@example.org'",
]
for cmdline in commands:
return_code, out, err = self.exec(cmdline)
assert return_code == 0
# This is also done in the INSTALL script to give the `aur`
# ssh user permissions on the repository. We don't need it
# during testing, since our testing user will be controlling
# the repository. It is left here as a note.
# self.exec("chown -R aur .")
def commit(self, pkg: Package, message: str):
"""
Commit a Package record to the git repository.
This function generates a PKGBUILD and .SRCINFO based on
`pkg`, then commits them to the repository with the
`message` commit message.
:param pkg: Package instance
:param message: Commit message
:return: Output of `git rev-parse HEAD` after committing
"""
ref = f"refs/namespaces/{pkg.Name}/refs/heads/master"
rc, out, err = self.exec(f"git checkout -q --orphan {ref}")
assert rc == 0, f"{(rc, out, err)}"
# Path to aur.git repository.
repo = os.path.join(self.file_lock.path)
licenses = [f"'{p.License.Name}'" for p in pkg.package_licenses]
depends = [f"'{p.DepName}'" for p in pkg.package_dependencies]
pkgbuild = base_template("testing/PKGBUILD.j2")
pkgbuild_path = os.path.join(repo, "PKGBUILD")
with open(pkgbuild_path, "w") as f:
data = pkgbuild.render(pkg=pkg, licenses=licenses, depends=depends)
f.write(data)
srcinfo = base_template("testing/SRCINFO.j2")
srcinfo_path = os.path.join(repo, ".SRCINFO")
with open(srcinfo_path, "w") as f:
f.write(srcinfo.render(pkg=pkg))
rc, out, err = self.exec("git add PKGBUILD .SRCINFO")
assert rc == 0, f"{(rc, out, err)}"
rc, out, err = self.exec(f"git commit -q -m '{message}'")
assert rc == 0, f"{(rc, out, err)}"
# Return stdout of `git rev-parse HEAD`, which is the new commit hash.
return self.exec("git rev-parse HEAD")[1]