#!/usr/bin/python3 import gi import git import os import sys from gi.repository import GLib gi.require_version("Modulemd", "2.0") from gi.repository import Modulemd def print_failure(failure): print("Error: %s" % failure.get_gerror()) print("Offending YAML: \n%s" % failure.get_yaml()) def unusable_baseline(): print("Baseline was unusable. Skipping test.") return os.EX_OK def get_index_and_defaults(repo, filename, commit): try: yaml = repo.git.show("%s:%s" % (commit, filename)) except git.exc.GitCommandError as e: # This file didn't exist in the commit, so return # FileNotFoundError to skip checking it. raise FileNotFoundError( "{} does not exist at commit {}".format(filename, commit) ) index = Modulemd.ModuleIndex.new() try: ret, failures = index.update_from_string(yaml, True) if ret != True: for failure in failures: print_failure(failure) raise IOError("Invalid modulemd-defaults document") except gi.repository.GLib.Error as e: print("Error: %s" % e) raise IOError("Invalid YAML document") module_names = index.get_module_names() if len(module_names) > 1: raise IOError("YAML contained multiple modules") elif len(module_names) < 1: raise IOError("YAML contained no modules") defaults = index.get_module(index.get_module_names()[0]).get_defaults() if not defaults: raise IOError("YAML contained no defaults") return index, defaults def main(): filename = sys.argv[1] baseline_commit = sys.argv[2] updated_commit = sys.argv[3] script_dir = os.path.dirname(os.path.realpath(__file__)) repo = git.Repo(script_dir, search_parent_directories=True) # First get the defaults from the baseline commit try: baseline_index, baseline_defaults = get_index_and_defaults( repo, filename, baseline_commit ) except FileNotFoundError as e: # The baseline file didn't exist, so there's no valid original # to compare to. Check it only with validate.py. print(e, file=sys.stderr) return unusable_baseline() except IOError as e: # The baseline file was invalid (which should never happen...). # Check it only with validate.py (in case this PR is trying to # correct the situation print(e, file=sys.stderr) return os.EX_DATAERR try: updated_commit = updated_commit updated_index, updated_defaults = get_index_and_defaults( repo, filename, updated_commit ) except FileNotFoundError as e: # The PR is removing this file. Assume that this is acceptable print( "{} is being removed. Not performing any comparison tests.".format( filename ), file=sys.stderr, ) return os.EX_OK except IOError as e: # If we hit this, the patch is broken. print(e, file=sys.stderr) return os.EX_DATAERR if updated_defaults.get_modified() <= baseline_defaults.get_modified(): print( "%s has changed but the 'modified' field has not increased." % filename ) print("Baseline modified: {}".format(baseline_defaults.get_modified())) print("Updated modified: {}".format(updated_defaults.get_modified())) return os.EX_DATAERR # Confirm that these two sets of defaults merge cleanly merger = Modulemd.ModuleIndexMerger.new() merger.associate_index(baseline_index, 0) merger.associate_index(baseline_index, 0) try: merger.resolve() except gi.repository.GLib.Error as e: print("Merge Error: %s" % e, file=sys.stderr) return os.EX_DATAERR return os.EX_OK if __name__ == "__main__": sys.exit(main())