dev-build: stop before phase (#14699)

Add `-b,--before` option to dev-build command to stop before the phase in question.
This commit is contained in:
Axel Huebl 2020-04-28 09:55:57 -07:00 committed by GitHub
parent 7670ae468f
commit 00d83cd79d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 67 additions and 8 deletions

View File

@ -37,10 +37,15 @@ def setup_parser(subparser):
subparser.add_argument( subparser.add_argument(
'-q', '--quiet', action='store_true', dest='quiet', '-q', '--quiet', action='store_true', dest='quiet',
help="do not display verbose build output while installing") help="do not display verbose build output while installing")
subparser.add_argument( arguments.add_common_arguments(subparser, ['spec'])
stop_group = subparser.add_mutually_exclusive_group()
stop_group.add_argument(
'-b', '--before', type=str, dest='before', default=None,
help="phase to stop before when installing (default None)")
stop_group.add_argument(
'-u', '--until', type=str, dest='until', default=None, '-u', '--until', type=str, dest='until', default=None,
help="phase to stop after when installing (default None)") help="phase to stop after when installing (default None)")
arguments.add_common_arguments(subparser, ['spec'])
cd_group = subparser.add_mutually_exclusive_group() cd_group = subparser.add_mutually_exclusive_group()
arguments.add_common_arguments(cd_group, ['clean', 'dirty']) arguments.add_common_arguments(cd_group, ['clean', 'dirty'])
@ -91,4 +96,5 @@ def dev_build(self, args):
verbose=not args.quiet, verbose=not args.quiet,
keep_stage=True, # don't remove source dir for dev build. keep_stage=True, # don't remove source dir for dev build.
dirty=args.dirty, dirty=args.dirty,
stop_before=args.before,
stop_at=args.until) stop_at=args.until)

View File

@ -562,6 +562,8 @@ def package_id(pkg):
even with exceptions. even with exceptions.
restage (bool): Force spack to restage the package source. restage (bool): Force spack to restage the package source.
skip_patch (bool): Skip patch stage of build if True. skip_patch (bool): Skip patch stage of build if True.
stop_before (InstallPhase): stop execution before this
installation phase (or None)
stop_at (InstallPhase): last installation phase to be executed stop_at (InstallPhase): last installation phase to be executed
(or None) (or None)
tests (bool or list or set): False to run no tests, True to test tests (bool or list or set): False to run no tests, True to test
@ -779,12 +781,20 @@ def _check_last_phase(self, **kwargs):
Ensures the package being installed has a valid last phase before Ensures the package being installed has a valid last phase before
proceeding with the installation. proceeding with the installation.
The ``stop_at`` argument is removed from the installation arguments. The ``stop_before`` or ``stop_at`` arguments are removed from the
installation arguments.
Args: Args:
kwargs: kwargs:
``stop_before``': stop before execution of this phase (or None)
``stop_at``': last installation phase to be executed (or None) ``stop_at``': last installation phase to be executed (or None)
""" """
self.pkg.stop_before_phase = kwargs.pop('stop_before', None)
if self.pkg.stop_before_phase is not None and \
self.pkg.stop_before_phase not in self.pkg.phases:
tty.die('\'{0}\' is not an allowed phase for package {1}'
.format(self.pkg.stop_before_phase, self.pkg.name))
self.pkg.last_phase = kwargs.pop('stop_at', None) self.pkg.last_phase = kwargs.pop('stop_at', None)
if self.pkg.last_phase is not None and \ if self.pkg.last_phase is not None and \
self.pkg.last_phase not in self.pkg.phases: self.pkg.last_phase not in self.pkg.phases:
@ -1504,8 +1514,10 @@ def install(self, **kwargs):
self._update_installed(task) self._update_installed(task)
# If we installed then we should keep the prefix # If we installed then we should keep the prefix
stop_before_phase = getattr(pkg, 'stop_before_phase', None)
last_phase = getattr(pkg, 'last_phase', None) last_phase = getattr(pkg, 'last_phase', None)
keep_prefix = last_phase is None or keep_prefix keep_prefix = keep_prefix or \
(stop_before_phase is None and last_phase is None)
except spack.directory_layout.InstallDirectoryAlreadyExistsError: except spack.directory_layout.InstallDirectoryAlreadyExistsError:
tty.debug("Keeping existing install prefix in place.") tty.debug("Keeping existing install prefix in place.")

View File

@ -115,7 +115,11 @@ def phase_wrapper(spec, prefix):
return phase_wrapper return phase_wrapper
def _on_phase_start(self, instance): def _on_phase_start(self, instance):
pass # If a phase has a matching stop_before_phase attribute,
# stop the installation process raising a StopIteration
if getattr(instance, 'stop_before_phase', None) == self.name:
raise StopIteration('Stopping before \'{0}\' phase'
.format(self.name))
def _on_phase_exit(self, instance): def _on_phase_exit(self, instance):
# If a phase has a matching last_phase attribute, # If a phase has a matching last_phase attribute,

View File

@ -3,8 +3,9 @@
# #
# SPDX-License-Identifier: (Apache-2.0 OR MIT) # SPDX-License-Identifier: (Apache-2.0 OR MIT)
import os import os
import pytest
import spack.spec import spack.spec
from spack.main import SpackCommand from spack.main import SpackCommand, SpackCommandError
dev_build = SpackCommand('dev-build') dev_build = SpackCommand('dev-build')
@ -23,6 +24,22 @@ def test_dev_build_basics(tmpdir, mock_packages, install_mockery):
assert f.read() == spec.package.replacement_string assert f.read() == spec.package.replacement_string
def test_dev_build_before(tmpdir, mock_packages, install_mockery):
spec = spack.spec.Spec('dev-build-test-install@0.0.0').concretized()
with tmpdir.as_cwd():
with open(spec.package.filename, 'w') as f:
f.write(spec.package.original_string)
dev_build('-b', 'edit', 'dev-build-test-install@0.0.0')
assert spec.package.filename in os.listdir(os.getcwd())
with open(spec.package.filename, 'r') as f:
assert f.read() == spec.package.original_string
assert not os.path.exists(spec.prefix)
def test_dev_build_until(tmpdir, mock_packages, install_mockery): def test_dev_build_until(tmpdir, mock_packages, install_mockery):
spec = spack.spec.Spec('dev-build-test-install@0.0.0').concretized() spec = spack.spec.Spec('dev-build-test-install@0.0.0').concretized()
@ -39,6 +56,26 @@ def test_dev_build_until(tmpdir, mock_packages, install_mockery):
assert not os.path.exists(spec.prefix) assert not os.path.exists(spec.prefix)
def test_dev_build_before_until(tmpdir, mock_packages, install_mockery):
spec = spack.spec.Spec('dev-build-test-install@0.0.0').concretized()
with tmpdir.as_cwd():
with open(spec.package.filename, 'w') as f:
f.write(spec.package.original_string)
with pytest.raises(SystemExit):
dev_build('-u', 'edit', '-b', 'edit',
'dev-build-test-install@0.0.0')
with pytest.raises(SpackCommandError):
dev_build('-u', 'phase_that_does_not_exist',
'dev-build-test-install@0.0.0')
with pytest.raises(SpackCommandError):
dev_build('-b', 'phase_that_does_not_exist',
'dev-build-test-install@0.0.0')
def test_dev_build_fails_already_installed(tmpdir, mock_packages, def test_dev_build_fails_already_installed(tmpdir, mock_packages,
install_mockery): install_mockery):
spec = spack.spec.Spec('dev-build-test-install@0.0.0').concretized() spec = spack.spec.Spec('dev-build-test-install@0.0.0').concretized()

View File

@ -697,7 +697,7 @@ _spack_deprecate() {
_spack_dev_build() { _spack_dev_build() {
if $list_options if $list_options
then then
SPACK_COMPREPLY="-h --help -j --jobs -d --source-path -i --ignore-dependencies -n --no-checksum --keep-prefix --skip-patch -q --quiet -u --until --clean --dirty" SPACK_COMPREPLY="-h --help -j --jobs -d --source-path -i --ignore-dependencies -n --no-checksum --keep-prefix --skip-patch -q --quiet -b --before -u --until --clean --dirty"
else else
_all_packages _all_packages
fi fi
@ -706,7 +706,7 @@ _spack_dev_build() {
_spack_diy() { _spack_diy() {
if $list_options if $list_options
then then
SPACK_COMPREPLY="-h --help -j --jobs -d --source-path -i --ignore-dependencies -n --no-checksum --keep-prefix --skip-patch -q --quiet -u --until --clean --dirty" SPACK_COMPREPLY="-h --help -j --jobs -d --source-path -i --ignore-dependencies -n --no-checksum --keep-prefix --skip-patch -q --quiet -b --before -u --until --clean --dirty"
else else
_all_packages _all_packages
fi fi