From 8496d8ff778e9c7dfb4dcb5557e8cfad36124620 Mon Sep 17 00:00:00 2001 From: Todd Gamblin Date: Tue, 13 Dec 2016 01:23:40 -0800 Subject: Add a test to ensure package names have the right case. (#2562) --- bin/spack | 4 +- lib/spack/spack/hooks/__init__.py | 7 +- lib/spack/spack/hooks/case_consistency.py | 101 ++++++++++++++++++++++++++++ lib/spack/spack/hooks/yaml_version_check.py | 57 ++++++++++++++++ lib/spack/spack/yaml_version_check.py | 57 ---------------- 5 files changed, 165 insertions(+), 61 deletions(-) create mode 100644 lib/spack/spack/hooks/case_consistency.py create mode 100644 lib/spack/spack/hooks/yaml_version_check.py delete mode 100644 lib/spack/spack/yaml_version_check.py diff --git a/bin/spack b/bin/spack index 454a9a5b2d..cc9450ade7 100755 --- a/bin/spack +++ b/bin/spack @@ -156,8 +156,8 @@ def main(): import spack.util.debug as debug debug.register_interrupt_handler() - from spack.yaml_version_check import check_yaml_versions - check_yaml_versions() + # Run any available pre-run hooks + spack.hooks.pre_run() spack.spack_working_dir = working_dir if args.mock: diff --git a/lib/spack/spack/hooks/__init__.py b/lib/spack/spack/hooks/__init__.py index ff4ebc2e57..6454a865b6 100644 --- a/lib/spack/spack/hooks/__init__.py +++ b/lib/spack/spack/hooks/__init__.py @@ -64,16 +64,19 @@ class HookRunner(object): def __init__(self, hook_name): self.hook_name = hook_name - def __call__(self, pkg): + def __call__(self, *args, **kwargs): for module in all_hook_modules(): if hasattr(module, self.hook_name): hook = getattr(module, self.hook_name) if hasattr(hook, '__call__'): - hook(pkg) + hook(*args, **kwargs) + # # Define some functions that can be called to fire off hooks. # +pre_run = HookRunner('pre_run') + pre_install = HookRunner('pre_install') post_install = HookRunner('post_install') diff --git a/lib/spack/spack/hooks/case_consistency.py b/lib/spack/spack/hooks/case_consistency.py new file mode 100644 index 0000000000..faf38f7ae3 --- /dev/null +++ b/lib/spack/spack/hooks/case_consistency.py @@ -0,0 +1,101 @@ +############################################################################## +# Copyright (c) 2013-2016, Lawrence Livermore National Security, LLC. +# Produced at the Lawrence Livermore National Laboratory. +# +# This file is part of Spack. +# Created by Todd Gamblin, tgamblin@llnl.gov, All rights reserved. +# LLNL-CODE-647188 +# +# For details, see https://github.com/llnl/spack +# Please also see the LICENSE file for our notice and the LGPL. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License (as +# published by the Free Software Foundation) version 2.1, February 1999. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY OF +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the terms and +# conditions of the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +############################################################################## +from __future__ import absolute_import +import os +import re +import platform + +from llnl.util.filesystem import * + +import spack +from spack.util.executable import * + + +def pre_run(): + if platform.system() != "Darwin": + return + + git_case_consistency_check(spack.repo.get_repo('builtin').packages_path) + + +def git_case_consistency_check(path): + """Re-sync case of files in a directory with git. + + On case-insensitive but case-preserving filesystems like Mac OS X, + Git doesn't properly rename files that only had their case changed. + + This checks files in a directory against git and does a + case-restoring rename (actually two renames, e.g.:: + + name -> tmp -> NAME + + We use this in Spack to ensure package directories are named + correctly. + + TODO: this check can probably be removed once package names have been + TODO: lowercase for a long while. + + """ + with working_dir(path): + # Don't bother fixing case if Spack isn't in a git repository + git = which('git') + if not git: + return + + try: + git_filenames = git('ls-tree', '--name-only', 'HEAD', output=str) + git_filenames = set(re.split(r'\s+', git_filenames.strip())) + except ProcessError: + return # Ignore errors calling git + + lower_to_mixed = {} + for fn in git_filenames: + lower = fn.lower() + mixed = lower_to_mixed.setdefault(lower, []) + mixed.append(fn) + + # Iterate through all actual files and make sure their names are + # the same as corresponding names in git + actual_filenames = os.listdir('.') + for actual in actual_filenames: + lower = actual.lower() + + # not tracked by git + if lower not in lower_to_mixed: + continue + + # Don't know what to do with multiple matches + if len(lower_to_mixed[lower]) != 1: + continue + + # Skip if case is already correct + git_name = lower_to_mixed[lower][0] + if git_name == actual: + continue + + # restore case with two renames + tmp_name = actual + '.spack.tmp' + os.rename(actual, tmp_name) + os.rename(tmp_name, git_name) diff --git a/lib/spack/spack/hooks/yaml_version_check.py b/lib/spack/spack/hooks/yaml_version_check.py new file mode 100644 index 0000000000..a4b38198bc --- /dev/null +++ b/lib/spack/spack/hooks/yaml_version_check.py @@ -0,0 +1,57 @@ +############################################################################## +# Copyright (c) 2013-2016, Lawrence Livermore National Security, LLC. +# Produced at the Lawrence Livermore National Laboratory. +# +# This file is part of Spack. +# Created by Todd Gamblin, tgamblin@llnl.gov, All rights reserved. +# LLNL-CODE-647188 +# +# For details, see https://github.com/llnl/spack +# Please also see the LICENSE file for our notice and the LGPL. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License (as +# published by the Free Software Foundation) version 2.1, February 1999. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY OF +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the terms and +# conditions of the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +############################################################################## +"""Yaml Version Check is a module for ensuring that config file +formats are compatible with the current version of Spack.""" +import os.path +import os +import llnl.util.tty as tty +import spack.util.spack_yaml as syaml +import spack.config + + +def pre_run(): + check_compiler_yaml_version() + + +def check_compiler_yaml_version(): + config_scopes = spack.config.config_scopes + for scope in config_scopes.values(): + file_name = os.path.join(scope.path, 'compilers.yaml') + data = None + if os.path.isfile(file_name): + with open(file_name) as f: + data = syaml.load(f) + + if data: + compilers = data['compilers'] + if len(compilers) > 0: + if (not isinstance(compilers, list) or + 'operating_system' not in compilers[0]['compiler']): + new_file = os.path.join(scope.path, '_old_compilers.yaml') + tty.warn('%s in out of date compilers format. ' + 'Moved to %s. Spack automatically generate ' + 'a compilers config file ' + % (file_name, new_file)) + os.rename(file_name, new_file) diff --git a/lib/spack/spack/yaml_version_check.py b/lib/spack/spack/yaml_version_check.py deleted file mode 100644 index 2c5b511d7f..0000000000 --- a/lib/spack/spack/yaml_version_check.py +++ /dev/null @@ -1,57 +0,0 @@ -############################################################################## -# Copyright (c) 2013-2016, Lawrence Livermore National Security, LLC. -# Produced at the Lawrence Livermore National Laboratory. -# -# This file is part of Spack. -# Created by Todd Gamblin, tgamblin@llnl.gov, All rights reserved. -# LLNL-CODE-647188 -# -# For details, see https://github.com/llnl/spack -# Please also see the LICENSE file for our notice and the LGPL. -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License (as -# published by the Free Software Foundation) version 2.1, February 1999. -# -# This program is distributed in the hope that it will be useful, but -# WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY OF -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the terms and -# conditions of the GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -############################################################################## -"""Yaml Version Check is a module for ensuring that config file -formats are compatible with the current version of Spack.""" -import os.path -import os -import llnl.util.tty as tty -import spack.util.spack_yaml as syaml -import spack.config - - -def check_yaml_versions(): - check_compiler_yaml_version() - - -def check_compiler_yaml_version(): - config_scopes = spack.config.config_scopes - for scope in config_scopes.values(): - file_name = os.path.join(scope.path, 'compilers.yaml') - data = None - if os.path.isfile(file_name): - with open(file_name) as f: - data = syaml.load(f) - - if data: - compilers = data['compilers'] - if len(compilers) > 0: - if (not isinstance(compilers, list) or - 'operating_system' not in compilers[0]['compiler']): - new_file = os.path.join(scope.path, '_old_compilers.yaml') - tty.warn('%s in out of date compilers format. ' - 'Moved to %s. Spack automatically generate ' - 'a compilers config file ' - % (file_name, new_file)) - os.rename(file_name, new_file) -- cgit v1.2.3-60-g2f50