Implement simple logging; ensure rust2rpm --stdout still works

This commit is contained in:
Fabio Valentini 2022-07-24 11:21:30 +02:00
parent a090caaa62
commit 67c878e32a
No known key found for this signature in database
GPG key ID: 5AC5F572E5D410AF
6 changed files with 81 additions and 51 deletions

View file

@ -1,4 +1,5 @@
jinja2 jinja2
pyparsing pyparsing
requests requests
termcolor
tqdm tqdm

View file

@ -18,7 +18,7 @@ import subprocess
import requests import requests
import tqdm import tqdm
from . import cfg, licensing, generator, util from . import cfg, licensing, generator, log, util
from .core.metadata import Metadata from .core.metadata import Metadata
XDG_CACHE_HOME = os.getenv("XDG_CACHE_HOME", os.path.expanduser("~/.cache")) XDG_CACHE_HOME = os.getenv("XDG_CACHE_HOME", os.path.expanduser("~/.cache"))
@ -114,11 +114,11 @@ def query_newest_version(crate):
for struct in versions: for struct in versions:
version = struct["num"] version = struct["num"]
if struct["yanked"]: if struct["yanked"]:
print(f'Ignoring yanked version {version}') log.info(f'Ignoring yanked version {version}')
elif re.search('alpha|beta|rc|pre', version): elif re.search('alpha|beta|rc|pre', version):
print(f'Ignoring pre-release version {version}') log.info(f'Ignoring pre-release version {version}')
else: else:
print(f'Found version {version}') log.success(f'Found version {version}')
return version return version
raise ValueError("Couldn't find any release versions. Specify a version explicitly.") raise ValueError("Couldn't find any release versions. Specify a version explicitly.")
@ -180,29 +180,24 @@ def drop_foreign_dependencies(lines):
value = True value = True
for line in lines: for line in lines:
# print(f'{line=}')
# [target.'cfg(not(any(target_os="windows", target_os="macos")))'.dependencies]
if m := TARGET_DEPENDENCY_LINE.match(line): if m := TARGET_DEPENDENCY_LINE.match(line):
expr = m.group('cfg') expr = m.group('cfg')
expr = ast.literal_eval(expr) expr = ast.literal_eval(expr)
# print(f'matched: {expr=}')
try: try:
value = cfg.parse_and_evaluate(expr) value = cfg.parse_and_evaluate(expr)
except (ValueError, cfg.ParseException): except (ValueError, cfg.ParseException):
print(f'Could not evaluate {expr!r}, treating as true') log.warn(f'Could not evaluate {expr!r}, treating as true')
value = True value = True
if not value: if not value:
feature = m.group('feature') feature = m.group('feature')
print(f'Skipping section {line.rstrip()} ({feature=})') log.info(f'Skipping section {line.rstrip()} ({feature=})')
dropped_features.add(feature) dropped_features.add(feature)
elif line.startswith('['): elif line.startswith('['):
# previous section ended, let's keep printing lines again # previous section ended, let's keep printing lines again
value = True value = True
# print(f'→ {value}')
if value: if value:
good_lines += [line] good_lines += [line]
else: else:
@ -349,7 +344,7 @@ def make_diff_metadata(args, crate, version):
diffs = make_patches(args, toml) diffs = make_patches(args, toml)
metadata = Metadata.from_file(toml) metadata = Metadata.from_file(toml)
if len(metadata) > 1: if len(metadata) > 1:
print(f"Warning: multiple metadata for {toml}") log.warn(f"More than one set of metadata found for {toml}, using the first one")
metadata = metadata[0] metadata = metadata[0]
return metadata.name, diffs, metadata, doc_files, license_files return metadata.name, diffs, metadata, doc_files, license_files
else: else:
@ -357,12 +352,12 @@ def make_diff_metadata(args, crate, version):
with files_from_crate(cratef, crate, version) as (toml, doc_files, license_files): with files_from_crate(cratef, crate, version) as (toml, doc_files, license_files):
if not license_files: if not license_files:
print(f"Warning: no license files detected in {crate}") log.warn(f"No license files detected in {crate}")
diffs = make_patches(args, toml) diffs = make_patches(args, toml)
metadata = Metadata.from_file(toml) metadata = Metadata.from_file(toml)
if len(metadata) > 1: if len(metadata) > 1:
print(f"Warning: multiple metadata for {toml}, ignoring everything except the first") log.warn(f"More than one set of metadata found for {toml}, using the first one")
metadata = metadata[0] metadata = metadata[0]
if args.store_crate: if args.store_crate:
shutil.copy2(cratef, os.path.join(os.getcwd(), f"{metadata.name}-{version}.crate")) shutil.copy2(cratef, os.path.join(os.getcwd(), f"{metadata.name}-{version}.crate"))
@ -403,30 +398,36 @@ def guess_crate_name():
dist-git directory, hence there'd be a spec file, so we can ignore this. dist-git directory, hence there'd be a spec file, so we can ignore this.
""" """
specs = glob.glob('*.spec') specs = glob.glob('*.spec')
if len(specs) > 1: if len(specs) > 1:
print('Multiple spec files found, cannot guess crate name') log.error(f"Found multiple spec files; unable to determine crate name automatically.")
return None return None
if len(specs) == 1: if len(specs) == 1:
crate = None crate = None
for line in open(specs[0]): spec = specs[0]
for line in open(spec):
if m := re.match(r'^%(?:global|define)\s+crate\s+(\S+)\s+', line): if m := re.match(r'^%(?:global|define)\s+crate\s+(\S+)\s+', line):
if crate: if crate:
print(f'{specs[0]}: Found duplicated %crate define, cannot guess crate name') log.error(f'Found multiple definitions of the %crate macro in {spec}; ' +
f'unable to determine crate name automatically.')
return None return None
crate = m.group(1) crate = m.group(1)
if '%' in crate: if '%' in crate:
print(f'{specs[0]}: Crate name appears to use a macro, and evaluation is not implemented') log.error(f'The value of the %crate macro appears to contain other macros and cannot be parsed.')
return None return None
if crate: if crate:
print(f'{specs[0]}: Found crate name {crate!r}') log.success(f'Found valid spec file {spec!r} for the {crate!r} crate.')
else: else:
print(f'{specs[0]}: %crate define not found, cannot guess crate name') log.error(f'Invalid spec file {spec!r}; unable to determine crate name automatically.')
return crate return crate
dirname = os.path.basename(os.getcwd()) dirname = os.path.basename(os.getcwd())
if m := re.match('^rust-([a-z+0-9_-]+)$', dirname): if m := re.match('^rust-([a-z+0-9_-]+)$', dirname):
print(f'Using crate name {m.group(1)!r} based on the directory name') crate = m.group(1)
return m.group(1) log.info(f'Using crate name {crate!r} based on the current working directory.')
return crate
return None return None
@ -496,7 +497,8 @@ def main():
if args.translate_license: if args.translate_license:
license, comments = licensing.translate_license(args.target, args.crate) license, comments = licensing.translate_license(args.target, args.crate)
if comments: if comments:
print(comments) for comment in comments.split("\n"):
log.info(comment)
print(license) print(license)
return return
@ -518,14 +520,13 @@ def main():
# No specfile, so this is probably a new package # No specfile, so this is probably a new package
if package_info := get_package_info(pkg_name): if package_info := get_package_info(pkg_name):
if args.suffix: if args.suffix:
print(f"Versions {args.suffix}.* of the crate '{metadata.name}' are already") log.warn(f"Version {args.suffix}.* of the crate '{metadata.name}' is already " +
print(f"packaged for Fedora: {package_info['full_url']}") f"packaged for Fedora: {package_info['full_url']}")
else: else:
print(f"Crate '{metadata.name}' is already packaged for Fedora:") log.warn(f"Crate '{metadata.name}' is already packaged for Fedora: " +
print(f"{package_info['full_url']}") f"{package_info['full_url']}")
print("Re-run with --no-existence-check if you still want to start from scratch.") log.info("Re-run with --no-existence-check to create a new spec file from scratch.")
sys.exit(1) sys.exit(1)
if args.rpmautospec is None: if args.rpmautospec is None:
@ -541,25 +542,25 @@ def main():
# clean up configuration files with deprecated names # clean up configuration files with deprecated names
if len(confs) > 1: if len(confs) > 1:
print("WARNING: More than one *rust2rpm.conf file is present in this directory.") log.error("More than one *rust2rpm.conf file is present in this directory. " +
print(" Ensure that there is only one, and that it has the correct contents.") "Ensure that there is only one, and that it has the correct contents.")
sys.exit(1) sys.exit(1)
if ".rust2rpm.conf" in confs and "rust2rpm.conf" not in confs: if ".rust2rpm.conf" in confs and "rust2rpm.conf" not in confs:
os.rename(".rust2rpm.conf", "rust2rpm.conf") os.rename(".rust2rpm.conf", "rust2rpm.conf")
print("Renamed deprecated, hidden .rust2rpm.conf file to rust2rpm.conf.") log.info("Renamed deprecated, hidden .rust2rpm.conf file to rust2rpm.conf.")
if "_rust2rpm.conf" in confs and "rust2rpm.conf" not in confs: if "_rust2rpm.conf" in confs and "rust2rpm.conf" not in confs:
os.rename("_rust2rpm.conf", "rust2rpm.conf") os.rename("_rust2rpm.conf", "rust2rpm.conf")
print("Renamed deprecated _rust2rpm.conf file to rust2rpm.conf.") log.info("Renamed deprecated _rust2rpm.conf file to rust2rpm.conf.")
if args.target not in conf: if args.target not in conf:
conf.add_section(args.target) conf.add_section(args.target)
conf_all_features = conf[args.target].getboolean("all-features") conf_all_features = conf[args.target].getboolean("all-features")
if conf_all_features is False and args.all_features: if conf_all_features is False and args.all_features:
print("WARNING: Conflicting settings for enabling all features: The setting is \"false\"") log.warn("Conflicting settings for enabling all features: The setting is \"false\"" +
print(" in rust2rpm.conf but it was enabled with the \"--all-features\" CLI flag.") "in rust2rpm.conf but it was enabled with the \"--all-features\" CLI flag.")
spec_contents = generator.spec_file_render( spec_contents = generator.spec_file_render(
args = args, args = args,
@ -585,12 +586,12 @@ def main():
else: else:
with open(spec_file, "w") as fobj: with open(spec_file, "w") as fobj:
fobj.write(spec_contents) fobj.write(spec_contents)
print(f'Wrote {fobj.name}') log.success(f'Generated: {fobj.name}.')
for fname, diff in zip(patch_files, diffs): for fname, diff in zip(patch_files, diffs):
if fname: if fname:
with open(fname, "w") as fobj: with open(fname, "w") as fobj:
fobj.writelines(diff) fobj.writelines(diff)
print(f'Wrote {fobj.name}') log.success(f'Generated: {fobj.name}')
if __name__ == "__main__": if __name__ == "__main__":
main() main()

View file

@ -7,6 +7,8 @@ import sys
import pyparsing as pp import pyparsing as pp
from pyparsing import ParseException from pyparsing import ParseException
from . import log
pp.ParserElement.enablePackrat() pp.ParserElement.enablePackrat()
# ConfigurationPredicate : # ConfigurationPredicate :
@ -59,7 +61,6 @@ def cfg_grammar():
@functools.cache @functools.cache
def evaluate_variable(name): def evaluate_variable(name):
# print(f'evaluate_variable: {expr}')
match name: match name:
case 'target_arch': case 'target_arch':
return platform.machine() return platform.machine()
@ -91,11 +92,10 @@ def evaluate_variable(name):
return 'unknown' return 'unknown'
case _: case _:
print(f'Unknown variable {name}, assuming False') log.warn(f'Unknown variable {name}, assuming False')
return False return False
def evaluate(expr, nested=False): def evaluate(expr, nested=False):
# print(f'evaluate: {expr}')
if hasattr(expr, 'asList'): if hasattr(expr, 'asList'):
expr = expr.asList() # compat with pyparsing 2.7.x expr = expr.asList() # compat with pyparsing 2.7.x
match expr: match expr:

View file

@ -1,22 +1,22 @@
import os as _os import os
import sys as _sys import csv
import csv as _csv import functools
import functools as _functools
SPDX_TO_FEDORA_CSV = _os.path.dirname(__file__) + '/spdx_to_fedora.csv' from . import log
SPDX_TO_FEDORA_CSV = os.path.dirname(__file__) + '/spdx_to_fedora.csv'
def translate_slashes(license): def translate_slashes(license):
"Replace all slashes with OR, emit warning" "Replace all slashes with OR, emit warning"
split = [l.strip() for l in license.split("/")] split = [l.strip() for l in license.split("/")]
if len(split) > 1: if len(split) > 1:
print('Upstream uses deprecated "/" syntax. Replacing with "OR"', log.info('Upstream uses deprecated "/" syntax. Replacing with "OR"')
file=_sys.stderr)
return ' OR '.join(split) return ' OR '.join(split)
@_functools.lru_cache() @functools.lru_cache()
def spdx_to_fedora_map(): def spdx_to_fedora_map():
with open(SPDX_TO_FEDORA_CSV, newline='') as f: with open(SPDX_TO_FEDORA_CSV, newline='') as f:
reader = _csv.DictReader(f) reader = csv.DictReader(f)
return {line['SPDX License Identifier']: line['Fedora Short Name'] return {line['SPDX License Identifier']: line['Fedora Short Name']
for line in reader for line in reader
if line['SPDX License Identifier']} if line['SPDX License Identifier']}
@ -52,8 +52,7 @@ def translate_license_fedora(license):
else: else:
final.append(mapped) final.append(mapped)
if mapped != tag: if mapped != tag:
print(f'Upstream license tag {fulltag} translated to {mapped}', log.info(f'Upstream license tag {fulltag} translated to {mapped}')
file=_sys.stderr)
return (' '.join(final), '\n'.join(comments) or None) return (' '.join(final), '\n'.join(comments) or None)
def translate_license(target, license): def translate_license(target, license):

28
rust2rpm/log.py Normal file
View file

@ -0,0 +1,28 @@
import sys
import textwrap
from termcolor import colored
def _eprint(message):
print(message, file=sys.stderr)
def _wrap(message, prefix):
return textwrap.wrap(message, 80, initial_indent=f"{prefix} ", subsequent_indent=" "*(len(prefix) + 1))
def success(message):
_eprint(colored("\n".join(_wrap(message, "")), "green"))
def info(message):
_eprint(colored("\n".join(_wrap(message, "")), "white"))
def warn(message):
_eprint(colored("\n".join(_wrap(message, "WARNING")), "yellow"))
def error(message):
_eprint(colored("\n".join(_wrap(message, "ERROR")), "red", attrs=["dark"]))

View file

@ -27,6 +27,7 @@ install_requires =
jinja2 jinja2
pyparsing pyparsing
requests requests
termcolor
tqdm tqdm
[options.package_data] [options.package_data]