def test_diystage_path_valid(self, tmpdir): """Ensure DIYStage for a valid path behaves as expected.""" path = str(tmpdir) stage = DIYStage(path) assert stage.path == path assert stage.source_path == path # Order doesn't really matter for DIYStage since they are # basically NOOPs; however, call each since they are part # of the normal stage usage and to ensure full test coverage. stage.create() # Only sets the flag value assert stage.created stage.cache_local() # Only outputs a message stage.fetch() # Only outputs a message stage.check() # Only outputs a message stage.expand_archive() # Only outputs a message assert stage.expanded # The path/source_path does exist with pytest.raises(spack.stage.RestageError): stage.restage() stage.destroy() # A no-op assert stage.path == path # Ensure can still access attributes assert os.path.exists(stage.source_path) # Ensure path still exists
def setup(self, args): if not args.spec: tty.die("spack setup requires a package spec argument.") specs = spack.cmd.parse_specs(args.spec) if len(specs) > 1: tty.die("spack setup only takes one spec.") # Take a write lock before checking for existence. with spack.store.db.write_transaction(): spec = specs[0] if not spack.repo.exists(spec.name): tty.die("No package for '{0}' was found.".format(spec.name), " Use `spack create` to create a new package") if not spec.versions.concrete: tty.die( "spack setup spec must have a single, concrete version. " "Did you forget a package version number?") spec.concretize() package = spack.repo.get(spec) if not isinstance(package, spack.CMakePackage): tty.die( 'Support for {0} derived packages not yet implemented'.format( package.build_system_class ) ) # It's OK if the package is already installed. # Forces the build to run out of the current directory. package.stage = DIYStage(os.getcwd()) # TODO: make this an argument, not a global. spack.do_checksum = False # Install dependencies if requested to do so if not args.ignore_deps: parser = argparse.ArgumentParser() install.setup_parser(parser) inst_args = copy.deepcopy(args) inst_args = parser.parse_args( ['--only=dependencies'] + args.spec, namespace=inst_args ) install.install(parser, inst_args) # Generate spconfig.py tty.msg( 'Generating spconfig.py [{0}]'.format(package.spec.cshort_spec) ) write_spconfig(package) # Install this package to register it in the DB and permit # module file regeneration inst_args = copy.deepcopy(args) inst_args = parser.parse_args( ['--only=package', '--fake'] + args.spec, namespace=inst_args ) install.install(parser, inst_args)
def setup(self, args): if not args.spec: tty.die("spack setup requires a package spec argument.") specs = spack.cmd.parse_specs(args.spec) if len(specs) > 1: tty.die("spack setup only takes one spec.") # Take a write lock before checking for existence. with spack.installed_db.write_transaction(): spec = specs[0] if not spack.repo.exists(spec.name): tty.warn("No such package: %s" % spec.name) create = tty.get_yes_or_no("Create this package?", default=False) if not create: tty.msg("Exiting without creating.") sys.exit(1) else: tty.msg("Running 'spack edit -f %s'" % spec.name) edit_package(spec.name, spack.repo.first_repo(), None, True) return if not spec.versions.concrete: tty.die("spack setup spec must have a single, concrete version. " "Did you forget a package version number?") spec.concretize() package = spack.repo.get(spec) if not isinstance(package, spack.CMakePackage): tty.die( 'Support for {0} derived packages not yet implemented'.format( package.build_system_class)) # It's OK if the package is already installed. # Forces the build to run out of the current directory. package.stage = DIYStage(os.getcwd()) # TODO: make this an argument, not a global. spack.do_checksum = False # Install dependencies if requested to do so if not args.ignore_deps: parser = argparse.ArgumentParser() install.setup_parser(parser) inst_args = copy.deepcopy(args) inst_args = parser.parse_args(['--only=dependencies'] + args.spec, namespace=inst_args) install.install(parser, inst_args) # Generate spconfig.py tty.msg('Generating spconfig.py [{0}]'.format( package.spec.cshort_spec)) write_spconfig(package) # Install this package to register it in the DB and permit # module file regeneration inst_args = copy.deepcopy(args) inst_args = parser.parse_args(['--only=package', '--fake'] + args.spec, namespace=inst_args) install.install(parser, inst_args)
def custom_devbuild(source_path, spec, jobs): package = spack.repo.get(spec) package.stage = DIYStage(source_path) if package.installed: package.do_uninstall(force=True) package.do_install(verbose=True, make_jobs=jobs)
def dev_build(self, args): if not args.spec: tty.die("spack dev-build requires a package spec argument.") specs = spack.cmd.parse_specs(args.spec) if len(specs) > 1: tty.die("spack dev-build only takes one spec.") spec = specs[0] if not spack.repo.path.exists(spec.name): tty.die("No package for '{0}' was found.".format(spec.name), " Use `spack create` to create a new package") if not spec.versions.concrete: tty.die("spack dev-build spec must have a single, concrete version. " "Did you forget a package version number?") spec.concretize() package = spack.repo.get(spec) if package.installed: tty.error("Already installed in %s" % package.prefix) tty.msg("Uninstall or try adding a version suffix for this dev build.") sys.exit(1) source_path = args.source_path if source_path is None: source_path = os.getcwd() source_path = os.path.abspath(source_path) # Forces the build to run out of the current directory. package.stage = DIYStage(source_path) # disable checksumming if requested if args.no_checksum: spack.config.set('config:checksum', False, scope='command_line') tests = False if args.test == 'all': tests = True elif args.test == 'root': tests = [spec.name for spec in specs] package.do_install( tests=tests, make_jobs=args.jobs, keep_prefix=args.keep_prefix, install_deps=not args.ignore_deps, 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) # drop into the build environment of the package? if args.shell is not None: spack.build_environment.setup_package(package, dirty=False) os.execvp(args.shell, [args.shell])
def diy(self, args): if not args.spec: tty.die("spack diy requires a package spec argument.") if args.jobs is not None: if args.jobs <= 0: tty.die("the -j option must be a positive integer") specs = spack.cmd.parse_specs(args.spec) if len(specs) > 1: tty.die("spack diy only takes one spec.") spec = specs[0] if not spack.repo.path.exists(spec.name): tty.die("No package for '{0}' was found.".format(spec.name), " Use `spack create` to create a new package") if not spec.versions.concrete: tty.die("spack diy spec must have a single, concrete version. " "Did you forget a package version number?") spec.concretize() package = spack.repo.get(spec) if package.installed: tty.error("Already installed in %s" % package.prefix) tty.msg("Uninstall or try adding a version suffix for this DIY build.") sys.exit(1) source_path = args.source_path if source_path is None: source_path = os.getcwd() source_path = os.path.abspath(source_path) # Forces the build to run out of the current directory. package.stage = DIYStage(source_path) # disable checksumming if requested if args.no_checksum: spack.config.set('config:checksum', False, scope='command_line') package.do_install( make_jobs=args.jobs, keep_prefix=args.keep_prefix, install_deps=not args.ignore_deps, verbose=not args.quiet, keep_stage=True, # don't remove source dir for DIY. dirty=args.dirty)
def diy(self, args): if not args.spec: tty.die("spack diy requires a package spec argument.") specs = spack.cmd.parse_specs(args.spec) if len(specs) > 1: tty.die("spack diy only takes one spec.") # Take a write lock before checking for existence. with spack.installed_db.write_transaction(): spec = specs[0] if not spack.repo.exists(spec.name): tty.warn("No such package: %s" % spec.name) create = tty.get_yes_or_no("Create this package?", default=False) if not create: tty.msg("Exiting without creating.") sys.exit(1) else: tty.msg("Running 'spack edit -f %s'" % spec.name) edit_package(spec.name, spack.repo.first_repo(), None, True) return if not spec.versions.concrete: tty.die( "spack diy spec must have a single, concrete version. Did you forget a package version number?" ) spec.concretize() package = spack.repo.get(spec) if package.installed: tty.error("Already installed in %s" % package.prefix) tty.msg( "Uninstall or try adding a version suffix for this DIY build.") sys.exit(1) # Forces the build to run out of the current directory. package.stage = DIYStage(os.getcwd()) # TODO: make this an argument, not a global. spack.do_checksum = False package.do_install(keep_prefix=args.keep_prefix, ignore_deps=args.ignore_deps, verbose=not args.quiet, keep_stage=True) # don't remove source dir for DIY.
def test_diystage_preserve_file(self, tmpdir): """Ensure DIYStage preserves an existing file.""" # Write a file to the temporary directory fn = tmpdir.join(_readme_fn) fn.write(_readme_contents) # Instantiate the DIYStage and ensure the above file is unchanged. path = str(tmpdir) stage = DIYStage(path) assert os.path.isdir(path) assert os.path.isfile(str(fn)) stage.create() # Only sets the flag value readmefn = str(fn) assert os.path.isfile(readmefn) with open(readmefn) as _file: _file.read() == _readme_contents
def test_apply_patch_twice(mock_patch_stage, tmpdir): """Ensure that patch doesn't fail if applied twice.""" stage = DIYStage(str(tmpdir)) with tmpdir.as_cwd(): write_file("foo.txt", file_to_patch) write_file("foo-expected.txt", expected_patch_result) write_file("foo.patch", patch_file) FakePackage = collections.namedtuple('FakePackage', ['name', 'namespace', 'fullname']) fake_pkg = FakePackage('fake-package', 'test', 'fake-package') def make_patch(filename): path = os.path.realpath(str(tmpdir.join(filename))) url = 'file://' + path sha256 = spack.util.crypto.checksum("sha256", path) return spack.patch.UrlPatch(fake_pkg, url, sha256=sha256) # apply the first time patch = make_patch('foo.patch') patch.fetch() patch.apply(stage) with working_dir(stage.source_path): assert filecmp.cmp('foo.txt', 'foo-expected.txt') # ensure apply() is idempotent patch.apply(stage) with working_dir(stage.source_path): assert filecmp.cmp('foo.txt', 'foo-expected.txt') # now write a file that can't be patched with working_dir(stage.source_path): write_file("foo.txt", file_patch_cant_apply_to) # this application should fail with a real error with pytest.raises(spack.util.executable.ProcessError): patch.apply(stage)
def diy(self, args): if not args.spec: tty.die("spack diy requires a package spec argument.") specs = spack.cmd.parse_specs(args.spec) if len(specs) > 1: tty.die("spack diy only takes one spec.") spec = specs[0] if not spack.repo.exists(spec.name): tty.die("No package for '{0}' was found.".format(spec.name), " Use `spack create` to create a new package") if not spec.versions.concrete: tty.die( "spack diy spec must have a single, concrete version. " "Did you forget a package version number?") spec.concretize() package = spack.repo.get(spec) if package.installed: tty.error("Already installed in %s" % package.prefix) tty.msg("Uninstall or try adding a version suffix for this DIY build.") sys.exit(1) # Forces the build to run out of the current directory. package.stage = DIYStage(os.getcwd()) # TODO: make this an argument, not a global. spack.do_checksum = False package.do_install( keep_prefix=args.keep_prefix, install_deps=not args.ignore_deps, verbose=not args.quiet, keep_stage=True, # don't remove source dir for DIY. dirty=args.dirty)
def custom_devbuild(source_path, spec, args): package = spack.repo.get(spec) package.stage = DIYStage(source_path) if package.installed: package.do_uninstall(force=True) if args.things_to_test == 'root': args.things_to_test = ['cosmo'] elif args.things_to_test == 'dycore': args.things_to_test = ['cosmo', 'cosmo-dycore'] elif args.things_to_test == 'all': args.things_to_test = True # Bugfix: somehow args are changed outside of function when changed inside here # Therefore, at second call of this function things_to_test is a list elif isinstance(args.things_to_test, list): if args.things_to_test[0] != 'cosmo': tty.die("unknown entry in devbuildcosmo for argument '--test' ") else: args.things_to_test = False kwargs = { 'make_jobs': args.jobs, 'restage': args.restage, 'tests': args.things_to_test } # for testing purposes we want to split build and install phase for COSMO if package.name == 'cosmo': kwargs['stop_at'] = args.until package.do_install(verbose=True, **kwargs)
def test_diystage_path_invalid(self): """Ensure DIYStage for an invalid path behaves as expected.""" with pytest.raises(spack.stage.StagePathError): DIYStage('/path/does/not/exist')
def test_diystage_path_none(self): """Ensure DIYStage for path=None behaves as expected.""" with pytest.raises(ValueError): DIYStage(None)
def dev_build(self, args): if not args.spec: tty.die("spack dev-build requires a package spec argument.") specs = spack.cmd.parse_specs(args.spec) if len(specs) > 1: tty.die("spack dev-build only takes one spec.") spec = specs[0] if not spack.repo.path.exists(spec.name): tty.die("No package for '{0}' was found.".format(spec.name), " Use `spack create` to create a new package") tests = False if args.test == 'all': tests = True elif args.test == 'root': tests = [spec.name] if not spec.versions.concrete: tty.die("spack dev-build spec must have a single, concrete version. " "Did you forget a package version number?") spec.concretize() package = spack.repo.get(spec) source_path = args.source_path if source_path is None: source_path = os.getcwd() source_path = os.path.abspath(source_path) # Forces the build to run out of the current directory. package.stage = DIYStage(source_path) # disable checksumming if requested if args.no_checksum or args.yes_to_all: spack.config.set('config:checksum', False, scope='command_line') kwargs = dict( make_jobs=args.jobs, keep_prefix=args.keep_prefix, install_deps=not args.ignore_deps, verbose=not args.quiet, keep_stage=True, # don't remove source dir for DIY. tests=tests, dirty=args.dirty, stop_at=args.until) display_args = {'long': True, 'show_flags': True, 'variants': True} if package.installed: if args.overwrite: if not args.yes_to_all: tty.msg('The following package will be reinstalled:\n') t = spack.store.db.query(spec) spack.cmd.display_specs(t, **display_args) answer = tty.get_yes_or_no('Do you want to proceed?', default=False) if not answer: tty.die('Reinstallation aborted.') with fs.replace_directory_transaction(spec.prefix): package.do_install(**kwargs) else: tty.error("Already installed in %s" % package.prefix) tty.msg( "Uninstall or try adding a version suffix for this DIY build.") sys.exit(1) # Give the user a last chance to think about overwriting an already # existing installation else: if args.overwrite: tty.msg("The following spec will be freshly installed, " "ignoring the --overwrite flag:") spack.cmd.display_specs([spec], **display_args) package.do_install(**kwargs)
def setup(self, args): tty.warn('DEPRECATED: use `spack dev-build` instead') if not args.spec: tty.die("spack setup requires a package spec argument.") specs = spack.cmd.parse_specs(args.spec) if len(specs) > 1: tty.die("spack setup only takes one spec.") # Take a write lock before checking for existence. with spack.store.db.write_transaction(): spec = specs[0] if not spack.repo.path.exists(spec.name): tty.die("No package for '{0}' was found.".format(spec.name), " Use `spack create` to create a new package") if not spec.versions.concrete: tty.die("spack setup spec must have a single, concrete version. " "Did you forget a package version number?") spec.concretize() package = spack.repo.get(spec) if not isinstance(package, spack.build_systems.cmake.CMakePackage): tty.die( 'Support for {0} derived packages not yet implemented'.format( package.build_system_class)) # It's OK if the package is already installed. # Forces the build to run out of the current directory. package.stage = DIYStage(os.getcwd()) # disable checksumming if requested if args.no_checksum: spack.config.set('config:checksum', False, scope='command_line') # Install dependencies if requested to do so if not args.ignore_deps: parser = argparse.ArgumentParser() install.setup_parser(parser) inst_args = copy.deepcopy(args) inst_args = parser.parse_args(['--only=dependencies'] + args.spec, namespace=inst_args) install.install(parser, inst_args) # Generate spconfig.py tty.msg('Generating spconfig.py [{0}]'.format( package.spec.cshort_spec)) dirty = args.dirty if args.shebang is None: shebang = sys.executable elif args.shebang == 'env': shebang = '/usr/bin/env python' else: shebang = args.shebang write_spconfig(package, dirty, shebang) # Install this package to register it in the DB and permit # module file regeneration inst_args = copy.deepcopy(args) inst_args = parser.parse_args(['--only=package', '--fake'] + args.spec, namespace=inst_args) install.install(parser, inst_args)