cmd/checksum: allow adding new versions to package (#24532)

This adds super-lazy maintainer mode to `spack checksum`: Instead of
only printing the new checksums to the terminal, `-a` and
`--add-to-package` will add the new checksums to the `package.py` file
and open it in the editor afterwards for final checks.
This commit is contained in:
Michael Kuhn
2022-11-23 01:30:49 +01:00
committed by GitHub
parent c5883fffd7
commit 0fd3c9f451
4 changed files with 99 additions and 9 deletions

View File

@@ -6,6 +6,7 @@
from __future__ import print_function
import argparse
import sys
import llnl.util.tty as tty
@@ -16,6 +17,7 @@
import spack.stage
import spack.util.crypto
from spack.package_base import deprecated_version, preferred_version
from spack.util.editor import editor
from spack.util.naming import valid_fully_qualified_module_name
from spack.version import VersionBase, ver
@@ -53,6 +55,13 @@ def setup_parser(subparser):
default=False,
help="checksum the preferred version only",
)
subparser.add_argument(
"-a",
"--add-to-package",
action="store_true",
default=False,
help="add new versions to package",
)
arguments.add_common_arguments(subparser, ["package"])
subparser.add_argument(
"versions", nargs=argparse.REMAINDER, help="versions to generate checksums for"
@@ -118,3 +127,46 @@ def checksum(parser, args):
print()
print(version_lines)
print()
if args.add_to_package:
filename = spack.repo.path.filename_for_package_name(pkg.name)
# Make sure we also have a newline after the last version
versions = [v + "\n" for v in version_lines.splitlines()]
versions.append("\n")
# We need to insert the versions in reversed order
versions.reverse()
versions.append(" # FIXME: Added by `spack checksum`\n")
version_line = None
with open(filename, "r") as f:
lines = f.readlines()
for i in range(len(lines)):
# Black is drunk, so this is what it looks like for now
# See https://github.com/psf/black/issues/2156 for more information
if lines[i].startswith(" # FIXME: Added by `spack checksum`") or lines[
i
].startswith(" version("):
version_line = i
break
if version_line is not None:
for v in versions:
lines.insert(version_line, v)
with open(filename, "w") as f:
f.writelines(lines)
msg = "opening editor to verify"
if not sys.stdout.isatty():
msg = "please verify"
tty.info(
"Added {0} new versions to {1}, "
"{2}.".format(len(versions) - 2, args.package, msg)
)
if sys.stdout.isatty():
editor(filename)
else:
tty.warn("Could not add new versions to {0}.".format(args.package))

View File

@@ -20,16 +20,17 @@
@pytest.mark.parametrize(
"arguments,expected",
[
(["--batch", "patch"], (True, False, False)),
(["--latest", "patch"], (False, True, False)),
(["--preferred", "patch"], (False, False, True)),
(["--batch", "patch"], (True, False, False, False)),
(["--latest", "patch"], (False, True, False, False)),
(["--preferred", "patch"], (False, False, True, False)),
(["--add-to-package", "patch"], (False, False, False, True)),
],
)
def test_checksum_args(arguments, expected):
parser = argparse.ArgumentParser()
spack.cmd.checksum.setup_parser(parser)
args = parser.parse_args(arguments)
check = args.batch, args.latest, args.preferred
check = args.batch, args.latest, args.preferred, args.add_to_package
assert check == expected
@@ -40,9 +41,10 @@ def test_checksum_args(arguments, expected):
(["--batch", "preferred-test"], "version of preferred-test"),
(["--latest", "preferred-test"], "Found 1 version"),
(["--preferred", "preferred-test"], "Found 1 version"),
(["--add-to-package", "preferred-test"], "Added 1 new versions to"),
],
)
def test_checksum(arguments, expected, mock_packages, mock_stage):
def test_checksum(arguments, expected, mock_packages, mock_clone_repo, mock_stage):
output = spack_checksum(*arguments)
assert expected in output
assert "version(" in output
@@ -62,19 +64,31 @@ def _get_number(*args, **kwargs):
assert "version(" in output
def test_checksum_versions(mock_packages, mock_fetch, mock_stage):
def test_checksum_versions(mock_packages, mock_clone_repo, mock_fetch, mock_stage):
pkg_cls = spack.repo.path.get_pkg_class("preferred-test")
versions = [str(v) for v in pkg_cls.versions if not v.isdevelop()]
output = spack_checksum("preferred-test", versions[0])
assert "Found 1 version" in output
assert "version(" in output
output = spack_checksum("--add-to-package", "preferred-test", versions[0])
assert "Found 1 version" in output
assert "version(" in output
assert "Added 1 new versions to" in output
def test_checksum_missing_version(mock_packages, mock_fetch, mock_stage):
def test_checksum_missing_version(mock_packages, mock_clone_repo, mock_fetch, mock_stage):
output = spack_checksum("preferred-test", "99.99.99", fail_on_error=False)
assert "Could not find any remote versions" in output
output = spack_checksum("--add-to-package", "preferred-test", "99.99.99", fail_on_error=False)
assert "Could not find any remote versions" in output
assert "Added 1 new versions to" not in output
def test_checksum_deprecated_version(mock_packages, mock_fetch, mock_stage):
def test_checksum_deprecated_version(mock_packages, mock_clone_repo, mock_fetch, mock_stage):
output = spack_checksum("deprecated-versions", "1.1.0", fail_on_error=False)
assert "Version 1.1.0 is deprecated" in output
output = spack_checksum(
"--add-to-package", "deprecated-versions", "1.1.0", fail_on_error=False
)
assert "Version 1.1.0 is deprecated" in output
assert "Added 1 new versions to" not in output

View File

@@ -1604,6 +1604,30 @@ def mock_test_repo(tmpdir_factory):
shutil.rmtree(str(repodir))
@pytest.fixture(scope="function")
def mock_clone_repo(tmpdir_factory):
"""Create a cloned repository."""
repo_namespace = "mock_clone_repo"
repodir = tmpdir_factory.mktemp(repo_namespace)
yaml = repodir.join("repo.yaml")
yaml.write(
"""
repo:
namespace: mock_clone_repo
"""
)
shutil.copytree(
os.path.join(spack.paths.mock_packages_path, spack.repo.packages_dir_name),
os.path.join(str(repodir), spack.repo.packages_dir_name),
)
with spack.repo.use_repositories(str(repodir)) as repo:
yield repo, repodir
shutil.rmtree(str(repodir))
##########
# Class and fixture to work around problems raising exceptions in directives,
# which cause tests like test_from_list_url to hang for Python 2.x metaclass