spack -V is now more descriptive for dev branches

`spack -V` previously always returned the version of spack from
`spack.spack_version`.  This gives us a general idea of what version
users are on, but if they're on `develop` or on some branch, we have to
ask more questions.

This PR makes `spack -V` check whether this instance of Spack is a git
repository, and if it is, it appends useful information from `git
describe --tags` to the version.  Specifically, it adds:

  - number of commits since the last release tag
  - abbreviated (but unique) commit hash

So, if you're on `develop` you might get something like this:

    $ spack -V
    0.13.3-912-3519a1762

This means you're on commit 3519a1762, which is 912 commits ahead of
the 0.13.3 release.

If you are on a release branch, or if you are using a tarball of Spack,
you'll get the usual `spack.spack_version`:

    $ spack -V
    0.13.3

This should help when asking users what version they are on, since a lot
of people use the `develop` branch.
This commit is contained in:
Todd Gamblin 2020-01-30 19:07:24 -08:00
parent d83309493f
commit c029c8ff89
2 changed files with 94 additions and 1 deletions

View File

@ -13,6 +13,7 @@
import sys
import re
import os
import os.path
import inspect
import pstats
import argparse
@ -35,6 +36,7 @@
import spack.store
import spack.util.debug
import spack.util.path
import spack.util.executable as exe
from spack.error import SpackError
@ -107,6 +109,34 @@ def add_all_commands(parser):
parser.add_command(cmd)
def get_version():
"""Get a descriptive version of this instance of Spack.
If this is a git repository, and if it is not on a release tag,
return a string like:
release_version-commits_since_release-commit
If we *are* at a release tag, or if this is not a git repo, return
the real spack release number (e.g., 0.13.3).
"""
git_path = os.path.join(spack.paths.prefix, ".git")
if os.path.exists(git_path):
git = exe.which("git")
if git:
desc = git("-C", spack.paths.prefix, "describe", "--tags",
output=str, fail_on_error=False)
if git.returncode == 0:
match = re.match(r"v([^-]+)-([^-]+)-g([a-f\d]+)", desc)
if match:
v, n, commit = match.groups()
return "%s-%s-%s" % (v, n, commit)
return spack.spack_version
def index_commands():
"""create an index of commands by section for this help level"""
index = {}
@ -679,7 +709,7 @@ def main(argv=None):
# -h, -H, and -V are special as they do not require a command, but
# all the other options do nothing without a command.
if args.version:
print(spack.spack_version)
print(get_version())
return 0
elif args.help:
sys.stdout.write(parser.format_help(level=args.help))

View File

@ -0,0 +1,63 @@
# Copyright 2013-2020 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
import os
import llnl.util.filesystem as fs
import spack.paths
from spack.main import get_version, main
def test_get_version_no_match_git(tmpdir, working_env):
git = str(tmpdir.join("git"))
with open(git, "w") as f:
f.write("""#!/bin/sh
echo v0.13.3
""")
fs.set_executable(git)
os.environ["PATH"] = str(tmpdir)
assert spack.spack_version == get_version()
def test_get_version_match_git(tmpdir, working_env):
git = str(tmpdir.join("git"))
with open(git, "w") as f:
f.write("""#!/bin/sh
echo v0.13.3-912-g3519a1762
""")
fs.set_executable(git)
os.environ["PATH"] = str(tmpdir)
assert "0.13.3-912-3519a1762" == get_version()
def test_get_version_no_repo(tmpdir, monkeypatch):
monkeypatch.setattr(spack.paths, "prefix", str(tmpdir))
assert spack.spack_version == get_version()
def test_get_version_no_git(tmpdir, working_env):
os.environ["PATH"] = str(tmpdir)
assert spack.spack_version == get_version()
def test_main_calls_get_version(tmpdir, capsys, working_env):
os.environ["PATH"] = str(tmpdir)
main(["-V"])
assert spack.spack_version == capsys.readouterr()[0].strip()
def test_get_version_bad_git(tmpdir, working_env):
bad_git = str(tmpdir.join("git"))
with open(bad_git, "w") as f:
f.write("""#!/bin/sh
exit 1
""")
fs.set_executable(bad_git)
os.environ["PATH"] = str(tmpdir)
assert spack.spack_version == get_version()