rpmdevtools/0002-rpmdevtools-git-83b35ac.patch
2025-01-23 16:10:01 +08:00

531 lines
16 KiB
Diff
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

diff --git a/Makefile.am b/Makefile.am
index bb6f7c6..d55f397 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -15,7 +15,7 @@ man8_MANS = rpmdev-rmdevelrpms.8
dist_pkgsysconf_DATA = curlrc newspec.conf rmdevelrpms.conf \
spectemplate-lib.spec spectemplate-minimal.spec \
spectemplate-perl.spec spectemplate-php-pear.spec \
- spectemplate-python.spec spectemplate-ruby.spec \
+ spectemplate-python.spec spectemplate-pyproject.spec spectemplate-ruby.spec \
spectemplate-ocaml.spec spectemplate-R.spec spectemplate-dummy.spec \
template.init
diff --git a/rpmdev-bumpspec b/rpmdev-bumpspec
index b8f4047..5a6a909 100755
--- a/rpmdev-bumpspec
+++ b/rpmdev-bumpspec
@@ -27,8 +27,10 @@ import time
try:
from rpmautospec import specfile_uses_rpmautospec
+ from rpmautospec.subcommands.release import calculate_release_number
except ImportError:
specfile_uses_rpmautospec = None
+ calculate_release_number = None
__version__ = "1.0.13"
@@ -378,19 +380,25 @@ the Free Software Foundation; either version 2 of the License, or
# Not actually a parser error, but... meh.
parser.error(e)
- uses_rpmautospec = False
+ uses_rpmautospec_autorelease = uses_rpmautospec_autochangelog = False
if specfile_uses_rpmautospec:
- uses_rpmautospec = specfile_uses_rpmautospec(
+ uses_rpmautospec_autorelease = specfile_uses_rpmautospec(
specpath=s.filename,
check_autorelease=True,
check_autochangelog=False
)
+ uses_rpmautospec_autochangelog = specfile_uses_rpmautospec(
+ specpath=s.filename,
+ check_autorelease=False,
+ check_autochangelog=True
+ )
- if uses_rpmautospec:
+ changed = False
+ if uses_rpmautospec_autorelease:
if opts.new:
print("RPMAutoSpec usage detected, only setting Version.")
changed = s.newVersion(opts.new, set_release=False)
- else:
+ elif uses_rpmautospec_autochangelog:
print("RPMAutoSpec usage detected, not changing the spec file.")
continue
else:
@@ -405,14 +413,12 @@ the Free Software Foundation; either version 2 of the License, or
changed = True
- # If we didn't change anything, no need to write and modify the
- # changelog.
if changed:
+ # Write out changed version or release if changed.
s.writeFile(aspec)
- else:
- continue
- if uses_rpmautospec:
+ if uses_rpmautospec_autochangelog:
+ print("RPMAutospec %autochangelog is used, no need to add %changelog entry.")
continue
if not s.checkChangelogPresence():
@@ -422,6 +428,10 @@ the Free Software Foundation; either version 2 of the License, or
# Get EVR for changelog entry.
cmd = ("rpm", "-q", "--specfile", "--define", "dist %{nil}",
"--qf=%|epoch?{%{epoch}:}:{}|%{version}-%{release}\n", aspec)
+ if not opts.new and calculate_release_number and uses_rpmautospec_autorelease:
+ # Rpmautospec doesnt see a change yet so the calculated number will be one too low.
+ release_number = calculate_release_number(aspec) + 1
+ cmd += ("--define", "_rpmautospec_release_number {}".format(release_number))
popen = subprocess.Popen(cmd, stdout=subprocess.PIPE)
evr = popen.communicate()[0].split(b"\n")[0]
if sys.version_info[0] > 2:
diff --git a/rpmdev-spectool b/rpmdev-spectool
index 1d57256..2c06ef8 100755
--- a/rpmdev-spectool
+++ b/rpmdev-spectool
@@ -25,7 +25,9 @@ import os
import tempfile
import time
from collections import OrderedDict
-from typing import Optional
+from typing import Any, Callable, Dict, List, Optional
+from typing import OrderedDict as OrderedDictT
+from typing import Tuple
from urllib.parse import urlparse
import progressbar
@@ -46,13 +48,13 @@ anything about missing sources or patches). The plan is to catch errors like
this in spectool itself and warn the user about it in the future."""
-def complete_spec_paths(prefix, **kwargs):
+def complete_spec_paths(prefix, **kwargs) -> List[str]:
import glob
return glob.glob(prefix + "*.spec")
-def get_args() -> dict:
+def get_args() -> Dict[str, Any]:
try:
import argcomplete
except ImportError:
@@ -191,6 +193,15 @@ def get_args() -> dict:
help="output debug info, don't clean up when done",
)
+ misc.add_argument(
+ "--http-header",
+ "-H",
+ action="append",
+ dest="headers",
+ default=[],
+ help="Optionally add custom headers",
+ )
+
specfile = parser.add_argument("specfile", action="store")
if argcomplete:
@@ -202,17 +213,17 @@ def get_args() -> dict:
return vars(parser.parse_args())
-def split_numbers(args: str) -> list:
+def split_numbers(args: str) -> List[str]:
return args.split(",")
# simple streamed file download progress tracker inspired by requests_download
class ProgressTracker:
- def __init__(self, progress_bar: progressbar.ProgressBar):
+ def __init__(self, progress_bar: progressbar.ProgressBar) -> None:
self.progress_bar = progress_bar
self.received = 0
- def on_start(self, response: requests.Response):
+ def on_start(self, response: requests.Response) -> None:
max_value = None
if "content-length" in response.headers:
@@ -221,7 +232,7 @@ class ProgressTracker:
self.progress_bar.start(max_value=max_value)
self.received = 0
- def on_chunk(self, chunk: bytes):
+ def on_chunk(self, chunk: bytes) -> None:
self.received += len(chunk)
try:
@@ -229,12 +240,13 @@ class ProgressTracker:
except ValueError:
pass
- def on_finish(self):
+ def on_finish(self) -> None:
self.progress_bar.finish()
# simple streamed file download implementation inspired by requests_download
-def download(url, target, headers=None, tracker: Optional[ProgressTracker] = None):
+def download(url, target, headers=None,
+ tracker: Optional[ProgressTracker] = None) -> None:
if headers is None:
headers = {}
@@ -263,7 +275,8 @@ def download(url, target, headers=None, tracker: Optional[ProgressTracker] = Non
tracker.on_finish()
-def get_file(url: str, path: str, force: bool) -> bool:
+def get_file(url: str, path: str, force: bool,
+ headers: Optional[Dict[str, str]] = None) -> bool:
if os.path.exists(path):
if force:
os.remove(path)
@@ -272,13 +285,13 @@ def get_file(url: str, path: str, force: bool) -> bool:
return False
progress = ProgressTracker(progressbar.DataTransferBar())
- download(url, path, tracker=progress)
+ download(url, path, tracker=progress, headers=headers)
return True
class Spec:
- def __init__(self, path: str):
+ def __init__(self, path: str) -> None:
self.path = path
self.spec = rpm.spec(self.path)
@@ -289,10 +302,10 @@ class Spec:
self.files = list(self.spec.sources)
self.files.sort(key=(lambda file: file[1]))
- self._sources = None
- self._patches = None
+ self._sources: Optional[OrderedDictT[str, str]] = None
+ self._patches: Optional[OrderedDictT[str, str]] = None
- def _files(self, typ) -> OrderedDict:
+ def _files(self, typ: int) -> OrderedDictT[str, str]:
# file is a 3-tuple of (path, number, type)
# type 1: source file
# type 2: patch file
@@ -305,41 +318,42 @@ class Spec:
return files
@property
- def sources(self) -> OrderedDict:
+ def sources(self) -> OrderedDictT[str, str]:
if not self._sources:
self._sources = self._files(1)
return self._sources
@property
- def patches(self) -> OrderedDict:
+ def patches(self) -> OrderedDictT[str, str]:
if not self._patches:
self._patches = self._files(2)
return self._patches
- def print_source(self, number: int, value: str = None):
+ def print_source(self, number: str, value: Optional[str] = None) -> None:
if not value:
value = self.sources[number]
print("Source{}: {}".format(number, value))
- def print_patch(self, number: int, value: str = None):
+ def print_patch(self, number: str, value: Optional[str] = None) -> None:
if not value:
value = self.patches[number]
print("Patch{}: {}".format(number, value))
- def list_sources(self):
+ def list_sources(self) -> None:
for (number, value) in self.sources.items():
self.print_source(number, value)
- def list_patches(self):
+ def list_patches(self) -> None:
for (number, value) in self.patches.items():
self.print_patch(number, value)
@staticmethod
- def _get_file(value: str, directory: str, force: bool, dry: bool):
+ def _get_file(value: str, directory: str, force: bool, dry: bool,
+ headers: Optional[Dict[str, str]] = None) -> None:
parsed = urlparse(value)
if "#" not in value:
@@ -354,19 +368,23 @@ class Spec:
return
if parsed.scheme:
+ if dry:
+ print("Would have downloaded: {}".format(value))
+ return None
if not dry:
path = os.path.join(directory, basename)
try:
print("Downloading: {}".format(value))
os.makedirs(directory, exist_ok=True)
- really = get_file(value, path, force)
+ really = get_file(value, path, force, headers=headers)
if really:
print("Downloaded: {}".format(basename))
except IOError as e:
print("Download failed:")
print(e)
+ raise e
except KeyboardInterrupt:
if os.path.isfile(path):
@@ -376,28 +394,53 @@ class Spec:
print("Download cancelled.")
raise
- else:
- print("Would have downloaded: {}".format(value))
-
- def get_source(self, number: int, directory: str, force: bool, dry: bool, value: str = None):
+ def get_source(self, number: str, directory: str, force: bool, dry: bool,
+ value: Optional[str] = None,
+ headers: Optional[Dict[str, str]] = None) -> bool:
if not value:
value = self.sources[number]
- self._get_file(value, directory, force, dry)
+ try:
+ self._get_file(value, directory, force, dry, headers=headers)
+ return False
+
+ except IOError:
+ return True
- def get_patch(self, number: int, directory: str, force: bool, dry: bool, value: str = None):
+ def get_patch(self, number: str, directory: str, force: bool, dry: bool,
+ value: Optional[str] = None,
+ headers: Optional[Dict[str, str]] = None) -> bool:
if not value:
value = self.patches[number]
- self._get_file(value, directory, force, dry)
+ try:
+ self._get_file(value, directory, force, dry, headers=headers)
+ return False
+
+ except IOError:
+ return True
+
+ def get_sources(self, directory: str, force: bool, dry: bool,
+ headers: Optional[Dict[str, str]] = None):
+ failure = False
- def get_sources(self, directory: str, force: bool, dry: bool):
for number, value in self.sources.items():
- self.get_source(number, directory, force, dry, value)
+ if self.get_source(number, directory, force, dry, value,
+ headers=headers):
+ failure = True
+
+ return failure
+
+ def get_patches(self, directory: str, force: bool, dry: bool,
+ headers: Optional[Dict[str, str]] = None):
+ failure = False
- def get_patches(self, directory: str, force: bool, dry: bool):
for number, value in self.patches.items():
- self.get_patch(number, directory, force, dry, value)
+ if self.get_patch(number, directory, force, dry, value,
+ headers=headers):
+ failure = True
+
+ return failure
def main() -> int:
@@ -484,6 +527,10 @@ def main() -> int:
if args["get_files"]:
force = args["force"]
dry = args["dry_run"]
+ headers = {}
+ for header in args["headers"]:
+ k, sep, v = header.partition(':')
+ headers[k.strip()] = v.strip()
if args["directory"] and args["sourcedir"]:
print("Conflicting requests for download directory.")
@@ -496,18 +543,21 @@ def main() -> int:
else:
directory = os.getcwd()
+ tasks: List[Tuple[Callable[..., bool], Tuple[Any, ...]]] = []
+
if args["source"]:
numbers = split_numbers(args["source"])
for number in numbers:
if number not in spec.sources.keys():
- print("No patch with number '{}' found.".format(number))
+ print("No source with number '{}' found.".format(number))
continue
- spec.get_source(number, directory, force, dry)
+ tasks.append((spec.get_source, (number, directory, force, dry,
+ headers)))
elif args["sources"] and not args["patch"]:
- spec.get_sources(directory, force, dry)
+ tasks.append((spec.get_sources, (directory, force, dry, headers)))
if args["patch"]:
numbers = split_numbers(args["patch"])
@@ -517,10 +567,22 @@ def main() -> int:
print("No patch with number '{}' found.".format(number))
continue
- spec.get_patch(number, directory, force, dry)
+ tasks.append((spec.get_patch, (number, directory, force, dry,
+ headers)))
elif args["patches"] and not args["source"]:
- spec.get_patches(directory, force, dry)
+ tasks.append((spec.get_patches, (directory, force, dry, headers)))
+
+ failure = False
+
+ for task, fargs in tasks:
+ fail = task(*fargs)
+
+ if fail:
+ failure = True
+
+ if failure:
+ return 1
return 0
diff --git a/spectemplate-cmake.spec b/spectemplate-cmake.spec
new file mode 100644
index 0000000..0cdcbb8
--- /dev/null
+++ b/spectemplate-cmake.spec
@@ -0,0 +1,38 @@
+Name:
+Version:
+Release: 1%{?dist}
+Summary:
+
+License:
+URL:
+Source0:
+
+BuildRequires: cmake
+
+%description
+%{summary}.
+
+
+%prep
+%autosetup -q
+
+
+%build
+%cmake
+%cmake_build
+
+
+%install
+%cmake_install
+
+
+%check
+%ctest
+
+
+%files
+%license add-license-file-here
+%doc add-docs-here
+
+
+%changelog
diff --git a/spectemplate-pyproject.spec b/spectemplate-pyproject.spec
new file mode 100644
index 0000000..15d5a65
--- /dev/null
+++ b/spectemplate-pyproject.spec
@@ -0,0 +1,60 @@
+Name: python-...
+Version: ...
+Release: 1%{?dist}
+Summary: ...
+
+License: ...
+URL: https://...
+# use a source from git forge or PyPI:
+Source: %{url}/archive/v%{version}/...-%{version}.tar.gz / %{pypi_source ...}
+
+# for pure Python packages:
+BuildArch: noarch
+# for packages with extension modules:
+BuildRequires: gcc
+
+BuildRequires: python3-devel
+
+%global _description %{expand:
+...}
+
+%description %_description
+
+%package -n python3-...
+Summary: %{summary}
+
+%description -n python3-... %_description
+
+
+%prep
+%autosetup -p1 -n ...-%{version}
+
+
+%generate_buildrequires
+# use the appropriate flags to get all test dependencies:
+%pyproject_buildrequires -x... / -t
+
+
+%build
+%pyproject_wheel
+
+
+%install
+%pyproject_install
+# list the installed top-level Python module names:
+%pyproject_save_files ...
+
+
+%check
+# testing the package is mandatory, at least somehow:
+%tox / %pytest / %pyproject_check_import ...
+
+
+%files -n python3-... -f %{pyproject_files}
+%doc README.*
+# only add LICENSE / COPYING if not included in %%{pyproject_files}
+%license LICENSE / COPYING
+%{_bindir}/...
+
+
+%changelog