Compare commits

...

14 Commits

Author SHA1 Message Date
William Douglas e822d6e48d Set extractall filter for tarfile
See
https://docs.python.org/3/library/tarfile.html#tarfile.TarFile.extractall

Signed-off-by: William Douglas <william.douglas@intel.com>
2024-11-04 11:40:24 -08:00
William Douglas 9bfe801c96 Fix subdir for pyproject
When using optimized builds for pyproject patterns that also need a
subdir, the path needs to be reset before attempting to change to the
optimized directory.

Signed-off-by: William Douglas <william.douglas@intel.com>
2024-11-04 11:13:46 -08:00
K1ngfish3r 412ce5ee2e i blame isort setting(?) 2024-10-27 22:39:42 -07:00
K1ngfish3r 1fa3bdd6e0 add subdir 2024-10-27 22:39:42 -07:00
William Douglas 4ea76c998e Remove %check for setup.py test
setup.py test is gone in 3.13 and projects seem to be doing custom
things for replacements. Until wider per project detection is in
place, just remove the %check section for setup.py.

Signed-off-by: William Douglas <william.douglas@intel.com>
2024-10-27 20:28:28 -07:00
Brett T. Warden b2d28bb55a Add path to Qt6 build tools in qmake build_pattern
When using the qmake build pattern, add the path /usr/lib64/qt6/bin/
that contains qmake6 and other Qt6 build tools.
2024-10-14 15:56:05 -07:00
Brett T. Warden 4d029647d7 parse_cmake: Also match hypen in pkg_check_modules(X)
If a cmake file defines a pkgconfig dependency with a hypen in it, make
sure we can handle it:
pkg_check_modules(DBUS-1 REQUIRED dbus-1 IMPORTED_TARGET)

Previously we used \w to match the first term (DBUS-1), which does *not*
match hyphens.
2024-10-01 11:40:23 -07:00
Brett T. Warden 5279a11b53 Split packages from cmake_modules when adding them as buildreqs
When parsing cmake files for find_package dependencies, we match against
entries in cmake_modules. Many of the entries of this file list
multiple packages, separated by space. Split on whitespace so we
actually feed only individual package names to each add_buildreq call.

Otherwise, if cmake_modules provides "extra-cmake-modules png2ico", for
example, and you have "png2ico" in buildreq_ban, the specfile would still
list both extra-cmake-modules and png2ico as build dependencies, because
add_buildreq only compared exact matches.
2024-10-01 11:40:23 -07:00
William Douglas a19cdc79b4 Always handle the common tmepfile prefix for license_skips
Modify license skips to handle the common tempfile prefix of '/tmp/*'
and normalize the case where lines lead with a slash vs not.

Also remove a duplicate test for globlike match.

Signed-off-by: William Douglas <william.douglas@intel.com>
2024-09-19 15:09:41 -07:00
K1ngfish3r 185099bba8 use_ninja for %check 2024-09-19 13:11:21 -07:00
William Douglas 7b01f0ba82 Add support for skipping license paths
Add support for a new config file with glob like handling of paths as
some projects contain license files that are not the license of the
project.

scan_for_licenses now looks at the configuration and does glob like
matching for all the potential license files it tries to add.

This change caused a few structural adjustments to the code and a
slight style change for importing just the toplevel util submodule
that are superficial.

Signed-off-by: William Douglas <william.douglas@intel.com>
2024-09-19 12:02:52 -07:00
William Douglas 6a4b23bb3e Update configs
Add new values needed for various package builds to the configuration
files.

Signed-off-by: William Douglas <william.douglas@intel.com>
2024-09-12 09:27:28 -07:00
William Douglas c6d7bdb41c Add new failed pattern
Signed-off-by: William Douglas <william.douglas@intel.com>
2024-09-12 09:27:28 -07:00
William Douglas a16ede7440 Add new test for _process_build_log
Adds the first example test to _process_build_log verifying it can
handle a bad patch.

Signed-off-by: William Douglas <william.douglas@intel.com>
2024-09-12 09:27:28 -07:00
15 changed files with 280 additions and 95 deletions
+8
View File
@@ -128,6 +128,14 @@ release
``.spec``. This is also bumped and generated on existing and new packages, ``.spec``. This is also bumped and generated on existing and new packages,
respectively. This results in less manual work via automatic management. respectively. This results in less manual work via automatic management.
license_skips
Each line in the file should be the path to a license file. That path needs
to account for the package tarfile prefix. Likely requires using '*' to be
effective (e.g. ``pkgname-*/path/to/license`` where ``*`` handles the version).
Files paths can contain a single '*' per directory such that
a line of ``/foo*/bar*`` is allowed but ``/foo*bar*`` is not.
$package.license $package.license
In certain cases, the package license may not be automatically discovered. In In certain cases, the package license may not be automatically discovered. In
this instance, ``autospec`` will exit with an error. Update this file to this instance, ``autospec`` will exit with an error. Update this file to
+8 -3
View File
@@ -508,7 +508,7 @@ class Requirements(object):
"""Scan a .cmake or CMakeLists.txt file for what's it's actually looking for.""" """Scan a .cmake or CMakeLists.txt file for what's it's actually looking for."""
findpackage = re.compile(r"^[^#]*find_package\((\w+)\b.*\)", re.I) findpackage = re.compile(r"^[^#]*find_package\((\w+)\b.*\)", re.I)
findpackage_multiline = re.compile(r"^[^#]*find_package\((\w+)\b.*", re.I) findpackage_multiline = re.compile(r"^[^#]*find_package\((\w+)\b.*", re.I)
pkgconfig = re.compile(r"^[^#]*pkg_check_modules\s*\(\w+ (.*)\)", re.I) pkgconfig = re.compile(r"^[^#]*pkg_check_modules\s*\([\w\-]+ (.*)\)", re.I)
pkg_search_modifiers = {'REQUIRED', 'QUIET', 'NO_CMAKE_PATH', pkg_search_modifiers = {'REQUIRED', 'QUIET', 'NO_CMAKE_PATH',
'NO_CMAKE_ENVIRONMENT_PATH', 'IMPORTED_TARGET'} 'NO_CMAKE_ENVIRONMENT_PATH', 'IMPORTED_TARGET'}
extractword = re.compile(r'(?:"([^"]+)"|(\S+))(.*)') extractword = re.compile(r'(?:"([^"]+)"|(\S+))(.*)')
@@ -518,8 +518,13 @@ class Requirements(object):
for line in lines: for line in lines:
if match := findpackage.search(line): if match := findpackage.search(line):
module = match.group(1) module = match.group(1)
if pkg := cmake_modules.get(module): if pkgs := cmake_modules.get(module):
self.add_buildreq(pkg) # Some of the entries in cmake_modules list multiple packages, space-separated, so we need to split.
# Otherwise, anything in buildreq_ban would have to match the entire string, not just a single package name.
# For example: Png2Ico, extra-cmake-modules png2ico
# buildreq_ban would have to contain "extra-cmake-modules png2ico" to match, instead of just "png2ico"
for pkg in pkgs.split():
self.add_buildreq(pkg)
elif findpackage_multiline.search(line): elif findpackage_multiline.search(line):
self.findpackage_parse_lines(line, lines, cmake_modules) self.findpackage_parse_lines(line, lines, cmake_modules)
+8 -17
View File
@@ -64,34 +64,32 @@ def scan_for_tests(src_dir, config, requirements, content):
if config.config_opts.get('skip_tests') or tests_config: if config.config_opts.get('skip_tests') or tests_config:
return return
make_command = "ninja" if config.config_opts.get('use_ninja') else "make"
makeflags = "%{?_smp_mflags} " if config.parallel_build else "" makeflags = "%{?_smp_mflags} " if config.parallel_build else ""
make_check = "make {}check".format(makeflags) make_check = "{} {}check".format(make_command, makeflags)
cmake_check = "make test" cmake_check = "{} test".format(make_command)
make_check_openmpi = "module load openmpi\nexport OMPI_MCA_rmaps_base_oversubscribe=1\n" \ make_check_openmpi = "module load openmpi\nexport OMPI_MCA_rmaps_base_oversubscribe=1\n" \
"make {}check\nmodule unload openmpi".format(makeflags) "{} {}check\nmodule unload openmpi".format(make_command, makeflags)
cmake_check_openmpi = "module load openmpi\nexport OMPI_MCA_rmaps_base_oversubscribe=1\n" \ cmake_check_openmpi = "module load openmpi\nexport OMPI_MCA_rmaps_base_oversubscribe=1\n" \
"make test\nmodule unload openmpi" "{} test\nmodule unload openmpi".format(make_command)
if config.config_opts.get('allow_test_failures'): if config.config_opts.get('allow_test_failures'):
make_check_openmpi = "module load openmpi\nexport OMPI_MCA_rmaps_base_oversubscribe=1\n" \ make_check_openmpi = "module load openmpi\nexport OMPI_MCA_rmaps_base_oversubscribe=1\n" \
"make {}check || :\nmodule unload openmpi".format(makeflags) "{} {}check || :\nmodule unload openmpi".format(make_command, makeflags)
cmake_check_openmpi = "module load openmpi\nexport OMPI_MCA_rmaps_base_oversubscribe=1\n" \ cmake_check_openmpi = "module load openmpi\nexport OMPI_MCA_rmaps_base_oversubscribe=1\n" \
"make test || :\nmodule unload openmpi" "{} test || :\nmodule unload openmpi".format(make_command)
perl_check = "make TEST_VERBOSE=1 test" perl_check = "{} TEST_VERBOSE=1 test".format(make_command)
setup_check = """PYTHONPATH=%{buildroot}$(python -c "import sys; print(sys.path[-1])") python setup.py test"""
meson_check = "meson test -C builddir --print-errorlogs" meson_check = "meson test -C builddir --print-errorlogs"
if config.config_opts.get('allow_test_failures'): if config.config_opts.get('allow_test_failures'):
make_check += " || :" make_check += " || :"
cmake_check += " || :" cmake_check += " || :"
perl_check += " || :" perl_check += " || :"
setup_check += " || :"
meson_check += " || :" meson_check += " || :"
testsuites = { testsuites = {
"makecheck": make_check, "makecheck": make_check,
"perlcheck": perl_check, "perlcheck": perl_check,
"setup.py": setup_check,
"cmake": "cd clr-build; " + cmake_check, "cmake": "cd clr-build; " + cmake_check,
"meson": meson_check, "meson": meson_check,
} }
@@ -144,13 +142,6 @@ def scan_for_tests(src_dir, config, requirements, content):
elif config.default_pattern in ["cpan"] and "Makefile.PL" in files: elif config.default_pattern in ["cpan"] and "Makefile.PL" in files:
tests_config = testsuites["perlcheck"] tests_config = testsuites["perlcheck"]
elif config.default_pattern == "distutils3" and "setup.py" in files:
with util.open_auto(os.path.join(src_dir, "setup.py"), 'r') as setup_fp:
setup_contents = setup_fp.read()
if "test_suite" in setup_contents or "pbr=True" in setup_contents:
tests_config = testsuites["setup.py"]
elif config.default_pattern == "R": elif config.default_pattern == "R":
tests_config = "export _R_CHECK_FORCE_SUGGESTS_=false\n" \ tests_config = "export _R_CHECK_FORCE_SUGGESTS_=false\n" \
"R CMD check --no-manual --no-examples --no-codoc . " \ "R CMD check --no-manual --no-examples --no-codoc . " \
+6
View File
@@ -110,6 +110,7 @@ class Config(object):
self.custom_summ = "" self.custom_summ = ""
self.license_fetch = None self.license_fetch = None
self.license_show = None self.license_show = None
self.license_skips = []
self.git_uri = None self.git_uri = None
self.os_packages = set() self.os_packages = set()
self.config_file = None self.config_file = None
@@ -320,6 +321,7 @@ class Config(object):
(r"checking for [a-zA-Z0-9\_\-]+ in (.*?)\.\.\. no", 0, None), (r"checking for [a-zA-Z0-9\_\-]+ in (.*?)\.\.\. no", 0, None),
(r"checking for library containing (.*)... no", 0, None), (r"checking for library containing (.*)... no", 0, None),
(r"checking for perl module ([a-zA-Z:]+) [0-9\.]+... no", 0, 'perl'), (r"checking for perl module ([a-zA-Z:]+) [0-9\.]+... no", 0, 'perl'),
("checking if (.*) is available...", 0, None),
(r"configure: error: (?:pkg-config missing|Unable to locate) (.*)", 0, None), (r"configure: error: (?:pkg-config missing|Unable to locate) (.*)", 0, None),
(r"configure: error: ([a-zA-Z0-9]+) (?:is required to build|not found)", 0, None), (r"configure: error: ([a-zA-Z0-9]+) (?:is required to build|not found)", 0, None),
(r"configure: error: Cannot find (.*)\. Make sure", 0, None), (r"configure: error: Cannot find (.*)\. Make sure", 0, None),
@@ -995,6 +997,10 @@ class Config(object):
if not license.add_license(word, self.license_translations, self.license_blacklist): if not license.add_license(word, self.license_translations, self.license_blacklist):
print_warning("{}: blacklisted license {} ignored.".format(self.content.name + ".license", word)) print_warning("{}: blacklisted license {} ignored.".format(self.content.name + ".license", word))
content = self.read_conf_file(os.path.join(self.download_path, "license_skips"))
if content:
self.license_skips = self.validate_extras_content(content, "license_skips")
# cargo_vendors is the output of 'cargo vendor' and should be read as is # cargo_vendors is the output of 'cargo vendor' and should be read as is
content = self.read_file(os.path.join(self.download_path, "cargo_vendors"), track=True) content = self.read_file(os.path.join(self.download_path, "cargo_vendors"), track=True)
if content: if content:
+12
View File
@@ -124,7 +124,9 @@ ACL_TYPE_EXTENDED, acl-dev
ALSA, alsa-lib-dev ALSA, alsa-lib-dev
APR, apr-dev APR, apr-dev
APR-util, apr-util-dev APR-util, apr-util-dev
ARPACK-NG, arpack-ng-dev
ASSIMP, assimp-dev ASSIMP, assimp-dev
Adwaita, libadwaita-dev
Analitza, analitza-dev Analitza, analitza-dev
Analitza5, analitza-dev Analitza5, analitza-dev
BABL, babl-dev BABL, babl-dev
@@ -175,6 +177,7 @@ EXPAT, expat-dev
Eet.h, eet-dev Eet.h, eet-dev
Eigen/Core, eigen-dev Eigen/Core, eigen-dev
Eigen/Dense, eigen-dev Eigen/Dense, eigen-dev
Eigen/Sparse, eigen-dev
Eigen3, eigen-dev Eigen3, eigen-dev
Epoxy, pkgconfig(epoxy) Epoxy, pkgconfig(epoxy)
Exiv2, exiv2-dev Exiv2, exiv2-dev
@@ -284,6 +287,7 @@ GSTREAMER, gstreamer-dev
GSettingSchemas, gsettings-desktop-schemas GSettingSchemas, gsettings-desktop-schemas
GSettingSchemas, gsettings-desktop-schemas-dev GSettingSchemas, gsettings-desktop-schemas-dev
GTK, gtk+-dev GTK, gtk+-dev
GTK4, gtk4-dev
GnuTLS, gnutls-dev GnuTLS, gnutls-dev
GooglePerftools, gperftools-dev GooglePerftools, gperftools-dev
Gperf, gperf Gperf, gperf
@@ -459,6 +463,7 @@ KF6NewStuff, knewstuff-def
KF6Notifications, knotifications-dev KF6Notifications, knotifications-dev
KF6NotifyConfig, knotifyconfig-dev KF6NotifyConfig, knotifyconfig-dev
KF6Package, kpackage-dev KF6Package, kpackage-dev
KF6Prison, kprison-dev
KF6Purpose, purpose-dev KF6Purpose, purpose-dev
KF6QuickCharts, kquickcharts-dev KF6QuickCharts, kquickcharts-dev
KF6Runner, krunner-dev KF6Runner, krunner-dev
@@ -548,6 +553,7 @@ NETTLE, nettle-dev
NUMA, numactl-dev NUMA, numactl-dev
Nepomuk, nepomuk-core-dev Nepomuk, nepomuk-core-dev
NetworkManager, NetworkManager-dev NetworkManager, NetworkManager-dev
Nice, libnice-dev
NumPy, pypi-numpy NumPy, pypi-numpy
Numa, numactl-dev Numa, numactl-dev
OPENEXR, openexr-dev OPENEXR, openexr-dev
@@ -621,6 +627,7 @@ Qt5Xdg, libqtxdg-dev
Qt5XdgIconLoader, libqtxdg-dev Qt5XdgIconLoader, libqtxdg-dev
Qt5XmlPatterns, qtxmlpatterns-dev Qt5XmlPatterns, qtxmlpatterns-dev
Qt6Positioning, qt6positioning-dev Qt6Positioning, qt6positioning-dev
Qt6Qml, qt6declarative-dev
Qt6Quick, qt6declarative-dev Qt6Quick, qt6declarative-dev
Qt6QuickTimeline, qt6quicktimeline-dev Qt6QuickTimeline, qt6quicktimeline-dev
Qt6ShaderTools, qt6shadertools-dev Qt6ShaderTools, qt6shadertools-dev
@@ -650,6 +657,7 @@ Soprano, soprano-dev
SpatialIndex, libspatialindex-dev SpatialIndex, libspatialindex-dev
Sphinx, pypi-sphinx Sphinx, pypi-sphinx
Sqlite, sqlite-autoconf-dev Sqlite, sqlite-autoconf-dev
Srtp2, libsrtp-dev
Startup notification library, libnotify-dev Startup notification library, libnotify-dev
TBB, tbb-dev TBB, tbb-dev
TIFF, tiff-dev TIFF, tiff-dev
@@ -1124,6 +1132,7 @@ libsecret-unstable, libsecret-dev
libsoup-2.4, libsoup-dev libsoup-2.4, libsoup-dev
libssh, libssh-dev libssh, libssh-dev
libssh2.h, libssh2-dev libssh2.h, libssh2-dev
libssl, openssl-dev
libsystemd, pkgconfig(systemd) libsystemd, pkgconfig(systemd)
libtirpc (via pkg-config), pkgconfig(libtirpc) libtirpc (via pkg-config), pkgconfig(libtirpc)
libudev.h, systemd-dev libudev.h, systemd-dev
@@ -1298,6 +1307,8 @@ pycparser, pypi(pycparser)
pycurl, pypi(pycurl) pycurl, pypi(pycurl)
pylint, pypi(pylint) pylint, pypi(pylint)
pyperclip, pypi(pyperclip) pyperclip, pypi(pyperclip)
pypi(openvino), openvino-python3
pypi(pytorch), pytorch-python3
pytest, pypi-pytest pytest, pypi-pytest
pytest-cov, pypi(pytest_cov) pytest-cov, pypi(pytest_cov)
python lxml, pypi(lxml) python lxml, pypi(lxml)
@@ -1492,6 +1503,7 @@ yaml-cpp, yaml-cpp-dev
yarg, pypi-yarg yarg, pypi-yarg
yasm, yasm yasm, yasm
yytext is a pointer, flex yytext is a pointer, flex
zconf.h, zlib-dev
zenity, zenity zenity, zenity
zip, zip zip, zip
zlib, zlib-dev zlib, zlib-dev
+1 -28
View File
@@ -197,33 +197,6 @@ class FileManager(object):
return removed return removed
def globlike_match(self, filename, match_name):
"""Compare the filename to the match_name in a way that simulates the shell glob '*'."""
fsplit = filename.split('/')
if len(fsplit) != len(match_name):
return False
match = True
for fpart, mpart in zip(fsplit, match_name):
if fpart != mpart:
if '*' not in mpart:
match = False
break
if len(mpart) > len(fpart) + 1:
match = False
break
mpl, mpr = mpart.split('*')
try:
if fpart.index(mpl) != 0:
match = False
break
if fpart.rindex(mpr) != len(fpart) - len(mpr):
match = False
break
except ValueError:
match = False
break
return match
def push_file(self, filename, pkg_name): def push_file(self, filename, pkg_name):
"""Perform a number of checks against the filename and push the filename if appropriate.""" """Perform a number of checks against the filename and push the filename if appropriate."""
if filename in self.files or filename in self.files_blacklist: if filename in self.files or filename in self.files_blacklist:
@@ -245,7 +218,7 @@ class FileManager(object):
elif len('/'.join(match_name)) <= (len(norm_filename) + 1): elif len('/'.join(match_name)) <= (len(norm_filename) + 1):
# the match name may be 1 longer due to a glob # the match name may be 1 longer due to a glob
# being able to match an empty string # being able to match an empty string
if self.globlike_match(norm_filename, match_name): if util.globlike_match(norm_filename, match_name):
path_prefix = '/' if not match else match.group() path_prefix = '/' if not match else match.group()
self.push_package_file(os.path.join(path_prefix, *match_name), k) self.push_package_file(os.path.join(path_prefix, *match_name), k)
return return
+27 -10
View File
@@ -29,7 +29,7 @@ import urllib.parse
import chardet import chardet
import download import download
from util import get_contents, get_sha1sum, print_fatal, print_warning import util
default_license = "TO BE DETERMINED" default_license = "TO BE DETERMINED"
@@ -96,7 +96,7 @@ def decode_license(license):
def license_from_copying_hash(copying, srcdir, config, name): def license_from_copying_hash(copying, srcdir, config, name):
"""Add licenses based on the hash of the copying file.""" """Add licenses based on the hash of the copying file."""
try: try:
data = get_contents(copying) data = util.get_contents(copying)
except FileNotFoundError: except FileNotFoundError:
# LICENSE file is a bad symlink (qemu-4.2.0!) # LICENSE file is a bad symlink (qemu-4.2.0!)
return return
@@ -109,7 +109,7 @@ def license_from_copying_hash(copying, srcdir, config, name):
if not data: if not data:
return return
hash_sum = get_sha1sum(copying) hash_sum = util.get_sha1sum(copying)
if config.license_fetch: if config.license_fetch:
values = {'hash': hash_sum, 'text': data, 'package': name} values = {'hash': hash_sum, 'text': data, 'package': name}
@@ -142,9 +142,24 @@ def license_from_copying_hash(copying, srcdir, config, name):
else: else:
if not config.license_show: if not config.license_show:
return return
print_warning("Unknown license {0} with hash {1}".format(copying, hash_sum)) util.print_warning("Unknown license {0} with hash {1}".format(copying, hash_sum))
hash_url = config.license_show % {'HASH': hash_sum} hash_url = config.license_show % {'HASH': hash_sum}
print_warning("Visit {0} to enter".format(hash_url)) util.print_warning("Visit {0} to enter".format(hash_url))
def skip_license(license_path, config):
"""Check if a given license file path should be skipped."""
skip_name = False
for skip in config.license_skips:
# handle the common tempfile prefix and normalize for
# skip lines without a starting '/'
skip = skip if skip[0] != '' else skip[1:]
skip_path = ['', 'tmp', '*'] + skip
if util.globlike_match(license_path, skip_path):
util.print_warning(f"Skip license detected for file at {license_path}")
skip_name = True
break
return skip_name
def scan_for_licenses(srcdir, config, pkg_name): def scan_for_licenses(srcdir, config, pkg_name):
@@ -166,8 +181,9 @@ def scan_for_licenses(srcdir, config, pkg_name):
for dirpath, dirnames, files in os.walk(srcdir): for dirpath, dirnames, files in os.walk(srcdir):
for name in files: for name in files:
if name.lower() in targets or target_pat.search(name.lower()): if name.lower() in targets or target_pat.search(name.lower()):
license_from_copying_hash(os.path.join(dirpath, name), license_path = os.path.join(dirpath, name)
srcdir, config, pkg_name) if not skip_license(license_path, config):
license_from_copying_hash(license_path, srcdir, config, pkg_name)
# Also search for license texts in project trees that are # Also search for license texts in project trees that are
# REUSE-compliant, or are in process of adopting this standard (for # REUSE-compliant, or are in process of adopting this standard (for
# example, KDE ecosystem packages). See https://reuse.software for # example, KDE ecosystem packages). See https://reuse.software for
@@ -179,11 +195,12 @@ def scan_for_licenses(srcdir, config, pkg_name):
# named `license` instead. # named `license` instead.
dirbase = os.path.basename(dirpath) dirbase = os.path.basename(dirpath)
if re.search(r'^(LICENSES|licenses?|licensing)$', dirbase) and re.search(r'\.txt$', name): if re.search(r'^(LICENSES|licenses?|licensing)$', dirbase) and re.search(r'\.txt$', name):
license_from_copying_hash(os.path.join(dirpath, name), license_path = os.path.join(dirpath, name)
srcdir, config, pkg_name) if not skip_license(license_path, config):
license_from_copying_hash(license_path, srcdir, config, pkg_name)
if not licenses: if not licenses:
print_fatal(" Cannot find any license or a valid {}.license file!\n".format(pkg_name)) util.print_fatal(" Cannot find any license or a valid {}.license file!\n".format(pkg_name))
sys.exit(1) sys.exit(1)
print("Licenses : ", " ".join(sorted(licenses))) print("Licenses : ", " ".join(sorted(licenses)))
+43 -11
View File
@@ -3,12 +3,12 @@
# This file is sorted with LC_COLLATE=C # This file is sorted with LC_COLLATE=C
# Lines beginning with '#' are ignored. # Lines beginning with '#' are ignored.
# For strings that start with '#', escape the '#' as '\#'. # For strings that start with '#', escape the '#' as '\#'.
=========================
% %
%license %license
(LGPL) (LGPL)
(new) (new)
(specified (specified
*
+ +
- -
-MIT -MIT
@@ -26,6 +26,8 @@
3-Clause 3-Clause
3-clause 3-clause
3BSD 3BSD
=========================
>=-2
@CPACK_RPM_PACKAGE_LICENSE@ @CPACK_RPM_PACKAGE_LICENSE@
AGPLv3+ AGPLv3+
ALv2 ALv2
@@ -35,7 +37,12 @@ APPLICATION__TYPE
ASL ASL
Artistic Artistic
BSD BSD
BSD(2
BSD(3 BSD(3
BSD-2-Clause-Views
BSD-3
BSD-compatible
BSD-derived(Repoze)
BSD-like BSD-like
BSD-style BSD-style
BSDL BSDL
@@ -43,6 +50,7 @@ BSD_3_clause
BSDish BSDish
BSL BSL
CC-BY CC-BY
Clause
Commercial Commercial
Corp. Corp.
Distribution Distribution
@@ -53,6 +61,7 @@ EPL
Eclipse Eclipse
Expat(MIT/X11) Expat(MIT/X11)
Expat/MIT Expat/MIT
FOUNDATION
Foundation Foundation
FreeBSD FreeBSD
GENERAL GENERAL
@@ -60,30 +69,39 @@ GFDL
GNU GNU
GPL GPL
GPL+ GPL+
GPL-1.0-only
GPL/BSD GPL/BSD
GPL/BSD/CPL GPL/BSD/CPL
GPLv2.1 GPLv2.1
General General
IBM IBM
Jupyter
LESSER LESSER
LGPL LGPL
LGPL+BSD LGPL+BSD
LGPL/MIT LGPL/MIT
LICENCE LICENCE
Lesser Lesser
Library
Licences Licences
License License
License(2.0) License(2.0)
License(==-2.0) License(==-2.0)
License(>=-2)
License(>=-2.0) License(>=-2.0)
License(LGPL)
License(MIT)
License, License,
License-2 License-2
License-2.0 License-2.0
License-2.0(MPL-2.0) License-2.0(MPL-2.0)
License-3(GPLv3)
Licensing Licensing
Lucent Lucent
MIT-0
MIT/Expat MIT/Expat
MPL MPL
Minpack
Modified Modified
Mozilla Mozilla
Muddy-MIT Muddy-MIT
@@ -95,9 +113,13 @@ Open
PIL PIL
PSF-2+ PSF-2+
PUBLIC PUBLIC
PYTHON
Permission
Public Public
Revised Revised
SIL SIL
SIP
SOFTWARE
See See
Set Set
Software Software
@@ -111,31 +133,46 @@ UNKNOWN
Unknown Unknown
Unkown Unkown
Unlimited Unlimited
VERSION-2
Version Version
Version-2.0 Version-2.0
Version-3
WITH
What What
\# \#
a
advertising advertising
and and
any any
bsd bsd
charge
classifiers) classifiers)
clause) clause)
copy
cryptsetup-OpenSSL-exception
details details
domain domain
domain.
dual dual
exceptions exceptions
for for
free
gpl gpl
granted
hereby
http://nmap.org/man/man-legal.html http://nmap.org/man/man-legal.html
into
is is
it it
later later
later(LGPLv2+) later(LGPLv2+)
license license
licensing
ndg/httpsclient/LICENCE ndg/httpsclient/LICENCE
new new
none none
obtaining
of
on on
open_source open_source
option option
@@ -143,11 +180,16 @@ option)
or or
or(at or(at
others others
person
public public
released
software
style style
terms terms
the the
to
under? under?
unencumbered
unknown unknown
unrestricted unrestricted
uses uses
@@ -160,13 +202,3 @@ with
your your
| |
~ ~
Permission
a
charge
copy
granted
hereby
obtaining
of
person
to
+2
View File
@@ -16,9 +16,11 @@ Apache License 2.0, Apache-2.0
Apache License, Version 2.0, Apache-2.0 Apache License, Version 2.0, Apache-2.0
Apache, Apache-2.0 Apache, Apache-2.0
Apache-2, Apache-2.0 Apache-2, Apache-2.0
Apache2, Apache-2.0
Apache2.0, Apache-2.0 Apache2.0, Apache-2.0
Apachev2, Apache-2.0 Apachev2, Apache-2.0
Artistic-1.0+GPL-1.0, Artistic-1.0 GPL-1.0 Artistic-1.0+GPL-1.0, Artistic-1.0 GPL-1.0
Artistic/GPL, Artistic-1.0-Perl GPL-1.0-or-later
Artistic_2, Artistic-2.0 Artistic_2, Artistic-2.0
BSD(3-clause), BSD-3-Clause BSD(3-clause), BSD-3-Clause
BSD-2-clause, BSD-2-Clause BSD-2-clause, BSD-2-Clause
+10 -2
View File
@@ -1345,6 +1345,8 @@ class Specfile(object):
self.write_lang_c(export_epoch=True) self.write_lang_c(export_epoch=True)
self.write_variables() self.write_variables()
self.write_profile_payload("autogen") self.write_profile_payload("autogen")
if self.config.subdir:
self._write_strip("pushd " + self.config.subdir)
self._write_strip("export GOAMD64=v2") self._write_strip("export GOAMD64=v2")
self._write_strip("{0}%autogen {1} {2} {3}" self._write_strip("{0}%autogen {1} {2} {3}"
.format(self.get_profile_use_flags(), .format(self.get_profile_use_flags(),
@@ -1353,6 +1355,8 @@ class Specfile(object):
self.config.extra_configure64)) self.config.extra_configure64))
self.write_make_line() self.write_make_line()
self._write_strip("\n") self._write_strip("\n")
if self.config.subdir:
self._write_strip("popd")
if self.config.config_opts['32bit']: if self.config.config_opts['32bit']:
self._write_strip("pushd ../build32/" + self.config.subdir) self._write_strip("pushd ../build32/" + self.config.subdir)
self.write_build_prepend() self.write_build_prepend()
@@ -1430,6 +1434,9 @@ class Specfile(object):
for module in self.config.pypi_overrides: for module in self.config.pypi_overrides:
self._write_strip(f"pypi-dep-fix.py . {module}") self._write_strip(f"pypi-dep-fix.py . {module}")
self._write_strip("python3 -m build --wheel --skip-dependency-check --no-isolation " + self.config.extra_configure) self._write_strip("python3 -m build --wheel --skip-dependency-check --no-isolation " + self.config.extra_configure)
self._write_strip("\n")
if self.config.subdir:
self._write_strip("popd")
if self.config.config_opts['use_avx2']: if self.config.config_opts['use_avx2']:
self._write_strip("pushd ../buildavx2/" + self.config.subdir) self._write_strip("pushd ../buildavx2/" + self.config.subdir)
@@ -1460,8 +1467,6 @@ class Specfile(object):
self._write_strip("popd") self._write_strip("popd")
self._write_strip("\n") self._write_strip("\n")
if self.config.subdir:
self._write_strip("popd")
self.write_build_append() self.write_build_append()
self.write_check() self.write_check()
self._write_strip("%install") self._write_strip("%install")
@@ -1825,6 +1830,9 @@ class Specfile(object):
self._write_strip('export QMAKE_CFLAGS_RELEASE=') self._write_strip('export QMAKE_CFLAGS_RELEASE=')
self._write_strip('export QMAKE_CXXFLAGS_RELEASE=') self._write_strip('export QMAKE_CXXFLAGS_RELEASE=')
# Add the qt6base tools to the path
self._write_strip('export PATH=/usr/lib64/qt6/bin:$PATH')
if self.config.make_command: if self.config.make_command:
qmake = self.config.make_command qmake = self.config.make_command
else: else:
+2 -2
View File
@@ -125,7 +125,7 @@ class Source():
def extract_tar(self, extraction_path): def extract_tar(self, extraction_path):
"""Extract tar in path.""" """Extract tar in path."""
with tarfile.open(self.path) as content: with tarfile.open(self.path) as content:
content.extractall(path=extraction_path) content.extractall(path=extraction_path, filter='data')
def extract_bz2(self, extraction_path): def extract_bz2(self, extraction_path):
"""Extract plain bz2 file in path.""" """Extract plain bz2 file in path."""
@@ -144,7 +144,7 @@ class Source():
def extract_zst(self, extraction_path): def extract_zst(self, extraction_path):
"""Extract zst in path.""" """Extract zst in path."""
with tarfile.open(fileobj=zstd.open(self.path, 'rb'), mode='r|') as content: with tarfile.open(fileobj=zstd.open(self.path, 'rb'), mode='r|') as content:
content.extractall(path=extraction_path) content.extractall(path=extraction_path, filter='data')
def convert_version(ver_str, name): def convert_version(ver_str, name):
+28
View File
@@ -274,3 +274,31 @@ def open_auto(*args, **kwargs):
assert 'encoding' not in kwargs assert 'encoding' not in kwargs
assert 'errors' not in kwargs assert 'errors' not in kwargs
return open(*args, encoding="utf-8", errors="surrogateescape", **kwargs) return open(*args, encoding="utf-8", errors="surrogateescape", **kwargs)
def globlike_match(filename, match_name):
"""Compare the filename to the match_name in a way that simulates the shell glob '*'."""
fsplit = filename.split('/')
if len(fsplit) != len(match_name):
return False
match = True
for fpart, mpart in zip(fsplit, match_name):
if fpart != mpart:
if '*' not in mpart:
match = False
break
if len(mpart) > len(fpart) + 1:
match = False
break
mpl, mpr = mpart.split('*')
try:
if fpart.index(mpl) != 0:
match = False
break
if fpart.rindex(mpr) != len(fpart) - len(mpr):
match = False
break
except ValueError:
match = False
break
return match
-20
View File
@@ -152,26 +152,6 @@ class TestTest(unittest.TestCase):
check.os.listdir = listdir_backup check.os.listdir = listdir_backup
self.assertEqual(check.tests_config, 'make TEST_VERBOSE=1 test') self.assertEqual(check.tests_config, 'make TEST_VERBOSE=1 test')
def test_scan_for_tests_setup(self):
"""
Test scan_for_tests with setup.py suite
"""
reqs = buildreq.Requirements("")
conf = config.Config("")
tcontent = tarball.Content("", "", "", [], conf, "")
listdir_backup = os.listdir
check.os.listdir = mock_generator(['setup.py'])
content = 'test_suite'
m_open = mock_open(read_data=content)
with patch(self.open_name, m_open, create=True):
conf.default_pattern = "distutils3"
check.scan_for_tests('pkgdir', conf, reqs, tcontent)
check.os.listdir = listdir_backup
self.assertEqual(check.tests_config,
'PYTHONPATH=%{buildroot}$(python -c "import sys; print(sys.path[-1])") '
'python setup.py test')
def test_scan_for_tests_cmake(self): def test_scan_for_tests_cmake(self):
""" """
Test scan_for_tests with cmake suite Test scan_for_tests with cmake suite
+57 -1
View File
@@ -71,7 +71,7 @@ class TestLicense(unittest.TestCase):
conf = config.Config("") conf = config.Config("")
conf.setup_patterns() conf.setup_patterns()
# remove the hash from license_hashes # remove the hash from license_hashes
del(conf.license_hashes[license.get_sha1sum('tests/COPYING_TEST')]) del(conf.license_hashes[license.util.get_sha1sum('tests/COPYING_TEST')])
conf.license_show = "license.show.url" conf.license_show = "license.show.url"
license.license_from_copying_hash('tests/COPYING_TEST', '', conf, '') license.license_from_copying_hash('tests/COPYING_TEST', '', conf, '')
@@ -233,6 +233,62 @@ class TestLicense(unittest.TestCase):
self.assertIn("Cannot find any license", out.getvalue()) self.assertIn("Cannot find any license", out.getvalue())
self.assertEqual(license.licenses, []) self.assertEqual(license.licenses, [])
def test_scan_for_licenses_skip(self):
"""
Test scan_for_licenses in temporary directory with licenses to skip
"""
conf = config.Config("")
conf.setup_patterns()
conf.license_skips = [['COPYING']]
with open('tests/COPYING_TEST', 'rb') as copyingf:
content = copyingf.read()
with tempfile.TemporaryDirectory() as tmpd:
# create the copying file
with open(os.path.join(tmpd, 'COPYING'), 'w') as newcopyingf:
newcopyingf.write(content.decode('utf-8'))
# create some cruft for testing
for testf in ['testlib.c', 'testmain.c', 'testheader.h']:
with open(os.path.join(tmpd, testf), 'w') as newtestf:
newtestf.write('test content')
# let's check that the proper thing is being printed as well
out = StringIO()
with redirect_stdout(out):
with self.assertRaises(SystemExit) as thread:
license.scan_for_licenses(tmpd, conf, '')
self.assertEqual(thread.exception.code, 1)
self.assertIn("Cannot find any license", out.getvalue())
self.assertEqual(license.licenses, [])
def test_scan_for_licenses_skip_prefix_slash(self):
"""
Test scan_for_licenses in temporary directory with licenses to skip
"""
conf = config.Config("")
conf.setup_patterns()
conf.license_skips = [['', 'COPYING']]
with open('tests/COPYING_TEST', 'rb') as copyingf:
content = copyingf.read()
with tempfile.TemporaryDirectory() as tmpd:
# create the copying file
with open(os.path.join(tmpd, 'COPYING'), 'w') as newcopyingf:
newcopyingf.write(content.decode('utf-8'))
# create some cruft for testing
for testf in ['testlib.c', 'testmain.c', 'testheader.h']:
with open(os.path.join(tmpd, testf), 'w') as newtestf:
newtestf.write('test content')
# let's check that the proper thing is being printed as well
out = StringIO()
with redirect_stdout(out):
with self.assertRaises(SystemExit) as thread:
license.scan_for_licenses(tmpd, conf, '')
self.assertEqual(thread.exception.code, 1)
self.assertIn("Cannot find any license", out.getvalue())
self.assertEqual(license.licenses, [])
def test_load_specfile(self): def test_load_specfile(self):
""" """
Test load_specfile with populated license list. This method is not Test load_specfile with populated license list. This method is not
+68 -1
View File
@@ -2,7 +2,8 @@ import subprocess
import os import os
import tempfile import tempfile
import unittest import unittest
import unittest.mock from unittest.mock import MagicMock, mock_open, patch
import util import util
@@ -64,5 +65,71 @@ class TestUtil(unittest.TestCase):
self.assertTrue(util.binary_in_path('testbin')) self.assertTrue(util.binary_in_path('testbin'))
self.assertEqual(util.os_paths, [tmpd]) self.assertEqual(util.os_paths, [tmpd])
def test__process_build_log_bad_patch(self):
"""
Test _process_build_log with a bad patch
"""
def isfile_mock(_):
return True
isfile_backup = util.os.path.isfile
util.os.path.isfile = isfile_mock
call_backup = util.call
util.call = MagicMock()
open_name = 'util.open_auto'
content = "Patch #1 (bad.patch):\nHunk #1 FAILED at 1."
m_open = mock_open(read_data=content)
with patch(open_name, m_open, create=True):
util._process_build_log('filename')
util.os.path.isfile = isfile_backup
mock_call = util.call
util.call = call_backup
self.assertTrue(len(mock_call.mock_calls) == 3)
def test_globlike_match(self):
"""
Test globlike_match
"""
match_name = ['a', 'b', 'c']
file_path = 'a/b'
self.assertFalse(util.globlike_match(file_path, match_name))
match_name = ['a', 'c']
file_path = 'a/b'
self.assertFalse(util.globlike_match(file_path, match_name))
match_name = ['a', 'bb*']
file_path = 'a/b'
self.assertFalse(util.globlike_match(file_path, match_name))
match_name = ['a', 'b*']
file_path = 'a/ab'
self.assertFalse(util.globlike_match(file_path, match_name))
match_name = ['a', '*a']
file_path = 'a/ab'
self.assertFalse(util.globlike_match(file_path, match_name))
match_name = ['a', 'c*']
file_path = 'a/b'
self.assertFalse(util.globlike_match(file_path, match_name))
match_name = ['a', '*c']
file_path = 'a/b'
self.assertFalse(util.globlike_match(file_path, match_name))
match_name = ['a', 'b*']
file_path = 'a/b'
self.assertTrue(util.globlike_match(file_path, match_name))
match_name = ['a', '*b']
file_path = 'a/b'
self.assertTrue(util.globlike_match(file_path, match_name))
match_name = ['a', 'b']
file_path = 'a/b'
self.assertTrue(util.globlike_match(file_path, match_name))
if __name__ == '__main__': if __name__ == '__main__':
unittest.main(buffer=True) unittest.main(buffer=True)