Skip to content

Commit

Permalink
rpmbuild, dist-git-client: new package dist-git-client
Browse files Browse the repository at this point in the history
The dist-git-client utility seems generic enough to have it built
separately.  This could be useful e.g. for the Konflux build initiative,
where we don't necessarily have to build the full copr-rpmbuild package
to operate with DistGit.
  • Loading branch information
praiskup committed Jun 6, 2024
1 parent 24becb0 commit 202acca
Show file tree
Hide file tree
Showing 11 changed files with 493 additions and 100 deletions.
1 change: 1 addition & 0 deletions .tito/packages/dist-git-client
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
1.1-0 dist-git-client/
339 changes: 339 additions & 0 deletions dist-git-client/LICENSE

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
#! /usr/bin/python
#! /usr/bin/python3

"""
From within a git checkout, try to download files from dist-git lookaside cache.
"""

from copr_distgit_client import main
from dist_git_client import main

if __name__ == "__main__":
main()
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,4 @@

absdir="$(dirname "$(readlink -f "$0")")"
export PYTHONPATH="$absdir${PYTHONPATH+:$PYTHONPATH}"
python3 "$absdir/bin/copr-distgit-client" "$@"
python3 "$absdir/bin/dist-git-client" "$@"
81 changes: 81 additions & 0 deletions dist-git-client/dist-git-client.spec
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# SPEC file overview:
# https://docs.fedoraproject.org/en-US/quick-docs/creating-rpm-packages/#con_rpm-spec-file-overview
# Fedora packaging guidelines:
# https://docs.fedoraproject.org/en-US/packaging-guidelines/


Name: dist-git-client
Version: 1.1
Release: 0%{?dist}
Summary: Get sources for RPM builds from DistGit repositories
BuildArch: noarch

License: GPL-2.0-or-later
URL: https://github.com/release-engineering/dist-git.git
Source0: %name-%version.tar.gz

Requires: curl
Requires: /usr/bin/git

BuildRequires: python3-pytest
BuildRequires: python3-rpm-macros
BuildRequires: python3-six
BuildRequires: /usr/bin/argparse-manpage
BuildRequires: /usr/bin/git

%if 0%{?fedora} || 0%{?rhel} > 9
Requires: python3-rpmautospec
BuildRequires: python3-rpmautospec
%endif

%description
A simple, configurable python utility that is able to clone package sources from
a DistGit repository, download sources from the corresponding lookaside cache
locations, and generate source RPMs.

The utility is able to automatically map the .git/config clone URL into the
corresponding DistGit instance configuration.


%prep
%setup -q


%build



%install
install -d %{buildroot}%{_bindir}
install -d %{buildroot}%{_mandir}/man1
install -d %{buildroot}%{_sysconfdir}/dist-git-client
install -d %{buildroot}%{python3_sitelib}
install -p -m 755 bin/dist-git-client %buildroot%_bindir
argparse-manpage --pyfile dist_git_client.py \
--function _get_argparser \
--author "Copr Team" \
--author-email "copr-team@redhat.com" \
--url %url --project-name Copr \
> %{buildroot}%{_mandir}/man1/dist-git-client.1
install -p -m 644 etc/default.ini \
%{buildroot}%{_sysconfdir}/dist-git-client
install -p -m 644 dist_git_client.py %{buildroot}%{python3_sitelib}


%check
PYTHON=python3 ./run_tests.sh -vv --no-coverage


%files
%license LICENSE
%_bindir/dist-git-client
%_mandir/man1/dist-git-client.1*
%dir %_sysconfdir/dist-git-client
%config %_sysconfdir/dist-git-client/default.ini
%python3_sitelib/dist_git_client.*
%python3_sitelib/__pycache__/dist_git_client*


%changelog
* Thu Jun 06 2024 Pavel Raiskup <praiskup@redhat.com> 1.1-0
- new package built with tito
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""
copr-distgit-client code, moved to module to simplify unit-testing
dist-git-client code, moved to a python module to simplify unit-testing
"""

import argparse
Expand All @@ -9,6 +9,7 @@
import logging
import shlex
import os
import shutil
import subprocess
import sys
from six.moves.urllib.parse import urlparse
Expand Down Expand Up @@ -370,18 +371,18 @@ def clone(args, config):
])

def _get_argparser():
parser = argparse.ArgumentParser(prog="copr-distgit-client",
parser = argparse.ArgumentParser(prog="dist-git-client",
description="""\
A simple, configurable python utility that is able to download sources from
various dist-git instances, and generate source RPMs.
The utility is able to automatically map the "origin" .git/config clone URL
(or --forked-from URL, if specified) to a corresponding dist-git instance
configured in /etc/copr-distgit-client directory.
configured in /etc/dist-git-client directory.
""")

# main parser
default_confdir = os.environ.get("COPR_DISTGIT_CLIENT_CONFDIR",
"/etc/copr-distgit-client")
"/etc/dist-git-client")
parser.add_argument(
"--configdir", default=default_confdir,
help="Where to load configuration files from")
Expand Down Expand Up @@ -441,7 +442,7 @@ def _get_argparser():
clone_parser.add_argument(
"--dist-git",
default="fedora",
help=("The DistGit ID as configured in /etc/copr-distgit-client/"),
help=("The DistGit ID as configured in /etc/dist-git-client/"),
)

clone_parser.add_argument(
Expand All @@ -456,6 +457,29 @@ def _get_argparser():
return parser


def unittests_init_git(files=None):
"""
Initialize .git/ directory. This method is only used for unit-testing.
"""
check_output(["git", "init", ".", "-b", "main"])
shutil.rmtree(".git/hooks")
check_output(["git", "config", "user.email", "you@example.com"])
check_output(["git", "config", "user.name", "Your Name"])
check_output(["git", "config", "advice.detachedHead", "false"])

for filename, content in files:
dirname = os.path.dirname(filename)
try:
os.makedirs(dirname)
except OSError:
pass
with open(filename, "w", encoding="utf-8") as filed:
filed.write(content)
check_output(["git", "add", filename])

check_output(["git", "commit", "-m", "initial"])


def main():
""" The entrypoint for the whole logic """
args = _get_argparser().parse_args()
Expand Down
File renamed without changes.
18 changes: 18 additions & 0 deletions dist-git-client/run_tests.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#! /bin/bash

set -e

args=()

coverage=( --cov-report term-missing --cov bin --cov dist_git_client )
for arg; do
case $arg in
--no-coverage) coverage=() ;;
*) args+=( "$arg" ) ;;
esac
done

abspath=$(readlink -f .)
export PYTHONPATH="${PYTHONPATH+$PYTHONPATH:}$abspath"
export PATH=$(readlink -f bin):$PATH
"${PYTHON:-python3}" -m pytest -s tests "${coverage[@]}" "${args[@]}"
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""
copr-distgit-client testsuite
dist-git-client testsuite
"""

import os
Expand All @@ -13,34 +13,12 @@
except ImportError:
import mock

from copr_distgit_client import (sources, srpm, _load_config, check_output,
_detect_clone_url, get_distgit_config,
from dist_git_client import (sources, srpm, _load_config, check_output,
_detect_clone_url, get_distgit_config, unittests_init_git,
)

# pylint: disable=useless-object-inheritance

def init_git(files=None):
""" Initialize .git/ directory """

check_output(["git", "init", "."])
shutil.rmtree(".git/hooks")
check_output(["git", "config", "user.email", "you@example.com"])
check_output(["git", "config", "user.name", "Your Name"])
check_output(["git", "config", "advice.detachedHead", "false"])

for filename, content in files:
dirname = os.path.dirname(filename)
try:
os.makedirs(dirname)
except OSError:
pass
with open(filename, "w") as filed:
filed.write(content)
check_output(["git", "add", filename])

check_output(["git", "commit", "-m", "initial"])


def git_origin_url(url):
""" setup .git/config with core.origin.url == URL """
with open(".git/config", "a+") as gcf:
Expand All @@ -59,24 +37,24 @@ def setup_method(self, method):
_unused_but_needed_for_el6 = (method)
testdir = os.path.dirname(__file__)
projdir = os.path.dirname(testdir)
self.config_dir = os.path.join(projdir, 'etc/copr-distgit-client')
self.config_dir = os.path.join(projdir, 'etc')
self.config = _load_config(self.config_dir)
class _Args:
# pylint: disable=too-few-public-methods
dry_run = False
forked_from = None
self.args = _Args()
self.workdir = tempfile.mkdtemp(prefix="copr-distgit-test-")
self.workdir = tempfile.mkdtemp(prefix="dist-git-client-test-")
os.chdir(self.workdir)

def teardown_method(self, method):
_unused_but_needed_for_el6 = (method)
shutil.rmtree(self.workdir)


@mock.patch('copr_distgit_client.download_file_and_check')
@mock.patch('dist_git_client.download_file_and_check')
def test_copr_distgit(self, download):
init_git([
unittests_init_git([
# <foo>.spec in <bar>.git, in Copr it is possible
("test.spec", ""),
("sources", "2102fd0602de72e58765adcbf92349d8 retrace-server-git-955.3e4742a.tar.gz\n"),
Expand All @@ -91,12 +69,12 @@ def test_copr_distgit(self, download):
)

@pytest.mark.parametrize('base', ["tar", "tar/"])
@mock.patch('copr_distgit_client.download_file_and_check')
@mock.patch('dist_git_client.download_file_and_check')
def test_fedora_old(self, download, base):
"""
Old sources format + ssh clone
"""
init_git([
unittests_init_git([
("tar.spec", ""),
("sources", "0ced6f20b9fa1bea588005b5ad4b52c1 tar-1.26.tar.xz\n"),
])
Expand All @@ -109,7 +87,7 @@ def test_fedora_old(self, download, base):
)

@pytest.mark.parametrize('base', ["tar.git", "tar.git/"])
@mock.patch('copr_distgit_client.download_file_and_check')
@mock.patch('dist_git_client.download_file_and_check')
def test_fedora_new(self, download, base):
"""
New sources format + anonymous clone
Expand All @@ -118,7 +96,7 @@ def test_fedora_new(self, download, base):
"1bd13854009b6ee08958481738e6bf661e40216a2befe461d06b4b350eb882e43"
"1b3a4eeea7ca1d35d37102df76194c9d933df2b18b3c5401350e9fc17017750"
)
init_git([
unittests_init_git([
("tar.spec", ""),
("sources", "SHA512 (tar-1.32.tar.xz) = {0}\n".format(sha512)),
])
Expand All @@ -131,20 +109,20 @@ def test_fedora_new(self, download, base):
).format(sha512=sha512)
assert download.call_args_list[0][0][0] == url

@mock.patch('copr_distgit_client.download_file_and_check')
@mock.patch('dist_git_client.download_file_and_check')
def test_centos(self, download):
"""
Anonymous centos clone
"""
init_git([
unittests_init_git([
("SPECS/centpkg-minimal.spec", ""),
(".centpkg-minimal.metadata", "cf9ce8d900768ed352a6f19a2857e64403643545 SOURCES/centpkg-minimal.tar.gz\n"),
])
git_origin_url("https://git.centos.org/rpms/centpkg-minimal.git")
sources(self.args, self.config)
assert len(download.call_args_list) == 1
assert download.call_args_list[0][0][0] == (
"https://git.centos.org/sources/centpkg-minimal/master/"
"https://git.centos.org/sources/centpkg-minimal/main/"
"cf9ce8d900768ed352a6f19a2857e64403643545"
)
assert download.call_args_list[0][0][2]["sources"] == "SOURCES"
Expand All @@ -164,9 +142,9 @@ def test_centos(self, download):
).format(oldref)


@mock.patch("copr_distgit_client.subprocess.check_call")
@mock.patch("dist_git_client.subprocess.check_call")
def test_centos_download(self, patched_check_call):
init_git([
unittests_init_git([
("SPECS/centpkg-minimal.spec", ""),
(".centpkg-minimal.metadata", "cf9ce8d900768ed352a6f19a2857e64403643545 SOURCES/centpkg-minimal.tar.gz\n"),
])
Expand Down Expand Up @@ -216,7 +194,7 @@ def test_load_prefix_fail(self):
assert msg in str(err)

def test_no_spec(self):
init_git([
unittests_init_git([
("sources", "0ced6f20b9fa1bea588005b5ad4b52c1 tar-1.26.tar.xz\n"),
])
git_origin_url("ssh://praiskup@pkgs.fedoraproject.org/rpms/tar")
Expand Down
Loading

0 comments on commit 202acca

Please sign in to comment.