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:
		@@ -37,10 +37,15 @@ def setup_parser(subparser):
 | 
			
		||||
    subparser.add_argument(
 | 
			
		||||
        '-q', '--quiet', action='store_true', dest='quiet',
 | 
			
		||||
        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,
 | 
			
		||||
        help="phase to stop after when installing (default None)")
 | 
			
		||||
    arguments.add_common_arguments(subparser, ['spec'])
 | 
			
		||||
 | 
			
		||||
    cd_group = subparser.add_mutually_exclusive_group()
 | 
			
		||||
    arguments.add_common_arguments(cd_group, ['clean', 'dirty'])
 | 
			
		||||
@@ -91,4 +96,5 @@ def dev_build(self, args):
 | 
			
		||||
        verbose=not args.quiet,
 | 
			
		||||
        keep_stage=True,   # don't remove source dir for dev build.
 | 
			
		||||
        dirty=args.dirty,
 | 
			
		||||
        stop_before=args.before,
 | 
			
		||||
        stop_at=args.until)
 | 
			
		||||
 
 | 
			
		||||
@@ -562,6 +562,8 @@ def package_id(pkg):
 | 
			
		||||
                even with exceptions.
 | 
			
		||||
            restage (bool): Force spack to restage the package source.
 | 
			
		||||
            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
 | 
			
		||||
                (or None)
 | 
			
		||||
            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
 | 
			
		||||
        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:
 | 
			
		||||
            kwargs:
 | 
			
		||||
              ``stop_before``': stop before execution of this phase (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)
 | 
			
		||||
        if self.pkg.last_phase is not None and \
 | 
			
		||||
                self.pkg.last_phase not in self.pkg.phases:
 | 
			
		||||
@@ -1504,8 +1514,10 @@ def install(self, **kwargs):
 | 
			
		||||
                self._update_installed(task)
 | 
			
		||||
 | 
			
		||||
                # 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)
 | 
			
		||||
                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:
 | 
			
		||||
                tty.debug("Keeping existing install prefix in place.")
 | 
			
		||||
 
 | 
			
		||||
@@ -115,7 +115,11 @@ def phase_wrapper(spec, prefix):
 | 
			
		||||
        return phase_wrapper
 | 
			
		||||
 | 
			
		||||
    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):
 | 
			
		||||
        # If a phase has a matching last_phase attribute,
 | 
			
		||||
 
 | 
			
		||||
@@ -3,8 +3,9 @@
 | 
			
		||||
#
 | 
			
		||||
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
 | 
			
		||||
import os
 | 
			
		||||
import pytest
 | 
			
		||||
import spack.spec
 | 
			
		||||
from spack.main import SpackCommand
 | 
			
		||||
from spack.main import SpackCommand, SpackCommandError
 | 
			
		||||
 | 
			
		||||
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
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
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):
 | 
			
		||||
    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)
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
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,
 | 
			
		||||
                                           install_mockery):
 | 
			
		||||
    spec = spack.spec.Spec('dev-build-test-install@0.0.0').concretized()
 | 
			
		||||
 
 | 
			
		||||
@@ -697,7 +697,7 @@ _spack_deprecate() {
 | 
			
		||||
_spack_dev_build() {
 | 
			
		||||
    if $list_options
 | 
			
		||||
    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
 | 
			
		||||
        _all_packages
 | 
			
		||||
    fi
 | 
			
		||||
@@ -706,7 +706,7 @@ _spack_dev_build() {
 | 
			
		||||
_spack_diy() {
 | 
			
		||||
    if $list_options
 | 
			
		||||
    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
 | 
			
		||||
        _all_packages
 | 
			
		||||
    fi
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user