New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Adding ability to compare git references to spack install #24639
Conversation
c7c0911
to
903ae09
Compare
okay updated to try and parse any semantic versions found in git tags. |
fb1b4f0
to
43967d5
Compare
This works by way of adding a property, is_commit, to a version, and then given that a version is a commit, we return a GitFetcherStrategy to use it. In additional, we instruct the version command to generate a lookup of commits that keeps track of the order (for comparing between commits) and the previous and next spack version (for comparison of a commit with a spack version string). If the commit does not have known releases before it, then the previous is None and we cannot determine the relationship and return False. The same is true if the commit does not have any known releases after it, although it is unlikely to hit this case unless the user is asking for a version that has been released but not added to spack. Signed-off-by: vsoch <vsoch@users.noreply.github.com>
43967d5
to
090c798
Compare
@becker33 the last test is still finishing but we can probably discuss it now anyway. Let me know if this is in the right direction of what we had in mind! |
Signed-off-by: vsoch <vsoch@users.noreply.github.com>
ping @becker33 ! I thought this was time sensitive (opened 12 days ago, and I think we only had under 2 months?) so would it be possible to get reviewed soon? |
@spackbot hello! |
Hello! |
@spackbot re-run pipeline |
I'm not able to re-run the pipeline now because I don't have authentication. |
@spackbot hello |
Hello! |
@spackbot re-run pipeline |
I've started that pipeline for you! |
@spackbot commands |
You can interact with me in many ways!
I'll also help to label your pull request and assign reviewers! |
Sorry spack-bot[bot], I cannot do that for you. Only users with write can make this request! |
Hola! |
…k into add/github-version-comparison
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is looking great -- only final requests are:
- Use bare repositories and
git fetch
in the cache (instead of repos with a work tree andgit pull
) to avoid checking out the whole work tree (which is slow). We don't need the work tree -- just the history. - Change the PR description to match what this ended up looking like.
And minor things below.
lib/spack/spack/test/conftest.py
Outdated
def mock_git_version_info(tmpdir, scope="function"): | ||
"""Create a mock git repo with known structure | ||
|
||
The structure of commits in this repo is as follows: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use two colons and indent so that text below is preformatted in docs. https://www.sphinx-doc.org/en/master/usage/restructuredtext/basics.html#literal-blocks
Oh, and finally: file locking on the caches if that is not already done. |
Is this still in the scope of this PR? Or is this about comparison only? Can we get a few lines in the docs about how version comparison works, whether it's necessary to add manual mappings from tags to spack versions or whether they're automatically mapped, what happens if a commit is not before / after a tagged commit (does the latest untagged commit on the release/1.x branch map to version 2.0, |
Spack added support in #24639 for ad-hoc Git-commit-hash-based versions: A user can install a package x@hash, where X is a package that stores its source code in a Git repository, and the hash refers to a commit in that repository which is not recorded as an explicit version in the package.py file for X. A couple issues were found relating to this: * If an environment defines an alternative package repo (i.e. with repos.yaml), and spack.yaml contains user Specs with ad-hoc Git-commit-hash-based versions for packages in that repo, then as part of retrieving the data needed for version comparisons it will attempt to retrieve the package before the environment's configuration is instantiated. * The bookkeeping information added to compare ad-hoc git versions was being stripped from Specs during concretization (such that user Specs which succeeded before concretizing would then fail after) This addresses the issues: * The first issue is resolved by deferring access to the associated Package until the versions are actually compared to one another. * The second issue is resolved by ensuring that the Git bookkeeping information is explicitly applied to Specs after they are concretized. This also: * Resolves an ambiguity in the mock_git_version_info fixture used to create a tree of Git commits and provide a list where each index maps to a known commit. * Isolates the cache used for Git repositories in tests using the mock_git_version_info fixture * Adds a TODO which points out that if the remote Git repository overwrites tags, that Spack will then fail when using ad-hoc Git-commit-hash-based versions
) Spack added support in spack#24639 for ad-hoc Git-commit-hash-based versions: A user can install a package x@hash, where X is a package that stores its source code in a Git repository, and the hash refers to a commit in that repository which is not recorded as an explicit version in the package.py file for X. A couple issues were found relating to this: * If an environment defines an alternative package repo (i.e. with repos.yaml), and spack.yaml contains user Specs with ad-hoc Git-commit-hash-based versions for packages in that repo, then as part of retrieving the data needed for version comparisons it will attempt to retrieve the package before the environment's configuration is instantiated. * The bookkeeping information added to compare ad-hoc git versions was being stripped from Specs during concretization (such that user Specs which succeeded before concretizing would then fail after) This addresses the issues: * The first issue is resolved by deferring access to the associated Package until the versions are actually compared to one another. * The second issue is resolved by ensuring that the Git bookkeeping information is explicitly applied to Specs after they are concretized. This also: * Resolves an ambiguity in the mock_git_version_info fixture used to create a tree of Git commits and provide a list where each index maps to a known commit. * Isolates the cache used for Git repositories in tests using the mock_git_version_info fixture * Adds a TODO which points out that if the remote Git repository overwrites tags, that Spack will then fail when using ad-hoc Git-commit-hash-based versions
Building on #24639, this allows versions to be prefixed by `git.`. If a version begins `git.`, it is treated as a git ref, and handled as git commits are starting in the referenced PR. An exception is made for versions that are `git.develop`, `git.main`, `git.master`, `git.head`, or `git.trunk`. Those are assumed to be greater than all other versions, as those prefixed strings are in other contexts.
Building on spack#24639, this allows versions to be prefixed by `git.`. If a version begins `git.`, it is treated as a git ref, and handled as git commits are starting in the referenced PR. An exception is made for versions that are `git.develop`, `git.main`, `git.master`, `git.head`, or `git.trunk`. Those are assumed to be greater than all other versions, as those prefixed strings are in other contexts.
@@ -276,10 +319,13 @@ def satisfies(self, other): | |||
gcc@4.7 so that when a user asks to build with gcc@4.7, we can find | |||
a suitable compiler. | |||
""" | |||
self_cmp = self._cmp(other.commit_lookup) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why was this mixing self
and other
?
This will allow a user to (from anywhere a Spec is parsed including both name and version) refer to a git commit in lieu of
a package version, and be able to make comparisons with releases in the history based on commits (or with other commits). We do this by way of:
~/.spack/git_repos
If a commit cannot be found in the cached git repo, we fetch from the repo. If a commit is found in the cached metadata, we do not recompare to newly downloaded tags (assuming repo structure does not change). The cached metadata may be thrown out by using the
spack clean -m
option if you know the repo structure has changed in a way that invalidates existing entries. Future work will include automatic updates.Finding previous versions
Spack will search the repo for any tags that match the string of a version given by the
version
directive. Spack will also search for any tags that matchv + string
for any version string. Beyond that, Spack will search for tags that match a SEMVER regex (i.e., tags of the form x.y.z) and interpret those tags as valid versions as well. Future work will increase the breadth of tags understood by SpackFor each tag, Spack queries git to determine whether the tag is an ancestor of the commit in question or not. Spack then sorts the tags that are ancestors of the commit by commit-distance in the repo, and takes the nearest ancestor. The version represented by that tag is listed as the previous version for the commit.
Not all commits will find a previous version, depending on the package workflow. Future work may enable more tangential relationships between commits and versions to be discovered, but many commits in real world git repos require human knowledge to associate with a most recent previous version. Future work will also allow packages to specify commit/tag/version relationships manually for such situations.
Version comparisons.
The empty string is a valid component of a Spack version tuple, and is in fact the lowest-valued component. It cannot be generated as part of any valid version. These two characteristics make it perfect for delineating previous versions from distances. For any version x.y.z, (x, y, z, '', _) will be less than any "real" version beginning x.y.z. This ensures that no distance from a release will cause the commit to be interpreted as "greater than" a version which is not an ancestor of it.
Signed-off-by: vsoch vsoch@users.noreply.github.com