summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/spack/llnl/util/tty/colify.py1
-rw-r--r--lib/spack/spack/cmd/buildcache.py26
-rw-r--r--lib/spack/spack/cmd/mirror.py107
-rw-r--r--lib/spack/spack/directives.py61
-rw-r--r--lib/spack/spack/package_base.py36
-rw-r--r--lib/spack/spack/test/cmd/buildcache.py7
-rw-r--r--lib/spack/spack/test/cmd/mirror.py31
-rw-r--r--lib/spack/spack/test/conftest.py11
-rw-r--r--lib/spack/spack/test/directives.py84
-rwxr-xr-xshare/spack/spack-completion.bash6
-rwxr-xr-xshare/spack/spack-completion.fish12
-rw-r--r--var/spack/repos/builtin.mock/packages/no-redistribute-dependent/package.py23
-rw-r--r--var/spack/repos/builtin.mock/packages/no-redistribute/package.py23
-rw-r--r--var/spack/repos/builtin/packages/namd/package.py1
-rw-r--r--var/spack/repos/builtin/packages/nvhpc/package.py2
15 files changed, 363 insertions, 68 deletions
diff --git a/lib/spack/llnl/util/tty/colify.py b/lib/spack/llnl/util/tty/colify.py
index 719b480e4a..a40b8fb116 100644
--- a/lib/spack/llnl/util/tty/colify.py
+++ b/lib/spack/llnl/util/tty/colify.py
@@ -237,7 +237,6 @@ def colify_table(
def colified(
elts: List[Any],
cols: int = 0,
- output: Optional[IO] = None,
indent: int = 0,
padding: int = 2,
tty: Optional[bool] = None,
diff --git a/lib/spack/spack/cmd/buildcache.py b/lib/spack/spack/cmd/buildcache.py
index 49f3d607d2..543570cf28 100644
--- a/lib/spack/spack/cmd/buildcache.py
+++ b/lib/spack/spack/cmd/buildcache.py
@@ -133,6 +133,11 @@ def setup_parser(subparser: argparse.ArgumentParser):
help="when pushing to an OCI registry, tag an image containing all root specs and their "
"runtime dependencies",
)
+ push.add_argument(
+ "--private",
+ action="store_true",
+ help="for a private mirror, include non-redistributable packages",
+ )
arguments.add_common_arguments(push, ["specs", "jobs"])
push.set_defaults(func=push_fn)
@@ -367,6 +372,25 @@ def _make_pool() -> MaybePool:
return NoPool()
+def _skip_no_redistribute_for_public(specs):
+ remaining_specs = list()
+ removed_specs = list()
+ for spec in specs:
+ if spec.package.redistribute_binary:
+ remaining_specs.append(spec)
+ else:
+ removed_specs.append(spec)
+ if removed_specs:
+ colified_output = tty.colify.colified(list(s.name for s in removed_specs), indent=4)
+ tty.debug(
+ "The following specs will not be added to the binary cache"
+ " because they cannot be redistributed:\n"
+ f"{colified_output}\n"
+ "You can use `--private` to include them."
+ )
+ return remaining_specs
+
+
def push_fn(args):
"""create a binary package and push it to a mirror"""
if args.spec_file:
@@ -417,6 +441,8 @@ def push_fn(args):
root="package" in args.things_to_install,
dependencies="dependencies" in args.things_to_install,
)
+ if not args.private:
+ specs = _skip_no_redistribute_for_public(specs)
# When pushing multiple specs, print the url once ahead of time, as well as how
# many specs are being pushed.
diff --git a/lib/spack/spack/cmd/mirror.py b/lib/spack/spack/cmd/mirror.py
index 4b7fa90e55..d25a9018e8 100644
--- a/lib/spack/spack/cmd/mirror.py
+++ b/lib/spack/spack/cmd/mirror.py
@@ -71,6 +71,11 @@ def setup_parser(subparser):
help="the number of versions to fetch for each spec, choose 'all' to"
" retrieve all versions of each package",
)
+ create_parser.add_argument(
+ "--private",
+ action="store_true",
+ help="for a private mirror, include non-redistributable packages",
+ )
arguments.add_common_arguments(create_parser, ["specs"])
arguments.add_concretizer_args(create_parser)
@@ -359,7 +364,6 @@ def concrete_specs_from_user(args):
specs = filter_externals(specs)
specs = list(set(specs))
specs.sort(key=lambda s: (s.name, s.version))
- specs, _ = lang.stable_partition(specs, predicate_fn=not_excluded_fn(args))
return specs
@@ -404,36 +408,50 @@ def concrete_specs_from_cli_or_file(args):
return specs
-def not_excluded_fn(args):
- """Return a predicate that evaluate to True if a spec was not explicitly
- excluded by the user.
- """
- exclude_specs = []
- if args.exclude_file:
- exclude_specs.extend(specs_from_text_file(args.exclude_file, concretize=False))
- if args.exclude_specs:
- exclude_specs.extend(spack.cmd.parse_specs(str(args.exclude_specs).split()))
-
- def not_excluded(x):
- return not any(x.satisfies(y) for y in exclude_specs)
+class IncludeFilter:
+ def __init__(self, args):
+ self.exclude_specs = []
+ if args.exclude_file:
+ self.exclude_specs.extend(specs_from_text_file(args.exclude_file, concretize=False))
+ if args.exclude_specs:
+ self.exclude_specs.extend(spack.cmd.parse_specs(str(args.exclude_specs).split()))
+ self.private = args.private
+
+ def __call__(self, x):
+ return all([self._not_license_excluded(x), self._not_cmdline_excluded(x)])
+
+ def _not_license_excluded(self, x):
+ """True if the spec is for a private mirror, or as long as the
+ package does not explicitly forbid redistributing source."""
+ if self.private:
+ return True
+ elif x.package_class.redistribute_source(x):
+ return True
+ else:
+ tty.debug(
+ "Skip adding {0} to mirror: the package.py file"
+ " indicates that a public mirror should not contain"
+ " it.".format(x.name)
+ )
+ return False
- return not_excluded
+ def _not_cmdline_excluded(self, x):
+ """True if a spec was not explicitly excluded by the user."""
+ return not any(x.satisfies(y) for y in self.exclude_specs)
-def concrete_specs_from_environment(selection_fn):
+def concrete_specs_from_environment():
env = ev.active_environment()
assert env, "an active environment is required"
mirror_specs = env.all_specs()
mirror_specs = filter_externals(mirror_specs)
- mirror_specs, _ = lang.stable_partition(mirror_specs, predicate_fn=selection_fn)
return mirror_specs
-def all_specs_with_all_versions(selection_fn):
+def all_specs_with_all_versions():
specs = [spack.spec.Spec(n) for n in spack.repo.all_package_names()]
mirror_specs = spack.mirror.get_all_versions(specs)
mirror_specs.sort(key=lambda s: (s.name, s.version))
- mirror_specs, _ = lang.stable_partition(mirror_specs, predicate_fn=selection_fn)
return mirror_specs
@@ -454,12 +472,6 @@ def versions_per_spec(args):
return num_versions
-def create_mirror_for_individual_specs(mirror_specs, path, skip_unstable_versions):
- present, mirrored, error = spack.mirror.create(path, mirror_specs, skip_unstable_versions)
- tty.msg("Summary for mirror in {}".format(path))
- process_mirror_stats(present, mirrored, error)
-
-
def process_mirror_stats(present, mirrored, error):
p, m, e = len(present), len(mirrored), len(error)
tty.msg(
@@ -505,30 +517,28 @@ def mirror_create(args):
# When no directory is provided, the source dir is used
path = args.directory or spack.caches.fetch_cache_location()
- if args.all and not ev.active_environment():
- create_mirror_for_all_specs(
- path=path,
- skip_unstable_versions=args.skip_unstable_versions,
- selection_fn=not_excluded_fn(args),
- )
- return
+ mirror_specs, mirror_fn = _specs_and_action(args)
+ mirror_fn(mirror_specs, path=path, skip_unstable_versions=args.skip_unstable_versions)
- if args.all and ev.active_environment():
- create_mirror_for_all_specs_inside_environment(
- path=path,
- skip_unstable_versions=args.skip_unstable_versions,
- selection_fn=not_excluded_fn(args),
- )
- return
- mirror_specs = concrete_specs_from_user(args)
- create_mirror_for_individual_specs(
- mirror_specs, path=path, skip_unstable_versions=args.skip_unstable_versions
- )
+def _specs_and_action(args):
+ include_fn = IncludeFilter(args)
+
+ if args.all and not ev.active_environment():
+ mirror_specs = all_specs_with_all_versions()
+ mirror_fn = create_mirror_for_all_specs
+ elif args.all and ev.active_environment():
+ mirror_specs = concrete_specs_from_environment()
+ mirror_fn = create_mirror_for_individual_specs
+ else:
+ mirror_specs = concrete_specs_from_user(args)
+ mirror_fn = create_mirror_for_individual_specs
+ mirror_specs, _ = lang.stable_partition(mirror_specs, predicate_fn=include_fn)
+ return mirror_specs, mirror_fn
-def create_mirror_for_all_specs(path, skip_unstable_versions, selection_fn):
- mirror_specs = all_specs_with_all_versions(selection_fn=selection_fn)
+
+def create_mirror_for_all_specs(mirror_specs, path, skip_unstable_versions):
mirror_cache, mirror_stats = spack.mirror.mirror_cache_and_stats(
path, skip_unstable_versions=skip_unstable_versions
)
@@ -540,11 +550,10 @@ def create_mirror_for_all_specs(path, skip_unstable_versions, selection_fn):
process_mirror_stats(*mirror_stats.stats())
-def create_mirror_for_all_specs_inside_environment(path, skip_unstable_versions, selection_fn):
- mirror_specs = concrete_specs_from_environment(selection_fn=selection_fn)
- create_mirror_for_individual_specs(
- mirror_specs, path=path, skip_unstable_versions=skip_unstable_versions
- )
+def create_mirror_for_individual_specs(mirror_specs, path, skip_unstable_versions):
+ present, mirrored, error = spack.mirror.create(path, mirror_specs, skip_unstable_versions)
+ tty.msg("Summary for mirror in {}".format(path))
+ process_mirror_stats(present, mirrored, error)
def mirror_destroy(args):
diff --git a/lib/spack/spack/directives.py b/lib/spack/spack/directives.py
index b1f5526d22..4991040142 100644
--- a/lib/spack/spack/directives.py
+++ b/lib/spack/spack/directives.py
@@ -27,6 +27,7 @@ The available directives are:
* ``variant``
* ``version``
* ``requires``
+ * ``redistribute``
"""
import collections
@@ -63,6 +64,7 @@ if TYPE_CHECKING:
__all__ = [
"DirectiveError",
"DirectiveMeta",
+ "DisableRedistribute",
"version",
"conflicts",
"depends_on",
@@ -75,6 +77,7 @@ __all__ = [
"resource",
"build_system",
"requires",
+ "redistribute",
]
#: These are variant names used by Spack internally; packages can't use them
@@ -598,6 +601,64 @@ def depends_on(
return _execute_depends_on
+#: Store whether a given Spec source/binary should not be redistributed.
+class DisableRedistribute:
+ def __init__(self, source, binary):
+ self.source = source
+ self.binary = binary
+
+
+@directive("disable_redistribute")
+def redistribute(source=None, binary=None, when: WhenType = None):
+ """Can be used inside a Package definition to declare that
+ the package source and/or compiled binaries should not be
+ redistributed.
+
+ By default, Packages allow source/binary distribution (i.e. in
+ mirrors). Because of this, and because overlapping enable/
+ disable specs are not allowed, this directive only allows users
+ to explicitly disable redistribution for specs.
+ """
+
+ return lambda pkg: _execute_redistribute(pkg, source, binary, when)
+
+
+def _execute_redistribute(
+ pkg: "spack.package_base.PackageBase", source=None, binary=None, when: WhenType = None
+):
+ if source is None and binary is None:
+ return
+ elif (source is True) or (binary is True):
+ raise DirectiveError(
+ "Source/binary distribution are true by default, they can only "
+ "be explicitly disabled."
+ )
+
+ if source is None:
+ source = True
+ if binary is None:
+ binary = True
+
+ when_spec = _make_when_spec(when)
+ if not when_spec:
+ return
+ if source is False:
+ max_constraint = spack.spec.Spec(f"{pkg.name}@{when_spec.versions}")
+ if not max_constraint.satisfies(when_spec):
+ raise DirectiveError("Source distribution can only be disabled for versions")
+
+ if when_spec in pkg.disable_redistribute:
+ disable = pkg.disable_redistribute[when_spec]
+ if not source:
+ disable.source = True
+ if not binary:
+ disable.binary = True
+ else:
+ pkg.disable_redistribute[when_spec] = DisableRedistribute(
+ source=not source, binary=not binary
+ )
+
+
@directive(("extendees", "dependencies"))
def extends(spec, when=None, type=("build", "run"), patches=None):
"""Same as depends_on, but also adds this package to the extendee list.
diff --git a/lib/spack/spack/package_base.py b/lib/spack/spack/package_base.py
index 89b45ff65f..0be36f08ea 100644
--- a/lib/spack/spack/package_base.py
+++ b/lib/spack/spack/package_base.py
@@ -468,7 +468,41 @@ def _names(when_indexed_dictionary):
return sorted(all_names)
-class PackageBase(WindowsRPath, PackageViewMixin, metaclass=PackageMeta):
+class RedistributionMixin:
+ """Logic for determining whether a Package is source/binary
+ redistributable.
+ """
+
+ #: Store whether a given Spec source/binary should not be
+ #: redistributed.
+ disable_redistribute: Dict["spack.spec.Spec", "spack.directives.DisableRedistribute"]
+
+ # Source redistribution must be determined before concretization
+ # (because source mirrors work with un-concretized Specs).
+ @classmethod
+ def redistribute_source(cls, spec):
+ """Whether it should be possible to add the source of this
+ package to a Spack mirror.
+ """
+ for when_spec, disable_redistribute in cls.disable_redistribute.items():
+ if disable_redistribute.source and spec.satisfies(when_spec):
+ return False
+
+ return True
+
+ @property
+ def redistribute_binary(self):
+ """Whether it should be possible to create a binary out of an
+ installed instance of this package.
+ """
+ for when_spec, disable_redistribute in self.__class__.disable_redistribute.items():
+ if disable_redistribute.binary and self.spec.satisfies(when_spec):
+ return False
+
+ return True
+
+
+class PackageBase(WindowsRPath, PackageViewMixin, RedistributionMixin, metaclass=PackageMeta):
"""This is the superclass for all spack packages.
***The Package class***
diff --git a/lib/spack/spack/test/cmd/buildcache.py b/lib/spack/spack/test/cmd/buildcache.py
index 40d2cbccba..b72d753fc3 100644
--- a/lib/spack/spack/test/cmd/buildcache.py
+++ b/lib/spack/spack/test/cmd/buildcache.py
@@ -446,3 +446,10 @@ def test_push_and_install_with_mirror_marked_unsigned_does_not_require_extra_fla
spec.package.do_uninstall(force=True)
spec.package.do_install(**kwargs)
+
+
+def test_skip_no_redistribute(mock_packages, config):
+ specs = list(Spec("no-redistribute-dependent").concretized().traverse())
+ filtered = spack.cmd.buildcache._skip_no_redistribute_for_public(specs)
+ assert not any(s.name == "no-redistribute" for s in filtered)
+ assert any(s.name == "no-redistribute-dependent" for s in filtered)
diff --git a/lib/spack/spack/test/cmd/mirror.py b/lib/spack/spack/test/cmd/mirror.py
index fe0a996e14..b5dec9c4bc 100644
--- a/lib/spack/spack/test/cmd/mirror.py
+++ b/lib/spack/spack/test/cmd/mirror.py
@@ -88,6 +88,7 @@ class MockMirrorArgs:
exclude_file=None,
exclude_specs=None,
directory=None,
+ private=False,
):
self.specs = specs or []
self.all = all
@@ -96,6 +97,7 @@ class MockMirrorArgs:
self.dependencies = dependencies
self.exclude_file = exclude_file
self.exclude_specs = exclude_specs
+ self.private = private
self.directory = directory
@@ -104,7 +106,7 @@ def test_exclude_specs(mock_packages, config):
specs=["mpich"], versions_per_spec="all", exclude_specs="mpich@3.0.1:3.0.2 mpich@1.0"
)
- mirror_specs = spack.cmd.mirror.concrete_specs_from_user(args)
+ mirror_specs, _ = spack.cmd.mirror._specs_and_action(args)
expected_include = set(
spack.spec.Spec(x).concretized() for x in ["mpich@3.0.3", "mpich@3.0.4", "mpich@3.0"]
)
@@ -113,6 +115,19 @@ def test_exclude_specs(mock_packages, config):
assert not any(spec.satisfies(y) for spec in mirror_specs for y in expected_exclude)
+def test_exclude_specs_public_mirror(mock_packages, config):
+ args = MockMirrorArgs(
+ specs=["no-redistribute-dependent"],
+ versions_per_spec="all",
+ dependencies=True,
+ private=False,
+ )
+
+ mirror_specs, _ = spack.cmd.mirror._specs_and_action(args)
+ assert not any(s.name == "no-redistribute" for s in mirror_specs)
+ assert any(s.name == "no-redistribute-dependent" for s in mirror_specs)
+
+
def test_exclude_file(mock_packages, tmpdir, config):
exclude_path = os.path.join(str(tmpdir), "test-exclude.txt")
with open(exclude_path, "w") as exclude_file:
@@ -125,7 +140,7 @@ mpich@1.0
args = MockMirrorArgs(specs=["mpich"], versions_per_spec="all", exclude_file=exclude_path)
- mirror_specs = spack.cmd.mirror.concrete_specs_from_user(args)
+ mirror_specs, _ = spack.cmd.mirror._specs_and_action(args)
expected_include = set(
spack.spec.Spec(x).concretized() for x in ["mpich@3.0.3", "mpich@3.0.4", "mpich@3.0"]
)
@@ -262,11 +277,9 @@ def test_mirror_destroy(
class TestMirrorCreate:
@pytest.mark.regression("31736", "31985")
def test_all_specs_with_all_versions_dont_concretize(self):
- args = MockMirrorArgs(exclude_file=None, exclude_specs=None)
- specs = spack.cmd.mirror.all_specs_with_all_versions(
- selection_fn=spack.cmd.mirror.not_excluded_fn(args)
- )
- assert all(not s.concrete for s in specs)
+ args = MockMirrorArgs(all=True, exclude_file=None, exclude_specs=None)
+ mirror_specs, _ = spack.cmd.mirror._specs_and_action(args)
+ assert all(not s.concrete for s in mirror_specs)
@pytest.mark.parametrize(
"cli_args,error_str",
@@ -324,8 +337,8 @@ class TestMirrorCreate:
],
)
def test_exclude_specs_from_user(self, cli_args, not_expected, config):
- specs = spack.cmd.mirror.concrete_specs_from_user(MockMirrorArgs(**cli_args))
- assert not any(s.satisfies(y) for s in specs for y in not_expected)
+ mirror_specs, _ = spack.cmd.mirror._specs_and_action(MockMirrorArgs(**cli_args))
+ assert not any(s.satisfies(y) for s in mirror_specs for y in not_expected)
@pytest.mark.parametrize("abstract_specs", [("bowtie", "callpath")])
def test_specs_from_cli_are_the_same_as_from_file(self, abstract_specs, config, tmpdir):
diff --git a/lib/spack/spack/test/conftest.py b/lib/spack/spack/test/conftest.py
index c8c300ca95..35dfff5193 100644
--- a/lib/spack/spack/test/conftest.py
+++ b/lib/spack/spack/test/conftest.py
@@ -1966,17 +1966,24 @@ def mock_modules_root(tmp_path, monkeypatch):
monkeypatch.setattr(spack.modules.common, "root_path", fn)
+_repo_name_id = 0
+
+
def create_test_repo(tmpdir, pkg_name_content_tuples):
+ global _repo_name_id
+
repo_path = str(tmpdir)
repo_yaml = tmpdir.join("repo.yaml")
with open(str(repo_yaml), "w") as f:
f.write(
- """\
+ f"""\
repo:
- namespace: testcfgrequirements
+ namespace: testrepo{str(_repo_name_id)}
"""
)
+ _repo_name_id += 1
+
packages_dir = tmpdir.join("packages")
for pkg_name, pkg_str in pkg_name_content_tuples:
pkg_dir = packages_dir.ensure(pkg_name, dir=True)
diff --git a/lib/spack/spack/test/directives.py b/lib/spack/spack/test/directives.py
index ca7b3b7c7a..6ae60b4f39 100644
--- a/lib/spack/spack/test/directives.py
+++ b/lib/spack/spack/test/directives.py
@@ -10,6 +10,7 @@ import spack.directives
import spack.repo
import spack.spec
import spack.version
+from spack.test.conftest import create_test_repo
def test_false_directives_do_not_exist(mock_packages):
@@ -142,3 +143,86 @@ def test_version_type_validation():
# Try passing a bogus type; it's just that we want a nice error message
with pytest.raises(spack.version.VersionError, match=msg):
spack.directives._execute_version(package(name="python"), {})
+
+
+_pkgx = (
+ "x",
+ """\
+class X(Package):
+ version("1.3")
+ version("1.2")
+ version("1.1")
+ version("1.0")
+
+ variant("foo", default=False)
+
+ redistribute(binary=False, when="@1.1")
+ redistribute(binary=False, when="@1.0:1.2+foo")
+ redistribute(source=False, when="@1.0:1.2")
+""",
+)
+
+
+_pkgy = (
+ "y",
+ """\
+class Y(Package):
+ version("2.1")
+ version("2.0")
+
+ variant("bar", default=False)
+
+ redistribute(binary=False, source=False)
+""",
+)
+
+
+@pytest.fixture
+def _create_test_repo(tmpdir, mutable_config):
+ yield create_test_repo(tmpdir, [_pkgx, _pkgy])
+
+
+@pytest.fixture
+def test_repo(_create_test_repo, monkeypatch, mock_stage):
+ with spack.repo.use_repositories(_create_test_repo) as mock_repo_path:
+ yield mock_repo_path
+
+
+@pytest.mark.parametrize(
+ "spec_str,distribute_src,distribute_bin",
+ [
+ ("x@1.1~foo", False, False),
+ ("x@1.2+foo", False, False),
+ ("x@1.2~foo", False, True),
+ ("x@1.0~foo", False, True),
+ ("x@1.3+foo", True, True),
+ ("y@2.0", False, False),
+ ("y@2.1+bar", False, False),
+ ],
+)
+def test_redistribute_directive(test_repo, spec_str, distribute_src, distribute_bin):
+ spec = spack.spec.Spec(spec_str)
+ assert spec.package_class.redistribute_source(spec) == distribute_src
+ concretized_spec = spec.concretized()
+ assert concretized_spec.package.redistribute_binary == distribute_bin
+
+
+def test_redistribute_override_when():
+ """Allow a user to call `redistribute` twice to separately disable
+ source and binary distribution for the same when spec.
+
+ The second call should not undo the effect of the first.
+ """
+
+ class MockPackage:
+ name = "mock"
+ disable_redistribute = {}
+
+ cls = MockPackage
+ spack.directives._execute_redistribute(cls, source=False, when="@1.0")
+ spec_key = spack.directives._make_when_spec("@1.0")
+ assert not cls.disable_redistribute[spec_key].binary
+ assert cls.disable_redistribute[spec_key].source
+ spack.directives._execute_redistribute(cls, binary=False, when="@1.0")
+ assert cls.disable_redistribute[spec_key].binary
+ assert cls.disable_redistribute[spec_key].source
diff --git a/share/spack/spack-completion.bash b/share/spack/spack-completion.bash
index 09043cec22..335748cb75 100755
--- a/share/spack/spack-completion.bash
+++ b/share/spack/spack-completion.bash
@@ -571,7 +571,7 @@ _spack_buildcache() {
_spack_buildcache_push() {
if $list_options
then
- SPACK_COMPREPLY="-h --help -f --force --allow-root -a --unsigned -u --signed --key -k --update-index --rebuild-index --spec-file --only --fail-fast --base-image --tag -t -j --jobs"
+ SPACK_COMPREPLY="-h --help -f --force --allow-root -a --unsigned -u --signed --key -k --update-index --rebuild-index --spec-file --only --fail-fast --base-image --tag -t --private -j --jobs"
else
_mirrors
fi
@@ -580,7 +580,7 @@ _spack_buildcache_push() {
_spack_buildcache_create() {
if $list_options
then
- SPACK_COMPREPLY="-h --help -f --force --allow-root -a --unsigned -u --signed --key -k --update-index --rebuild-index --spec-file --only --fail-fast --base-image --tag -t -j --jobs"
+ SPACK_COMPREPLY="-h --help -f --force --allow-root -a --unsigned -u --signed --key -k --update-index --rebuild-index --spec-file --only --fail-fast --base-image --tag -t --private -j --jobs"
else
_mirrors
fi
@@ -1428,7 +1428,7 @@ _spack_mirror() {
_spack_mirror_create() {
if $list_options
then
- SPACK_COMPREPLY="-h --help -d --directory -a --all -f --file --exclude-file --exclude-specs --skip-unstable-versions -D --dependencies -n --versions-per-spec -U --fresh --reuse --reuse-deps --deprecated"
+ SPACK_COMPREPLY="-h --help -d --directory -a --all -f --file --exclude-file --exclude-specs --skip-unstable-versions -D --dependencies -n --versions-per-spec --private -U --fresh --reuse --reuse-deps --deprecated"
else
_all_packages
fi
diff --git a/share/spack/spack-completion.fish b/share/spack/spack-completion.fish
index e4b8689e55..d69f58d701 100755
--- a/share/spack/spack-completion.fish
+++ b/share/spack/spack-completion.fish
@@ -700,7 +700,7 @@ complete -c spack -n '__fish_spack_using_command buildcache' -s h -l help -f -a
complete -c spack -n '__fish_spack_using_command buildcache' -s h -l help -d 'show this help message and exit'
# spack buildcache push
-set -g __fish_spack_optspecs_spack_buildcache_push h/help f/force a/allow-root u/unsigned signed k/key= update-index spec-file= only= fail-fast base-image= t/tag= j/jobs=
+set -g __fish_spack_optspecs_spack_buildcache_push h/help f/force a/allow-root u/unsigned signed k/key= update-index spec-file= only= fail-fast base-image= t/tag= private j/jobs=
complete -c spack -n '__fish_spack_using_command_pos_remainder 1 buildcache push' -f -k -a '(__fish_spack_specs)'
complete -c spack -n '__fish_spack_using_command buildcache push' -s h -l help -f -a help
complete -c spack -n '__fish_spack_using_command buildcache push' -s h -l help -d 'show this help message and exit'
@@ -726,11 +726,13 @@ complete -c spack -n '__fish_spack_using_command buildcache push' -l base-image
complete -c spack -n '__fish_spack_using_command buildcache push' -l base-image -r -d 'specify the base image for the buildcache'
complete -c spack -n '__fish_spack_using_command buildcache push' -l tag -s t -r -f -a tag
complete -c spack -n '__fish_spack_using_command buildcache push' -l tag -s t -r -d 'when pushing to an OCI registry, tag an image containing all root specs and their runtime dependencies'
+complete -c spack -n '__fish_spack_using_command buildcache push' -l private -f -a private
+complete -c spack -n '__fish_spack_using_command buildcache push' -l private -d 'for a private mirror, include non-redistributable packages'
complete -c spack -n '__fish_spack_using_command buildcache push' -s j -l jobs -r -f -a jobs
complete -c spack -n '__fish_spack_using_command buildcache push' -s j -l jobs -r -d 'explicitly set number of parallel jobs'
# spack buildcache create
-set -g __fish_spack_optspecs_spack_buildcache_create h/help f/force a/allow-root u/unsigned signed k/key= update-index spec-file= only= fail-fast base-image= t/tag= j/jobs=
+set -g __fish_spack_optspecs_spack_buildcache_create h/help f/force a/allow-root u/unsigned signed k/key= update-index spec-file= only= fail-fast base-image= t/tag= private j/jobs=
complete -c spack -n '__fish_spack_using_command_pos_remainder 1 buildcache create' -f -k -a '(__fish_spack_specs)'
complete -c spack -n '__fish_spack_using_command buildcache create' -s h -l help -f -a help
complete -c spack -n '__fish_spack_using_command buildcache create' -s h -l help -d 'show this help message and exit'
@@ -756,6 +758,8 @@ complete -c spack -n '__fish_spack_using_command buildcache create' -l base-imag
complete -c spack -n '__fish_spack_using_command buildcache create' -l base-image -r -d 'specify the base image for the buildcache'
complete -c spack -n '__fish_spack_using_command buildcache create' -l tag -s t -r -f -a tag
complete -c spack -n '__fish_spack_using_command buildcache create' -l tag -s t -r -d 'when pushing to an OCI registry, tag an image containing all root specs and their runtime dependencies'
+complete -c spack -n '__fish_spack_using_command buildcache create' -l private -f -a private
+complete -c spack -n '__fish_spack_using_command buildcache create' -l private -d 'for a private mirror, include non-redistributable packages'
complete -c spack -n '__fish_spack_using_command buildcache create' -s j -l jobs -r -f -a jobs
complete -c spack -n '__fish_spack_using_command buildcache create' -s j -l jobs -r -d 'explicitly set number of parallel jobs'
@@ -2216,7 +2220,7 @@ complete -c spack -n '__fish_spack_using_command mirror' -s n -l no-checksum -f
complete -c spack -n '__fish_spack_using_command mirror' -s n -l no-checksum -d 'do not use checksums to verify downloaded files (unsafe)'
# spack mirror create
-set -g __fish_spack_optspecs_spack_mirror_create h/help d/directory= a/all f/file= exclude-file= exclude-specs= skip-unstable-versions D/dependencies n/versions-per-spec= U/fresh reuse reuse-deps deprecated
+set -g __fish_spack_optspecs_spack_mirror_create h/help d/directory= a/all f/file= exclude-file= exclude-specs= skip-unstable-versions D/dependencies n/versions-per-spec= private U/fresh reuse reuse-deps deprecated
complete -c spack -n '__fish_spack_using_command_pos_remainder 0 mirror create' -f -k -a '(__fish_spack_specs)'
complete -c spack -n '__fish_spack_using_command mirror create' -s h -l help -f -a help
complete -c spack -n '__fish_spack_using_command mirror create' -s h -l help -d 'show this help message and exit'
@@ -2236,6 +2240,8 @@ complete -c spack -n '__fish_spack_using_command mirror create' -s D -l dependen
complete -c spack -n '__fish_spack_using_command mirror create' -s D -l dependencies -d 'also fetch all dependencies'
complete -c spack -n '__fish_spack_using_command mirror create' -s n -l versions-per-spec -r -f -a versions_per_spec
complete -c spack -n '__fish_spack_using_command mirror create' -s n -l versions-per-spec -r -d 'the number of versions to fetch for each spec, choose \'all\' to retrieve all versions of each package'
+complete -c spack -n '__fish_spack_using_command mirror create' -l private -f -a private
+complete -c spack -n '__fish_spack_using_command mirror create' -l private -d 'for a private mirror, include non-redistributable packages'
complete -c spack -n '__fish_spack_using_command mirror create' -s U -l fresh -f -a concretizer_reuse
complete -c spack -n '__fish_spack_using_command mirror create' -s U -l fresh -d 'do not reuse installed deps; build newest configuration'
complete -c spack -n '__fish_spack_using_command mirror create' -l reuse -f -a concretizer_reuse
diff --git a/var/spack/repos/builtin.mock/packages/no-redistribute-dependent/package.py b/var/spack/repos/builtin.mock/packages/no-redistribute-dependent/package.py
new file mode 100644
index 0000000000..a362b84ab8
--- /dev/null
+++ b/var/spack/repos/builtin.mock/packages/no-redistribute-dependent/package.py
@@ -0,0 +1,23 @@
+# Copyright 2013-2024 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)
+
+from spack.package import *
+
+
+class NoRedistributeDependent(AutotoolsPackage):
+ """Package with one dependency on a package that should not be
+ redistributed"""
+
+ homepage = "http://www.example.com"
+ url = "http://www.example.com/no-redistribute-dependent-1.0.tar.gz"
+
+ version("1.0", "0123456789abcdef0123456789abcdef")
+
+ depends_on("no-redistribute")
+
+ def install(self, spec, prefix):
+ # sanity_check_prefix requires something in the install directory
+ # Test requires overriding the one provided by `AutotoolsPackage`
+ mkdirp(prefix.bin)
diff --git a/var/spack/repos/builtin.mock/packages/no-redistribute/package.py b/var/spack/repos/builtin.mock/packages/no-redistribute/package.py
new file mode 100644
index 0000000000..b9dfd5fae3
--- /dev/null
+++ b/var/spack/repos/builtin.mock/packages/no-redistribute/package.py
@@ -0,0 +1,23 @@
+# Copyright 2013-2024 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)
+
+from spack.package import *
+
+
+class NoRedistribute(Package):
+ """Package which has source code that should not be added to a public
+ mirror"""
+
+ homepage = "http://www.example.com"
+ url = "http://www.example.com/no-redistribute-1.0.tar.gz"
+
+ redistribute(source=False, binary=False)
+
+ version("1.0", "0123456789abcdef0123456789abcdef")
+
+ def install(self, spec, prefix):
+ # sanity_check_prefix requires something in the install directory
+ # Test requires overriding the one provided by `AutotoolsPackage`
+ mkdirp(prefix.bin)
diff --git a/var/spack/repos/builtin/packages/namd/package.py b/var/spack/repos/builtin/packages/namd/package.py
index 9d9d87b250..ae47ddd46b 100644
--- a/var/spack/repos/builtin/packages/namd/package.py
+++ b/var/spack/repos/builtin/packages/namd/package.py
@@ -20,6 +20,7 @@ class Namd(MakefilePackage, CudaPackage):
url = "file://{0}/NAMD_2.12_Source.tar.gz".format(os.getcwd())
git = "https://charm.cs.illinois.edu/gerrit/namd.git"
manual_download = True
+ redistribute(source=False, binary=False)
maintainers("jcphill")
diff --git a/var/spack/repos/builtin/packages/nvhpc/package.py b/var/spack/repos/builtin/packages/nvhpc/package.py
index 4531965a18..d627548cd5 100644
--- a/var/spack/repos/builtin/packages/nvhpc/package.py
+++ b/var/spack/repos/builtin/packages/nvhpc/package.py
@@ -390,6 +390,8 @@ class Nvhpc(Package):
skip_version_audit = ["platform=darwin"]
+ redistribute(source=False, binary=False)
+
for ver, packages in _versions.items():
key = "{0}-{1}".format(platform.system(), platform.machine())
pkg = packages.get(key)