concretizer: deterministic order for asp output for better diffs

Technically the ASP output order does not matter, but it's hard to diff
two different solve fomulations unless we order it.

- [x] make sure ASP output is emitted in a deterministic order (by
      sorting all hash keys)
This commit is contained in:
Todd Gamblin 2019-12-07 22:26:52 -05:00
parent 36dae9ee05
commit 1859ff31c9

View file

@ -245,7 +245,7 @@ def spec_versions(self, spec):
# version must be *one* of the ones the spec allows. # version must be *one* of the ones the spec allows.
allowed_versions = [ allowed_versions = [
v for v in self.possible_versions[spec.name] v for v in sorted(self.possible_versions[spec.name])
if v.satisfies(spec.versions) if v.satisfies(spec.versions)
] ]
@ -268,7 +268,7 @@ def compiler_defaults(self):
for compiler in compilers: for compiler in compilers:
compiler_versions[compiler.name].add(compiler.version) compiler_versions[compiler.name].add(compiler.version)
for compiler in compiler_versions: for compiler in sorted(compiler_versions):
self.fact(fn.compiler(compiler)) self.fact(fn.compiler(compiler))
self.rule( self.rule(
self._or( self._or(
@ -307,7 +307,7 @@ def pkg_rules(self, pkg):
self.out.write('\n') self.out.write('\n')
# variants # variants
for name, variant in pkg.variants.items(): for name, variant in sorted(pkg.variants.items()):
self.rule(fn.variant(pkg.name, name), self.rule(fn.variant(pkg.name, name),
fn.node(pkg.name)) fn.node(pkg.name))
@ -321,7 +321,7 @@ def pkg_rules(self, pkg):
else: else:
self.rule(self._not(single), fn.node(pkg.name)) self.rule(self._not(single), fn.node(pkg.name))
defaults = variant.default.split(',') defaults = variant.default.split(',')
for val in defaults: for val in sorted(defaults):
self.rule( self.rule(
fn.variant_default_value(pkg.name, name, val), fn.variant_default_value(pkg.name, name, val),
fn.node(pkg.name)) fn.node(pkg.name))
@ -335,7 +335,7 @@ def pkg_rules(self, pkg):
union.update(s) union.update(s)
values = union values = union
for value in values: for value in sorted(values):
self.fact(fn.variant_possible_value(pkg.name, name, value)) self.fact(fn.variant_possible_value(pkg.name, name, value))
self.out.write('\n') self.out.write('\n')
@ -344,21 +344,21 @@ def pkg_rules(self, pkg):
self.package_compiler_defaults(pkg) self.package_compiler_defaults(pkg)
# dependencies # dependencies
for name, conditions in pkg.dependencies.items(): for name, conditions in sorted(pkg.dependencies.items()):
for cond, dep in conditions.items(): for cond, dep in sorted(conditions.items()):
named_cond = cond.copy() named_cond = cond.copy()
if not named_cond.name: if not named_cond.name:
named_cond.name = pkg.name named_cond.name = pkg.name
if cond == spack.spec.Spec(): if cond == spack.spec.Spec():
for t in dep.type: for t in sorted(dep.type):
self.fact( self.fact(
fn.declared_dependency( fn.declared_dependency(
dep.pkg.name, dep.spec.name, t dep.pkg.name, dep.spec.name, t
) )
) )
else: else:
for t in dep.type: for t in sorted(dep.type):
self.rule( self.rule(
fn.declared_dependency( fn.declared_dependency(
dep.pkg.name, dep.spec.name, t dep.pkg.name, dep.spec.name, t
@ -453,7 +453,7 @@ class Body(object):
clauses.append(f.arch_target(spec.name, arch.target)) clauses.append(f.arch_target(spec.name, arch.target))
# variants # variants
for vname, variant in spec.variants.items(): for vname, variant in sorted(spec.variants.items()):
value = variant.value value = variant.value
if isinstance(value, tuple): if isinstance(value, tuple):
for v in value: for v in value:
@ -503,9 +503,9 @@ def virtual_providers(self):
assert self.possible_virtuals is not None assert self.possible_virtuals is not None
# what provides what # what provides what
for vspec in self.possible_virtuals: for vspec in sorted(self.possible_virtuals):
self.fact(fn.virtual(vspec)) self.fact(fn.virtual(vspec))
for provider in spack.repo.path.providers_for(vspec): for provider in sorted(spack.repo.path.providers_for(vspec)):
# TODO: handle versioned virtuals # TODO: handle versioned virtuals
self.fact(fn.provides_virtual(provider.name, vspec)) self.fact(fn.provides_virtual(provider.name, vspec))
@ -543,12 +543,12 @@ def generate_asp_program(self, specs):
self.provider_defaults() self.provider_defaults()
self.h1('Package Constraints') self.h1('Package Constraints')
for pkg in pkgs: for pkg in sorted(pkgs):
self.h2('Package: %s' % pkg) self.h2('Package: %s' % pkg)
self.pkg_rules(pkg) self.pkg_rules(pkg)
self.h1('Spec Constraints') self.h1('Spec Constraints')
for spec in specs: for spec in sorted(specs):
self.fact(fn.root(spec.name)) self.fact(fn.root(spec.name))
for dep in spec.traverse(): for dep in spec.traverse():
self.h2('Spec: %s' % str(dep)) self.h2('Spec: %s' % str(dep))