From f92a2d688de53b5dd38891bb6546286bc7151236 Mon Sep 17 00:00:00 2001 From: "Mark W. Krentel" Date: Thu, 11 Nov 2021 19:04:53 -0600 Subject: elfutils: add version 0.186 (#27345) --- var/spack/repos/builtin/packages/elfutils/package.py | 1 + 1 file changed, 1 insertion(+) diff --git a/var/spack/repos/builtin/packages/elfutils/package.py b/var/spack/repos/builtin/packages/elfutils/package.py index e32b8fcbc1..731c7f69a7 100644 --- a/var/spack/repos/builtin/packages/elfutils/package.py +++ b/var/spack/repos/builtin/packages/elfutils/package.py @@ -22,6 +22,7 @@ class Elfutils(AutotoolsPackage, SourcewarePackage): list_url = "https://sourceware.org/elfutils/ftp" list_depth = 1 + version('0.186', sha256='7f6fb9149b1673d38d9178a0d3e0fb8a1ec4f53a9f4c2ff89469609879641177') version('0.185', sha256='dc8d3e74ab209465e7f568e1b3bb9a5a142f8656e2b57d10049a73da2ae6b5a6') version('0.184', sha256='87e7d1d7f0333815dd1f62135d047a4dc4082068f361452f357997c11360644b') version('0.183', sha256='c3637c208d309d58714a51e61e63f1958808fead882e9b607506a29e5474f2c5') -- cgit v1.2.3-60-g2f50 From 544826c8259edef6d9a3b67435e5a3b07f283ba7 Mon Sep 17 00:00:00 2001 From: Dylan Simon Date: Tue, 9 Nov 2021 05:52:08 -0500 Subject: make --enable-locks actually enable locks (#24675) --- lib/spack/spack/main.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/lib/spack/spack/main.py b/lib/spack/spack/main.py index 31a4bfe4ed..86f5c76002 100644 --- a/lib/spack/spack/main.py +++ b/lib/spack/spack/main.py @@ -491,8 +491,9 @@ def setup_main_options(args): # override lock configuration if passed on command line if args.locks is not None: - spack.util.lock.check_lock_safety(spack.paths.prefix) - spack.config.set('config:locks', False, scope='command_line') + if args.locks is False: + spack.util.lock.check_lock_safety(spack.paths.prefix) + spack.config.set('config:locks', args.locks, scope='command_line') if args.mock: rp = spack.repo.RepoPath(spack.paths.mock_packages_path) -- cgit v1.2.3-60-g2f50 From abd418cc315fff968da242522c6bf403ea841161 Mon Sep 17 00:00:00 2001 From: Robert Underwood Date: Tue, 9 Nov 2021 05:58:14 -0500 Subject: openmpi fix external find for 0.17 (#27255) --- var/spack/repos/builtin/packages/openmpi/package.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/var/spack/repos/builtin/packages/openmpi/package.py b/var/spack/repos/builtin/packages/openmpi/package.py index 6d3e12d6e5..0d48cfc523 100644 --- a/var/spack/repos/builtin/packages/openmpi/package.py +++ b/var/spack/repos/builtin/packages/openmpi/package.py @@ -1058,7 +1058,7 @@ def is_enabled(text): # This code gets all the fabric names from the variants list # Idea taken from the AutotoolsPackage source. def get_options_from_variant(self, name): - values = self.variants[name].values + values = self.variants[name][0].values if getattr(values, 'feature_values', None): values = values.feature_values return values -- cgit v1.2.3-60-g2f50 From 7c6b253d89cb4e91c2683d150e46da00a6085695 Mon Sep 17 00:00:00 2001 From: Jordan Galby <67924449+Jordan474@users.noreply.github.com> Date: Tue, 9 Nov 2021 16:47:32 +0100 Subject: Fix log-format reporter ignoring install errors (#25961) When running `spack install --log-format junit|cdash ...`, install errors were ignored. This made spack continue building dependents of failed install, ignoring `--fail-fast`, and exit 0 at the end. --- lib/spack/spack/report.py | 34 +++++++++++++++++--------------- lib/spack/spack/test/cmd/install.py | 39 ++++++++++++++++++++++++------------- lib/spack/spack/test/cmd/test.py | 6 ++++-- 3 files changed, 48 insertions(+), 31 deletions(-) diff --git a/lib/spack/spack/report.py b/lib/spack/spack/report.py index 4685321bc8..83bb89e27f 100644 --- a/lib/spack/spack/report.py +++ b/lib/spack/spack/report.py @@ -151,6 +151,22 @@ class InfoCollector(object): 'installed_from_binary_cache': False } + # Append the package to the correct spec report. In some + # cases it may happen that a spec that is asked to be + # installed explicitly will also be installed as a + # dependency of another spec. In this case append to both + # spec reports. + for s in llnl.util.lang.dedupe([pkg.spec.root, pkg.spec]): + name = name_fmt.format(s.name, s.dag_hash(length=7)) + try: + item = next(( + x for x in self.specs + if x['name'] == name + )) + item['packages'].append(package) + except StopIteration: + pass + start_time = time.time() value = None try: @@ -170,6 +186,7 @@ class InfoCollector(object): package['stdout'] = fetch_log(pkg, do_fn, self.dir) package['stdout'] += package['message'] package['exception'] = e.traceback + raise except (Exception, BaseException) as e: # Everything else is an error (the installation @@ -178,26 +195,11 @@ class InfoCollector(object): package['stdout'] = fetch_log(pkg, do_fn, self.dir) package['message'] = str(e) or 'Unknown error' package['exception'] = traceback.format_exc() + raise finally: package['elapsed_time'] = time.time() - start_time - # Append the package to the correct spec report. In some - # cases it may happen that a spec that is asked to be - # installed explicitly will also be installed as a - # dependency of another spec. In this case append to both - # spec reports. - for s in llnl.util.lang.dedupe([pkg.spec.root, pkg.spec]): - name = name_fmt.format(s.name, s.dag_hash(length=7)) - try: - item = next(( - x for x in self.specs - if x['name'] == name - )) - item['packages'].append(package) - except StopIteration: - pass - return value return wrapper diff --git a/lib/spack/spack/test/cmd/install.py b/lib/spack/spack/test/cmd/install.py index b0b10d1287..4fa022d168 100644 --- a/lib/spack/spack/test/cmd/install.py +++ b/lib/spack/spack/test/cmd/install.py @@ -393,9 +393,14 @@ def test_junit_output_with_failures(tmpdir, exc_typename, msg): '--log-format=junit', '--log-file=test.xml', 'raiser', 'exc_type={0}'.format(exc_typename), - 'msg="{0}"'.format(msg) + 'msg="{0}"'.format(msg), + fail_on_error=False, ) + assert isinstance(install.error, spack.build_environment.ChildError) + assert install.error.name == exc_typename + assert install.error.pkg.name == 'raiser' + files = tmpdir.listdir() filename = tmpdir.join('test.xml') assert filename in files @@ -407,18 +412,22 @@ def test_junit_output_with_failures(tmpdir, exc_typename, msg): assert 'failures="1"' in content assert 'errors="0"' in content + # Nothing should have succeeded + assert 'tests="0"' not in content + assert 'failures="0"' not in content + # We want to have both stdout and stderr assert '' in content assert msg in content @pytest.mark.disable_clean_stage_check -@pytest.mark.parametrize('exc_typename,msg', [ - ('RuntimeError', 'something weird happened'), - ('KeyboardInterrupt', 'Ctrl-C strikes again') +@pytest.mark.parametrize('exc_typename,expected_exc,msg', [ + ('RuntimeError', spack.installer.InstallError, 'something weird happened'), + ('KeyboardInterrupt', KeyboardInterrupt, 'Ctrl-C strikes again') ]) def test_junit_output_with_errors( - exc_typename, msg, + exc_typename, expected_exc, msg, mock_packages, mock_archive, mock_fetch, install_mockery, config, tmpdir, monkeypatch): @@ -429,11 +438,11 @@ def test_junit_output_with_errors( monkeypatch.setattr(spack.installer.PackageInstaller, '_install_task', just_throw) - # TODO: Why does junit output capture appear to swallow the exception - # TODO: as evidenced by the two failing packages getting tagged as - # TODO: installed? with tmpdir.as_cwd(): - install('--log-format=junit', '--log-file=test.xml', 'libdwarf') + install('--log-format=junit', '--log-file=test.xml', 'libdwarf', + fail_on_error=False) + + assert isinstance(install.error, expected_exc) files = tmpdir.listdir() filename = tmpdir.join('test.xml') @@ -441,10 +450,14 @@ def test_junit_output_with_errors( content = filename.open().read() - # Count failures and errors correctly: libdwarf _and_ libelf - assert 'tests="2"' in content + # Only libelf error is reported (through libdwarf root spec). libdwarf + # install is skipped and it is not an error. + assert 'tests="1"' in content assert 'failures="0"' in content - assert 'errors="2"' in content + assert 'errors="1"' in content + + # Nothing should have succeeded + assert 'errors="0"' not in content # We want to have both stdout and stderr assert '' in content @@ -877,7 +890,7 @@ def test_install_help_cdash(capsys): @pytest.mark.disable_clean_stage_check -def test_cdash_auth_token(tmpdir, install_mockery, capfd): +def test_cdash_auth_token(tmpdir, mock_fetch, install_mockery, capfd): # capfd interferes with Spack's capturing with tmpdir.as_cwd(): with capfd.disabled(): diff --git a/lib/spack/spack/test/cmd/test.py b/lib/spack/spack/test/cmd/test.py index df9fb35db1..9ee117b281 100644 --- a/lib/spack/spack/test/cmd/test.py +++ b/lib/spack/spack/test/cmd/test.py @@ -133,7 +133,8 @@ def test_junit_output_with_failures(tmpdir, mock_test_stage, pkg_name, msgs): with tmpdir.as_cwd(): spack_test('run', '--log-format=junit', '--log-file=test.xml', - pkg_name) + pkg_name, + fail_on_error=False) files = tmpdir.listdir() filename = tmpdir.join('test.xml') @@ -160,7 +161,8 @@ def test_cdash_output_test_error( spack_test('run', '--log-format=cdash', '--log-file=cdash_reports', - 'test-error') + 'test-error', + fail_on_error=False) report_dir = tmpdir.join('cdash_reports') print(tmpdir.listdir()) assert report_dir in tmpdir.listdir() -- cgit v1.2.3-60-g2f50 From d862507bcf41a80ecb98493aef5d5bcd7d2a0518 Mon Sep 17 00:00:00 2001 From: Harmen Stoppels Date: Fri, 12 Nov 2021 08:34:18 +0100 Subject: Fix overloaded argparse keys (#27379) Commands should not reuse option names defined in main. --- lib/spack/spack/cmd/env.py | 16 +++++++--------- lib/spack/spack/cmd/install.py | 6 ++++-- lib/spack/spack/cmd/python.py | 4 ++-- lib/spack/spack/reporters/cdash.py | 1 - lib/spack/spack/test/cmd/env.py | 2 +- share/spack/spack-completion.bash | 7 +------ 6 files changed, 15 insertions(+), 21 deletions(-) diff --git a/lib/spack/spack/cmd/env.py b/lib/spack/spack/cmd/env.py index b88e1281bc..2f94bbc445 100644 --- a/lib/spack/spack/cmd/env.py +++ b/lib/spack/spack/cmd/env.py @@ -411,8 +411,6 @@ def env_status(args): # def env_loads_setup_parser(subparser): """list modules for an installed environment '(see spack module loads)'""" - subparser.add_argument( - 'env', nargs='?', help='name of env to generate loads file for') subparser.add_argument( '-n', '--module-set-name', default='default', help='module set for which to generate load operations') @@ -448,19 +446,19 @@ def env_loads(args): def env_update_setup_parser(subparser): """update environments to the latest format""" subparser.add_argument( - metavar='env', dest='env', + metavar='env', dest='update_env', help='name or directory of the environment to activate' ) spack.cmd.common.arguments.add_common_arguments(subparser, ['yes_to_all']) def env_update(args): - manifest_file = ev.manifest_file(args.env) + manifest_file = ev.manifest_file(args.update_env) backup_file = manifest_file + ".bkp" needs_update = not ev.is_latest_format(manifest_file) if not needs_update: - tty.msg('No update needed for the environment "{0}"'.format(args.env)) + tty.msg('No update needed for the environment "{0}"'.format(args.update_env)) return proceed = True @@ -470,7 +468,7 @@ def env_update(args): 'Spack that are older than this version may not be able to ' 'read it. Spack stores backups of the updated environment ' 'which can be retrieved with "spack env revert"') - tty.msg(msg.format(args.env)) + tty.msg(msg.format(args.update_env)) proceed = tty.get_yes_or_no('Do you want to proceed?', default=False) if not proceed: @@ -478,20 +476,20 @@ def env_update(args): ev.update_yaml(manifest_file, backup_file=backup_file) msg = 'Environment "{0}" has been updated [backup={1}]' - tty.msg(msg.format(args.env, backup_file)) + tty.msg(msg.format(args.update_env, backup_file)) def env_revert_setup_parser(subparser): """restore environments to their state before update""" subparser.add_argument( - metavar='env', dest='env', + metavar='env', dest='revert_env', help='name or directory of the environment to activate' ) spack.cmd.common.arguments.add_common_arguments(subparser, ['yes_to_all']) def env_revert(args): - manifest_file = ev.manifest_file(args.env) + manifest_file = ev.manifest_file(args.revert_env) backup_file = manifest_file + ".bkp" # Check that both the spack.yaml and the backup exist, the inform user diff --git a/lib/spack/spack/cmd/install.py b/lib/spack/spack/cmd/install.py index c04fb23ea3..95b195bc53 100644 --- a/lib/spack/spack/cmd/install.py +++ b/lib/spack/spack/cmd/install.py @@ -38,7 +38,7 @@ def update_kwargs_from_args(args, kwargs): 'keep_stage': args.keep_stage, 'restage': not args.dont_restage, 'install_source': args.install_source, - 'verbose': args.verbose, + 'verbose': args.verbose or args.install_verbose, 'fake': args.fake, 'dirty': args.dirty, 'use_cache': args.use_cache, @@ -130,7 +130,7 @@ remote spec matches that of the local spec""") help="install source files in prefix") arguments.add_common_arguments(subparser, ['no_checksum', 'deprecated']) subparser.add_argument( - '-v', '--verbose', action='store_true', + '-v', '--verbose', action='store_true', dest='install_verbose', help="display verbose build output while installing") subparser.add_argument( '--fake', action='store_true', @@ -285,6 +285,8 @@ def install_specs(cli_args, kwargs, specs): def install(parser, args, **kwargs): + # TODO: unify args.verbose? + tty.set_verbose(args.verbose or args.install_verbose) if args.help_cdash: parser = argparse.ArgumentParser( diff --git a/lib/spack/spack/cmd/python.py b/lib/spack/spack/cmd/python.py index 156e01b4ba..a7b998a8da 100644 --- a/lib/spack/spack/cmd/python.py +++ b/lib/spack/spack/cmd/python.py @@ -23,7 +23,7 @@ level = "long" def setup_parser(subparser): subparser.add_argument( - '-V', '--version', action='store_true', + '-V', '--version', action='store_true', dest='python_version', help='print the Python version number and exit') subparser.add_argument( '-c', dest='python_command', help='command to execute') @@ -42,7 +42,7 @@ def setup_parser(subparser): def python(parser, args, unknown_args): - if args.version: + if args.python_version: print('Python', platform.python_version()) return diff --git a/lib/spack/spack/reporters/cdash.py b/lib/spack/spack/reporters/cdash.py index cb9539b2d7..19721fc676 100644 --- a/lib/spack/spack/reporters/cdash.py +++ b/lib/spack/spack/reporters/cdash.py @@ -62,7 +62,6 @@ class CDash(Reporter): def __init__(self, args): Reporter.__init__(self, args) - tty.set_verbose(args.verbose) self.success = True self.template_dir = os.path.join('reports', 'cdash') self.cdash_upload_url = args.cdash_upload_url diff --git a/lib/spack/spack/test/cmd/env.py b/lib/spack/spack/test/cmd/env.py index 553d80c562..d7e712d3d0 100644 --- a/lib/spack/spack/test/cmd/env.py +++ b/lib/spack/spack/test/cmd/env.py @@ -868,7 +868,7 @@ def test_env_loads(install_mockery, mock_fetch): install('--fake') with ev.read('test'): - env('loads', 'test') + env('loads') e = ev.read('test') diff --git a/share/spack/spack-completion.bash b/share/spack/spack-completion.bash index e9022d47bb..fa3ebd3c3e 100755 --- a/share/spack/spack-completion.bash +++ b/share/spack/spack-completion.bash @@ -969,12 +969,7 @@ _spack_env_st() { } _spack_env_loads() { - if $list_options - then - SPACK_COMPREPLY="-h --help -n --module-set-name -m --module-type --input-only -p --prefix -x --exclude -r --dependencies" - else - _environments - fi + SPACK_COMPREPLY="-h --help -n --module-set-name -m --module-type --input-only -p --prefix -x --exclude -r --dependencies" } _spack_env_view() { -- cgit v1.2.3-60-g2f50 From c8daa7218de7904151e61f2d9a1458e63b0e3363 Mon Sep 17 00:00:00 2001 From: Harmen Stoppels Date: Mon, 15 Nov 2021 11:21:37 +0100 Subject: Turn some verbose messages into debug messages (#27408) --- lib/spack/spack/installer.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/lib/spack/spack/installer.py b/lib/spack/spack/installer.py index 798f63cb81..010632076c 100644 --- a/lib/spack/spack/installer.py +++ b/lib/spack/spack/installer.py @@ -1022,7 +1022,7 @@ class PackageInstaller(object): tty.debug(msg.format('Upgrading to', desc, pkg_id, timeout)) op = 'upgrade to' lock.upgrade_read_to_write(timeout) - tty.verbose('{0} is now {1} locked'.format(pkg_id, lock_type)) + tty.debug('{0} is now {1} locked'.format(pkg_id, lock_type)) except (lk.LockDowngradeError, lk.LockTimeoutError) as exc: tty.debug(err.format(op, desc, pkg_id, exc.__class__.__name__, @@ -1254,7 +1254,7 @@ class PackageInstaller(object): # Remove any associated build task since its sequence will change self._remove_task(task.pkg_id) desc = 'Queueing' if task.attempts == 0 else 'Requeueing' - tty.verbose(msg.format(desc, task.pkg_id, task.status)) + tty.debug(msg.format(desc, task.pkg_id, task.status)) # Now add the new task to the queue with a new sequence number to # ensure it is the last entry popped with the same priority. This @@ -1276,7 +1276,7 @@ class PackageInstaller(object): ltype, lock = self.locks[pkg_id] if lock is not None: try: - tty.verbose(msg.format(ltype, pkg_id)) + tty.debug(msg.format(ltype, pkg_id)) if ltype == 'read': lock.release_read() else: @@ -1296,8 +1296,8 @@ class PackageInstaller(object): pkg_id (str): identifier for the package to be removed """ if pkg_id in self.build_tasks: - tty.verbose('Removing build task for {0} from list' - .format(pkg_id)) + tty.debug('Removing build task for {0} from list' + .format(pkg_id)) task = self.build_tasks.pop(pkg_id) task.status = STATUS_REMOVED return task @@ -1381,8 +1381,8 @@ class PackageInstaller(object): self._update_failed(dep_task, mark) self._remove_task(dep_id) else: - tty.verbose('No build task for {0} to skip since {1} failed' - .format(dep_id, pkg_id)) + tty.debug('No build task for {0} to skip since {1} failed' + .format(dep_id, pkg_id)) def _update_installed(self, task): """ @@ -1511,7 +1511,7 @@ class PackageInstaller(object): pkg, pkg_id, spec = task.pkg, task.pkg_id, task.pkg.spec term_title.set('Processing {0}'.format(pkg.name)) - tty.verbose('Processing {0}: task={1}'.format(pkg_id, task)) + tty.debug('Processing {0}: task={1}'.format(pkg_id, task)) # Ensure that the current spec has NO uninstalled dependencies, # which is assumed to be reflected directly in its priority. # -- cgit v1.2.3-60-g2f50 From 654f6839ebe33d64710b5e7f3c388539e84f8e35 Mon Sep 17 00:00:00 2001 From: Harmen Stoppels Date: Thu, 18 Nov 2021 13:00:39 +0100 Subject: ci: run style unit tests only if we target develop (#27472) Some tests assume the base branch is develop, but this branch may not have been checked out. --- .github/workflows/setup_git.sh | 9 ++++----- .github/workflows/unit_tests.yaml | 2 ++ lib/spack/spack/test/cmd/style.py | 13 ++++++++++++- lib/spack/spack/test/package_sanity.py | 6 +++++- share/spack/qa/run-style-tests | 10 +++++----- 5 files changed, 28 insertions(+), 12 deletions(-) diff --git a/.github/workflows/setup_git.sh b/.github/workflows/setup_git.sh index bd79daf268..e319e07512 100755 --- a/.github/workflows/setup_git.sh +++ b/.github/workflows/setup_git.sh @@ -1,9 +1,8 @@ #!/usr/bin/env sh git config --global user.email "spack@example.com" git config --global user.name "Test User" -# With fetch-depth: 0 we have a remote develop -# but not a local branch. Don't do this on develop -if [ "$(git branch --show-current)" != "develop" ] -then - git branch develop origin/develop + +# create a local pr base branch +if [[ -n $GITHUB_BASE_REF ]]; then + git fetch origin "${GITHUB_BASE_REF}:${GITHUB_BASE_REF}" fi diff --git a/.github/workflows/unit_tests.yaml b/.github/workflows/unit_tests.yaml index 35722b9137..764a9cdcf0 100644 --- a/.github/workflows/unit_tests.yaml +++ b/.github/workflows/unit_tests.yaml @@ -211,6 +211,7 @@ jobs: git clone "${{ github.server_url }}/${{ github.repository }}.git" && cd spack git fetch origin "${{ github.ref }}:test-branch" git checkout test-branch + . .github/workflows/setup_git.sh bin/spack unit-test -x - name: Run unit tests (only package tests) if: ${{ needs.changes.outputs.with_coverage == 'false' }} @@ -223,6 +224,7 @@ jobs: git clone "${{ github.server_url }}/${{ github.repository }}.git" && cd spack git fetch origin "${{ github.ref }}:test-branch" git checkout test-branch + . .github/workflows/setup_git.sh bin/spack unit-test -x -m "not maybeslow" -k "package_sanity" # Test RHEL8 UBI with platform Python. This job is run diff --git a/lib/spack/spack/test/cmd/style.py b/lib/spack/spack/test/cmd/style.py index af0fc47d24..29cde14400 100644 --- a/lib/spack/spack/test/cmd/style.py +++ b/lib/spack/spack/test/cmd/style.py @@ -24,8 +24,19 @@ style_data = os.path.join(spack.paths.test_path, 'data', 'style') style = spack.main.SpackCommand("style") + +def has_develop_branch(): + git = which('git') + if not git: + return False + git("show-ref", "--verify", "--quiet", + "refs/heads/develop", fail_on_error=False) + return git.returncode == 0 + + # spack style requires git to run -- skip the tests if it's not there -pytestmark = pytest.mark.skipif(not which('git'), reason='requires git') +pytestmark = pytest.mark.skipif(not has_develop_branch(), + reason='requires git with develop branch') # The style tools have requirements to use newer Python versions. We simplify by # requiring Python 3.6 or higher to run spack style. diff --git a/lib/spack/spack/test/package_sanity.py b/lib/spack/spack/test/package_sanity.py index 35840d85da..dd2f4b425f 100644 --- a/lib/spack/spack/test/package_sanity.py +++ b/lib/spack/spack/test/package_sanity.py @@ -206,8 +206,12 @@ def test_prs_update_old_api(): """Ensures that every package modified in a PR doesn't contain deprecated calls to any method. """ + ref = os.getenv("GITHUB_BASE_REF") + if not ref: + pytest.skip("No base ref found") + changed_package_files = [ - x for x in style.changed_files() if style.is_package(x) + x for x in style.changed_files(base=ref) if style.is_package(x) ] failing = [] for file in changed_package_files: diff --git a/share/spack/qa/run-style-tests b/share/spack/qa/run-style-tests index 72c47ff055..9f0cbdb266 100755 --- a/share/spack/qa/run-style-tests +++ b/share/spack/qa/run-style-tests @@ -14,15 +14,15 @@ # Usage: # run-flake8-tests # -. "$(dirname $0)/setup.sh" +. "$(dirname "$0")/setup.sh" -BASE="" -if [ -n "$GITHUB_BASE_REF" ]; then - BASE="--base ${GITHUB_BASE_REF}" +args=() +if [[ -n $GITHUB_BASE_REF ]]; then + args+=("--base" "${GITHUB_BASE_REF}") fi # verify that the code style is correct -spack style --root-relative $BASE +spack style --root-relative "${args[@]}" # verify that the license headers are present spack license verify -- cgit v1.2.3-60-g2f50 From 8f98f1d1820970a72b64000cc5003006f0a9b945 Mon Sep 17 00:00:00 2001 From: Harmen Stoppels Date: Fri, 26 Nov 2021 19:03:05 +0100 Subject: Use bash in setup_git.sh (#27676) --- .github/workflows/setup_git.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/setup_git.sh b/.github/workflows/setup_git.sh index e319e07512..4eb416720b 100755 --- a/.github/workflows/setup_git.sh +++ b/.github/workflows/setup_git.sh @@ -1,4 +1,4 @@ -#!/usr/bin/env sh +#!/bin/bash -e git config --global user.email "spack@example.com" git config --global user.name "Test User" -- cgit v1.2.3-60-g2f50 From 9d4291e590b304164598f32f63a8afbd6a2f2ec0 Mon Sep 17 00:00:00 2001 From: Paul Ferrell <51765748+Paul-Ferrell@users.noreply.github.com> Date: Mon, 29 Nov 2021 05:27:02 -0700 Subject: Handle byte sequences which are not encoded as UTF8 while logging. (#21447) Fix builds which produce a lines with non-UTF8 output while logging The alternative is to read in binary mode, and then decode while ignoring errors. --- lib/spack/llnl/util/tty/log.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/spack/llnl/util/tty/log.py b/lib/spack/llnl/util/tty/log.py index efcd487f23..a7a4637ba9 100644 --- a/lib/spack/llnl/util/tty/log.py +++ b/lib/spack/llnl/util/tty/log.py @@ -780,7 +780,12 @@ def _writer_daemon(stdin_multiprocess_fd, read_multiprocess_fd, write_fd, echo, try: while line_count < 100: # Handle output from the calling process. - line = _retry(in_pipe.readline)() + try: + line = _retry(in_pipe.readline)() + except UnicodeDecodeError: + # installs like --test=root gpgme produce non-UTF8 logs + line = '\n' + if not line: return line_count += 1 -- cgit v1.2.3-60-g2f50 From e9f7fb03c9f92e78637480cbda7e5ecdc3e28dda Mon Sep 17 00:00:00 2001 From: Massimiliano Culpo Date: Tue, 30 Nov 2021 14:59:55 +0100 Subject: spack audit: fix API calls (#27713) This broke in #24858 --- lib/spack/spack/audit.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/spack/spack/audit.py b/lib/spack/spack/audit.py index 47894383a5..f6ef90e0b8 100644 --- a/lib/spack/spack/audit.py +++ b/lib/spack/spack/audit.py @@ -389,9 +389,8 @@ def _unknown_variants_in_dependencies(pkgs, error_cls): dependency_variants = dependency_edge.spec.variants for name, value in dependency_variants.items(): try: - dependency_pkg.variants[name].validate_or_raise( - value, pkg=dependency_pkg - ) + v, _ = dependency_pkg.variants[name] + v.validate_or_raise(value, pkg=dependency_pkg) except Exception as e: summary = (pkg_name + ": wrong variant used for a " "dependency in a 'depends_on' directive") @@ -419,7 +418,8 @@ def _analyze_variants_in_directive(pkg, constraint, directive, error_cls): errors = [] for name, v in constraint.variants.items(): try: - pkg.variants[name].validate_or_raise(v, pkg=pkg) + variant, _ = pkg.variants[name] + variant.validate_or_raise(v, pkg=pkg) except variant_exceptions as e: summary = pkg.name + ': wrong variant in "{0}" directive' summary = summary.format(directive) -- cgit v1.2.3-60-g2f50 From 7e5de95a3025237247fda6552eea24cd406a1ded Mon Sep 17 00:00:00 2001 From: Greg Becker Date: Fri, 10 Dec 2021 01:49:33 -0800 Subject: Improve debug info from concretizer (#27707) --- lib/spack/spack/solver/asp.py | 24 ++++++++++++++++++++++-- lib/spack/spack/test/concretize.py | 11 +++++++++++ 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/lib/spack/spack/solver/asp.py b/lib/spack/spack/solver/asp.py index c1c3cb33a9..4ad05cd9bf 100644 --- a/lib/spack/spack/solver/asp.py +++ b/lib/spack/spack/solver/asp.py @@ -366,6 +366,19 @@ class Result(object): string_list.extend(self.format_core(core)) return string_list + def format_cores(self): + """List of facts for each core + + Separate cores are separated by an empty line + Cores are not minimized + """ + string_list = [] + for core in self.cores: + if string_list: + string_list.append('\n') + string_list.extend(self.format_core(core)) + return string_list + def raise_if_unsat(self): """ Raise an appropriate error if the result is unsatisfiable. @@ -379,7 +392,9 @@ class Result(object): constraints = self.abstract_specs if len(constraints) == 1: constraints = constraints[0] - conflicts = self.format_minimal_cores() + + debug = spack.config.get('config:debug', False) + conflicts = self.format_cores() if debug else self.format_minimal_cores() raise spack.error.UnsatisfiableSpecError(constraints, conflicts=conflicts) @@ -496,7 +511,12 @@ class PyclingoDriver(object): self.out.write("%s.\n" % str(symbol)) atom = self.backend.add_atom(symbol) - choice = self.cores and assumption + + # in debug mode, make all facts choices/assumptions + # otherwise, only if we're generating cores and assumption=True + debug = spack.config.get('config:debug', False) + choice = debug or (self.cores and assumption) + self.backend.add_rule([atom], [], choice=choice) if choice: self.assumptions.append(atom) diff --git a/lib/spack/spack/test/concretize.py b/lib/spack/spack/test/concretize.py index 54d886a55b..5e9188b888 100644 --- a/lib/spack/spack/test/concretize.py +++ b/lib/spack/spack/test/concretize.py @@ -557,6 +557,17 @@ class TestConcretize(object): with pytest.raises(spack.error.SpackError): s.concretize() + def test_conflicts_new_concretizer_debug(self, conflict_spec, mutable_config): + if spack.config.get('config:concretizer') == 'original': + pytest.skip('Testing debug statements specific to new concretizer') + + spack.config.set('config:debug', True) + s = Spec(conflict_spec) + with pytest.raises(spack.error.SpackError) as e: + s.concretize() + + assert "conflict_trigger(" in e.value.message + def test_conflict_in_all_directives_true(self): s = Spec('when-directives-true') with pytest.raises(spack.error.SpackError): -- cgit v1.2.3-60-g2f50 From 20ad47f9e19e7650491a43aa4376d2b7095eba10 Mon Sep 17 00:00:00 2001 From: Harmen Stoppels Date: Mon, 13 Dec 2021 11:45:31 +0100 Subject: Install dir creation message demoted to "debug" level (#27911) --- lib/spack/spack/installer.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/lib/spack/spack/installer.py b/lib/spack/spack/installer.py index 010632076c..196858830a 100644 --- a/lib/spack/spack/installer.py +++ b/lib/spack/spack/installer.py @@ -1328,8 +1328,7 @@ class PackageInstaller(object): pkg (spack.package.Package): the package to be built and installed """ if not os.path.exists(pkg.spec.prefix): - tty.verbose('Creating the installation directory {0}' - .format(pkg.spec.prefix)) + tty.debug('Creating the installation directory {0}'.format(pkg.spec.prefix)) spack.store.layout.create_install_directory(pkg.spec) else: # Set the proper group for the prefix -- cgit v1.2.3-60-g2f50 From adf4e91658cce82592500337d86e6444bbde1817 Mon Sep 17 00:00:00 2001 From: Dan Bonachea Date: Wed, 10 Nov 2021 16:48:02 -0500 Subject: upcxx: Update the UPC++ package to 2021.9.0 (#26996) * upcxx: Update the UPC++ package to 2021.9.0 * Add the new release, and a missing older one. * Remove the spack package cruft for supporting the obsolete build system that was present in older versions that are no longer supported. * General cleanups. Support for library versions older than 2020.3.0 is officially retired, for two reasons: 1. Releases prior to 2020.3.0 had a required dependency on Python 2, which is [officially EOL](https://www.python.org/doc/sunset-python-2/) as of Jan 1 2020, and is no longer considered secure. 2. (Most importantly) The UPC++ development team is unable/unwilling to support releases more than two years old. UPC++ provides robust backwards-compatibility to earlier releases of UPC++ v1.0, with very rare well-documented/well-motivated exceptions. Users are strongly encouraged to update to a current version of UPC++. NOTE: Most of the lines changed in this commit are simply re-indentation, and thus might be best reviewed in a diff that ignores whitespace. * upcxx: Detect Cray XC more explicitly This change is necessary to prevent false matches occuring on new Cray Shasta systems, which do not use the aries network but were incorrectly being treated as a Cray XC + aries platform. UPC++ has not yet deployed official native support for Cray Shasta, but this change is sufficient to allow building the portable backends there. --- var/spack/repos/builtin/packages/upcxx/package.py | 206 ++++++++++------------ 1 file changed, 89 insertions(+), 117 deletions(-) diff --git a/var/spack/repos/builtin/packages/upcxx/package.py b/var/spack/repos/builtin/packages/upcxx/package.py index 2661be4283..61011a35ac 100644 --- a/var/spack/repos/builtin/packages/upcxx/package.py +++ b/var/spack/repos/builtin/packages/upcxx/package.py @@ -3,11 +3,18 @@ # # SPDX-License-Identifier: (Apache-2.0 OR MIT) +import os + from spack import * +def is_CrayXC(): + return (spack.platforms.host().name == 'cray') and \ + (os.environ.get('CRAYPE_NETWORK_TARGET') == "aries") + + def cross_detect(): - if spack.platforms.host().name == 'cray': + if is_CrayXC(): if which('srun'): return 'cray-aries-slurm' if which('aprun'): @@ -24,6 +31,7 @@ class Upcxx(Package): homepage = "https://upcxx.lbl.gov" maintainers = ['bonachea'] + url = "https://bitbucket.org/berkeleylab/upcxx/downloads/upcxx-2021.3.0.tar.gz" git = 'https://bitbucket.org/berkeleylab/upcxx.git' tags = ['e4s'] @@ -31,13 +39,15 @@ class Upcxx(Package): version('develop', branch='develop') version('master', branch='master') + version('2021.9.0', sha256='9299e17602bcc8c05542cdc339897a9c2dba5b5c3838d6ef2df7a02250f42177') version('2021.3.0', sha256='3433714cd4162ffd8aad9a727c12dbf1c207b7d6664879fc41259a4b351595b7') version('2020.11.0', sha256='f6f212760a485a9f346ca11bb4751e7095bbe748b8e5b2389ff9238e9e321317', url='https://bitbucket.org/berkeleylab/upcxx/downloads/upcxx-2020.11.0-memory_kinds_prototype.tar.gz') version('2020.10.0', sha256='623e074b512bf8cad770a04040272e1cc660d2749760398b311f9bcc9d381a37') + version('2020.3.2', sha256='978adc315d21089c739d5efda764b77fc9a2a7c5860f169fe5cd2ca1d840620f') version('2020.3.0', sha256='01be35bef4c0cfd24e9b3d50c88866521b9cac3ad4cbb5b1fc97aea55078810f') - version('2019.9.0', sha256='7d67ccbeeefb59de9f403acc719f52127a30801a2c2b9774a1df03f850f8f1d4') - version('2019.3.2', sha256='dcb0b337c05a0feb2ed5386f5da6c60342412b49cab10f282f461e74411018ad') + # Do NOT add older versions here. + # UPC++ releases over 2 years old are not supported. variant('mpi', default=False, description='Enables MPI-based spawners and mpi-conduit') @@ -48,8 +58,8 @@ class Upcxx(Package): variant('cross', default=cross_detect(), description="UPC++ cross-compile target (autodetect by default)") - conflicts('cross=none', when='platform=cray', - msg='cross=none is unacceptable on Cray.' + + conflicts('cross=none', when=is_CrayXC(), + msg='cross=none is unacceptable on Cray XC.' + 'Please specify an appropriate "cross" value') # UPC++ always relies on GASNet-EX. @@ -61,47 +71,15 @@ class Upcxx(Package): depends_on('mpi', when='+mpi') depends_on('cuda', when='+cuda') - # Require Python2 2.7.5+ up to v2019.9.0 - depends_on('python@2.7.5:2', - type=("build", "run"), when='@:2019.9.0') - # v2020.3.0 and later also permit Python3 - depends_on('python@2.7.5:', type=("build", "run"), when='@2020.3.0:') + depends_on('python@2.7.5:', type=("build", "run")) # All flags should be passed to the build-env in autoconf-like vars flag_handler = env_flags - def url_for_version(self, version): - if version > Version('2019.3.2'): - url = "https://bitbucket.org/berkeleylab/upcxx/downloads/upcxx-{0}.tar.gz" - else: - url = "https://bitbucket.org/berkeleylab/upcxx/downloads/upcxx-{0}-offline.tar.gz" - return url.format(version) - - def setup_build_environment(self, env): - # ensure we use the correct python - env.set('UPCXX_PYTHON', self.spec['python'].command.path) - - if '+mpi' in self.spec: - env.set('GASNET_CONFIGURE_ARGS', - '--enable-mpi --enable-mpi-compat') - else: - env.set('GASNET_CONFIGURE_ARGS', '--without-mpicc') - - if 'cross=none' not in self.spec: - env.set('CROSS', self.spec.variants['cross'].value) - - if '+cuda' in self.spec: - env.set('UPCXX_CUDA', '1') - env.set('UPCXX_CUDA_NVCC', self.spec['cuda'].prefix.bin.nvcc) - def setup_run_environment(self, env): - # ensure we use the correct python - env.set('UPCXX_PYTHON', self.spec['python'].command.path) - env.set('UPCXX_INSTALL', self.prefix) env.set('UPCXX', self.prefix.bin.upcxx) - if 'platform=cray' in self.spec: - env.set('UPCXX_GASNET_CONDUIT', 'aries') + if is_CrayXC(): env.set('UPCXX_NETWORK', 'aries') def setup_dependent_package(self, module, dep_spec): @@ -110,97 +88,91 @@ class Upcxx(Package): def setup_dependent_build_environment(self, env, dependent_spec): env.set('UPCXX_INSTALL', self.prefix) env.set('UPCXX', self.prefix.bin.upcxx) - if 'platform=cray' in self.spec: - env.set('UPCXX_GASNET_CONDUIT', 'aries') + if is_CrayXC(): env.set('UPCXX_NETWORK', 'aries') def install(self, spec, prefix): + env = os.environ # UPC++ follows autoconf naming convention for LDLIBS, which is 'LIBS' if (env.get('LDLIBS')): env['LIBS'] = env['LDLIBS'] - if spec.version <= Version('2019.9.0'): - env['CC'] = self.compiler.cc - if '+mpi' in self.spec: - if 'platform=cray' in self.spec: - env['GASNET_CONFIGURE_ARGS'] += \ - " --with-mpicc=" + self.compiler.cc - else: - env['CXX'] = spec['mpi'].mpicxx - else: - env['CXX'] = self.compiler.cxx - if '+gasnet' in self.spec: - env['GASNET'] = spec['gasnet'].prefix.src - installsh = Executable("./install") - installsh(prefix) + options = ["--prefix=%s" % prefix] + + if 'cross=none' in spec: + options.append('--without-cross') else: - if 'platform=cray' in self.spec: - # Spack loads the cray-libsci module incorrectly on ALCF theta, - # breaking the Cray compiler wrappers - # cray-libsci is irrelevant to our build, so disable it - for var in ['PE_PKGCONFIG_PRODUCTS', 'PE_PKGCONFIG_LIBS']: - env[var] = ":".join( - filter(lambda x: "libsci" not in x.lower(), - env[var].split(":"))) - # Undo spack compiler wrappers: - # the C/C++ compilers must work post-install - # hack above no longer works after the fix to UPC++ issue #287 - real_cc = join_path(env['CRAYPE_DIR'], 'bin', 'cc') - real_cxx = join_path(env['CRAYPE_DIR'], 'bin', 'CC') - # workaround a bug in the UPC++ installer: (issue #346) - env['GASNET_CONFIGURE_ARGS'] += \ - " --with-cc=" + real_cc + " --with-cxx=" + real_cxx - if '+mpi' in self.spec: - env['GASNET_CONFIGURE_ARGS'] += " --with-mpicc=" + real_cc - else: - real_cc = self.compiler.cc - real_cxx = self.compiler.cxx - if '+mpi' in self.spec: - real_cxx = spec['mpi'].mpicxx - - env['CC'] = real_cc - env['CXX'] = real_cxx - - options = ["--prefix=%s" % prefix] - - if '+gasnet' in self.spec: - options.append('--with-gasnet=' + spec['gasnet'].prefix.src) - - configure(*options) - - make() - - make('install') + options.append('--with-cross=' + spec.variants['cross'].value) + + if is_CrayXC(): + # Spack loads the cray-libsci module incorrectly on ALCF theta, + # breaking the Cray compiler wrappers + # cray-libsci is irrelevant to our build, so disable it + for var in ['PE_PKGCONFIG_PRODUCTS', 'PE_PKGCONFIG_LIBS']: + env[var] = ":".join( + filter(lambda x: "libsci" not in x.lower(), + env[var].split(":"))) + # Undo spack compiler wrappers: + # the C/C++ compilers must work post-install + real_cc = join_path(env['CRAYPE_DIR'], 'bin', 'cc') + real_cxx = join_path(env['CRAYPE_DIR'], 'bin', 'CC') + # workaround a bug in the UPC++ installer: (issue #346) + if (env.get('GASNET_CONFIGURE_ARGS') is None): + env['GASNET_CONFIGURE_ARGS'] = '' + env['GASNET_CONFIGURE_ARGS'] += \ + " --with-cc=" + real_cc + " --with-cxx=" + real_cxx + if '+mpi' in spec: + env['GASNET_CONFIGURE_ARGS'] += " --with-mpicc=" + real_cc + else: + real_cc = self.compiler.cc + real_cxx = self.compiler.cxx + if '+mpi' in spec: + real_cxx = spec['mpi'].mpicxx + + options.append('--with-cc=' + real_cc) + options.append('--with-cxx=' + real_cxx) + + if '+gasnet' in spec: + options.append('--with-gasnet=' + spec['gasnet'].prefix.src) + + options.append('--with-python=' + spec['python'].command.path) + + if '+mpi' in spec: + options.append('--enable-mpi') + options.append('--enable-mpi-compat') + else: + options.append('--without-mpicc') + + if '+cuda' in spec: + options.append('--with-cuda') + options.append('--with-nvcc=' + spec['cuda'].prefix.bin.nvcc) + + configure(*options) + + make() + + make('install') install_tree('example', prefix.example) @run_after('install') @on_package_attributes(run_tests=True) def test_install(self): - if self.spec.version <= Version('2019.9.0'): - spack.main.send_warning_to_tty( - "run_tests not supported in UPC++ version " + - self.spec.version.string + " -- SKIPPED") - else: - # enable testing of unofficial conduits (mpi) - test_networks = 'NETWORKS=$(CONDUITS)' - # build hello world against installed tree in all configurations - make('test_install', test_networks) - make('tests-clean') # cleanup - # build all tests for all networks in debug mode - make('tests', test_networks) - if 'cross=none' in self.spec: - make('run-tests', 'NETWORKS=smp') # runs tests for smp backend - make('tests-clean') # cleanup + # enable testing of unofficial conduits (mpi) + test_networks = 'NETWORKS=$(CONDUITS)' + # build hello world against installed tree in all configurations + make('test_install', test_networks) + make('tests-clean') # cleanup + # build all tests for all networks in debug mode + make('tests', test_networks) + if 'cross=none' in self.spec: + make('run-tests', 'NETWORKS=smp') # runs tests for smp backend + make('tests-clean') # cleanup def test(self): - if self.spec.version <= Version('2019.9.0'): - spack.main.send_warning_to_tty( - "post-install tests not supported in UPC++ version " + - self.spec.version.string + " -- SKIPPED") - else: # run post-install smoke test: - test_install = join_path(self.prefix.bin, 'test-upcxx-install.sh') - self.run_test(test_install, expected=['SUCCESS'], status=0, - installed=True, - purpose='Checking UPC++ compile+link ' + - 'for all installed backends') + # run post-install smoke test: + test_install = join_path(self.prefix.bin, 'test-upcxx-install.sh') + self.run_test(test_install, expected=['SUCCESS'], status=0, + installed=True, + purpose='Checking UPC++ compile+link ' + + 'for all installed backends') -- cgit v1.2.3-60-g2f50 From 9345bf81b95641a4e9728664f87777ed05f56b8f Mon Sep 17 00:00:00 2001 From: Greg Becker Date: Tue, 14 Dec 2021 23:52:53 -0800 Subject: Add option to minimize full debug cores. include warning message about performance (#27970) Co-authored-by: Harmen Stoppels --- lib/spack/spack/error.py | 17 ++++-------- lib/spack/spack/main.py | 18 +++++++++++++ lib/spack/spack/solver/asp.py | 53 +++++++++++++++++++++++++++++++++----- lib/spack/spack/test/concretize.py | 6 +++-- share/spack/spack-completion.bash | 2 +- 5 files changed, 74 insertions(+), 22 deletions(-) diff --git a/lib/spack/spack/error.py b/lib/spack/spack/error.py index be49656c07..700f4ea1d8 100644 --- a/lib/spack/spack/error.py +++ b/lib/spack/spack/error.py @@ -123,18 +123,11 @@ class UnsatisfiableSpecError(SpecError): For original concretizer, provide the requirement that was violated when raising. """ - def __init__(self, provided, required=None, constraint_type=None, conflicts=None): - # required is only set by the original concretizer. - # clingo concretizer handles error messages differently. - if required is not None: - assert not conflicts # can't mix formats - super(UnsatisfiableSpecError, self).__init__( - "%s does not satisfy %s" % (provided, required)) - else: - indented = [' %s\n' % conflict for conflict in conflicts] - conflict_msg = ''.join(indented) - msg = '%s is unsatisfiable, conflicts are:\n%s' % (provided, conflict_msg) - super(UnsatisfiableSpecError, self).__init__(msg) + def __init__(self, provided, required, constraint_type): + # This is only the entrypoint for old concretizer errors + super(UnsatisfiableSpecError, self).__init__( + "%s does not satisfy %s" % (provided, required)) + self.provided = provided self.required = required self.constraint_type = constraint_type diff --git a/lib/spack/spack/main.py b/lib/spack/spack/main.py index 86f5c76002..f41423fa1e 100644 --- a/lib/spack/spack/main.py +++ b/lib/spack/spack/main.py @@ -41,6 +41,7 @@ import spack.modules import spack.paths import spack.platforms import spack.repo +import spack.solver.asp import spack.spec import spack.store import spack.util.debug @@ -380,6 +381,13 @@ def make_argument_parser(**kwargs): # stat names in groups of 7, for nice wrapping. stat_lines = list(zip(*(iter(stat_names),) * 7)) + # help message for --show-cores + show_cores_help = 'provide additional information on concretization failures\n' + show_cores_help += 'off (default): show only the violated rule\n' + show_cores_help += 'full: show raw unsat cores from clingo\n' + show_cores_help += 'minimized: show subset-minimal unsat cores ' + show_cores_help += '(Warning: this may take hours for some specs)' + parser.add_argument( '-h', '--help', dest='help', action='store_const', const='short', default=None, @@ -403,6 +411,9 @@ def make_argument_parser(**kwargs): '-d', '--debug', action='count', default=0, help="write out debug messages " "(more d's for more verbosity: -d, -dd, -ddd, etc.)") + parser.add_argument( + '--show-cores', choices=["off", "full", "minimized"], default="off", + help=show_cores_help) parser.add_argument( '--timestamp', action='store_true', help="Add a timestamp to tty output") @@ -486,6 +497,13 @@ def setup_main_options(args): spack.config.set('config:debug', True, scope='command_line') spack.util.environment.tracing_enabled = True + if args.show_cores != "off": + # minimize_cores defaults to true, turn it off if we're showing full core + # but don't want to wait to minimize it. + spack.solver.asp.full_cores = True + if args.show_cores == 'full': + spack.solver.asp.minimize_cores = False + if args.timestamp: tty.set_timestamp(True) diff --git a/lib/spack/spack/solver/asp.py b/lib/spack/spack/solver/asp.py index 4ad05cd9bf..957f363960 100644 --- a/lib/spack/spack/solver/asp.py +++ b/lib/spack/spack/solver/asp.py @@ -59,6 +59,14 @@ ASTType = None parse_files = None +#: whether we should write ASP unsat cores quickly in debug mode when the cores +#: may be very large or take the time (sometimes hours) to minimize them +minimize_cores = True + +#: whether we should include all facts in the unsat cores or only error messages +full_cores = False + + # backward compatibility functions for clingo ASTs def ast_getter(*names): def getter(node): @@ -393,10 +401,12 @@ class Result(object): if len(constraints) == 1: constraints = constraints[0] - debug = spack.config.get('config:debug', False) - conflicts = self.format_cores() if debug else self.format_minimal_cores() + if minimize_cores: + conflicts = self.format_minimal_cores() + else: + conflicts = self.format_cores() - raise spack.error.UnsatisfiableSpecError(constraints, conflicts=conflicts) + raise UnsatisfiableSpecError(constraints, conflicts=conflicts) @property def specs(self): @@ -512,10 +522,9 @@ class PyclingoDriver(object): atom = self.backend.add_atom(symbol) - # in debug mode, make all facts choices/assumptions - # otherwise, only if we're generating cores and assumption=True - debug = spack.config.get('config:debug', False) - choice = debug or (self.cores and assumption) + # with `--show-cores=full or --show-cores=minimized, make all facts + # choices/assumptions, otherwise only if assumption=True + choice = self.cores and (full_cores or assumption) self.backend.add_rule([atom], [], choice=choice) if choice: @@ -2044,3 +2053,33 @@ def solve(specs, dump=(), models=0, timers=False, stats=False, tests=False, return driver.solve( setup, specs, dump, models, timers, stats, tests, reuse ) + + +class UnsatisfiableSpecError(spack.error.UnsatisfiableSpecError): + """ + Subclass for new constructor signature for new concretizer + """ + def __init__(self, provided, conflicts): + indented = [' %s\n' % conflict for conflict in conflicts] + conflict_msg = ''.join(indented) + issue = 'conflicts' if full_cores else 'errors' + msg = '%s is unsatisfiable, %s are:\n%s' % (provided, issue, conflict_msg) + + newline_indent = '\n ' + if not full_cores: + msg += newline_indent + 'To see full clingo unsat cores, ' + msg += 're-run with `spack --show-cores=full`' + if not minimize_cores or not full_cores: + # not solver.minimalize_cores and not solver.full_cores impossible + msg += newline_indent + 'For full, subset-minimal unsat cores, ' + msg += 're-run with `spack --show-cores=minimized' + msg += newline_indent + msg += 'Warning: This may take (up to) hours for some specs' + + super(spack.error.UnsatisfiableSpecError, self).__init__(msg) + + self.provided = provided + + # Add attribute expected of the superclass interface + self.required = None + self.constraint_type = None diff --git a/lib/spack/spack/test/concretize.py b/lib/spack/spack/test/concretize.py index 5e9188b888..179a4e26d8 100644 --- a/lib/spack/spack/test/concretize.py +++ b/lib/spack/spack/test/concretize.py @@ -557,11 +557,13 @@ class TestConcretize(object): with pytest.raises(spack.error.SpackError): s.concretize() - def test_conflicts_new_concretizer_debug(self, conflict_spec, mutable_config): + def test_conflicts_show_cores(self, conflict_spec, monkeypatch): if spack.config.get('config:concretizer') == 'original': pytest.skip('Testing debug statements specific to new concretizer') - spack.config.set('config:debug', True) + monkeypatch.setattr(spack.solver.asp, 'full_cores', True) + monkeypatch.setattr(spack.solver.asp, 'minimize_cores', False) + s = Spec(conflict_spec) with pytest.raises(spack.error.SpackError) as e: s.concretize() diff --git a/share/spack/spack-completion.bash b/share/spack/spack-completion.bash index fa3ebd3c3e..c7e4d10197 100755 --- a/share/spack/spack-completion.bash +++ b/share/spack/spack-completion.bash @@ -335,7 +335,7 @@ _spacktivate() { _spack() { if $list_options then - SPACK_COMPREPLY="-h --help -H --all-help --color -c --config -C --config-scope -d --debug --timestamp --pdb -e --env -D --env-dir -E --no-env --use-env-repo -k --insecure -l --enable-locks -L --disable-locks -m --mock -p --profile --sorted-profile --lines -v --verbose --stacktrace -V --version --print-shell-vars" + SPACK_COMPREPLY="-h --help -H --all-help --color -c --config -C --config-scope -d --debug --show-cores --timestamp --pdb -e --env -D --env-dir -E --no-env --use-env-repo -k --insecure -l --enable-locks -L --disable-locks -m --mock -p --profile --sorted-profile --lines -v --verbose --stacktrace -V --version --print-shell-vars" else SPACK_COMPREPLY="activate add analyze arch audit blame bootstrap build-env buildcache cd checksum ci clean clone commands compiler compilers concretize config containerize create deactivate debug dependencies dependents deprecate dev-build develop diff docs edit env extensions external fetch find flake8 gc gpg graph help info install license list load location log-parse maintainers mark mirror module monitor patch pkg providers pydoc python reindex remove rm repo resource restage solve spec stage style tags test test-env tutorial undevelop uninstall unit-test unload url verify versions view" fi -- cgit v1.2.3-60-g2f50 From 314867e6358377d6a46de442bb04314f75959e25 Mon Sep 17 00:00:00 2001 From: Tamara Dahlgren <35777542+tldahlgren@users.noreply.github.com> Date: Wed, 15 Dec 2021 22:56:54 -0800 Subject: Provide meaningful message for empty environment installs (#28031) * Provide a meaningful failure message for installation of an empty environment * Allow regenerating view per offline discussion --- lib/spack/spack/cmd/install.py | 23 ++++++++++++++--------- lib/spack/spack/test/cmd/install.py | 12 ++++++++++++ 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/lib/spack/spack/cmd/install.py b/lib/spack/spack/cmd/install.py index 95b195bc53..f4a4644312 100644 --- a/lib/spack/spack/cmd/install.py +++ b/lib/spack/spack/cmd/install.py @@ -348,17 +348,22 @@ environment variables: env.write(regenerate=False) specs = env.all_specs() - if not args.log_file and not reporter.filename: - reporter.filename = default_log_file(specs[0]) - reporter.specs = specs + if specs: + if not args.log_file and not reporter.filename: + reporter.filename = default_log_file(specs[0]) + reporter.specs = specs - # Tell the monitor about the specs - if args.use_monitor and specs: - monitor.new_configuration(specs) + # Tell the monitor about the specs + if args.use_monitor and specs: + monitor.new_configuration(specs) - tty.msg("Installing environment {0}".format(env.name)) - with reporter('build'): - env.install_all(**kwargs) + tty.msg("Installing environment {0}".format(env.name)) + with reporter('build'): + env.install_all(**kwargs) + + else: + msg = '{0} environment has no specs to install'.format(env.name) + tty.msg(msg) tty.debug("Regenerating environment views for {0}" .format(env.name)) diff --git a/lib/spack/spack/test/cmd/install.py b/lib/spack/spack/test/cmd/install.py index 4fa022d168..2c79880088 100644 --- a/lib/spack/spack/test/cmd/install.py +++ b/lib/spack/spack/test/cmd/install.py @@ -1099,3 +1099,15 @@ def test_install_env_with_tests_root(tmpdir, mock_packages, mock_fetch, add('depb') install('--test', 'root') assert not os.path.exists(test_dep.prefix) + + +def test_install_empty_env(tmpdir, mock_packages, mock_fetch, + install_mockery, mutable_mock_env_path): + env_name = 'empty' + env('create', env_name) + with ev.read(env_name): + out = install(fail_on_error=False) + + assert env_name in out + assert 'environment' in out + assert 'no specs to install' in out -- cgit v1.2.3-60-g2f50 From 37fbe30c4a5b6b9c453078270f7511cc5a1eb146 Mon Sep 17 00:00:00 2001 From: Christian Goll Date: Thu, 16 Dec 2021 10:47:15 +0100 Subject: Added opensuse/leap:15 to spack containerize (#27837) Co-authored-by: Massimiliano Culpo --- lib/spack/docs/containers.rst | 3 +++ lib/spack/spack/container/images.json | 18 ++++++++++++++++++ share/spack/docker/leap-15.dockerfile | 21 ++++++++++++++++----- share/spack/templates/container/leap-15.dockerfile | 21 +++++++++++++++++++++ 4 files changed, 58 insertions(+), 5 deletions(-) create mode 100644 share/spack/templates/container/leap-15.dockerfile diff --git a/lib/spack/docs/containers.rst b/lib/spack/docs/containers.rst index 3d32de0841..57a9cad189 100644 --- a/lib/spack/docs/containers.rst +++ b/lib/spack/docs/containers.rst @@ -129,6 +129,9 @@ are currently supported are summarized in the table below: * - CentOS 7 - ``centos:7`` - ``spack/centos7`` + * - openSUSE Leap + - ``opensuse/leap`` + - ``spack/leap15`` All the images are tagged with the corresponding release of Spack: diff --git a/lib/spack/spack/container/images.json b/lib/spack/spack/container/images.json index ee4e5a2caa..b82596f20c 100644 --- a/lib/spack/spack/container/images.json +++ b/lib/spack/spack/container/images.json @@ -28,6 +28,19 @@ "develop": "latest" } }, + "opensuse/leap:15": { + "bootstrap": { + "template": "container/leap-15.dockerfile" + }, + "os_package_manager": "zypper", + "build": "spack/leap15", + "build_tags": { + "develop": "latest" + }, + "final": { + "image": "opensuse/leap:latest" + } + }, "nvidia/cuda:11.2.1": { "bootstrap": { "template": "container/cuda_11_2_1.dockerfile", @@ -85,6 +98,11 @@ "update": "yum update -y && amazon-linux-extras install epel -y", "install": "yum install -y", "clean": "rm -rf /var/cache/yum && yum clean all" + }, + "zypper": { + "update": "zypper update -y", + "install": "zypper install -y", + "clean": "rm -rf /var/cache/zypp && zypper clean -a" } } } diff --git a/share/spack/docker/leap-15.dockerfile b/share/spack/docker/leap-15.dockerfile index 65375c359b..1bf41c6149 100644 --- a/share/spack/docker/leap-15.dockerfile +++ b/share/spack/docker/leap-15.dockerfile @@ -2,7 +2,7 @@ FROM opensuse/leap:15.3 MAINTAINER Christian Goll ENV DOCKERFILE_BASE=opensuse \ - DOCKERFILE_DISTRO=opensuse_leap \ + DOCKERFILE_DISTRO=leap \ DOCKERFILE_DISTRO_VERSION=15.3 \ SPACK_ROOT=/opt/spack \ DEBIAN_FRONTEND=noninteractive \ @@ -11,10 +11,21 @@ ENV DOCKERFILE_BASE=opensuse \ RUN zypper ref && \ zypper up -y && \ - zypper in -y python3-base python3-boto3 \ - xz gzip tar bzip2 curl patch patchelf file \ - gcc-c++ gcc-fortran make cmake automake && \ - zypper clean + zypper in -y \ + bzip2\ + curl\ + file\ + gcc-c++\ + gcc-fortran\ + make\ + gzip\ + patch\ + patchelf\ + python3-base \ + python3-boto3\ + tar\ + xz\ +&& zypper clean # clean up manpages RUN rm -rf /var/cache/zypp/* \ diff --git a/share/spack/templates/container/leap-15.dockerfile b/share/spack/templates/container/leap-15.dockerfile new file mode 100644 index 0000000000..38e4f1c009 --- /dev/null +++ b/share/spack/templates/container/leap-15.dockerfile @@ -0,0 +1,21 @@ +{% extends "container/bootstrap-base.dockerfile" %} +{% block install_os_packages %} +RUN zypper ref && \ + zypper up -y && \ + zypper in -y \ + bzip2\ + curl\ + file\ + gcc-c++\ + gcc-fortran\ + make\ + git\ + gzip\ + patch\ + patchelf\ + python3-base \ + python3-boto3\ + tar\ + xz\ +&& zypper clean +{% endblock %} -- cgit v1.2.3-60-g2f50 From 8f3b025b5502120c99c483b619ae83d2ead07c7f Mon Sep 17 00:00:00 2001 From: Andrew W Elble Date: Thu, 16 Dec 2021 05:54:35 -0500 Subject: MANPATH needs a trailing ':' to utilize system defaults (#21682) otherwise spack breaks using system man pages by default. Co-authored-by: Harmen Stoppels --- lib/spack/spack/test/cmd/load.py | 19 +++++++++++++++++++ lib/spack/spack/util/environment.py | 4 +++- .../repos/builtin.mock/packages/mpileaks/package.py | 1 + 3 files changed, 23 insertions(+), 1 deletion(-) diff --git a/lib/spack/spack/test/cmd/load.py b/lib/spack/spack/test/cmd/load.py index ef014418c7..51867b548c 100644 --- a/lib/spack/spack/test/cmd/load.py +++ b/lib/spack/spack/test/cmd/load.py @@ -3,6 +3,7 @@ # # SPDX-License-Identifier: (Apache-2.0 OR MIT) import os +import re import pytest @@ -16,6 +17,24 @@ install = SpackCommand('install') location = SpackCommand('location') +def test_manpath_trailing_colon(install_mockery, mock_fetch, mock_archive, + mock_packages, working_env): + """Test that the commands generated by load add the MANPATH prefix + inspections. Also test that Spack correctly preserves the default/existing + manpath search path via a trailing colon""" + install('mpileaks') + + sh_out = load('--sh', '--only', 'package', 'mpileaks') + lines = sh_out.split('\n') + assert any(re.match(r'export MANPATH=.*:;', ln) for ln in lines) + + os.environ['MANPATH'] = '/tmp/man:' + + sh_out = load('--sh', '--only', 'package', 'mpileaks') + lines = sh_out.split('\n') + assert any(re.match(r'export MANPATH=.*:/tmp/man:;', ln) for ln in lines) + + def test_load(install_mockery, mock_fetch, mock_archive, mock_packages): """Test that the commands generated by load add the specified prefix inspections. Also test that Spack records loaded specs by hash in the diff --git a/lib/spack/spack/util/environment.py b/lib/spack/spack/util/environment.py index a0a6c4a3aa..f0457c27b8 100644 --- a/lib/spack/spack/util/environment.py +++ b/lib/spack/spack/util/environment.py @@ -611,7 +611,6 @@ class EnvironmentModifications(object): def shell_modifications(self, shell='sh', explicit=False, env=None): """Return shell code to apply the modifications and clears the list.""" modifications = self.group_by_name() - new_env = os.environ.copy() if env is None: env = os.environ @@ -622,6 +621,9 @@ class EnvironmentModifications(object): for x in actions: x.execute(new_env) + if 'MANPATH' in new_env and not new_env.get('MANPATH').endswith(':'): + new_env['MANPATH'] += ':' + cmds = '' for name in sorted(set(modifications)): diff --git a/var/spack/repos/builtin.mock/packages/mpileaks/package.py b/var/spack/repos/builtin.mock/packages/mpileaks/package.py index e0bff0673b..36c073ccf0 100644 --- a/var/spack/repos/builtin.mock/packages/mpileaks/package.py +++ b/var/spack/repos/builtin.mock/packages/mpileaks/package.py @@ -28,6 +28,7 @@ class Mpileaks(Package): def install(self, spec, prefix): touch(prefix.mpileaks) + mkdirp(prefix.man) def setup_environment(self, senv, renv): renv.set('FOOBAR', self.name) -- cgit v1.2.3-60-g2f50 From b2694013d4f3a564a0d1e4a9b02feaab15a5abef Mon Sep 17 00:00:00 2001 From: Harmen Stoppels Date: Wed, 15 Dec 2021 17:56:03 +0100 Subject: Revert "patches: make re-applied patches idempotent (#26784)" (#27625) This reverts commit c5ca0db27fce5d772dc8a4fcffec3b62bb0bf1f3. --- lib/spack/spack/patch.py | 36 ++------------ lib/spack/spack/test/patch.py | 97 ++++++-------------------------------- lib/spack/spack/util/crypto.py | 5 -- lib/spack/spack/util/executable.py | 24 +++------- 4 files changed, 25 insertions(+), 137 deletions(-) diff --git a/lib/spack/spack/patch.py b/lib/spack/spack/patch.py index cdd9ad0387..a273514636 100644 --- a/lib/spack/spack/patch.py +++ b/lib/spack/spack/patch.py @@ -7,7 +7,6 @@ import hashlib import inspect import os import os.path -import sys import llnl.util.filesystem import llnl.util.lang @@ -26,12 +25,6 @@ from spack.util.executable import which def apply_patch(stage, patch_path, level=1, working_dir='.'): """Apply the patch at patch_path to code in the stage. - Spack runs ``patch`` with ``-N`` so that it does not reject already-applied - patches. This is useful for develop specs, so that the build does not fail - due to repeated application of patches, and for easing requirements on patch - specifications in packages -- packages won't stop working when patches we - previously had to apply land in upstream. - Args: stage (spack.stage.Stage): stage with code that will be patched patch_path (str): filesystem location for the patch to apply @@ -41,31 +34,10 @@ def apply_patch(stage, patch_path, level=1, working_dir='.'): """ patch = which("patch", required=True) with llnl.util.filesystem.working_dir(stage.source_path): - output = patch( - '-N', # don't reject already-applied patches - '-p', str(level), # patch level (directory depth) - '-i', patch_path, # input source is the patch file - '-d', working_dir, # patch chdir's to here before patching - output=str, - fail_on_error=False, - ) - - if patch.returncode != 0: - # `patch` returns 1 both: - # a) when an error applying a patch, and - # b) when -N is supplied and the patch has already been applied - # - # It returns > 1 if there's something more serious wrong. - # - # So, the best we can do is to look for return code 1, look for output - # indicating that the patch was already applied, and ignore the error - # if we see it. Most implementations (BSD and GNU) seem to have the - # same messages, so we expect these checks to be reliable. - if patch.returncode > 1 or not any( - s in output for s in ("Skipping patch", "ignored") - ): - sys.stderr.write(output) - raise patch.error + patch('-s', + '-p', str(level), + '-i', patch_path, + '-d', working_dir) class Patch(object): diff --git a/lib/spack/spack/test/patch.py b/lib/spack/spack/test/patch.py index 5285be8ba9..8383100440 100644 --- a/lib/spack/spack/test/patch.py +++ b/lib/spack/spack/test/patch.py @@ -15,9 +15,8 @@ import spack.patch import spack.paths import spack.repo import spack.util.compression -import spack.util.crypto from spack.spec import Spec -from spack.stage import DIYStage, Stage +from spack.stage import Stage from spack.util.executable import Executable # various sha256 sums (using variables for legibility) @@ -34,43 +33,6 @@ url2_sha256 = '1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd1234abcd' url2_archive_sha256 = 'abcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcdabcd' -# some simple files for patch tests -file_to_patch = """\ -first line -second line -""" - -patch_file = """\ -diff a/foo.txt b/foo-expected.txt ---- a/foo.txt -+++ b/foo-expected.txt -@@ -1,2 +1,3 @@ -+zeroth line - first line --second line -+third line -""" - -expected_patch_result = """\ -zeroth line -first line -third line -""" - -file_patch_cant_apply_to = """\ -this file -is completely different -from anything in the files -or patch above -""" - - -def write_file(filename, contents): - """Helper function for setting up tests.""" - with open(filename, 'w') as f: - f.write(contents) - - @pytest.fixture() def mock_patch_stage(tmpdir_factory, monkeypatch): # Don't disrupt the spack install directory with tests. @@ -105,9 +67,19 @@ def test_url_patch(mock_patch_stage, filename, sha256, archive_sha256): mkdirp(stage.source_path) with working_dir(stage.source_path): - write_file("foo.txt", file_to_patch) - write_file("foo-expected.txt", expected_patch_result) - + # write a file to be patched + with open('foo.txt', 'w') as f: + f.write("""\ +first line +second line +""") + # write the expected result of patching. + with open('foo-expected.txt', 'w') as f: + f.write("""\ +zeroth line +first line +third line +""") # apply the patch and compare files patch.fetch() patch.apply(stage) @@ -117,47 +89,6 @@ def test_url_patch(mock_patch_stage, filename, sha256, archive_sha256): assert filecmp.cmp('foo.txt', 'foo-expected.txt') -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 test_patch_in_spec(mock_packages, config): """Test whether patches in a package appear in the spec.""" spec = Spec('patch') diff --git a/lib/spack/spack/util/crypto.py b/lib/spack/spack/util/crypto.py index 8e055126fe..549216a4c6 100644 --- a/lib/spack/spack/util/crypto.py +++ b/lib/spack/spack/util/crypto.py @@ -92,11 +92,6 @@ def checksum(hashlib_algo, filename, **kwargs): """Returns a hex digest of the filename generated using an algorithm from hashlib. """ - if isinstance(hashlib_algo, str): - if hashlib_algo not in hashes: - raise ValueError("Invalid hash algorithm: ", hashlib_algo) - hashlib_algo = hash_fun_for_algo(hashlib_algo) - block_size = kwargs.get('block_size', 2**20) hasher = hashlib_algo() with open(filename, 'rb') as file: diff --git a/lib/spack/spack/util/executable.py b/lib/spack/spack/util/executable.py index ded429c2e6..e615ccdcfd 100644 --- a/lib/spack/spack/util/executable.py +++ b/lib/spack/spack/util/executable.py @@ -27,7 +27,6 @@ class Executable(object): from spack.util.environment import EnvironmentModifications # no cycle self.default_envmod = EnvironmentModifications() self.returncode = None - self.error = None # saved ProcessError when fail_on_error if not self.exe: raise ProcessError("Cannot construct executable for '%s'" % name) @@ -91,8 +90,7 @@ class Executable(object): the environment (neither requires nor precludes env) fail_on_error (bool): Raise an exception if the subprocess returns an error. Default is True. The return code is available as - ``exe.returncode``, and a saved ``ProcessError`` that would - have been raised is in ``exe.error``. + ``exe.returncode`` ignore_errors (int or list): A list of error codes to ignore. If these codes are returned, this process will not raise an exception even if ``fail_on_error`` is set to ``True`` @@ -215,7 +213,7 @@ class Executable(object): sys.stderr.write(errstr) rc = self.returncode = proc.returncode - if rc != 0: + if fail_on_error and rc != 0 and (rc not in ignore_errors): long_msg = cmd_line_string if result: # If the output is not captured in the result, it will have @@ -224,11 +222,8 @@ class Executable(object): # stdout/stderr (e.g. if 'output' is not specified) long_msg += '\n' + result - self.error = ProcessError( - 'Command exited with status %d:' % proc.returncode, long_msg - ) - if fail_on_error and (rc not in ignore_errors): - raise self.error + raise ProcessError('Command exited with status %d:' % + proc.returncode, long_msg) return result @@ -237,15 +232,10 @@ class Executable(object): '%s: %s' % (self.exe[0], e.strerror), 'Command: ' + cmd_line_string) except subprocess.CalledProcessError as e: - self.error = ProcessError( - str(e), - '\nExit status %d when invoking command: %s' % ( - proc.returncode, - cmd_line_string, - ), - ) if fail_on_error: - raise self.error + raise ProcessError( + str(e), '\nExit status %d when invoking command: %s' % + (proc.returncode, cmd_line_string)) finally: if close_ostream: -- cgit v1.2.3-60-g2f50 From 13e36c5457422120105c1fdaf2f9945723f2bcf9 Mon Sep 17 00:00:00 2001 From: Harmen Stoppels Date: Thu, 16 Dec 2021 13:13:12 +0100 Subject: Fix table formatting (#28037) --- lib/spack/docs/packaging_guide.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/spack/docs/packaging_guide.rst b/lib/spack/docs/packaging_guide.rst index e2e3e297fd..e974924e7a 100644 --- a/lib/spack/docs/packaging_guide.rst +++ b/lib/spack/docs/packaging_guide.rst @@ -2943,7 +2943,7 @@ The package base class, usually specialized for a given build system, determines actual set of entities available for overriding. The classes that are currently provided by Spack are: -+-------------------------=--------------------------------+----------------------------------+ ++----------------------------------------------------------+----------------------------------+ | **Base Class** | **Purpose** | +==========================================================+==================================+ | :class:`~spack.package.Package` | General base class not | -- cgit v1.2.3-60-g2f50 From 79fd1c5114e8aa7fb2d44a3f17c7b3dc1547cbcd Mon Sep 17 00:00:00 2001 From: Harmen Stoppels Date: Thu, 16 Dec 2021 13:50:20 +0100 Subject: Set backup=False by default in filter_file (#28036) --- lib/spack/llnl/util/filesystem.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/spack/llnl/util/filesystem.py b/lib/spack/llnl/util/filesystem.py index 4c4ea1d5b8..753129b78e 100644 --- a/lib/spack/llnl/util/filesystem.py +++ b/lib/spack/llnl/util/filesystem.py @@ -141,7 +141,7 @@ def filter_file(regex, repl, *filenames, **kwargs): file. """ string = kwargs.get('string', False) - backup = kwargs.get('backup', True) + backup = kwargs.get('backup', False) ignore_absent = kwargs.get('ignore_absent', False) stop_at = kwargs.get('stop_at', None) -- cgit v1.2.3-60-g2f50 From 17edf1ae90a9b56eb50ec002027a424bef58d97d Mon Sep 17 00:00:00 2001 From: victorusu Date: Fri, 17 Dec 2021 10:05:32 +0100 Subject: Add setdefault option to tcl module (#14686) This commit introduces the command spack module tcl setdefault similar to the one already available for lmod Co-authored-by: Massimiliano Culpo --- lib/spack/spack/cmd/modules/lmod.py | 30 +++++++++++++++++----------- lib/spack/spack/cmd/modules/tcl.py | 40 ++++++++++++++++++++++++++++++++++--- lib/spack/spack/modules/common.py | 3 +++ lib/spack/spack/test/cmd/module.py | 14 ++++++++++--- share/spack/spack-completion.bash | 11 +++++++++- 5 files changed, 79 insertions(+), 19 deletions(-) diff --git a/lib/spack/spack/cmd/modules/lmod.py b/lib/spack/spack/cmd/modules/lmod.py index d28ccb3eaf..1920f8ec66 100644 --- a/lib/spack/spack/cmd/modules/lmod.py +++ b/lib/spack/spack/cmd/modules/lmod.py @@ -4,12 +4,11 @@ # SPDX-License-Identifier: (Apache-2.0 OR MIT) import functools -import os - -import llnl.util.filesystem import spack.cmd.common.arguments import spack.cmd.modules +import spack.config +import spack.modules.lmod def add_command(parser, command_dict): @@ -41,12 +40,19 @@ def setdefault(module_type, specs, args): # https://lmod.readthedocs.io/en/latest/060_locating.html#marking-a-version-as-default # spack.cmd.modules.one_spec_or_raise(specs) - writer = spack.modules.module_types['lmod']( - specs[0], args.module_set_name) - - module_folder = os.path.dirname(writer.layout.filename) - module_basename = os.path.basename(writer.layout.filename) - with llnl.util.filesystem.working_dir(module_folder): - if os.path.exists('default') and os.path.islink('default'): - os.remove('default') - os.symlink(module_basename, 'default') + spec = specs[0] + data = { + 'modules': { + args.module_set_name: { + 'lmod': { + 'defaults': [str(spec)] + } + } + } + } + # Need to clear the cache if a SpackCommand is called during scripting + spack.modules.lmod.configuration_registry = {} + scope = spack.config.InternalConfigScope('lmod-setdefault', data) + with spack.config.override(scope): + writer = spack.modules.module_types['lmod'](spec, args.module_set_name) + writer.update_module_defaults() diff --git a/lib/spack/spack/cmd/modules/tcl.py b/lib/spack/spack/cmd/modules/tcl.py index a9486b9de4..5a29bc6df5 100644 --- a/lib/spack/spack/cmd/modules/tcl.py +++ b/lib/spack/spack/cmd/modules/tcl.py @@ -2,18 +2,52 @@ # Spack Project Developers. See the top-level COPYRIGHT file for details. # # SPDX-License-Identifier: (Apache-2.0 OR MIT) - import functools +import spack.cmd.common.arguments import spack.cmd.modules +import spack.config +import spack.modules.tcl def add_command(parser, command_dict): tcl_parser = parser.add_parser( 'tcl', help='manipulate non-hierarchical module files' ) - spack.cmd.modules.setup_parser(tcl_parser) + sp = spack.cmd.modules.setup_parser(tcl_parser) + + # Set default module file for a package + setdefault_parser = sp.add_parser( + 'setdefault', help='set the default module file for a package' + ) + spack.cmd.common.arguments.add_common_arguments( + setdefault_parser, ['constraint'] + ) + + callbacks = dict(spack.cmd.modules.callbacks.items()) + callbacks['setdefault'] = setdefault command_dict['tcl'] = functools.partial( - spack.cmd.modules.modules_cmd, module_type='tcl' + spack.cmd.modules.modules_cmd, module_type='tcl', callbacks=callbacks ) + + +def setdefault(module_type, specs, args): + """Set the default module file, when multiple are present""" + # Currently, accepts only a single matching spec + spack.cmd.modules.one_spec_or_raise(specs) + spec = specs[0] + data = { + 'modules': { + args.module_set_name: { + 'tcl': { + 'defaults': [str(spec)] + } + } + } + } + spack.modules.tcl.configuration_registry = {} + scope = spack.config.InternalConfigScope('tcl-setdefault', data) + with spack.config.override(scope): + writer = spack.modules.module_types['tcl'](spec, args.module_set_name) + writer.update_module_defaults() diff --git a/lib/spack/spack/modules/common.py b/lib/spack/spack/modules/common.py index 8855e57e64..aee1c1cc17 100644 --- a/lib/spack/spack/modules/common.py +++ b/lib/spack/spack/modules/common.py @@ -906,6 +906,9 @@ class BaseModuleFileWriter(object): fp.set_permissions_by_spec(self.layout.filename, self.spec) # Symlink defaults if needed + self.update_module_defaults() + + def update_module_defaults(self): if any(self.spec.satisfies(default) for default in self.conf.defaults): # This spec matches a default, it needs to be symlinked to default # Symlink to a tmp location first and move, so that existing diff --git a/lib/spack/spack/test/cmd/module.py b/lib/spack/spack/test/cmd/module.py index 3bced1d335..b157e1be6b 100644 --- a/lib/spack/spack/test/cmd/module.py +++ b/lib/spack/spack/test/cmd/module.py @@ -178,10 +178,18 @@ writer_cls = spack.modules.lmod.LmodModulefileWriter @pytest.mark.db def test_setdefault_command( - mutable_database, module_configuration + mutable_database, mutable_config ): - module_configuration('autoload_direct') - + data = { + 'default': { + 'enable': ['lmod'], + 'lmod': { + 'core_compilers': ['clang@3.3'], + 'hierarchy': ['mpi'] + } + } + } + spack.config.set('modules', data) # Install two different versions of a package other_spec, preferred = 'a@1.0', 'a@2.0' diff --git a/share/spack/spack-completion.bash b/share/spack/spack-completion.bash index c7e4d10197..b41a21946c 100755 --- a/share/spack/spack-completion.bash +++ b/share/spack/spack-completion.bash @@ -1382,7 +1382,7 @@ _spack_module_tcl() { then SPACK_COMPREPLY="-h --help -n --name" else - SPACK_COMPREPLY="refresh find rm loads" + SPACK_COMPREPLY="refresh find rm loads setdefault" fi } @@ -1422,6 +1422,15 @@ _spack_module_tcl_loads() { fi } +_spack_module_tcl_setdefault() { + if $list_options + then + SPACK_COMPREPLY="-h --help" + else + _installed_packages + fi +} + _spack_monitor() { SPACK_COMPREPLY="-h --help --monitor --monitor-save-local --monitor-no-auth --monitor-tags --monitor-keep-going --monitor-host --monitor-prefix" } -- cgit v1.2.3-60-g2f50 From e1cc28a30a21da9d17967bc21e93d94c7fa03466 Mon Sep 17 00:00:00 2001 From: Paul Spencer <32964672+pwablito@users.noreply.github.com> Date: Sat, 18 Dec 2021 23:07:20 -0700 Subject: sbang: respect package permissive package permissions for sbang (#25764) Co-authored-by: Todd Gamblin Co-authored-by: Tamara Dahlgren <35777542+tldahlgren@users.noreply.github.com> --- lib/spack/spack/hooks/sbang.py | 45 ++++++++++++++++++++++++++++-- lib/spack/spack/test/sbang.py | 63 ++++++++++++++++++++++++++++++++++++------ 2 files changed, 96 insertions(+), 12 deletions(-) diff --git a/lib/spack/spack/hooks/sbang.py b/lib/spack/spack/hooks/sbang.py index ce2cf3435d..179416f03c 100644 --- a/lib/spack/spack/hooks/sbang.py +++ b/lib/spack/spack/hooks/sbang.py @@ -4,6 +4,7 @@ # SPDX-License-Identifier: (Apache-2.0 OR MIT) import filecmp +import grp import os import re import shutil @@ -14,7 +15,9 @@ import tempfile import llnl.util.filesystem as fs import llnl.util.tty as tty +import spack.package_prefs import spack.paths +import spack.spec import spack.store #: OS-imposed character limit for shebang line: 127 for Linux; 511 for Mac. @@ -187,11 +190,47 @@ def install_sbang(): spack.paths.sbang_script, sbang_path): return - # make $install_tree/bin and copy in a new version of sbang if needed + # make $install_tree/bin sbang_bin_dir = os.path.dirname(sbang_path) fs.mkdirp(sbang_bin_dir) - fs.install(spack.paths.sbang_script, sbang_path) - fs.set_install_permissions(sbang_bin_dir) + + # get permissions for bin dir from configuration files + group_name = spack.package_prefs.get_package_group(spack.spec.Spec("all")) + config_mode = spack.package_prefs.get_package_dir_permissions( + spack.spec.Spec("all") + ) + + if group_name: + os.chmod(sbang_bin_dir, config_mode) # Use package directory permissions + else: + fs.set_install_permissions(sbang_bin_dir) + + # set group on sbang_bin_dir if not already set (only if set in configuration) + if group_name and grp.getgrgid(os.stat(sbang_bin_dir).st_gid).gr_name != group_name: + os.chown( + sbang_bin_dir, + os.stat(sbang_bin_dir).st_uid, + grp.getgrnam(group_name).gr_gid + ) + + # copy over the fresh copy of `sbang` + sbang_tmp_path = os.path.join( + os.path.dirname(sbang_path), + ".%s.tmp" % os.path.basename(sbang_path), + ) + shutil.copy(spack.paths.sbang_script, sbang_tmp_path) + + # set permissions on `sbang` (including group if set in configuration) + os.chmod(sbang_tmp_path, config_mode) + if group_name: + os.chown( + sbang_tmp_path, + os.stat(sbang_tmp_path).st_uid, + grp.getgrnam(group_name).gr_gid + ) + + # Finally, move the new `sbang` into place atomically + os.rename(sbang_tmp_path, sbang_path) def post_install(spec): diff --git a/lib/spack/spack/test/sbang.py b/lib/spack/spack/test/sbang.py index 6d26bd1ba8..6e0d00eba0 100644 --- a/lib/spack/spack/test/sbang.py +++ b/lib/spack/spack/test/sbang.py @@ -7,6 +7,7 @@ Test that Spack's shebang filtering works correctly. """ import filecmp +import grp import os import shutil import stat @@ -19,6 +20,7 @@ import llnl.util.filesystem as fs import spack.hooks.sbang as sbang import spack.paths import spack.store +import spack.util.spack_yaml as syaml from spack.util.executable import which too_long = sbang.system_shebang_limit + 1 @@ -256,7 +258,34 @@ def test_shebang_handles_non_writable_files(script_dir, sbang_line): assert oct(not_writable_mode) == oct(st.st_mode) -def check_sbang_installation(): +@pytest.fixture(scope='function') +def configure_group_perms(): + conf = syaml.load_config("""\ +all: + permissions: + read: world + write: group + group: {0} +""".format(grp.getgrgid(os.getegid()).gr_name)) + spack.config.set('packages', conf, scope='user') + + yield + + +@pytest.fixture(scope='function') +def configure_user_perms(): + conf = syaml.load_config("""\ +all: + permissions: + read: world + write: user +""") + spack.config.set('packages', conf, scope='user') + + yield + + +def check_sbang_installation(group=False): sbang_path = sbang.sbang_install_path() sbang_bin_dir = os.path.dirname(sbang_path) assert sbang_path.startswith(spack.store.store.unpadded_root) @@ -264,14 +293,22 @@ def check_sbang_installation(): assert os.path.exists(sbang_path) assert fs.is_exe(sbang_path) - status = os.stat(sbang_path) - assert (status.st_mode & 0o777) == 0o755 - status = os.stat(sbang_bin_dir) - assert (status.st_mode & 0o777) == 0o755 + mode = (status.st_mode & 0o777) + if group: + assert mode == 0o775, 'Unexpected {0}'.format(oct(mode)) + else: + assert mode == 0o755, 'Unexpected {0}'.format(oct(mode)) + + status = os.stat(sbang_path) + mode = (status.st_mode & 0o777) + if group: + assert mode == 0o775, 'Unexpected {0}'.format(oct(mode)) + else: + assert mode == 0o755, 'Unexpected {0}'.format(oct(mode)) -def test_install_sbang(install_mockery): +def run_test_install_sbang(group): sbang_path = sbang.sbang_install_path() sbang_bin_dir = os.path.dirname(sbang_path) @@ -279,7 +316,7 @@ def test_install_sbang(install_mockery): assert not os.path.exists(sbang_bin_dir) sbang.install_sbang() - check_sbang_installation() + check_sbang_installation(group) # put an invalid file in for sbang fs.mkdirp(sbang_bin_dir) @@ -287,11 +324,19 @@ def test_install_sbang(install_mockery): f.write("foo") sbang.install_sbang() - check_sbang_installation() + check_sbang_installation(group) # install again and make sure sbang is still fine sbang.install_sbang() - check_sbang_installation() + check_sbang_installation(group) + + +def test_install_group_sbang(install_mockery, configure_group_perms): + run_test_install_sbang(True) + + +def test_install_user_sbang(install_mockery, configure_user_perms): + run_test_install_sbang(False) def test_install_sbang_too_long(tmpdir): -- cgit v1.2.3-60-g2f50 From fa5e186d4a25996f0d5ef4cff363117ee423513f Mon Sep 17 00:00:00 2001 From: Morten Kristensen Date: Sat, 18 Dec 2021 19:17:02 +0100 Subject: py-vermin: add latest version 1.3.2 (#28072) * py-vermin: add latest version 1.3.2 * [vermin] Fixed usages of super() without arguments (v3+) --- var/spack/repos/builtin/packages/openloops/get-process-list.py | 2 +- var/spack/repos/builtin/packages/py-charm4py/package.py | 2 +- var/spack/repos/builtin/packages/py-vermin/package.py | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/var/spack/repos/builtin/packages/openloops/get-process-list.py b/var/spack/repos/builtin/packages/openloops/get-process-list.py index 6481865eef..e9a8d8104f 100644 --- a/var/spack/repos/builtin/packages/openloops/get-process-list.py +++ b/var/spack/repos/builtin/packages/openloops/get-process-list.py @@ -8,7 +8,7 @@ class my_html_parser(HTMLParser): pass def __init__(self): - super().__init__() + super(HTMLParser, self).__init__() self.state = 0 self.processes = [] diff --git a/var/spack/repos/builtin/packages/py-charm4py/package.py b/var/spack/repos/builtin/packages/py-charm4py/package.py index ebe181bcea..e2f93215be 100644 --- a/var/spack/repos/builtin/packages/py-charm4py/package.py +++ b/var/spack/repos/builtin/packages/py-charm4py/package.py @@ -66,7 +66,7 @@ class PyCharm4py(PythonPackage): def install_args(self, spec, prefix): # Have the parent class version set prefix - args = super().install_args(spec, prefix) + args = super(PythonPackage, self).install_args(spec, prefix) if '+mpi' in spec: args.append('--mpi') return args diff --git a/var/spack/repos/builtin/packages/py-vermin/package.py b/var/spack/repos/builtin/packages/py-vermin/package.py index b7962716cf..c592b78493 100644 --- a/var/spack/repos/builtin/packages/py-vermin/package.py +++ b/var/spack/repos/builtin/packages/py-vermin/package.py @@ -8,10 +8,11 @@ class PyVermin(PythonPackage): """Concurrently detect the minimum Python versions needed to run code.""" homepage = "https://github.com/netromdk/vermin" - url = "https://github.com/netromdk/vermin/archive/v1.3.1.tar.gz" + url = "https://github.com/netromdk/vermin/archive/v1.3.2.tar.gz" maintainers = ['netromdk'] + version('1.3.2', sha256='2818eaea24c5be5dae1f374ddb2377e9cfaad04d0a3372ad129cffc46cec5404') version('1.3.1', sha256='ddcdaad5a708a483af192075f5d2eaaaf3aa4661b5101ddafa40d7837eeb5368') version('1.3.0', sha256='adf2b6ea34c01c3a81fc4fa78c2e5fa6c8dd6d35327a8e5a4caeeaef7ec21668') version('1.2.2', sha256='d0343b2a78d7e4de67dfd2d882eeaf8b241db724f7e67f83bdd4111edb97f1e2') -- cgit v1.2.3-60-g2f50 From 87abda4cdd689bf9dff66960558dc63268794d87 Mon Sep 17 00:00:00 2001 From: Massimiliano Culpo Date: Mon, 20 Dec 2021 09:05:06 +0100 Subject: py-pandas: fix issue reported by vermin --- var/spack/repos/builtin/packages/py-pandas/package.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/var/spack/repos/builtin/packages/py-pandas/package.py b/var/spack/repos/builtin/packages/py-pandas/package.py index 9d5fa53c7c..9496908dd4 100644 --- a/var/spack/repos/builtin/packages/py-pandas/package.py +++ b/var/spack/repos/builtin/packages/py-pandas/package.py @@ -91,7 +91,7 @@ class PyPandas(PythonPackage): @property def import_modules(self): - modules = super().import_modules + modules = super(PyPandas, self).import_modules() ignored_imports = ["pandas.tests", "pandas.plotting._matplotlib"] -- cgit v1.2.3-60-g2f50 From 5daf023aecf3d72943cff0a010dfafd95edfdf3b Mon Sep 17 00:00:00 2001 From: Harmen Stoppels Date: Tue, 21 Dec 2021 18:41:12 +0100 Subject: Regenerate views when specs already installed (#28113) With this commit: ``` $ spack env activate --temp $ spack install zlib ==> All of the packages are already installed ==> Updating view at /tmp/spack-faiirgmt/.spack-env/view $ spack install zlib ==> All of the packages are already installed ``` Before this PR: ``` $ spack env activate --temp $ spack install zlib ==> All of the packages are already installed $ spack install zlib ==> All of the packages are already installed ``` No view was generated --- lib/spack/spack/environment/environment.py | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/spack/spack/environment/environment.py b/lib/spack/spack/environment/environment.py index a6be5d1c50..3114f55638 100644 --- a/lib/spack/spack/environment/environment.py +++ b/lib/spack/spack/environment/environment.py @@ -1500,10 +1500,8 @@ class Environment(object): if not specs_to_install: tty.msg('All of the packages are already installed') - return - - tty.debug('Processing {0} uninstalled specs'.format( - len(specs_to_install))) + else: + tty.debug('Processing {0} uninstalled specs'.format(len(specs_to_install))) install_args['overwrite'] = install_args.get( 'overwrite', []) + self._get_overwrite_specs() -- cgit v1.2.3-60-g2f50 From 8e659f512e00534c6af427ef3832db68fcd2f2d3 Mon Sep 17 00:00:00 2001 From: Tom Scogland Date: Wed, 22 Dec 2021 07:25:05 -0800 Subject: locks: allow locks to work under high contention (#27846) * locks: allow locks to work under high contention This is a bug found by Harshitha Menon. The `lock=None` line shouldn't be a release but should be ``` return (lock_type, None) ``` to inform the caller it couldn't get the lock type requested without disturbing the existing lock object in the database. There were also a couple of bugs due to taking write locks at the beginning without any checking or release, and not releasing read locks before requeueing. This version no longer gives me read upgrade to write errors, even running 200 instances on one box. * Change lock in check_deps_status to read, release if not installed, not sure why this was ever write, but read definitely is more appropriate here, and the read lock is only held out of the scope if the package is installed. * Release read lock before requeueing to reduce chance of livelock, the timeout that caused the original issue now happens in roughly 3 of 200 workers instead of 199 on average. --- lib/spack/spack/installer.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/lib/spack/spack/installer.py b/lib/spack/spack/installer.py index 196858830a..df1d704cd7 100644 --- a/lib/spack/spack/installer.py +++ b/lib/spack/spack/installer.py @@ -794,10 +794,10 @@ class PackageInstaller(object): .format(dep_id, action) raise InstallError(err.format(request.pkg_id, msg)) - # Attempt to get a write lock to ensure another process does not + # Attempt to get a read lock to ensure another process does not # uninstall the dependency while the requested spec is being # installed - ltype, lock = self._ensure_locked('write', dep_pkg) + ltype, lock = self._ensure_locked('read', dep_pkg) if lock is None: msg = '{0} is write locked by another process'.format(dep_id) raise InstallError(err.format(request.pkg_id, msg)) @@ -816,6 +816,8 @@ class PackageInstaller(object): tty.debug('Flagging {0} as installed per the database' .format(dep_id)) self._flag_installed(dep_pkg) + else: + lock.release_read() def _prepare_for_install(self, task): """ @@ -1027,7 +1029,7 @@ class PackageInstaller(object): except (lk.LockDowngradeError, lk.LockTimeoutError) as exc: tty.debug(err.format(op, desc, pkg_id, exc.__class__.__name__, str(exc))) - lock = None + return (lock_type, None) except (Exception, KeyboardInterrupt, SystemExit) as exc: tty.error(err.format(op, desc, pkg_id, exc.__class__.__name__, @@ -1626,6 +1628,7 @@ class PackageInstaller(object): # established by the other process -- failed, installed, or # uninstalled -- on the next pass. if ltype == 'read': + lock.release_read() self._requeue_task(task) continue -- cgit v1.2.3-60-g2f50 From 69b8cddb1b5bca729d8983450fe0b0e1ac1a2f46 Mon Sep 17 00:00:00 2001 From: Massimiliano Culpo Date: Thu, 23 Dec 2021 13:56:58 +0100 Subject: Bump version and update CHANGELOG.md --- CHANGELOG.md | 25 +++++++++++++++++++++++++ lib/spack/spack/__init__.py | 2 +- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e9bcb548ee..44123606df 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,28 @@ +# v0.17.1 (2021-12-23) + +### Spack Bugfixes +* Allow locks to work under high contention (#27846) +* Improve errors messages from clingo (#27707 #27970) +* Respect package permissions for sbang (#25764) +* Fix --enable-locks behavior (#24675) +* Fix log-format reporter ignoring install errors (#25961) +* Fix overloaded argparse keys (#27379) +* Allow style commands to run with targets other than "develop" (#27472) +* Log lock messages to debug level, instead of verbose level (#27408) +* Handle invalid unicode while logging (#21447) +* spack audit: fix API calls to variants (#27713) +* Provide meaningful message for empty environment installs (#28031) +* Added opensuse leap containers to spack containerize (#27837) +* Revert "patches: make re-applied patches idempotent" (#27625) +* MANPATH can use system defaults (#21682) +* Add "setdefault" subcommand to `spack module tcl` (#14686) +* Regenerate views when specs already installed (#28113) + +### Package bugfixes +* Fix external package detection for OpenMPI (#27255) +* Update the UPC++ package to 2021.9.0 (#26996) +* Added py-vermin v1.3.2 (#28072) + # v0.17.0 (2021-11-05) `v0.17.0` is a major feature release. diff --git a/lib/spack/spack/__init__.py b/lib/spack/spack/__init__.py index 5686f27a6d..e0c472dfb9 100644 --- a/lib/spack/spack/__init__.py +++ b/lib/spack/spack/__init__.py @@ -4,7 +4,7 @@ # SPDX-License-Identifier: (Apache-2.0 OR MIT) #: major, minor, patch version for Spack, in a tuple -spack_version_info = (0, 17, 0) +spack_version_info = (0, 17, 1) #: String containing Spack version joined with .'s spack_version = '.'.join(str(v) for v in spack_version_info) -- cgit v1.2.3-60-g2f50 From e974b44e8673ded449ce4a3ed5844398b68e81a2 Mon Sep 17 00:00:00 2001 From: Massimiliano Culpo Date: Thu, 23 Dec 2021 16:34:31 +0100 Subject: Fix execution of style tests --- share/spack/qa/run-style-tests | 2 ++ 1 file changed, 2 insertions(+) diff --git a/share/spack/qa/run-style-tests b/share/spack/qa/run-style-tests index 9f0cbdb266..df3d441c75 100755 --- a/share/spack/qa/run-style-tests +++ b/share/spack/qa/run-style-tests @@ -19,6 +19,8 @@ args=() if [[ -n $GITHUB_BASE_REF ]]; then args+=("--base" "${GITHUB_BASE_REF}") +else + args+=("--base" "${GITHUB_REF_NAME}") fi # verify that the code style is correct -- cgit v1.2.3-60-g2f50