Skip to content

Allow different instances of build deps in environment#10792

Merged
becker33 merged 3 commits intospack:developfrom
scheibelp:bugfix/build-deps-in-envs
Jul 22, 2019
Merged

Allow different instances of build deps in environment#10792
becker33 merged 3 commits intospack:developfrom
scheibelp:bugfix/build-deps-in-envs

Conversation

@scheibelp
Copy link
Copy Markdown
Member

@tgamblin

Environments currently stores the full spec dag (including build dependencies) but indexes by dag hash, which excludes build dependencies. This can lead to reference errors for example given:

X-[L]->Y
X-[B]->Z1
Y-[B]->Z2

This PR

  • Updates specs to track dag hashes both with and without build dependencies
  • Updates the lockfile format to index based on the full dag hash (including build deps)
  • Automatically updates older lockfiles to newer ones (where the indices are hashes based on the full dag)

Copy link
Copy Markdown
Member

@becker33 becker33 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would consider changing the all_deps booleans in to_node_dict and dag_hash to be named include_build_deps for clarity.

Similarly, I would consider changing _build_hash and _hash to something that's more descriptive of their differences. I think it might be hard for others to pick up this code, but I'm not sure what a better name for these two is so I'm not requesting changes since I don't have a good answer.

Overall LGTM.

Copy link
Copy Markdown
Member

@becker33 becker33 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@scheibelp Does this mean we can get rid of the yaml round-trip at line 746 in environment.py?

Copy link
Copy Markdown
Member

@tgamblin tgamblin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@scheibelp @becker33: this looks mostly awesome -- I definitely think environments should be keyed by full hash. But this duplicates some work by @scottwittenburg on the release pipeline.

Requests:

  1. There is already a full_hash() function on Spec, and we should consolidate build_hash into that.
  2. I have a clarifying question about whether the lockfile already includes the build dependencies -- see the comments.
  3. After reading the whole thing, I think it would probably be good to make the deptype arguments (deptypes, all_deps) consistent and use the convention that we use when we have deptypes as a keyword argument. I think it would improve the PR.


if read_lock_version == 1:
shutil.copy(self.lock_path, self._lock_backup_v1_path)
tty.debug("Storing backup of old lockfile format")
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add the path to the message here.

self.specs_by_hash = {}
for _, spec in specs_by_hash.items():
old_hash = spec.dag_hash()
full_hash = spec.dag_hash(all_deps=True)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is already a full_hash() method on Spec. Can we use this here? It's used for the release pipeline work by Kitware -- I think it's more consistent to just use the method since it's there, but it may not actually be what you want.

I'm looking at the full_hash() implementation and it looks like it mostly copies the dag_hash() code -- can it just be implemented as spec.dag_hash(all_deps=True)?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case full_hash is just the dag hash computed with all dependencies (including build deps). Spec.full_hash includes Package.content_hash, which is more-specific than we have wanted so far and would be going a bit beyond the original fix.

Given that, I will rename this variable in this context to build_hash to avoid confusion.

Copy link
Copy Markdown
Member

@tgamblin tgamblin Jul 12, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@scheibelp: ok thanks -- that is very clear and makes sense. Can we:

  1. Have 3 methods: dag_hash(), full_hash(), and build_hash(), with comments making them clear, and
  2. Implement full_hash and build_hash() in terms of dag_hash()? I think it would be clearer if dag_hash() looked something like this:
    def dag_hash(self, length=none, deptypes=default_deptype, include_package=False):
       deptypes = canonical_deptype(deptypes)
       ...

Then implement full_hash and build_hash in terms of that. Does that seem clearer?

if deps:
if hash_function is None:
hash_function = lambda s: s.dag_hash()
hash_function = lambda s: s.dag_hash(all_deps=all_deps)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found this hard to read because all_deps is not nearly as clear as the deptype argument that other functions have. I think it would be clearer that this is NOT the default case if we refactored to use deptype=....

node = s.to_node_dict(all_deps=all_deps)
node[s.name]['hash'] = s.dag_hash()
if all_deps:
node[s.name]['build_hash'] = s.dag_hash(all_deps=True)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this would be clearer with a deptype argument too.

@scheibelp
Copy link
Copy Markdown
Member Author

@becker33 Regarding #10792 (review):

Does this mean we can get rid of the yaml round-trip at line 746 in environment.py?

No: views still don't store build deps

@tgamblin tgamblin self-assigned this Jul 18, 2019
@scheibelp
Copy link
Copy Markdown
Member Author

This could likely be compressed into two commits: everything up to and including a9a9466, and then everything after (refactoring the hash calculations).

@tgamblin tgamblin requested a review from becker33 July 20, 2019 00:36
@tgamblin tgamblin assigned scheibelp and unassigned scheibelp Jul 20, 2019
@tgamblin tgamblin force-pushed the bugfix/build-deps-in-envs branch from 007201b to 30ca77c Compare July 20, 2019 01:05
@tgamblin
Copy link
Copy Markdown
Member

@becker33: this is ready for re-review. There is at least one failing test, but I think it has to do with the rebase I did on top of develop, which now has stacks.

I think that, barring any changes you want to the code, I can hand this off to you now.

There are a few things I noticed here while working on this PR and the old develop branch -- it's very easy to create an environment that doesn't validate with an old Spack instance. We should think about how we want to handle that. It would probably help if we fixed the issue where envs create empty default values for all keys. I think we should think about that fairly soon in a follow-on PR.

@tgamblin tgamblin assigned becker33 and unassigned tgamblin Jul 20, 2019
@tgamblin
Copy link
Copy Markdown
Member

@becker33: last point here. When merging this, we should probably squash everything before
35befe8 (experimental refactoring of hash functions) into one commit authored by me and @scheibelp, and everything before it into one commit authored by @scheibelp.


# TODO: restore build dependencies here once we have less picky
# TODO: concretization.
if all_deps:
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment above here should probably be removed now.

@tgamblin tgamblin force-pushed the bugfix/build-deps-in-envs branch from 30ca77c to 672b600 Compare July 20, 2019 07:23
@tgamblin
Copy link
Copy Markdown
Member

@becker33: make sure my bugfix commit here is correct. I believe it fixes an issue in stacks.

@tgamblin tgamblin force-pushed the bugfix/build-deps-in-envs branch from 672b600 to a6becb2 Compare July 20, 2019 16:50
@becker33 becker33 force-pushed the bugfix/build-deps-in-envs branch from a6becb2 to 0843b13 Compare July 22, 2019 14:27
scheibelp and others added 3 commits July 22, 2019 12:02
- ensure that Spec._build_hash attr is defined
- add logic to compute _build_hash when it is not already computed (e.g. for specs prior to this PR)
- add test to ensure that different instance of a build dep are preserved
- test conversion of old env lockfile format to new format
- tests: avoid view creation, DAG display in tests using MockPackage
- add regression test for more-general bug also fixed by this PR
- update lockfile version since the way we are maintaining hashes has changed
- write out backup for version-1 lockfiles and test that
Spack has evolved to have three types of hash functions, and it's
becoming hard to tell when each one is called. Whlie we aren't yet ready
to get rid of them, we can refactor them so that the code is clearer and
easier to track.

- Add a `hash_types` module with concise descriptors for hashes.

- Consolidate hashing logic in a private `Spec._spec_hash()` function.

- `dag_hash()`, `build_hash()`, and `full_hash()` all call `_spec_hash()`

- `to_node_dict()`, `to_dict()`, `to_yaml()` and `to_json()` now take a
  `hash` parameter consistent with the one that `_spec_hash()` requires.

Co-authored-by: Todd Gamblin <[email protected]>
- Setting specs from lockfiles was not correctly stringifying concretized
  user specs.

- Fix `_set_user_specs_from_lockfile`

- Add some validation code to `SpecList` constructor
@becker33 becker33 force-pushed the bugfix/build-deps-in-envs branch from 0843b13 to 0bb00e3 Compare July 22, 2019 17:03
@becker33 becker33 merged commit cc4094b into spack:develop Jul 22, 2019
@glennpj glennpj mentioned this pull request Jul 23, 2019
tgamblin added a commit that referenced this pull request Nov 5, 2019
This fixes a regression introduced in #10792.  `spack uninstall` in an
environment would not match concrete query specs properly after the index
hash of enviroments changed.

- [x] Search by DAG hash for specs to remove instead of by build hash
tgamblin added a commit that referenced this pull request Nov 5, 2019
This fixes a regression introduced in #10792.  `spack uninstall` in an
environment would not match concrete query specs properly after the index
hash of enviroments changed.

- [x] Search by DAG hash for specs to remove instead of by build hash
tgamblin added a commit that referenced this pull request Nov 5, 2019
This fixes a regression introduced in #10792.  `spack uninstall` in an
environment would not match concrete query specs properly after the index
hash of enviroments changed.

- [x] Search by DAG hash for specs to remove instead of by build hash
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants