| |
@@ -1,6 +1,5 @@
|
| |
#!/usr/bin/python3
|
| |
|
| |
-
|
| |
import gi
|
| |
import git
|
| |
import os
|
| |
@@ -16,7 +15,7 @@
|
| |
logging.getLogger().setLevel(logging.INFO)
|
| |
|
| |
|
| |
- def do_validate(filename):
|
| |
+ def do_validate(filename, obsoletes=False):
|
| |
# Valid filenames must end in ".yaml" to be properly included by Pungi
|
| |
if not filename.endswith(".yaml"):
|
| |
error(
|
| |
@@ -49,11 +48,23 @@
|
| |
error("There must be exactly one module represented by this file")
|
| |
return False, None
|
| |
|
| |
- # The files must have exactly one Modulemd.Defaults object
|
| |
+ # The files must have exactly one Modulemd object
|
| |
module = idx.get_module(names[0])
|
| |
- defaults = module.get_defaults()
|
| |
|
| |
- if defaults is None:
|
| |
+ if obsoletes:
|
| |
+ mmds = module.get_obsoletes()
|
| |
+ if not len(mmds) == 1:
|
| |
+ error(
|
| |
+ "There must be exactly one module obsoletes document for {}".format(
|
| |
+ module.props.module_name
|
| |
+ )
|
| |
+ )
|
| |
+ return False, None
|
| |
+ mmd = mmds[0]
|
| |
+ else:
|
| |
+ mmd = module.get_defaults()
|
| |
+
|
| |
+ if mmd is None:
|
| |
error(
|
| |
"No defaults document provided for {}".format(
|
| |
module.props.module_name
|
| |
@@ -69,21 +80,29 @@
|
| |
# Filenames must match their contents
|
| |
expected_name = os.path.basename(filename).rsplit(".", maxsplit=1)[0]
|
| |
|
| |
- if expected_name != defaults.props.module_name:
|
| |
+ if expected_name != mmd.props.module_name:
|
| |
error(
|
| |
'Module name "{}" doesn\'t match filename "{}.yaml"'.format(
|
| |
- defaults.props.module_name, expected_name
|
| |
+ mmd.props.module_name, expected_name
|
| |
)
|
| |
)
|
| |
return False, None
|
| |
|
| |
- default_stream = defaults.get_default_stream()
|
| |
+ if obsoletes:
|
| |
+ is_valid = mmd.validate()
|
| |
+ if is_valid:
|
| |
+ info("{} obsoletes are valid".format(filename))
|
| |
+ else:
|
| |
+ error("{} obsoletes are NOT valid".format(filename))
|
| |
+ return (mmd.validate(), mmd)
|
| |
+
|
| |
+ default_stream = mmd.get_default_stream()
|
| |
if default_stream:
|
| |
# Default streams must also appear in the profiles list
|
| |
- if defaults.get_default_profiles_for_stream(default_stream) is None:
|
| |
+ if mmd.get_default_profiles_for_stream(default_stream) is None:
|
| |
error(
|
| |
"Stream '{}' is missing from the profiles for '{}'".format(
|
| |
- default_stream, defaults.get_module_name()
|
| |
+ default_stream, mmd.get_module_name()
|
| |
)
|
| |
)
|
| |
return False, None
|
| |
@@ -91,7 +110,7 @@
|
| |
# Modules in Fedora must not specify "Intents"
|
| |
# TODO: This needs a new interface exposed in libmodulemd v2
|
| |
|
| |
- info("{} is valid".format(filename))
|
| |
+ info("{} defaults are valid".format(filename))
|
| |
return (True, idx)
|
| |
|
| |
|
| |
@@ -104,12 +123,23 @@
|
| |
script_dir = os.path.dirname(os.path.realpath(__file__))
|
| |
defaults_dir = os.path.abspath(os.path.join(script_dir, '..'))
|
| |
overrides_dir = os.path.join(defaults_dir, 'overrides')
|
| |
+ #obsoletes_dir = os.path.abspath(os.path.join(defaults_dir, 'obsoletes'))
|
| |
+ #obsoletes_tests_dir = os.path.abspath(os.path.join(script_dir, 'obsoletes'))
|
| |
|
| |
# Get the repo we're running in
|
| |
repo = git.Repo(defaults_dir, search_parent_directories=True)
|
| |
|
| |
# Get the list of files in this repository
|
| |
- files = [x for (x, y) in repo.index.entries.keys()]
|
| |
+ defaults_files = list()
|
| |
+ obsoletes_files = list()
|
| |
+ obsoletes_test_files = list()
|
| |
+ for (x, y) in repo.index.entries.keys():
|
| |
+ if x.startswith('obsoletes/'):
|
| |
+ obsoletes_files.append(x)
|
| |
+ elif x.startswith('tests/obsoletes/'):
|
| |
+ obsoletes_test_files.append(x)
|
| |
+ else:
|
| |
+ defaults_files.append(x)
|
| |
|
| |
# Get the list of excluded files
|
| |
exclusions = []
|
| |
@@ -121,15 +151,24 @@
|
| |
continue
|
| |
exclusions.append(line.strip())
|
| |
|
| |
- # Validate all of the files
|
| |
- for file in files:
|
| |
- excluded = False
|
| |
+ # Validate module defaults files
|
| |
+ for file in defaults_files:
|
| |
+ for excl in exclusions:
|
| |
+ if file.startswith(excl):
|
| |
+ break
|
| |
+ else:
|
| |
+ (valid, _) = do_validate(file)
|
| |
+ if not valid:
|
| |
+ error("{} failed to validate".format(file))
|
| |
+ result = os.EX_DATAERR
|
| |
+
|
| |
+ # Validate module obsoletes test files
|
| |
+ for file in obsoletes_test_files:
|
| |
for excl in exclusions:
|
| |
if file.startswith(excl):
|
| |
- excluded = True
|
| |
break
|
| |
- if not excluded:
|
| |
- (valid, idx) = do_validate(file)
|
| |
+ else:
|
| |
+ (valid, _) = do_validate(file, obsoletes=True)
|
| |
if not valid:
|
| |
error("{} failed to validate".format(file))
|
| |
result = os.EX_DATAERR
|
| |
@@ -141,9 +180,14 @@
|
| |
# conflicts arise that weren't detected by the above tests. This should be
|
| |
# impossible.
|
| |
try:
|
| |
- idx = Modulemd.ModuleIndex()
|
| |
- idx.update_from_defaults_directory(path=defaults_dir,
|
| |
- strict=True)
|
| |
+ idx_runtime = Modulemd.ModuleIndex()
|
| |
+ idx_runtime.update_from_defaults_directory(path=defaults_dir,
|
| |
+ strict=True)
|
| |
+ # for obsoletes tests, because simple index copy is not possible
|
| |
+ # due to: GObject descendants' instances are non-copyable
|
| |
+ idx_tests = Modulemd.ModuleIndex()
|
| |
+ idx_tests.update_from_defaults_directory(path=defaults_dir,
|
| |
+ strict=True)
|
| |
except GLib.Error as e:
|
| |
error("Could not merge all defaults: {}".format(e.message))
|
| |
result = os.EX_DATAERR
|
| |
@@ -153,14 +197,14 @@
|
| |
|
| |
print("\nDefault streams (Runtime):")
|
| |
print("================")
|
| |
- for m, s in idx.get_default_streams().items():
|
| |
+ for m, s in idx_runtime.get_default_streams().items():
|
| |
print("{}:{}".format(m, s))
|
| |
|
| |
try:
|
| |
- idx = Modulemd.ModuleIndex()
|
| |
- idx.update_from_defaults_directory(path=defaults_dir,
|
| |
- overrides_path=overrides_dir,
|
| |
- strict=True)
|
| |
+ idx_buildroot = Modulemd.ModuleIndex()
|
| |
+ idx_buildroot.update_from_defaults_directory(path=defaults_dir,
|
| |
+ overrides_path=overrides_dir,
|
| |
+ strict=True)
|
| |
except GLib.Error as e:
|
| |
error("Could not merge all defaults: {}".format(e.message))
|
| |
result = os.EX_DATAERR
|
| |
@@ -170,9 +214,51 @@
|
| |
|
| |
print("\nDefault streams (Buildroot):")
|
| |
print("================")
|
| |
- for m, s in idx.get_default_streams().items():
|
| |
+ for m, s in idx_buildroot.get_default_streams().items():
|
| |
print("{}:{}".format(m, s))
|
| |
|
| |
+ # Try merging TEST module obsoletes into the module defaults index.
|
| |
+ for file in obsoletes_test_files:
|
| |
+ for excl in exclusions:
|
| |
+ if file.startswith(excl):
|
| |
+ break
|
| |
+ else:
|
| |
+ (_, idx) = do_validate(file, obsoletes=True)
|
| |
+ idx_tests.add_obsoletes(idx)
|
| |
+
|
| |
+ print("\nObsoletes (tests):")
|
| |
+ print("================")
|
| |
+ for module_name in idx_tests.get_module_names():
|
| |
+ module = idx_tests.get_module(module_name)
|
| |
+ obsoletes = module.get_obsoletes()
|
| |
+ if not obsoletes:
|
| |
+ continue
|
| |
+ if len(obsoletes) > 1:
|
| |
+ result = os.EX_DATAERR
|
| |
+ break
|
| |
+ print("{}:{}".format(module_name, obsoletes[0]))
|
| |
+
|
| |
+ # Try merging module obsoletes into the module defaults index.
|
| |
+ for file in obsoletes_files:
|
| |
+ for excl in exclusions:
|
| |
+ if file.startswith(excl):
|
| |
+ break
|
| |
+ else:
|
| |
+ (_, idx) = do_validate(file, obsoletes=True)
|
| |
+ idx_runtime.add_obsoletes(idx)
|
| |
+
|
| |
+ print("\nObsoletes:")
|
| |
+ print("================")
|
| |
+ for module_name in idx_runtime.get_module_names():
|
| |
+ module = idx_runtime.get_module(module_name)
|
| |
+ obsoletes = module.get_obsoletes()
|
| |
+ if not obsoletes:
|
| |
+ continue
|
| |
+ if len(obsoletes) > 1:
|
| |
+ result = os.EX_DATAERR
|
| |
+ break
|
| |
+ print("{}:{}".format(module_name, obsoletes[0]))
|
| |
+
|
| |
return result
|
| |
|
| |
|
| |
Do not run mmd.validate() twice. I recommend "return(is_valid, mmd)" instead.