Compare commits

...

11 Commits

Author SHA1 Message Date
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
William Douglas a62a849262 Add github url handling for tags with slashes
vectorscan uses 'vectorscan/' as a tag prefix which confuses our
version parsing (even more so with v being the tag prefix). Add
support for matching any '*/version' tag names as the top priority.

Signed-off-by: William Douglas <william.douglas@intel.com>
2024-09-09 12:42:57 -07:00
William Douglas eaa4f711da Fix type mismatch
current_patch is modified in the called as an array so make sure it is
created as one.

Signed-off-by: William Douglas <william.douglas@intel.com>
2024-08-01 16:49:45 -07:00
William Douglas f35655a0cc More error report matching
Signed-off-by: William Douglas <william.douglas@intel.com>
2024-08-01 11:54:35 -07:00
William Douglas 0c573b604b Fix setup line for packages without a prefix folder
Previously in a cleanup commit 74c0833c the support for packages that
didn't have a prefix folder was unintentionally removed. This change
updates the setup call for non-R packages to add the support back.

Signed-off-by: William Douglas <william.douglas@intel.com>
2024-07-31 14:59:15 -07:00
William Douglas 356da62750 Enable working with Jinja2 spec templates
Allow autospec to handle building packages that use a
Jinja2 formatted *.spec.template file. Currently only package_name,
package_version, package_release and package_url fields are supported
but others can be added as needed (patches and archives are good next
steps).

Signed-off-by: William Douglas <william.douglas@intel.com>
2024-07-25 13:06:51 -07:00
16 changed files with 329 additions and 84 deletions
+8
View File
@@ -128,6 +128,14 @@ release
``.spec``. This is also bumped and generated on existing and new packages,
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
In certain cases, the package license may not be automatically discovered. In
this instance, ``autospec`` will exit with an error. Update this file to
+7 -2
View File
@@ -269,9 +269,13 @@ def package(args, url, name, archives, workingdir):
pkg_integrity.check(url, conf, interactive=interactive_mode)
pkg_integrity.load_specfile(specfile)
specfile.write_spec()
spec_type = specfile.write_spec()
while 1:
package.package(filemanager, args.mock_config, args.mock_opts, conf, requirements, content, args.cleanup)
if spec_type == "template":
# specfile template is assumed "correct" and any failures need to be manually addressed
break
filemanager.load_specfile(specfile)
specfile.write_spec()
filemanager.newfiles_printed = 0
@@ -304,7 +308,8 @@ def package(args, url, name, archives, workingdir):
except Exception:
pass
check.check_regression(conf.download_path, conf.config_opts['skip_tests'], package.round - 1)
if spec_type == "generate":
check.check_regression(conf.download_path, conf.config_opts['skip_tests'], package.round - 1)
examine_abi(conf.download_path, content.name)
if os.path.exists("/var/lib/rpm"):
+8 -7
View File
@@ -64,21 +64,22 @@ def scan_for_tests(src_dir, config, requirements, content):
if config.config_opts.get('skip_tests') or tests_config:
return
make_command = "ninja" if config.config_opts.get('use_ninja') else "make"
makeflags = "%{?_smp_mflags} " if config.parallel_build else ""
make_check = "make {}check".format(makeflags)
cmake_check = "make test"
make_check = "{} {}check".format(make_command, makeflags)
cmake_check = "{} test".format(make_command)
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" \
"make test\nmodule unload openmpi"
"{} test\nmodule unload openmpi".format(make_command)
if config.config_opts.get('allow_test_failures'):
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" \
"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"
if config.config_opts.get('allow_test_failures'):
+6
View File
@@ -110,6 +110,7 @@ class Config(object):
self.custom_summ = ""
self.license_fetch = None
self.license_show = None
self.license_skips = []
self.git_uri = None
self.os_packages = set()
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 library containing (.*)... no", 0, None),
(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: ([a-zA-Z0-9]+) (?:is required to build|not found)", 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):
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
content = self.read_file(os.path.join(self.download_path, "cargo_vendors"), track=True)
if content:
+12
View File
@@ -124,7 +124,9 @@ ACL_TYPE_EXTENDED, acl-dev
ALSA, alsa-lib-dev
APR, apr-dev
APR-util, apr-util-dev
ARPACK-NG, arpack-ng-dev
ASSIMP, assimp-dev
Adwaita, libadwaita-dev
Analitza, analitza-dev
Analitza5, analitza-dev
BABL, babl-dev
@@ -175,6 +177,7 @@ EXPAT, expat-dev
Eet.h, eet-dev
Eigen/Core, eigen-dev
Eigen/Dense, eigen-dev
Eigen/Sparse, eigen-dev
Eigen3, eigen-dev
Epoxy, pkgconfig(epoxy)
Exiv2, exiv2-dev
@@ -284,6 +287,7 @@ GSTREAMER, gstreamer-dev
GSettingSchemas, gsettings-desktop-schemas
GSettingSchemas, gsettings-desktop-schemas-dev
GTK, gtk+-dev
GTK4, gtk4-dev
GnuTLS, gnutls-dev
GooglePerftools, gperftools-dev
Gperf, gperf
@@ -459,6 +463,7 @@ KF6NewStuff, knewstuff-def
KF6Notifications, knotifications-dev
KF6NotifyConfig, knotifyconfig-dev
KF6Package, kpackage-dev
KF6Prison, kprison-dev
KF6Purpose, purpose-dev
KF6QuickCharts, kquickcharts-dev
KF6Runner, krunner-dev
@@ -548,6 +553,7 @@ NETTLE, nettle-dev
NUMA, numactl-dev
Nepomuk, nepomuk-core-dev
NetworkManager, NetworkManager-dev
Nice, libnice-dev
NumPy, pypi-numpy
Numa, numactl-dev
OPENEXR, openexr-dev
@@ -621,6 +627,7 @@ Qt5Xdg, libqtxdg-dev
Qt5XdgIconLoader, libqtxdg-dev
Qt5XmlPatterns, qtxmlpatterns-dev
Qt6Positioning, qt6positioning-dev
Qt6Qml, qt6declarative-dev
Qt6Quick, qt6declarative-dev
Qt6QuickTimeline, qt6quicktimeline-dev
Qt6ShaderTools, qt6shadertools-dev
@@ -650,6 +657,7 @@ Soprano, soprano-dev
SpatialIndex, libspatialindex-dev
Sphinx, pypi-sphinx
Sqlite, sqlite-autoconf-dev
Srtp2, libsrtp-dev
Startup notification library, libnotify-dev
TBB, tbb-dev
TIFF, tiff-dev
@@ -1124,6 +1132,7 @@ libsecret-unstable, libsecret-dev
libsoup-2.4, libsoup-dev
libssh, libssh-dev
libssh2.h, libssh2-dev
libssl, openssl-dev
libsystemd, pkgconfig(systemd)
libtirpc (via pkg-config), pkgconfig(libtirpc)
libudev.h, systemd-dev
@@ -1298,6 +1307,8 @@ pycparser, pypi(pycparser)
pycurl, pypi(pycurl)
pylint, pypi(pylint)
pyperclip, pypi(pyperclip)
pypi(openvino), openvino-python3
pypi(pytorch), pytorch-python3
pytest, pypi-pytest
pytest-cov, pypi(pytest_cov)
python lxml, pypi(lxml)
@@ -1492,6 +1503,7 @@ yaml-cpp, yaml-cpp-dev
yarg, pypi-yarg
yasm, yasm
yytext is a pointer, flex
zconf.h, zlib-dev
zenity, zenity
zip, zip
zlib, zlib-dev
+1 -28
View File
@@ -197,33 +197,6 @@ class FileManager(object):
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):
"""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:
@@ -245,7 +218,7 @@ class FileManager(object):
elif len('/'.join(match_name)) <= (len(norm_filename) + 1):
# the match name may be 1 longer due to a glob
# 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()
self.push_package_file(os.path.join(path_prefix, *match_name), k)
return
+27 -10
View File
@@ -29,7 +29,7 @@ import urllib.parse
import chardet
import download
from util import get_contents, get_sha1sum, print_fatal, print_warning
import util
default_license = "TO BE DETERMINED"
@@ -96,7 +96,7 @@ def decode_license(license):
def license_from_copying_hash(copying, srcdir, config, name):
"""Add licenses based on the hash of the copying file."""
try:
data = get_contents(copying)
data = util.get_contents(copying)
except FileNotFoundError:
# LICENSE file is a bad symlink (qemu-4.2.0!)
return
@@ -109,7 +109,7 @@ def license_from_copying_hash(copying, srcdir, config, name):
if not data:
return
hash_sum = get_sha1sum(copying)
hash_sum = util.get_sha1sum(copying)
if config.license_fetch:
values = {'hash': hash_sum, 'text': data, 'package': name}
@@ -142,9 +142,24 @@ def license_from_copying_hash(copying, srcdir, config, name):
else:
if not config.license_show:
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}
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):
@@ -166,8 +181,9 @@ def scan_for_licenses(srcdir, config, pkg_name):
for dirpath, dirnames, files in os.walk(srcdir):
for name in files:
if name.lower() in targets or target_pat.search(name.lower()):
license_from_copying_hash(os.path.join(dirpath, name),
srcdir, config, pkg_name)
license_path = os.path.join(dirpath, 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
# REUSE-compliant, or are in process of adopting this standard (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.
dirbase = os.path.basename(dirpath)
if re.search(r'^(LICENSES|licenses?|licensing)$', dirbase) and re.search(r'\.txt$', name):
license_from_copying_hash(os.path.join(dirpath, name),
srcdir, config, pkg_name)
license_path = os.path.join(dirpath, name)
if not skip_license(license_path, config):
license_from_copying_hash(license_path, srcdir, config, pkg_name)
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)
print("Licenses : ", " ".join(sorted(licenses)))
+43 -11
View File
@@ -3,12 +3,12 @@
# This file is sorted with LC_COLLATE=C
# Lines beginning with '#' are ignored.
# For strings that start with '#', escape the '#' as '\#'.
=========================
%
%license
(LGPL)
(new)
(specified
*
+
-
-MIT
@@ -26,6 +26,8 @@
3-Clause
3-clause
3BSD
=========================
>=-2
@CPACK_RPM_PACKAGE_LICENSE@
AGPLv3+
ALv2
@@ -35,7 +37,12 @@ APPLICATION__TYPE
ASL
Artistic
BSD
BSD(2
BSD(3
BSD-2-Clause-Views
BSD-3
BSD-compatible
BSD-derived(Repoze)
BSD-like
BSD-style
BSDL
@@ -43,6 +50,7 @@ BSD_3_clause
BSDish
BSL
CC-BY
Clause
Commercial
Corp.
Distribution
@@ -53,6 +61,7 @@ EPL
Eclipse
Expat(MIT/X11)
Expat/MIT
FOUNDATION
Foundation
FreeBSD
GENERAL
@@ -60,30 +69,39 @@ GFDL
GNU
GPL
GPL+
GPL-1.0-only
GPL/BSD
GPL/BSD/CPL
GPLv2.1
General
IBM
Jupyter
LESSER
LGPL
LGPL+BSD
LGPL/MIT
LICENCE
Lesser
Library
Licences
License
License(2.0)
License(==-2.0)
License(>=-2)
License(>=-2.0)
License(LGPL)
License(MIT)
License,
License-2
License-2.0
License-2.0(MPL-2.0)
License-3(GPLv3)
Licensing
Lucent
MIT-0
MIT/Expat
MPL
Minpack
Modified
Mozilla
Muddy-MIT
@@ -95,9 +113,13 @@ Open
PIL
PSF-2+
PUBLIC
PYTHON
Permission
Public
Revised
SIL
SIP
SOFTWARE
See
Set
Software
@@ -111,31 +133,46 @@ UNKNOWN
Unknown
Unkown
Unlimited
VERSION-2
Version
Version-2.0
Version-3
WITH
What
\#
a
advertising
and
any
bsd
charge
classifiers)
clause)
copy
cryptsetup-OpenSSL-exception
details
domain
domain.
dual
exceptions
for
free
gpl
granted
hereby
http://nmap.org/man/man-legal.html
into
is
it
later
later(LGPLv2+)
license
licensing
ndg/httpsclient/LICENCE
new
none
obtaining
of
on
open_source
option
@@ -143,11 +180,16 @@ option)
or
or(at
others
person
public
released
software
style
terms
the
to
under?
unencumbered
unknown
unrestricted
uses
@@ -160,13 +202,3 @@ with
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, Apache-2.0
Apache-2, Apache-2.0
Apache2, Apache-2.0
Apache2.0, Apache-2.0
Apachev2, Apache-2.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
BSD(3-clause), BSD-3-Clause
BSD-2-clause, BSD-2-Clause
+43 -8
View File
@@ -26,6 +26,8 @@ import types
from collections import OrderedDict
import git
from jinja2 import Environment
from jinja2.loaders import DictLoader
from util import _file_write, open_auto
AVX2_CFLAGS = "-march=x86-64-v3"
@@ -73,12 +75,42 @@ class Specfile(object):
def write_spec(self):
"""Write spec file."""
self.specfile = open_auto("{}/{}.spec".format(self.config.download_path, self.name), "w")
spec_path = f"{os.path.join(self.config.download_path, self.name)}.spec"
self.specfile = open_auto(spec_path, "w")
self.specfile.write_strip = types.MethodType(_file_write, self.specfile)
# last chance to sanitize url for template and build types
if self.config.urlban:
clean_url = re.sub(self.config.urlban, "localhost", self.url)
# Duplicate prefixes entry before we change the url
self.content.prefixes[clean_url] = self.content.prefixes.get(self.url)
self.url = clean_url
template_path = f"{spec_path}.template"
if os.path.isfile(template_path):
# make templates have a template build pattern
self.config.default_pattern = "template"
# spec file comment header
self.write_comment_header()
if os.path.isfile(template_path):
with open_auto(template_path) as tfile:
template_content = tfile.read()
template = Environment(loader=DictLoader({'spec': template_content})).get_template('spec')
kw = {
'package_name': self.name,
'package_version': self.version,
'package_url': self.url,
'package_release': self.release,
}
self.specfile.write(template.render(**kw))
self.specfile.write_strip('\n')
self.specfile.close()
# return specfile type built so autospec knows how to
# handle build results (template should only builds once)
return "template"
if self.config.config_opts.get('keepstatic'):
self._write("%define keepstatic 1\n")
@@ -110,6 +142,10 @@ class Specfile(object):
self.specfile.close()
# return specfile type built so autospec knows how to
# handle build results (generate has multiple builds)
return "generate"
def write_comment_header(self):
"""Write comment header to spec file."""
self._write("#\n")
@@ -132,11 +168,6 @@ class Specfile(object):
def write_nvr(self):
"""Write name, version, and release information."""
if self.config.urlban:
clean_url = re.sub(self.config.urlban, "localhost", self.url)
# Duplicate prefixes entry before we change the url
self.content.prefixes[clean_url] = self.content.prefixes.get(self.url)
self.url = clean_url
self._write("Name : {}\n".format(self.name))
self._write("Version : {}\n".format(self.version))
self._write("Release : {}\n".format(str(self.release)))
@@ -452,12 +483,16 @@ class Specfile(object):
self._write_strip(f"gpg --homedir .gnupg --status-fd 1 --verify {self.config.signature_macro} %{{SOURCE0}} > gpg.status")
self._write_strip(f"grep -E '^\\[GNUPG:\\] (GOODSIG|EXPKEYSIG) {self.keyid}' gpg.status")
self.write_prep_prepend()
prefix = self.content.prefixes[self.url]
if self.config.default_pattern == 'R':
prefix = self.content.tarball_prefix
self._write_strip("%setup -q -n " + prefix)
else:
self._write_strip("%setup -q -n " + prefix)
prefix = self.content.prefixes[self.url]
if not prefix:
prefix = os.path.splitext(os.path.basename(self.url))[0]
self._write_strip("%setup -q -c -n " + prefix)
else:
self._write_strip("%setup -q -n " + prefix)
for archive in self.config.sources["archive"]:
# Handle various archive types
extract_cmd = 'tar xf {}'
+2 -1
View File
@@ -295,7 +295,8 @@ class Content():
if "github.com" in self.url:
# define regex accepted for valid packages, important for specific
# patterns to come before general ones
github_patterns = [r"https?://github.com/(.*)/(.*?)/archive/refs/tags/[vVrR]?(.*)\.tar",
github_patterns = [r"https?://github.com/(.*)/(.*?)/archive/refs/tags/.*/(.*).tar",
r"https?://github.com/(.*)/(.*?)/archive/refs/tags/[vVrR]?(.*)\.tar",
r"https?://github.com/(.*)/(.*?)/archive/[v|r]?.*/(.*).tar",
r"https?://github.com/(.*)/(.*?)/archive/[-a-zA-Z_]*-(.*).tar",
r"https?://github.com/(.*)/(.*?)/archive/[vVrR]?(.*).tar",
+43 -1
View File
@@ -90,6 +90,20 @@ def _process_line(line, prev_line, current_patch, reported_patches, error):
_log_error("Compiler: " + m.group('error'))
return True
if m := re.match(r'Could NOT find (?P<package>.*) .missing', line):
_log_error("CMake module " + m.group('package') + " not found")
return True
if m := re.match(r'Could not find a package configuration file provided by (?P<package>.*) with', line):
_log_error("CMake module " + m.group('package') + " not found")
return True
# Unable to find program 'gperf'
if m := re.match(r"Failed to find program (?P<module>.*)", line):
_log_error("Failed to find " + m.group('module'))
return True
if m := re.match(r"Failed to find (?P<module>.*)", line):
_log_error("Failed to find " + m.group('module'))
return True
return False
@@ -98,7 +112,7 @@ def _process_build_log(filename):
lines = lfile.readlines()
prev_line = ''
current_patch = ''
current_patch = ['']
reported_patches = {}
error = False
for line in lines:
@@ -260,3 +274,31 @@ def open_auto(*args, **kwargs):
assert 'encoding' not in kwargs
assert 'errors' not in 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
+1
View File
@@ -1612,3 +1612,4 @@ http://sourceforge.net/projects/zsh/files/zsh/5.4.2/zsh-5.4.2.tar.gz,zsh,5.4.2
https://pigeonhole.dovecot.org/releases/2.3/dovecot-2.3.11-pigeonhole-0.5.11.tar.gz,pigeonhole,0.5.11
https://pigeonhole.dovecot.org/releases/2.3/dovecot-2.3-pigeonhole-0.5.20.tar.gz,pigeonhole,0.5.20
https://www.ezix.org/software/files/lshw-B.02.19.2.tar.gz,lshw,02.19.2
https://github.com/VectorCamp/vectorscan/archive/refs/tags/vectorscan/5.4.11.tar.gz,vectorscan,5.4.11
+57 -1
View File
@@ -71,7 +71,7 @@ class TestLicense(unittest.TestCase):
conf = config.Config("")
conf.setup_patterns()
# 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"
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.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):
"""
Test load_specfile with populated license list. This method is not
+1 -14
View File
@@ -47,7 +47,7 @@ class TestSpecfileWrite(unittest.TestCase):
self.WRITES = self.WRITES[:4] + self.WRITES[6:]
self.assertEqual(expect, self.WRITES)
def test_write_nvr_no_urlban(self):
def test_write_nvr(self):
"""
test Specfile.write_nvr with no urlban set
"""
@@ -59,19 +59,6 @@ class TestSpecfileWrite(unittest.TestCase):
"Source0 : http://www.testpkg.com/testpkg/pkg-1.0.tar.gz\n"]
self.assertEqual(expect, self.WRITES)
def test_write_nvr_urlban(self):
"""
test Specfile.write_nvr with urlban set
"""
self.specfile.config.urlban = "www.testpkg.com"
self.specfile.write_nvr()
expect = ["Name : pkg\n",
"Version : 1.0\n",
"Release : 2\n",
"URL : http://localhost/testpkg/pkg-1.0.tar.gz\n",
"Source0 : http://localhost/testpkg/pkg-1.0.tar.gz\n"]
self.assertEqual(expect, self.WRITES)
def test_write_sources(self):
"""
test write_sources with all Specfile.sources set.
+68 -1
View File
@@ -2,7 +2,8 @@ import subprocess
import os
import tempfile
import unittest
import unittest.mock
from unittest.mock import MagicMock, mock_open, patch
import util
@@ -64,5 +65,71 @@ class TestUtil(unittest.TestCase):
self.assertTrue(util.binary_in_path('testbin'))
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__':
unittest.main(buffer=True)