summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOlav Vitters <olav@vitters.nl>2020-04-29 14:46:17 +0200
committerOlav Vitters <olav@vitters.nl>2020-04-29 14:46:17 +0200
commit9be921d7c924d94f488cbfa0066a4334f84d89bb (patch)
tree361990a9b13629d0b51d2bbb30fcfe9367a69b47
parent4a619f2b0ea515fd692a80dd8b83f5ebc1755b2f (diff)
downloadmgagnome-9be921d7c924d94f488cbfa0066a4334f84d89bb.tar
mgagnome-9be921d7c924d94f488cbfa0066a4334f84d89bb.tar.gz
mgagnome-9be921d7c924d94f488cbfa0066a4334f84d89bb.tar.bz2
mgagnome-9be921d7c924d94f488cbfa0066a4334f84d89bb.tar.xz
mgagnome-9be921d7c924d94f488cbfa0066a4334f84d89bb.zip
pylint: fix too long lines, missing docstrings, etc
-rwxr-xr-xmgagnome594
1 files changed, 446 insertions, 148 deletions
diff --git a/mgagnome b/mgagnome
index 03843fe..ef87d7e 100755
--- a/mgagnome
+++ b/mgagnome
@@ -5,7 +5,7 @@
# https://git.gnome.org/browse/sysadmin-bin/tree/ftpadmin
# Written by Olav Vitters
-from functools import wraps, lru_cache
+from functools import wraps, lru_cache, cached_property
# basic modules:
import os
@@ -62,8 +62,8 @@ SLEEP_INITIAL = 180
SLEEP_REPEAT = 30
SLEEP_TIMES = 30
-re_majmin = re.compile(r'^([0-9]+\.[0-9]+).*')
-re_version = re.compile(r'([-.]|\d+|[^-.\d]+)')
+_re_majmin = re.compile(r'^([0-9]+\.[0-9]+).*')
+_re_version = re.compile(r'([-.]|\d+|[^-.\d]+)')
@@ -144,6 +144,7 @@ MAJOR_VERSIONS = {
}
def get_majmin(version, module=None):
+ """Return a tuple with major and minor versions given a version"""
nrs = version.split('.')
if module and module.lower() in MAJOR_VERSIONS:
@@ -161,7 +162,10 @@ def get_majmin(version, module=None):
def get_safe_max_version(version, module=None):
- match = re_majmin.match(version)
+ """Provide the maximum version a module could safely be increased to
+
+ This assumed the module is uses symantic versioning"""
+ match = _re_majmin.match(version)
if version is None or not match:
return None
@@ -197,7 +201,7 @@ def judge_version_increase(version_old, version_new, module=None):
return (-3, "Version %s is older than current version %s!" % (version_new, version_old))
# Version is newer, but we don't want to see if it follows the GNOME versioning scheme
- majmins = [get_majmin(ver, module) for ver in versions if re_majmin.match(ver) is not None]
+ majmins = [get_majmin(ver, module) for ver in versions if _re_majmin.match(ver) is not None]
if len(majmins) == 1:
return (-1, "Version number scheme changes: %s" % (", ".join(versions)))
@@ -244,6 +248,7 @@ def judge_version_increase(version_old, version_new, module=None):
return (4, "Stable version increase")
def line_input(file):
+ """Iterate over a file and ignore any newline"""
for line in file:
if line[-1] == '\n':
yield line[:-1]
@@ -251,6 +256,7 @@ def line_input(file):
yield line
def distinct(iterable, keyfunc=None):
+ """Iterate over an iterable and only return unique/distinct iterables"""
seen = set()
for item in iterable:
key = item if keyfunc is None else keyfunc(item)
@@ -283,6 +289,9 @@ def call_editor(filename):
return True
class URLLister(HTMLParser):
+ """Parse links from HTML"""
+ # pylint: disable=abstract-method
+
def reset(self):
HTMLParser.reset(self)
self.urls = []
@@ -293,17 +302,17 @@ class URLLister(HTMLParser):
if href:
self.urls.extend(href)
-def is_valid_hash(path, algo, hexdigest):
+def _is_valid_hash(path, algo, hexdigest):
if algo not in hashlib.algorithms_available:
raise ValueError("Unknown hash algorithm: %s" % algo)
local_hash = getattr(hashlib, algo)()
- with open(path, 'rb') as fp:
- data = fp.read(32768)
+ with open(path, 'rb') as fp_file:
+ data = fp_file.read(32768)
while data:
local_hash.update(data)
- data = fp.read(32768)
+ data = fp_file.read(32768)
return local_hash.hexdigest() == hexdigest
@@ -318,18 +327,46 @@ class SpecFileError(Exception):
class SpecFile():
- re_update_version = re.compile(r'^(?P<pre>Version[ \t]*:\s*)(?P<version>.+)(?P<post>\s*)$', re.MULTILINE + re.IGNORECASE)
- re_update_release = re.compile(r'^(?P<pre>Release[ \t]*:\s*)(?P<release>%mkrel [0-9.]+)(?P<post>\s*)$', re.MULTILINE + re.IGNORECASE)
- re_update_patch = re.compile(r'^(?P<pre>Patch0*?)(?P<nr>[0-9]*)(?P<pre2>[ \t]*:\s*)(?P<patch>.+)(?P<post>\s*)\n', re.MULTILINE + re.IGNORECASE)
-
- re_br_part = re.compile(r'(?P<br>[^\s%{},<>=][^\s%{},<>=]*)\b(?P<post>\s*(?:(?P<operator>=|>=|<=|=<|=>|>|<)\s*(?P<version>[^\s%{},]+|\%\{[^\s{%}]+\}|\%[^\s%{},]+)\b)?)')
-
- #re_update_br = re.compile(r'^(?P<pre>BuildRequires:\s*)(?P<br>[^\s%{},]+?)(?P<post>\s*(?:(?:[<>]=?|=)\s+[^\s%{},]+?)?\s*\n)', re.MULTILINE + re.IGNORECASE)
- re_update_br = re.compile(r'^(?P<pre>BuildRequires[ \t]*:\s*)(?P<br>[^\s%{},]+?)(?P<post>\s*(?:(?:[<>]=?|=)\s+(?:[^\s%{},]+|\%\{[^\s{%}]+\}|\%[^\s%{},]+))?\s*\n)', re.MULTILINE + re.IGNORECASE)
-# re_update_br_unsplit = re.compile(r'^(?P<pre>BuildRequires:\s*)(?P<unsplit>[^\n,]+,[^\n]*)(?P<post>\s*\n)', re.MULTILINE + re.IGNORECASE)
-
- re_update_br_fix_operator = re.compile(r'^(?P<pre>BuildRequires[ \t]*:\s*[^\n]*)(?P<operator>=<|=>)(?P<post>[^\n]+)\n', re.MULTILINE + re.IGNORECASE)
- re_update_br_unsplit = re.compile(r'^(?P<pre>BuildRequires[ \t]*:\s*)(?P<unsplit>(?:%s,?(?:[ \t\f\v]+|$)){2,})(?P<unsplitpost>\n)' % (re_br_part.pattern,), re.MULTILINE + re.IGNORECASE)
+ """Functions related to a spec file"""
+ re_update_version = re.compile(
+ r'^(?P<pre>Version[ \t]*:\s*)(?P<version>.+)(?P<post>\s*)$',
+ re.MULTILINE + re.IGNORECASE
+ )
+ re_update_release = re.compile(
+ r'^(?P<pre>Release[ \t]*:\s*)(?P<release>%mkrel [0-9.]+)(?P<post>\s*)$',
+ re.MULTILINE + re.IGNORECASE
+ )
+ re_update_patch = re.compile(
+ r'^(?P<pre>Patch0*?)(?P<nr>[0-9]*)(?P<pre2>[ \t]*:\s*)(?P<patch>.+)(?P<post>\s*)\n',
+ re.MULTILINE + re.IGNORECASE
+ )
+ re_br_part = re.compile(
+ r'(?P<br>[^\s%{},<>=][^\s%{},<>=]*)\b(?P<post>\s*(?:(?P<operator>=|>=|<=|=<|=>|>|<)\s*' \
+ r'(?P<version>[^\s%{},]+|\%\{[^\s{%}]+\}|\%[^\s%{},]+)\b)?)'
+ )
+ #re_update_br = re.compile(
+ # r'^(?P<pre>BuildRequires:\s*)(?P<br>[^\s%{},]+?)(?P<post>\s*(?:(?:[<>]=?|=)\s+[^\s%{},]+?)?\s*\n)',
+ # re.MULTILINE + re.IGNORECASE
+ #)
+ re_update_br = re.compile(
+ r'^(?P<pre>BuildRequires[ \t]*:\s*)(?P<br>[^\s%{},]+?)' \
+ r'(?P<post>\s*(?:(?:[<>]=?|=)\s+(?:[^\s%{},]+|\%\{[^\s{%}]+\}|\%[^\s%{},]+))?\s*\n)',
+ re.MULTILINE + re.IGNORECASE
+ )
+ #re_update_br_unsplit = re.compile(
+ # r'^(?P<pre>BuildRequires:\s*)(?P<unsplit>[^\n,]+,[^\n]*)(?P<post>\s*\n)',
+ # re.MULTILINE + re.IGNORECASE
+ #)
+
+ re_update_br_fix_operator = re.compile(
+ r'^(?P<pre>BuildRequires[ \t]*:\s*[^\n]*)(?P<operator>=<|=>)(?P<post>[^\n]+)\n',
+ re.MULTILINE + re.IGNORECASE
+ )
+ re_update_br_unsplit = re.compile(
+ r'^(?P<pre>BuildRequires[ \t]*:\s*)(?P<unsplit>(?:%s,?(?:[ \t\f\v]+|$)){2,})' \
+ r'(?P<unsplitpost>\n)' % (re_br_part.pattern,),
+ re.MULTILINE + re.IGNORECASE
+ )
def __init__(self, path, module=None):
self.path = path
@@ -341,23 +378,34 @@ class SpecFile():
@property
def changes(self):
- return ''.join(self._changes.keys()) if len(self._changes) == 1 else "\n".join(("- %s" % change for change in self._changes.keys()))
+ """Description of the changes made to the spec file"""
+ return ''.join(self._changes.keys()) \
+ if len(self._changes) == 1 \
+ else "\n".join(("- %s" % change for change in self._changes.keys()))
@property
def made_changes(self):
+ """Determine if the spec file was changed"""
return self._changed_spec_file
@property
def version(self):
- return subprocess.check_output(["rpm", "--define", "_topdir %s" % os.path.join(self.cwd, ".."), "--specfile", self.path, "--queryformat", "%{VERSION}\n"]).decode("utf-8").splitlines()[0]
+ """Provide the version as parsed by rpm"""
+ cmd = ["rpm", "--define", "_topdir %s" % os.path.join(self.cwd, ".."), "--specfile", self.path,
+ "--queryformat", "%{VERSION}\n"]
+ return subprocess.check_output(cmd).decode("utf-8").splitlines()[0]
@property
def should_rebuild(self):
+ """Determine if the package should be rebuilt"""
return self._should_rebuild
@property
def release(self):
- return subprocess.check_output(["rpm", "--define", "%dist %nil", "--define", "_topdir %s" % os.path.join(self.cwd, ".."), "--specfile", self.path, "--queryformat", "%{RELEASE}\n"]).decode("utf-8").splitlines()[0]
+ """Provide the release as parsed by rpm"""
+ cmd = ["rpm", "--define", "%dist %nil", "--define", "_topdir %s" % os.path.join(self.cwd, ".."),
+ "--specfile", self.path, "--queryformat", "%{RELEASE}\n"]
+ return subprocess.check_output(cmd).decode("utf-8").splitlines()[0]
def _sources_and_patches(self, flag=None):
os.chdir(self.cwd)
@@ -375,34 +423,100 @@ class SpecFile():
# trans_set.parseSpec can affect changing of internal macros, e.g. redefining things like mkrel and so on
# reload the config to fix this
rpm.reloadConfig()
- return dict((os.path.basename(name), [name, 0 if no == 2147483647 and flags == 2 else no]) for name, no, flags in srclist if flag is None or flags == flag)
+ return dict(
+ (os.path.basename(name), [name, 0 if no == 2147483647 and flags == 2 else no])
+ for name, no, flags in srclist if flag is None or flags == flag
+ )
@property
def patches(self):
+ """Return the patches"""
return self._sources_and_patches(flag=2)
@property
def sources(self):
+ """Return the sources"""
return self._sources_and_patches(flag=1)
def clean_spec(self):
- re_rm_buildroot = r'^(?:\s*\[[^\n\]\[]+\][ \t]+\&\&[ \t]+)?(?:rm|\%__rm|\%\{__rm\}) *(?:-rf|-fr|-r) *"?(?:[%$]buildroot|[%$]\{buildroot\}|[%$]\{buildroot\}|\$RPM_BUILDROOT|\$RPM_BUILD_ROOT|\$\{RPM_BUILD_ROOT\}|\$RPM_BUILD_DIR)"?/?[ \t]*\n'
+ """Clean the spec file of deprecated statements"""
+
+ re_rm_buildroot = r'^(?:\s*\[[^\n\]\[]+\][ \t]+\&\&[ \t]+)?(?:rm|\%__rm|\%\{__rm\}) *' \
+ r'(?:-rf|-fr|-r) *"?(?:[%$]buildroot|[%$]\{buildroot\}|[%$]\{buildroot\}|' \
+ r'\$RPM_BUILDROOT|\$RPM_BUILD_ROOT|\$\{RPM_BUILD_ROOT\}|\$RPM_BUILD_DIR)"?/?[ \t]*\n'
+
re_clean_spec = [
# remove %defattr
- ('remove defattr', None, re.compile(r'(?P<keeppre>^\%files(?:[ \t]+[^\n]*)?\n(?:^\%doc [^\n]+\n)?)^\%defattr\s*\(- *, *root *, *root *(?:, *-)?\)\s*\n', re.MULTILINE + re.IGNORECASE)),
- ('remove cleaning buildroot in install', None, re.compile(r'(?P<keeppre>^\%install(?:[ \t]+[^\n]*)?\n)' + re_rm_buildroot + r'\n?', re.MULTILINE + re.IGNORECASE)),
- ('remove clean section', None, re.compile(r'^\%clean[ \t]*\n(?:' + re_rm_buildroot + r')?\s*(?P<keeppost>(?:^#[^%\n]+\n)*^(?:\%files|\%post|\%pre|\%trigger|\%install|\%package|\%check|\%_font_pkg|$(?!.|\n)))', re.MULTILINE + re.IGNORECASE)),
- ('remove buildroot definition', None, re.compile(r'^BuildRoot[ \t]*:[^\n]+\n', re.MULTILINE + re.IGNORECASE)),
- ('remove unneeded setup option', None, re.compile(r'^(?P<keeppre>\%setup -q)(?: -n|n) (?:\%name|\%\{name\})-(?:\%version|\%\{version\})(?P<keeppost>\n)', re.MULTILINE + re.IGNORECASE)),
- ('https for download.gnome.org', r'\g<keeppre>https://\g<keeppost>', re.compile(r'^(?P<keeppre>Source[0-9]*[ \t]*:[^\n]+)http://(?P<keeppost>download.gnome.org/[^\n]+\n)', re.MULTILINE + re.IGNORECASE)),
- ('download.gnome.org instead of ftp.gnome.org', r'\g<keeppre>https://download.gnome.org\g<keeppost>', re.compile(r'^(?P<keeppre>Source[0-9]*[ \t]*:[^\n]+)(?:ftp|http|https)://ftp.gnome.org/pub/GNOME(?P<keeppost>/[^\n]+\n)', re.MULTILINE + re.IGNORECASE)),
- ('restrict what libraries are matched with major numbers', r'\g<keeppre>{,.*}', re.compile(r'^(?P<keeppre>%{_libdir}[^\n]+})\*$', re.MULTILINE)),
- ('keep library matching using two lines', r'\g<keeppre>\n\g<keeppre>.*', re.compile(r'^(?P<keeppre>%{_libdir}[^\n]+})$\n(?P=keeppre)\{,\.\*\}$', re.MULTILINE)),
+ (
+ 'remove defattr',
+ None,
+ re.compile(r'(?P<keeppre>^\%files(?:[ \t]+[^\n]*)?\n(?:^\%doc [^\n]+\n)?)'
+ r'^\%defattr\s*\(- *, *root *, *root *(?:, *-)?\)\s*\n',
+ re.MULTILINE + re.IGNORECASE)
+ ),
+ (
+ 'remove cleaning buildroot in install',
+ None,
+ re.compile(r'(?P<keeppre>^\%install(?:[ \t]+[^\n]*)?\n)' + re_rm_buildroot + r'\n?',
+ re.MULTILINE + re.IGNORECASE)
+ ),
+ (
+ 'remove clean section',
+ None,
+ re.compile(r'^\%clean[ \t]*\n(?:' + re_rm_buildroot +
+ r')?\s*(?P<keeppost>(?:^#[^%\n]+\n)*^(?:\%files|\%post|\%pre|\%trigger|'
+ r'\%install|\%package|\%check|\%_font_pkg|$(?!.|\n)))',
+ re.MULTILINE + re.IGNORECASE)
+ ),
+ (
+ 'remove buildroot definition',
+ None,
+ re.compile(r'^BuildRoot[ \t]*:[^\n]+\n', re.MULTILINE + re.IGNORECASE)
+ ),
+ (
+ 'remove unneeded setup option',
+ None,
+ re.compile(r'^(?P<keeppre>\%setup -q)(?: -n|n) (?:\%name|\%\{name\})-'
+ r'(?:\%version|\%\{version\})(?P<keeppost>\n)',
+ re.MULTILINE + re.IGNORECASE)),
+ (
+ 'https for download.gnome.org',
+ r'\g<keeppre>https://\g<keeppost>',
+ re.compile(r'^(?P<keeppre>Source[0-9]*[ \t]*:[^\n]+)http://(?P<keeppost>download.gnome.org/[^\n]+\n)',
+ re.MULTILINE + re.IGNORECASE)
+ ),
+ (
+ 'download.gnome.org instead of ftp.gnome.org',
+ r'\g<keeppre>https://download.gnome.org\g<keeppost>',
+ re.compile(r'^(?P<keeppre>Source[0-9]*[ \t]*:[^\n]+)(?:ftp|http|https):' +
+ r'//ftp.gnome.org/pub/GNOME(?P<keeppost>/[^\n]+\n)',
+ re.MULTILINE + re.IGNORECASE)
+ ),
+ (
+ 'restrict what libraries are matched with major numbers',
+ r'\g<keeppre>{,.*}',
+ re.compile(r'^(?P<keeppre>%{_libdir}[^\n]+})\*$', re.MULTILINE)
+ ),
+ (
+ 'keep library matching using two lines',
+ r'\g<keeppre>\n\g<keeppre>.*',
+ re.compile(r'^(?P<keeppre>%{_libdir}[^\n]+})$\n(?P=keeppre)\{,\.\*\}$', re.MULTILINE)
+ ),
('make use of autopatch', r'%autopatch -p1', re.compile(r'^%apply_patches$', re.MULTILINE)),
('change configure2_5x macro to configure', r'%configure', re.compile(r'^%configure2_5x\b', re.MULTILINE)),
('change make macro to make_build', r'%make_build', re.compile(r'^%make\b', re.MULTILINE), True),
- ('change find_lang --with-help into --with-gnome', r'\g<keeppre> --with-gnome\g<keeppost>', re.compile(r'^(?P<keeppre>\s*\%find_lang[^\\\n]+) --with-help(?P<keeppost>[^\\\n]*\n)', re.MULTILINE + re.IGNORECASE)),
- ('change find_lang remove duplicate with_gnome', None, re.compile(r'^(?P<keeppre>\%find_lang[^\\\n]+ --with-gnome) --with-gnome(?P<keeppost>[^\\\n]*\n)', re.MULTILINE + re.IGNORECASE)),
+ (
+ 'change find_lang --with-help into --with-gnome',
+ r'\g<keeppre> --with-gnome\g<keeppost>',
+ re.compile(r'^(?P<keeppre>\s*\%find_lang[^\\\n]+) --with-help(?P<keeppost>[^\\\n]*\n)',
+ re.MULTILINE + re.IGNORECASE)
+ ),
+ (
+ 'change find_lang remove duplicate with_gnome',
+ None,
+ re.compile(r'^(?P<keeppre>\%find_lang[^\\\n]+ --with-gnome) --with-gnome(?P<keeppost>[^\\\n]*\n)',
+ re.MULTILINE + re.IGNORECASE)
+ ),
# Use new Python macros
('use new Python macros', r'%py3_build', re.compile(r'^%{__python3} setup.py build$', re.MULTILINE)),
@@ -411,13 +525,21 @@ class SpecFile():
('use new Python macros', r'%{python3_version}', re.compile(r'%{py3ver}', re.MULTILINE)),
]
re_convert_br = [
- ('remove py_requires', ('python',), re.compile(r'^\%(?:py_requires|\{py_requires\})[ \t]*\n', re.MULTILINE)),
- ('remove py_requires -d', ('python', 'python-devel'), re.compile(r'^\%(?:py_requires[ \t]+-d|\{py_requires[ \t]+-d\})[ \t]*\n', re.MULTILINE)),
+ (
+ 'remove py_requires',
+ ('python',),
+ re.compile(r'^\%(?:py_requires|\{py_requires\})[ \t]*\n', re.MULTILINE)
+ ),
+ (
+ 'remove py_requires -d',
+ ('python', 'python-devel'),
+ re.compile(r'^\%(?:py_requires[ \t]+-d|\{py_requires[ \t]+-d\})[ \t]*\n', re.MULTILINE)
+ ),
]
made_changes = False
- with open(self.path, "r", encoding="utf-8") as f:
- data = f.read()
+ with open(self.path, "r", encoding="utf-8") as fp_spec:
+ data = fp_spec.read()
for reason, change_to, regexp, *extra in re_clean_spec:
if extra:
should_rebuild = extra[0]
@@ -468,14 +590,25 @@ class SpecFile():
converted_defines = []
for search_for in ('name', 'version', 'release', 'summary', 'Summary', 'group'):
search_for_ignore_case = ''.join(("[%s%s]" % (letter, letter.swapcase()) for letter in search_for))
- re_spec = re.compile(r'^(?P<keeppre>' + re.escape(search_for_ignore_case) + r'[ \t]*:[ \t]*)(?:\%' + re.escape(search_for) + r'|\%\{' + re.escape(search_for) + r'\})(?P<keeppost>[ \t]*\n)', re.MULTILINE)
- re_variable = re.compile(r'^(?P<keeppre>\%define[ \t]+'+ re.escape(search_for) + r'[ \t]+(?P<definition>[^\n]+?))(?P<keeppost>[ \t]*\n)', re.MULTILINE)
+ re_spec = re.compile(
+ r'^(?P<keeppre>' + re.escape(search_for_ignore_case) + r'[ \t]*:[ \t]*)(?:\%' +
+ re.escape(search_for) + r'|\%\{' + re.escape(search_for) +
+ r'\})(?P<keeppost>[ \t]*\n)', re.MULTILINE
+ )
+ re_variable = re.compile(
+ r'^(?P<keeppre>\%define[ \t]+' + re.escape(search_for) +
+ r'[ \t]+(?P<definition>[^\n]+?))(?P<keeppost>[ \t]*\n)',
+ re.MULTILINE
+ )
match = re_variable.search(data)
if match and match.group('definition') and len(re_variable.findall(data)) == 1:
match2 = re_spec.search(data)
if match2:
- data, subs = re_spec.subn(r'\g<keeppre>' + match.group('definition').replace('\\', '\\\\') + r'\g<keeppost>', data)
+ data, subs = re_spec.subn(
+ r'\g<keeppre>' + match.group('definition').replace('\\', '\\\\') + r'\g<keeppost>',
+ data
+ )
if subs:
made_changes = True
data, subs = re_variable.subn('', data)
@@ -497,12 +630,24 @@ class SpecFile():
def _clean_spec_patches(self, made_changes, data):
re_autopatch = re.compile(r'^[ \t]*\%autopatch(?:[ \t]+-p(?P<strip>[0-9]+))?$', re.MULTILINE)
- re_patch_header = re.compile('^Patch(?P<nr>[0-9]*)[ \t]*:[ \t]*(?P<filename>[^\n]+)\n', re.MULTILINE + re.IGNORECASE)
+ re_patch_header = re.compile(
+ '^Patch(?P<nr>[0-9]*)[ \t]*:[ \t]*(?P<filename>[^\n]+)\n',
+ re.MULTILINE + re.IGNORECASE
+ )
re_patch_any = re.compile(r'^[ \t]*\%patch(?P<nr>[0-9]*)', re.MULTILINE)
- re_patch_valid = re.compile(r'^[ \t+]*\%patch(?P<nr>[0-9]*)(?:[ \t]+-p(?P<strip>[0-9]+))?(?:[ \t]+-b[ \t]+\S+)?$\n?', re.MULTILINE)
- re_prep_patches = re.compile(r'^\%setup[^\n]+$(?:' + re_patch_valid.pattern + r'|^#[^%\n]+\n|^[ \t]*(?:%{_bindir}/|%_bindir)?autoreconf[ \t][^\n]+$|\s)+\n\%build', re.MULTILINE)
-
- give_patchnr = lambda match: (match.group('nr') if len(match.group('nr')) == 1 else match.group('nr').lstrip('0')) if match.group('nr') else "0"
+ re_patch_valid = re.compile(
+ r'^[ \t+]*\%patch(?P<nr>[0-9]*)(?:[ \t]+-p(?P<strip>[0-9]+))?(?:[ \t]+-b[ \t]+\S+)?$\n?',
+ re.MULTILINE
+ )
+ re_prep_patches = re.compile(
+ r'^\%setup[^\n]+$(?:' + re_patch_valid.pattern +
+ r'|^#[^%\n]+\n|^[ \t]*(?:%{_bindir}/|%_bindir)?autoreconf[ \t][^\n]+$|\s)+\n\%build',
+ re.MULTILINE
+ )
+
+ give_patchnr = lambda match: (
+ match.group('nr') if len(match.group('nr')) == 1 else match.group('nr').lstrip('0')
+ ) if match.group('nr') else "0"
# Make use of %apply_patches
@@ -518,27 +663,37 @@ class SpecFile():
print("NOTICE: More than 5 patches, skipping package", file=sys.stderr)
return made_changes, data
- if self.uses_apply_patches:
+ if self.uses_autopatch:
return made_changes, data
# XXX -- apparently this is really inefficient with e.g. apache
match2 = re_prep_patches.search(data)
patch_nrs_header = set((give_patchnr(match) for match in re_patch_header.finditer(data)))
patch_nrs_any = set((give_patchnr(match) for match in re_patch_any.finditer(data)))
- patch_nrs_valid = set((give_patchnr(match) for match in re_patch_valid.finditer(match2.group(0)))) if match2 else set()
+ patch_nrs_valid = set(
+ (give_patchnr(match) for match in re_patch_valid.finditer(match2.group(0)))
+ ) if match2 else set()
if not patch_nrs_header:
# XXX -- weird, self.patches should've returned 0 already
return made_changes, data
if not patch_nrs_header == patch_nrs_any == patch_nrs_valid:
- print("NOTICE: Unable to automatically convert %s patches into %%autopatch (header/patch/valid: %s, %s, %s)" % (self.module, len(patch_nrs_header), len(patch_nrs_any), len(patch_nrs_valid)), file=sys.stderr)
+ print("NOTICE: Unable to automatically convert %s patches into %%autopatch "
+ "(header/patch/valid: %s, %s, %s)" % (self.module, len(patch_nrs_header), len(patch_nrs_any),
+ len(patch_nrs_valid)),
+ file=sys.stderr \
+ )
return made_changes, data
- patch_flags = set((0 if match.group('strip') is None else match.group('strip') for match in re_patch_valid.finditer(match2.group(0))))
+ patch_flags = set((
+ 0 if match.group('strip') is None else match.group('strip')
+ for match in re_patch_valid.finditer(match2.group(0))
+ ))
if len(patch_flags) != 1:
- print("NOTICE: Unable to automatically convert patches into as different -p / strip levels used", file=sys.stderr)
+ print("NOTICE: Unable to automatically convert spec file to use autopatch as"
+ "different -p / strip levels are used", file=sys.stderr)
return made_changes, data
# Whoot, we can convert!!
@@ -571,6 +726,10 @@ class SpecFile():
@property
def buildrequires(self):
+ """Get the BuildRequires of this spec file
+
+ Parses the spec file to do this, so any macros are expanded"""
+
rpm.delMacro("_topdir")
rpm.addMacro("_topdir", os.path.join(self.cwd, '..'))
trans_set = rpm.ts()
@@ -606,7 +765,8 @@ class SpecFile():
return buildreqs
@property
- def uses_apply_patches(self):
+ def uses_autopatch(self):
+ """Check if autopatch (or similar) is used"""
return subprocess.call(['grep', '-Eq', '^%(apply_patches|autopatch|autosetup)', '--', self.path]) == 0
def _revert_changes(self):
@@ -621,11 +781,14 @@ class SpecFile():
if patchnr == 0:
nrs.append('')
- with open(self.path, "r", encoding="utf-8") as f:
- data = f.read()
-
- data, subs = self.re_update_patch.subn(lambda match: '' if match.group('nr') in nrs or (match.group('nr').isdigit() and int(match.group('nr')) in nrs) else match.group(0), data)
+ with open(self.path, "r", encoding="utf-8") as fp_spec:
+ data = fp_spec.read()
+ data, subs = self.re_update_patch.subn(
+ lambda match: '' if match.group('nr') in nrs or (match.group('nr').isdigit()
+ and int(match.group('nr')) in nrs)
+ else match.group(0), data
+ )
if not subs:
print("ERROR: Could not remove patch nr %s!" % patchnr, file=sys.stderr)
return False
@@ -649,7 +812,7 @@ class SpecFile():
initial_patches = self.patches
patches = initial_patches
- uses_apply_patches = self.uses_apply_patches if patches else False
+ uses_autopatch = self.uses_autopatch if patches else False
while True:
try:
@@ -665,8 +828,8 @@ class SpecFile():
# Determine the last command that failed
if os.path.exists(logfile):
print(logfile)
- with open(logfile, "r", encoding="utf-8") as f:
- for line in line_input(f):
+ with open(logfile, "r", encoding="utf-8") as fp_logfile:
+ for line in line_input(fp_logfile):
if line.startswith('+ '):
cmd_before = (cmd, cmd_before)
cmd = line[2:]
@@ -677,14 +840,14 @@ class SpecFile():
cmd_parsed = shlex.split(cmd) if cmd else []
cmd_before_parsed = shlex.split(cmd_before[0]) if cmd_before[0] else []
- if not check_only and uses_apply_patches and patches and cmd_parsed:
+ if not check_only and uses_autopatch and patches and cmd_parsed:
if os.path.basename(cmd_parsed[0]) in ('patch', 'cat'):
if os.path.exists(cmd_parsed[-1]):
failed_patch = os.path.basename(cmd_parsed[-1])
elif cmd_parsed[-1].startswith('-') and os.path.exists(cmd_before_parsed[-1]):
- # for %autopatch as well as %patch
- #+ /usr/bin/cat /home/src/pkgs/gnome-getting-started-docs/SOURCES/gs-browse-web-firefox.page.patch
- #+ /usr/bin/patch -p1 -s
+# for %autopatch as well as %patch
+#+ /usr/bin/cat /home/src/pkgs/gnome-getting-started-docs/SOURCES/gs-browse-web-firefox.page.patch
+#+ /usr/bin/patch -p1 -s
failed_patch = os.path.basename(cmd_before_parsed[-1])
# Patch is merged if there is at least one 'ignored' line and no 'FAILED' line anywhere
@@ -746,23 +909,35 @@ class SpecFile():
# XXX - doesn't handle buildrequires with version numbers :-(
made_changes = False
- with open(self.path, "r", encoding="utf-8") as f:
- data = f.read()
+ with open(self.path, "r", encoding="utf-8") as fp_spec:
+ data = fp_spec.read()
# Change any "," in buildrequires into multiple lines
- data, subs = self.re_update_br_unsplit.subn(lambda match: ''.join((''.join((match.group('pre'), match2.group(0), match.group('unsplitpost'))) for match2 in self.re_br_part.finditer(match.group('unsplit')) if match.group(0).strip() != '')), data)
+ data, subs = self.re_update_br_unsplit.subn(
+ lambda match: ''.join((''.join((match.group('pre'), match2.group(0), match.group('unsplitpost')))
+ for match2 in self.re_br_part.finditer(match.group('unsplit'))
+ if match.group(0).strip() != '')),
+ data
+ )
if subs:
made_changes = True
self._changes['SILENT one line per buildrequirement'] = True
# Change =< and => operators into <= and >=
- data, subs = self.re_update_br_fix_operator.subn(lambda match: match.group(0).replace('=>', '>=').replace('=<', '<') if self.re_update_br.match(match.group(0).replace('=>', '>=').replace('=<', '<')) else match.group(0), data)
+ data, subs = self.re_update_br_fix_operator.subn(
+ lambda match: match.group(0).replace('=>', '>=').replace('=<', '<')
+ if self.re_update_br.match(match.group(0).replace('=>', '>=').replace('=<', '<'))
+ else match.group(0), data
+ )
if subs:
made_changes = True
self._changes['SILENT fix operator in buildrequires'] = True
# Now update buildrequires if any
- data, subs = self.re_update_br.subn(lambda match: ''.join((match.group('pre'), changes[match.group('br')], match.group('post'))) if match.group('br') in changes else match.group(0), data)
+ data, subs = self.re_update_br.subn(
+ lambda match: ''.join((match.group('pre'), changes[match.group('br')], match.group('post')))
+ if match.group('br') in changes else match.group(0), data
+ )
if subs:
made_changes = True
@@ -782,8 +957,14 @@ class SpecFile():
MAX_JUDGEMENT = 5
def ensure_no_local_changes(self, force=False):
+ """Check if the repository has any local changes
+
+ Can optionally force a clean checkout (by reverting any local
+ changes). This should possibily be moved to Downstream class, or move
+ this into a new Package class"""
# XXX - os.path.join is hackish
- svn_diff_output = subprocess.check_output(["svn", "diff", os.path.normpath(os.path.join(self.cwd, '..'))]).decode('utf-8')
+ cmd = ["svn", "diff", os.path.normpath(os.path.join(self.cwd, '..'))]
+ svn_diff_output = subprocess.check_output(cmd).decode('utf-8')
if svn_diff_output != '':
print(svn_diff_output)
print("ERROR: Package has uncommitted changes!", file=sys.stderr)
@@ -804,8 +985,8 @@ class SpecFile():
if not self.ensure_no_local_changes(force):
return None
- with open(self.path, "r", encoding="utf-8") as f:
- data = f.read()
+ with open(self.path, "r", encoding="utf-8") as fp_spec:
+ data = fp_spec.read()
if data.count("%subrel") != 0:
print("ERROR: %subrel found; don't know what to do!", file=sys.stderr)
@@ -916,29 +1097,35 @@ class Patch():
def __str__(self):
return self.path if self.show_path else os.path.basename(self.path)
- @property
+ @cached_property
def svn_author(self):
- if not hasattr(self, '_svn_author'):
- try:
- contents = subprocess.check_output(['svn', 'log', '-q', "--", self.path], close_fds=True).strip("\n").decode('utf-8').splitlines()
+ """Return the svn author of this patch
- for line in contents:
- if ' | ' not in line:
- continue
+ Makes use of svn log."""
+ try:
+ cmd = ['svn', 'log', '-q', "--", self.path]
+ contents = subprocess.check_output(cmd, close_fds=True).strip("\n").decode('utf-8').splitlines()
- fields = line.split(' | ')
- if len(fields) >= 3:
- self._svn_author = fields[1]
- except subprocess.CalledProcessError:
- pass
+ for line in contents:
+ if ' | ' not in line:
+ continue
- if not hasattr(self, '_svn_author'):
- return None
+ fields = line.split(' | ')
+ if len(fields) >= 3:
+ return fields[1]
+ except subprocess.CalledProcessError:
+ pass
- return self._svn_author
+ return None
class Upstream():
+ """Class handling anything related to upstream (meaning: GNOME)
+
+ For now this is limited to:
+ - finding the module names
+ - finding latest version of a module"""
+
URL = "https://download.gnome.org/sources/"
limit = None
@@ -965,6 +1152,7 @@ class Upstream():
@classmethod
@lru_cache(maxsize=4096)
def versions(cls, module):
+ """Return the possible versions for a given module"""
versions = None
url = '%s%s/cache.json' % (cls.URL, module)
@@ -976,7 +1164,13 @@ class Upstream():
return versions
class Downstream():
- re_file = re.compile(r'^(?P<module>.*)[_-](?:(?P<oldversion>([0-9]+[\.])*[0-9]+)-)?(?P<version>([0-9]+[\.\-])*[0-9]+)\.(?P<format>(?:tar\.|diff\.)?[a-z][a-z0-9]*)$')
+ """Class handling anything related to downstream (meaning: Mageia)"""
+
+
+ re_file = re.compile(
+ r'^(?P<module>.*)[_-](?:(?P<oldversion>([0-9]+[\.])*[0-9]+)-)?(?P<version>([0-9]+[\.\-])*[0-9]+)' \
+ r'\.(?P<format>(?:tar\.|diff\.)?[a-z][a-z0-9]*)$'
+ )
MEDIA = "Core Release Source"
# PKGROOT will be overwritten (command line option)
@@ -985,13 +1179,14 @@ class Downstream():
SECTION = None
def __init__(self):
- contents = subprocess.check_output(['urpmf', '--qf', '%name|%version|%files', '.', "--media", self.MEDIA], close_fds=True).decode("utf-8").strip("\n").splitlines()
+ cmd = ['urpmf', '--qf', '%name|%version|%files', '.', "--media", self.MEDIA]
+ contents = subprocess.check_output(cmd, close_fds=True).decode("utf-8").strip("\n").splitlines()
srpm_files = {}
module_srpm_tarballs = {}
packages = set()
- for line in contents:
+ for line in contents:
try:
srpm, version, filename = line.split("|")
except SpecFileError:
@@ -1026,6 +1221,7 @@ class Downstream():
@property
def packages(self):
+ """Return all downstream package names"""
return sorted(self._packages)
_provide_to_alternate = {}
@@ -1044,7 +1240,8 @@ class Downstream():
if not cls._provide_to_alternate:
_provide_to_pkg = {}
_pkg_to_provide = {}
- for myline in subprocess.check_output(['urpmf', "--qf", "%name\t%provides\t%arch", '.']).decode("utf-8").splitlines():
+ cmd = ['urpmf', "--qf", "%name\t%provides\t%arch", '.']
+ for myline in subprocess.check_output(cmd).decode("utf-8").splitlines():
pkgname, pkgprovide, pkgarch = myline.split("\t")
if pkgarch in ('src', 'i586'):
continue
@@ -1100,10 +1297,14 @@ class Downstream():
@classmethod
def package_path(cls, package):
+ """Provide the local checkout path for a given package
+
+ Package might not be checked out yet!"""
return os.path.join(os.path.expanduser(Downstream.PKGROOT), package)
@classmethod
def package_spec(cls, package):
+ """Return the SpecFile for a given package"""
path = cls.package_path(package)
return SpecFile(os.path.join(path, "SPECS", "%s.spec" % package), module=package)
@@ -1111,7 +1312,8 @@ class Downstream():
@classmethod
@retry(subprocess.CalledProcessError)
- def co(cls, package, cwd=None, spec_only=False):
+ def checkout(cls, package, cwd=None, spec_only=False):
+ """Check out a package from the repository"""
if cwd is None:
cwd = os.path.expanduser(cls.PKGROOT)
@@ -1125,7 +1327,9 @@ class Downstream():
@classmethod
@retry(subprocess.CalledProcessError)
- def ci(cls, package, changes, cwd=None):
+ def checkin(cls, package, changes, cwd=None):
+ """Check in changes to the repository"""
+
if cwd is None:
cwd = cls.package_path(package)
@@ -1134,6 +1338,10 @@ class Downstream():
@classmethod
def submit(cls, package, cwd=None):
+ """Submit a package to the buildsystem
+
+ If a specific distro release is chosen, the section will be set to
+ core/updates_testing."""
if cwd is None:
cwd = cls.package_path(package)
@@ -1151,6 +1359,13 @@ class Downstream():
def get_downstream_from_upstream(self, upstream, version):
+ """Provide the downstream package(s) for a given upstream module name
+ and version
+
+ This will raise a ValueError exception in case a good match cannot be
+ found"""
+
+
if upstream not in self.tarballs:
raise ValueError("No packages for upstream name: %s" % upstream)
@@ -1161,7 +1376,7 @@ class Downstream():
for package in list(self.tarballs[upstream].keys()):
# Checkout package to ensure the checkout reflects the latest changes
try:
- self.co(package)
+ self.checkout(package)
except subprocess.CalledProcessError:
raise ValueError("Multiple packages found and cannot checkout %s" % package)
@@ -1188,7 +1403,9 @@ class Downstream():
# ensure it follows get_safe_max_version
if latest_version != latest_possible_version and version_cmp(get_safe_max_version(latest_version, upstream), \
version) != 1:
- raise ValueError("Multiple packages found and unsafe version increase: %s (%s => %s)" % (upstream, latest_version, version))
+ raise ValueError("Multiple packages found and unsafe version increase: %s (%s => %s)" % (
+ upstream, latest_version, version) \
+ )
# - now really get the right packages
matches = [package for package in packages if packages[package] == latest_version]
@@ -1199,22 +1416,26 @@ class Downstream():
raise ValueError("Multiple packages found and cannot determine package for version %s" % version)
def write_file(path, data):
+ """Write to a file by creating a temporary file and renaming that to the
+ new file"""
+
with tempfile.NamedTemporaryFile(mode='w+t', dir=os.path.dirname(path), delete=False, encoding="utf-8") as fdst:
fdst.write(data)
fdst.flush()
os.rename(fdst.name, path)
-def cmd_co_multi(args):
+def _cmd_checkout_multi(args):
package, what_to_print, options = args
print(what_to_print)
try:
- Downstream.co(package, spec_only=options.spec_only)
+ Downstream.checkout(package, spec_only=options.spec_only)
except subprocess.CalledProcessError:
pass
-def cmd_co(options):
+def cmd_checkout(options):
+ """Check out various packages in parallel"""
if options.all:
packages = ((package, package, options) for package in Downstream().packages)
elif options.package:
@@ -1224,12 +1445,20 @@ def cmd_co(options):
if options.debug:
for package in packages:
- cmd_co_multi(package)
+ _cmd_checkout_multi(package)
else:
with concurrent.futures.ProcessPoolExecutor(max_workers=8) as executor:
- executor.map(cmd_co_multi, packages)
+ executor.map(_cmd_checkout_multi, packages)
def join_streams(show_version=False, only_diff_version=False, auto_update=True):
+ """Links upstream modules with downstream packages
+
+ To figure out the downstream name of an upstream package, the Downstream
+ class has logic to extract the name from a tarball file.
+
+ If information is requested whereby the spec file is needed this function
+ will automatically checkout any package"""
+
upstream = Upstream().names
downstream = Downstream()
@@ -1244,7 +1473,7 @@ def join_streams(show_version=False, only_diff_version=False, auto_update=True):
# ensure package is checked out
if not os.path.exists(cwd):
try:
- downstream.co(package)
+ downstream.checkout(package)
except subprocess.CalledProcessError:
# XXX - ignoring packages which cannot be checked out
continue
@@ -1256,7 +1485,7 @@ def join_streams(show_version=False, only_diff_version=False, auto_update=True):
# in case upstream version is newer, update checkout
if auto_update and package_version != spec_version and version_cmp(package_version, spec_version) == 1:
try:
- downstream.co(package)
+ downstream.checkout(package)
spec_version = downstream.package_spec(package).version
except subprocess.CalledProcessError:
pass
@@ -1267,9 +1496,13 @@ def join_streams(show_version=False, only_diff_version=False, auto_update=True):
yield (package, module, package_version, spec_version, downstream.files[package])
def cmd_group_owner(options):
+ """Show the packages of a rpm group"""
+
+
groups = set(options.group)
- output = [pkg.split("\t") for pkg in subprocess.check_output(["urpmf", "-F|", "--qf", "%group\t%name\t%sourcerpm\t%version\t%release", "."]).decode("utf-8").splitlines()]
+ cmd = ["urpmf", "-F|", "--qf", "%group\t%name\t%sourcerpm\t%version\t%release", "."]
+ output = [pkg.split("\t") for pkg in subprocess.check_output(cmd).decode("utf-8").splitlines()]
if not output:
return
@@ -1284,12 +1517,9 @@ def cmd_group_owner(options):
packages[group] = {}
source = sourcerpm if sourcerpm else name
- end = ".src.rpm"
- if source.endswith(end):
- source = source[:len(source) - len(end)]
- end = "-%s-%s" %(version, release)
- if source.endswith(end):
- source = source[:len(source) - len(end)]
+ for end in (".src.rpm", "-%s-%s" % (version, release)):
+ if source.endswith(end):
+ source = source[:len(source) - len(end)]
if source not in packages[group]:
packages[group][source] = set()
@@ -1297,7 +1527,10 @@ def cmd_group_owner(options):
packages[group][source].add(name)
- maints = {line.rpartition(" ")[::2] for line in subprocess.check_output(["mgarepo", "maintdb", "get"]).decode("utf-8").splitlines()}
+ maints = {
+ line.rpartition(" ")[::2]
+ for line in subprocess.check_output(["mgarepo", "maintdb", "get"]).decode("utf-8").splitlines()
+ }
def get_output(source, maints, packages):
for package in list(packages.keys()):
@@ -1319,6 +1552,16 @@ def cmd_group_owner(options):
print(line)
def cmd_cleanup(_):
+ """Clean up the package root
+
+ Removes things such as:
+ - unneeded files in SOURCES (e.g. old tarballs)
+
+ In future will also:
+ - clean old directories in BUILDDIR
+ - clean old files in RPMS and SRPMS"""
+
+
root = os.path.expanduser(Downstream.PKGROOT)
# packages = set(Downstream().packages)
@@ -1327,20 +1570,23 @@ def cmd_cleanup(_):
# dirs = dirs - packages
- import pysvn
+ import pysvn # pylint: disable=import-outside-toplevel
dirs = [o for o in dirs if os.path.exists(os.path.join(root, o, "SOURCES", 'sha1.lst'))]
for path in dirs:
try:
- binaries = set((l.split(' ', 1)[1] for l in open(os.path.join(root, path, 'SOURCES', 'sha1.lst')).read().splitlines()))
+ binaries = set((l.split(' ', 1)[1]
+ for l in open(os.path.join(root, path, 'SOURCES', 'sha1.lst')).read().splitlines()))
except IndexError:
print(os.path.join(root, path, 'SOURCES', 'sha1.lst'))
# shutil.rmtree(os.path.join(root, path))
-# Downstream.co(path)
+# Downstream.checkout(path)
continue
vcs = pysvn.Client()
- stats = [stat for stat in vcs.status(os.path.join(root, path, 'SOURCES'), depth=pysvn.depth.immediates) if stat.text_status == pysvn.wc_status_kind.unversioned and os.path.basename(stat.path) not in binaries]
+ stats = [stat for stat in vcs.status(os.path.join(root, path, 'SOURCES'), depth=pysvn.depth.immediates) # pylint: disable=no-member
+ if stat.text_status == pysvn.wc_status_kind.unversioned # pylint: disable=no-member
+ and os.path.basename(stat.path) not in binaries] # pylint: disable=no-member
if stats:
print(path)
@@ -1353,6 +1599,10 @@ def cmd_cleanup(_):
shutil.rmtree(stat.path)
def cmd_ls(options):
+ """Show upstream module names, downstream package names
+
+ Optionally can even show version numbers"""
+
streams = join_streams(show_version=options.show_version, only_diff_version=options.diff)
if options.sort:
# Sort packages on the line number in the file
@@ -1373,6 +1623,12 @@ def cmd_ls(options):
print()
def cmd_check_version(_):
+ """Check for version mismatches between what's available in the spec
+ version and as a source rpm.
+
+ Example usage: locally check for failed builds"""
+
+
streams = join_streams(show_version=True)
for package, _, package_version, spec_version, _ in streams:
@@ -1384,6 +1640,8 @@ def cmd_check_version(_):
sys.stdout.write("\n")
def cmd_check_latest(options):
+ """Check if a package has a newer version upstream"""
+
streams = join_streams(show_version=True)
for package, module, package_version, spec_version, _ in streams:
@@ -1425,20 +1683,24 @@ def cmd_check_latest(options):
subprocess.call(cmd, cwd=Downstream.package_path(package))
def cmd_patches(options):
+ """List files with extension .patch or .diff as found in the source rpms"""
root = os.path.expanduser(Downstream.PKGROOT)
for package, module, _, _, downstream_files in sorted(join_streams()):
for filename in downstream_files:
if '.patch' in filename or '.diff' in filename:
- p = Patch(os.path.join(root, package, "SOURCES", filename), show_path=options.path)
- print("\t".join((module, package, str(p))))
+ this_patch = Patch(os.path.join(root, package, "SOURCES", filename), show_path=options.path)
+ print("\t".join((module, package, str(this_patch))))
def cmd_check_prep(options):
+ """Check if the %prep stage can be ran sucessfully
+
+ This runs the %prep stage without dependencies"""
spec = Downstream.package_spec(options.package)
spec.check_and_update_patches()
-def cmd_clean_spec_multi(args):
+def _cmd_clean_spec_multi(args):
options, package = args
print(package)
@@ -1447,7 +1709,7 @@ def cmd_clean_spec_multi(args):
path = os.path.join(cwd, "SPECS", "%s.spec" % package)
if not os.path.exists(path):
try:
- Downstream.co(package)
+ Downstream.checkout(package)
except subprocess.CalledProcessError:
print('WARNING: Cannot check package %s. Skipping.' % package, file=sys.stderr)
return False
@@ -1479,12 +1741,17 @@ def cmd_clean_spec_multi(args):
'check_br': lambda req: req.endswith('-devel'),
'check_provide': lambda prov: prov.startswith('pkgconfig('),
'basereqs': lambda req: [req[:-len('-devel')]],
- 'basereq_no_version': lambda basereqs: [basereq.rstrip('1234567890.') for basereq in basereqs if basereq[-1] in '1234567890'],
- 'versions_from_basereq': lambda basereqs: set((basereq[len(basereq.rstrip('01234567890.')):] for basereq in basereqs if basereq[-1] in '1234567890')),
- 'versions_basereq_extra': lambda versions: set(("%s.0" % version for version in versions if '.' not in version)),
+ 'basereq_no_version': lambda basereqs: [basereq.rstrip('1234567890.') for basereq in basereqs
+ if basereq[-1] in '1234567890'],
+ 'versions_from_basereq': lambda basereqs: set((basereq[len(basereq.rstrip('01234567890.')):]
+ for basereq in basereqs if basereq[-1] in '1234567890')),
+ 'versions_basereq_extra': lambda versions: set(("%s.0" % version for version in versions
+ if '.' not in version)),
'extra': lambda basereqs, versions: \
['pkgconfig(%s)' % basereq for basereq in basereqs] +
- ['pkgconfig(%s)' % basereq[len('lib'):] if basereq.startswith('lib') else 'pkgconfig(lib%s)' % basereq for basereq in basereqs] +
+ ['pkgconfig(%s)' % basereq[len('lib'):]
+ if basereq.startswith('lib') else 'pkgconfig(lib%s)' % basereq
+ for basereq in basereqs] +
['pkgconfig(%s-%s)' % (basereq, version) for basereq in basereqs for version in versions],
},
'perl': {
@@ -1505,14 +1772,14 @@ def cmd_clean_spec_multi(args):
'python-pkg': {
'disabled': True,
'desc': 'convert python buildrequires into python3dist()',
- 'check_br': lambda req: req.startswith('python3-'),
+ 'check_br': lambda req: req.startswith('python3-'),
'check_provide': lambda prov: prov.startswith('python3dist('),
'basereqs': lambda req: [req[len('python3-'):]],
'extra': lambda basereqs, versions: ['python3dist(%s)' % basereq for basereq in basereqs],
},
'python-egg': {
'desc': 'convert pythonegg(3) into python3dist()',
- 'check_br': lambda req: req.startswith('pythonegg(3)(') and req.endswith(')'),
+ 'check_br': lambda req: req.startswith('pythonegg(3)(') and req.endswith(')'),
'check_provide': lambda prov: prov.startswith('python3dist('),
'basereqs': lambda req: [req[len('pythonegg(3)('):-1]],
'extra': lambda basereqs, versions: ['python3dist(%s)' % basereq for basereq in basereqs],
@@ -1531,8 +1798,12 @@ def cmd_clean_spec_multi(args):
every_provides, every_ignored_provide = Downstream.alternative_provides(req)
# XXX - document what clean_pkgconfig_prov is for
# maybe integrate clean_pkgconfig_prov in alternative_provides function?
- provides = [clean_pkgconfig_prov(prov) for prov in every_provides if keys['check_provide'](prov)]
- provides_ignored = [clean_pkgconfig_prov(prov) for prov in every_ignored_provide if keys['check_provide'](prov)]
+ provides = [clean_pkgconfig_prov(prov)
+ for prov in every_provides
+ if keys['check_provide'](prov)]
+ provides_ignored = [clean_pkgconfig_prov(prov)
+ for prov in every_ignored_provide
+ if keys['check_provide'](prov)]
change_to = None
if len(provides) == 1 and not provides_ignored:
if options.debug:
@@ -1568,7 +1839,8 @@ def cmd_clean_spec_multi(args):
for prov in provides:
for match in re_prov_get_version.finditer(prov):
if options.debug:
- print("NOTICE: Heuristically adding version %s from provide %s" % (match.group('version'), prov))
+ print("NOTICE: Heuristically adding version %s from provide %s" \
+ % (match.group('version'), prov))
versions.add(match.group('version'))
check_for = keys['extra'](basereqs, versions)
@@ -1633,7 +1905,7 @@ def cmd_clean_spec_multi(args):
# If we made it this far, checkin the changes
if made_changes:
if options.doit:
- Downstream.ci(package, spec.changes, cwd=cwd)
+ Downstream.checkin(package, spec.changes, cwd=cwd)
if spec.should_rebuild:
cmd = ['mgagnome', 'rebuild', '-s', '-m', 'to test removal of deprecated macros', package]
subprocess.call(cmd, cwd=cwd)
@@ -1646,7 +1918,7 @@ def cmd_clean_spec_multi(args):
return made_changes
-def cmd_check_spec_multi(args):
+def _cmd_check_spec_multi(args):
_, package = args
cwd = Downstream.package_path(package)
@@ -1666,6 +1938,7 @@ def cmd_check_spec_multi(args):
def cmd_check_spec(options):
+ """Check if the spec files can be parsed by rpm"""
if options.all:
packages = Downstream().packages
else:
@@ -1674,15 +1947,21 @@ def cmd_check_spec(options):
if options.debug:
for package in packages:
- cmd_check_spec_multi((options, package))
+ _cmd_check_spec_multi((options, package))
else:
workers = os.cpu_count() or 4
with concurrent.futures.ThreadPoolExecutor(max_workers=workers) as executor:
- executor.map(cmd_check_spec_multi, ((options, package) for package in packages))
+ executor.map(_cmd_check_spec_multi, ((options, package) for package in packages))
def cmd_clean_spec(options):
+ """Clean spec files
+
+ Updates spec files to remove known deprecated statements from spec files
+
+ Can optionally also change the BuildRequires"""
+
if options.all:
packages = Downstream().packages
else:
@@ -1691,16 +1970,20 @@ def cmd_clean_spec(options):
if options.debug:
for package in packages:
- cmd_clean_spec_multi((options, package))
+ _cmd_clean_spec_multi((options, package))
else:
workers = os.cpu_count() or 4
# Hack: warm alternative provides cache
if options.convert_br:
Downstream.alternative_provides('XXXX')
with concurrent.futures.ProcessPoolExecutor(max_workers=workers) as executor:
- executor.map(cmd_clean_spec_multi, ((options, package) for package in packages))
+ executor.map(_cmd_clean_spec_multi, ((options, package) for package in packages))
def cmd_new_release(options):
+ """Increase the release of a package (source rpm) and submit that to the buildsystem
+
+ Also called a rebuild"""
+
success = True
for pkg in options.package:
# Determine the package name
@@ -1718,7 +2001,7 @@ def cmd_new_release(options):
# Checkout package to ensure the checkout reflects the latest changes
try:
- Downstream.co(package)
+ Downstream.checkout(package)
except subprocess.CalledProcessError:
subprocess.call(['svn', 'revert', '-R', cwd], cwd=cwd)
success = False
@@ -1749,7 +2032,7 @@ def cmd_new_release(options):
try:
# If we made it this far, checkin the changes
- Downstream.ci(package, spec.changes, cwd=cwd)
+ Downstream.checkin(package, spec.changes, cwd=cwd)
# Submit is optional
if options.submit:
@@ -1762,6 +2045,10 @@ def cmd_new_release(options):
sys.exit(1)
def cmd_package_new_version(options):
+ """Increase the version number of a package (source rpm)
+
+ Can optionally submit the package to the buildsystem."""
+
# Determine the package name
if options.upstream:
try:
@@ -1777,7 +2064,7 @@ def cmd_package_new_version(options):
# Checkout package to ensure the checkout reflects the latest changes
try:
- Downstream.co(package)
+ Downstream.checkout(package)
except subprocess.CalledProcessError:
subprocess.call(['svn', 'revert', '-R', cwd], cwd=cwd)
sys.exit(1)
@@ -1813,7 +2100,7 @@ def cmd_package_new_version(options):
for filename in sources:
path = os.path.join(cwd, "SOURCES", filename)
- if not is_valid_hash(path, options.algo, options.hexdigest):
+ if not _is_valid_hash(path, options.algo, options.hexdigest):
print("ERROR: Hash file failed check for %s!" % path, file=sys.stderr)
print("ERROR: Reverting changes!", file=sys.stderr)
subprocess.call(['svn', 'revert', '-R', cwd], cwd=cwd)
@@ -1821,7 +2108,7 @@ def cmd_package_new_version(options):
try:
# If we made it this far, checkin the changes
- Downstream.ci(package, spec.changes, cwd=cwd)
+ Downstream.checkin(package, spec.changes, cwd=cwd)
# Submit is optional
if options.submit:
@@ -1831,6 +2118,10 @@ def cmd_package_new_version(options):
sys.exit(1)
def cmd_parse_ftp_release_list(options):
+ """Submit packages by parsing the GNOME ftp-release-list email
+
+ """
+
def _send_reply_mail(contents, orig_msg, to_addr, packages=None, error=False):
"""Send an reply email"""
contents.seek(0)
@@ -1861,11 +2152,11 @@ def cmd_parse_ftp_release_list(options):
# Call sendmail program directly so it doesn't matter if the service is running
cmd = ['/usr/sbin/sendmail', '-oi', '--']
cmd.extend([to_addr])
- p = subprocess.Popen(cmd, stdin=subprocess.PIPE)
- p.stdin.write(msg.as_bytes())
- p.stdin.flush()
- p.stdin.close()
- p.wait()
+ proc = subprocess.Popen(cmd, stdin=subprocess.PIPE)
+ proc.stdin.write(msg.as_bytes())
+ proc.stdin.flush()
+ proc.stdin.close()
+ proc.wait()
msg = email.message_from_file(sys.stdin)
@@ -1930,6 +2221,11 @@ def cmd_parse_ftp_release_list(options):
_send_reply_mail(stdout, msg, options.mail, packages=packages, error=error)
def main():
+ """Parse arguments and call main subfunction
+
+ The Subfunctions are the functions whose name starts with cmd_"""
+
+
description = """Mageia GNOME commands."""
epilog = """Report bugs to Olav Vitters"""
parser = argparse.ArgumentParser(description=description, epilog=epilog)
@@ -1998,10 +2294,11 @@ def main():
help="only checkout SPECS/ directory")
subparser.add_argument("package", help="Package name", nargs='*')
subparser.set_defaults(
- func=cmd_co, all=False
+ func=cmd_checkout, all=False
)
- subparser = subparsers.add_parser('gnome-release-email', help='submit packages based on GNOME ftp-release-list email')
+ subparser = subparsers.add_parser('gnome-release-email',
+ help='submit packages based on GNOME ftp-release-list email')
subparser.add_argument("-m", "--mail", help="Email address to send the progress to")
subparser.add_argument("--fork", action="store_true",
help="Fork as quickly as possible")
@@ -2094,7 +2391,8 @@ def main():
Downstream.PKGROOT = options.PKGROOT
if options.distro:
Downstream.PKGROOT = os.path.join(options.PKGROOT, options.distro)
- Downstream.MEDIA = "Core Release {0} Source,Core {0} Updates Source,Core {0} Updates Testing Source".format(options.distro)
+ Downstream.MEDIA = "Core Release {0} Source,Core {0} Updates Source," \
+ "Core {0} Updates Testing Source".format(options.distro)
Downstream.DISTRO = options.distro
try: