Windows: Non config changes to support Gitlab CI (#43965)
* Quote python for shlex * Remove python path quoting patch * spack env: Allow `C` "protocol" for config_path When running spack on windows, a path beginning with `C://...` is a valid path. * Remove makefile from ci rebuild * GPG use llnl.util.filesystem.getuid * Cleanup process_command * Remove unused lines * Fix tyop in encode_path * Double quote arguments * Cleanup process_command * Pass cdash args with = * Escape parens in CMD script * escape parens doesn't only apply to paths * Install deps * sfn prefix * use sfn with libxml2 * Add hash to dep install * WIP * REview * Changes missed in prior review commit * Style * Ensure we handle Windows paths with config scopes * clarify docstring * No more MAKE_COMMAND * syntax cleanup * Actually correct is_path_url * Correct call * raise on other errors * url2path behaves differently on unix * Ensure proper quoting * actually prepend slash in slash_hash --------- Co-authored-by: Ryan Krattiger <ryan.krattiger@kitware.com> Co-authored-by: Mike VanDenburgh <michael.vandenburgh@kitware.com>
This commit is contained in:
		@@ -187,12 +187,18 @@ def polite_filename(filename: str) -> str:
 | 
				
			|||||||
    return _polite_antipattern().sub("_", filename)
 | 
					    return _polite_antipattern().sub("_", filename)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def getuid():
 | 
					def getuid() -> Union[str, int]:
 | 
				
			||||||
 | 
					    """Returns os getuid on non Windows
 | 
				
			||||||
 | 
					    On Windows returns 0 for admin users, login string otherwise
 | 
				
			||||||
 | 
					    This is in line with behavior from get_owner_uid which
 | 
				
			||||||
 | 
					    always returns the login string on Windows
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
    if sys.platform == "win32":
 | 
					    if sys.platform == "win32":
 | 
				
			||||||
        import ctypes
 | 
					        import ctypes
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        # If not admin, use the string name of the login as a unique ID
 | 
				
			||||||
        if ctypes.windll.shell32.IsUserAnAdmin() == 0:
 | 
					        if ctypes.windll.shell32.IsUserAnAdmin() == 0:
 | 
				
			||||||
            return 1
 | 
					            return os.getlogin()
 | 
				
			||||||
        return 0
 | 
					        return 0
 | 
				
			||||||
    else:
 | 
					    else:
 | 
				
			||||||
        return os.getuid()
 | 
					        return os.getuid()
 | 
				
			||||||
@@ -213,6 +219,15 @@ def _win_rename(src, dst):
 | 
				
			|||||||
    os.replace(src, dst)
 | 
					    os.replace(src, dst)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@system_path_filter
 | 
				
			||||||
 | 
					def msdos_escape_parens(path):
 | 
				
			||||||
 | 
					    """MS-DOS interprets parens as grouping parameters even in a quoted string"""
 | 
				
			||||||
 | 
					    if sys.platform == "win32":
 | 
				
			||||||
 | 
					        return path.replace("(", "^(").replace(")", "^)")
 | 
				
			||||||
 | 
					    else:
 | 
				
			||||||
 | 
					        return path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@system_path_filter
 | 
					@system_path_filter
 | 
				
			||||||
def rename(src, dst):
 | 
					def rename(src, dst):
 | 
				
			||||||
    # On Windows, os.rename will fail if the destination file already exists
 | 
					    # On Windows, os.rename will fail if the destination file already exists
 | 
				
			||||||
@@ -553,7 +568,13 @@ def exploding_archive_handler(tarball_container, stage):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@system_path_filter(arg_slice=slice(1))
 | 
					@system_path_filter(arg_slice=slice(1))
 | 
				
			||||||
def get_owner_uid(path, err_msg=None):
 | 
					def get_owner_uid(path, err_msg=None) -> Union[str, int]:
 | 
				
			||||||
 | 
					    """Returns owner UID of path destination
 | 
				
			||||||
 | 
					    On non Windows this is the value of st_uid
 | 
				
			||||||
 | 
					    On Windows this is the login string associated with the
 | 
				
			||||||
 | 
					     owning user.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    """
 | 
				
			||||||
    if not os.path.exists(path):
 | 
					    if not os.path.exists(path):
 | 
				
			||||||
        mkdirp(path, mode=stat.S_IRWXU)
 | 
					        mkdirp(path, mode=stat.S_IRWXU)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -145,7 +145,7 @@ def install(self, pkg, spec, prefix):
 | 
				
			|||||||
        opts += self.nmake_install_args()
 | 
					        opts += self.nmake_install_args()
 | 
				
			||||||
        if self.makefile_name:
 | 
					        if self.makefile_name:
 | 
				
			||||||
            opts.append("/F{}".format(self.makefile_name))
 | 
					            opts.append("/F{}".format(self.makefile_name))
 | 
				
			||||||
        opts.append(self.define("PREFIX", prefix))
 | 
					        opts.append(self.define("PREFIX", fs.windows_sfn(prefix)))
 | 
				
			||||||
        with fs.working_dir(self.build_directory):
 | 
					        with fs.working_dir(self.build_directory):
 | 
				
			||||||
            inspect.getmodule(self.pkg).nmake(
 | 
					            inspect.getmodule(self.pkg).nmake(
 | 
				
			||||||
                *opts, *self.install_targets, ignore_quotes=self.ignore_quotes
 | 
					                *opts, *self.install_targets, ignore_quotes=self.ignore_quotes
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1478,6 +1478,12 @@ def copy_test_logs_to_artifacts(test_stage, job_test_dir):
 | 
				
			|||||||
    copy_files_to_artifacts(os.path.join(test_stage, "*", "*.txt"), job_test_dir)
 | 
					    copy_files_to_artifacts(os.path.join(test_stage, "*", "*.txt"), job_test_dir)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def win_quote(quote_str: str) -> str:
 | 
				
			||||||
 | 
					    if IS_WINDOWS:
 | 
				
			||||||
 | 
					        quote_str = f'"{quote_str}"'
 | 
				
			||||||
 | 
					    return quote_str
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def download_and_extract_artifacts(url, work_dir):
 | 
					def download_and_extract_artifacts(url, work_dir):
 | 
				
			||||||
    """Look for gitlab artifacts.zip at the given url, and attempt to download
 | 
					    """Look for gitlab artifacts.zip at the given url, and attempt to download
 | 
				
			||||||
        and extract the contents into the given work_dir
 | 
					        and extract the contents into the given work_dir
 | 
				
			||||||
@@ -1942,9 +1948,9 @@ def compose_command_err_handling(args):
 | 
				
			|||||||
        # but we need to handle EXEs (git, etc) ourselves
 | 
					        # but we need to handle EXEs (git, etc) ourselves
 | 
				
			||||||
        catch_exe_failure = (
 | 
					        catch_exe_failure = (
 | 
				
			||||||
            """
 | 
					            """
 | 
				
			||||||
if ($LASTEXITCODE -ne 0){
 | 
					if ($LASTEXITCODE -ne 0){{
 | 
				
			||||||
    throw "Command {} has failed"
 | 
					    throw 'Command {} has failed'
 | 
				
			||||||
}
 | 
					}}
 | 
				
			||||||
"""
 | 
					"""
 | 
				
			||||||
            if IS_WINDOWS
 | 
					            if IS_WINDOWS
 | 
				
			||||||
            else ""
 | 
					            else ""
 | 
				
			||||||
@@ -2176,13 +2182,13 @@ def __init__(self, ci_cdash):
 | 
				
			|||||||
    def args(self):
 | 
					    def args(self):
 | 
				
			||||||
        return [
 | 
					        return [
 | 
				
			||||||
            "--cdash-upload-url",
 | 
					            "--cdash-upload-url",
 | 
				
			||||||
            self.upload_url,
 | 
					            win_quote(self.upload_url),
 | 
				
			||||||
            "--cdash-build",
 | 
					            "--cdash-build",
 | 
				
			||||||
            self.build_name,
 | 
					            win_quote(self.build_name),
 | 
				
			||||||
            "--cdash-site",
 | 
					            "--cdash-site",
 | 
				
			||||||
            self.site,
 | 
					            win_quote(self.site),
 | 
				
			||||||
            "--cdash-buildstamp",
 | 
					            "--cdash-buildstamp",
 | 
				
			||||||
            self.build_stamp,
 | 
					            win_quote(self.build_stamp),
 | 
				
			||||||
        ]
 | 
					        ]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @property  # type: ignore
 | 
					    @property  # type: ignore
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -31,7 +31,6 @@
 | 
				
			|||||||
level = "long"
 | 
					level = "long"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
SPACK_COMMAND = "spack"
 | 
					SPACK_COMMAND = "spack"
 | 
				
			||||||
MAKE_COMMAND = "make"
 | 
					 | 
				
			||||||
INSTALL_FAIL_CODE = 1
 | 
					INSTALL_FAIL_CODE = 1
 | 
				
			||||||
FAILED_CREATE_BUILDCACHE_CODE = 100
 | 
					FAILED_CREATE_BUILDCACHE_CODE = 100
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -40,6 +39,12 @@ def deindent(desc):
 | 
				
			|||||||
    return desc.replace("    ", "")
 | 
					    return desc.replace("    ", "")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def unicode_escape(path: str) -> str:
 | 
				
			||||||
 | 
					    """Returns transformed path with any unicode
 | 
				
			||||||
 | 
					    characters replaced with their corresponding escapes"""
 | 
				
			||||||
 | 
					    return path.encode("unicode-escape").decode("utf-8")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def setup_parser(subparser):
 | 
					def setup_parser(subparser):
 | 
				
			||||||
    setup_parser.parser = subparser
 | 
					    setup_parser.parser = subparser
 | 
				
			||||||
    subparsers = subparser.add_subparsers(help="CI sub-commands")
 | 
					    subparsers = subparser.add_subparsers(help="CI sub-commands")
 | 
				
			||||||
@@ -551,75 +556,35 @@ def ci_rebuild(args):
 | 
				
			|||||||
    # No hash match anywhere means we need to rebuild spec
 | 
					    # No hash match anywhere means we need to rebuild spec
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Start with spack arguments
 | 
					    # Start with spack arguments
 | 
				
			||||||
    spack_cmd = [SPACK_COMMAND, "--color=always", "--backtrace", "--verbose"]
 | 
					    spack_cmd = [SPACK_COMMAND, "--color=always", "--backtrace", "--verbose", "install"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    config = cfg.get("config")
 | 
					    config = cfg.get("config")
 | 
				
			||||||
    if not config["verify_ssl"]:
 | 
					    if not config["verify_ssl"]:
 | 
				
			||||||
        spack_cmd.append("-k")
 | 
					        spack_cmd.append("-k")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    install_args = []
 | 
					    install_args = [f'--use-buildcache={spack_ci.win_quote("package:never,dependencies:only")}']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    can_verify = spack_ci.can_verify_binaries()
 | 
					    can_verify = spack_ci.can_verify_binaries()
 | 
				
			||||||
    verify_binaries = can_verify and spack_is_pr_pipeline is False
 | 
					    verify_binaries = can_verify and spack_is_pr_pipeline is False
 | 
				
			||||||
    if not verify_binaries:
 | 
					    if not verify_binaries:
 | 
				
			||||||
        install_args.append("--no-check-signature")
 | 
					        install_args.append("--no-check-signature")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    slash_hash = "/{}".format(job_spec.dag_hash())
 | 
					    slash_hash = spack_ci.win_quote("/" + job_spec.dag_hash())
 | 
				
			||||||
 | 
					 | 
				
			||||||
    # Arguments when installing dependencies from cache
 | 
					 | 
				
			||||||
    deps_install_args = install_args
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Arguments when installing the root from sources
 | 
					    # Arguments when installing the root from sources
 | 
				
			||||||
    root_install_args = install_args + [
 | 
					    deps_install_args = install_args + ["--only=dependencies"]
 | 
				
			||||||
        "--keep-stage",
 | 
					    root_install_args = install_args + ["--keep-stage", "--only=package"]
 | 
				
			||||||
        "--only=package",
 | 
					
 | 
				
			||||||
        "--use-buildcache=package:never,dependencies:only",
 | 
					 | 
				
			||||||
    ]
 | 
					 | 
				
			||||||
    if cdash_handler:
 | 
					    if cdash_handler:
 | 
				
			||||||
        # Add additional arguments to `spack install` for CDash reporting.
 | 
					        # Add additional arguments to `spack install` for CDash reporting.
 | 
				
			||||||
        root_install_args.extend(cdash_handler.args())
 | 
					        root_install_args.extend(cdash_handler.args())
 | 
				
			||||||
    root_install_args.append(slash_hash)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # ["x", "y"] -> "'x' 'y'"
 | 
					 | 
				
			||||||
    args_to_string = lambda args: " ".join("'{}'".format(arg) for arg in args)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    commands = [
 | 
					    commands = [
 | 
				
			||||||
        # apparently there's a race when spack bootstraps? do it up front once
 | 
					        # apparently there's a race when spack bootstraps? do it up front once
 | 
				
			||||||
        [SPACK_COMMAND, "-e", env.path, "bootstrap", "now"],
 | 
					        [SPACK_COMMAND, "-e", unicode_escape(env.path), "bootstrap", "now"],
 | 
				
			||||||
        [
 | 
					        spack_cmd + deps_install_args + [slash_hash],
 | 
				
			||||||
            SPACK_COMMAND,
 | 
					        spack_cmd + root_install_args + [slash_hash],
 | 
				
			||||||
            "-e",
 | 
					 | 
				
			||||||
            env.path,
 | 
					 | 
				
			||||||
            "env",
 | 
					 | 
				
			||||||
            "depfile",
 | 
					 | 
				
			||||||
            "-o",
 | 
					 | 
				
			||||||
            "Makefile",
 | 
					 | 
				
			||||||
            "--use-buildcache=package:never,dependencies:only",
 | 
					 | 
				
			||||||
            slash_hash,  # limit to spec we're building
 | 
					 | 
				
			||||||
        ],
 | 
					 | 
				
			||||||
        [
 | 
					 | 
				
			||||||
            # --output-sync requires GNU make 4.x.
 | 
					 | 
				
			||||||
            # Old make errors when you pass it a flag it doesn't recognize,
 | 
					 | 
				
			||||||
            # but it doesn't error or warn when you set unrecognized flags in
 | 
					 | 
				
			||||||
            # this variable.
 | 
					 | 
				
			||||||
            "export",
 | 
					 | 
				
			||||||
            "GNUMAKEFLAGS=--output-sync=recurse",
 | 
					 | 
				
			||||||
        ],
 | 
					 | 
				
			||||||
        [
 | 
					 | 
				
			||||||
            MAKE_COMMAND,
 | 
					 | 
				
			||||||
            "SPACK={}".format(args_to_string(spack_cmd)),
 | 
					 | 
				
			||||||
            "SPACK_COLOR=always",
 | 
					 | 
				
			||||||
            "SPACK_INSTALL_FLAGS={}".format(args_to_string(deps_install_args)),
 | 
					 | 
				
			||||||
            "-j$(nproc)",
 | 
					 | 
				
			||||||
            "install-deps/{}".format(
 | 
					 | 
				
			||||||
                spack.environment.depfile.MakefileSpec(job_spec).safe_format(
 | 
					 | 
				
			||||||
                    "{name}-{version}-{hash}"
 | 
					 | 
				
			||||||
                )
 | 
					 | 
				
			||||||
            ),
 | 
					 | 
				
			||||||
        ],
 | 
					 | 
				
			||||||
        spack_cmd + ["install"] + root_install_args,
 | 
					 | 
				
			||||||
    ]
 | 
					    ]
 | 
				
			||||||
 | 
					 | 
				
			||||||
    tty.debug("Installing {0} from source".format(job_spec.name))
 | 
					    tty.debug("Installing {0} from source".format(job_spec.name))
 | 
				
			||||||
    install_exit_code = spack_ci.process_command("install", commands, repro_dir)
 | 
					    install_exit_code = spack_ci.process_command("install", commands, repro_dir)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3036,54 +3036,56 @@ def included_config_scopes(self) -> List[spack.config.ConfigScope]:
 | 
				
			|||||||
        for i, config_path in enumerate(reversed(includes)):
 | 
					        for i, config_path in enumerate(reversed(includes)):
 | 
				
			||||||
            # allow paths to contain spack config/environment variables, etc.
 | 
					            # allow paths to contain spack config/environment variables, etc.
 | 
				
			||||||
            config_path = substitute_path_variables(config_path)
 | 
					            config_path = substitute_path_variables(config_path)
 | 
				
			||||||
 | 
					 | 
				
			||||||
            include_url = urllib.parse.urlparse(config_path)
 | 
					            include_url = urllib.parse.urlparse(config_path)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            # Transform file:// URLs to direct includes.
 | 
					            # If scheme is not valid, config_path is not a url
 | 
				
			||||||
            if include_url.scheme == "file":
 | 
					            # of a type Spack is generally aware
 | 
				
			||||||
                config_path = urllib.request.url2pathname(include_url.path)
 | 
					            if spack.util.url.validate_scheme(include_url.scheme):
 | 
				
			||||||
 | 
					                # Transform file:// URLs to direct includes.
 | 
				
			||||||
 | 
					                if include_url.scheme == "file":
 | 
				
			||||||
 | 
					                    config_path = urllib.request.url2pathname(include_url.path)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            # Any other URL should be fetched.
 | 
					                # Any other URL should be fetched.
 | 
				
			||||||
            elif include_url.scheme in ("http", "https", "ftp"):
 | 
					                elif include_url.scheme in ("http", "https", "ftp"):
 | 
				
			||||||
                # Stage any remote configuration file(s)
 | 
					                    # Stage any remote configuration file(s)
 | 
				
			||||||
                staged_configs = (
 | 
					                    staged_configs = (
 | 
				
			||||||
                    os.listdir(self.config_stage_dir)
 | 
					                        os.listdir(self.config_stage_dir)
 | 
				
			||||||
                    if os.path.exists(self.config_stage_dir)
 | 
					                        if os.path.exists(self.config_stage_dir)
 | 
				
			||||||
                    else []
 | 
					                        else []
 | 
				
			||||||
                )
 | 
					 | 
				
			||||||
                remote_path = urllib.request.url2pathname(include_url.path)
 | 
					 | 
				
			||||||
                basename = os.path.basename(remote_path)
 | 
					 | 
				
			||||||
                if basename in staged_configs:
 | 
					 | 
				
			||||||
                    # Do NOT re-stage configuration files over existing
 | 
					 | 
				
			||||||
                    # ones with the same name since there is a risk of
 | 
					 | 
				
			||||||
                    # losing changes (e.g., from 'spack config update').
 | 
					 | 
				
			||||||
                    tty.warn(
 | 
					 | 
				
			||||||
                        "Will not re-stage configuration from {0} to avoid "
 | 
					 | 
				
			||||||
                        "losing changes to the already staged file of the "
 | 
					 | 
				
			||||||
                        "same name.".format(remote_path)
 | 
					 | 
				
			||||||
                    )
 | 
					                    )
 | 
				
			||||||
 | 
					                    remote_path = urllib.request.url2pathname(include_url.path)
 | 
				
			||||||
                    # Recognize the configuration stage directory
 | 
					                    basename = os.path.basename(remote_path)
 | 
				
			||||||
                    # is flattened to ensure a single copy of each
 | 
					                    if basename in staged_configs:
 | 
				
			||||||
                    # configuration file.
 | 
					                        # Do NOT re-stage configuration files over existing
 | 
				
			||||||
                    config_path = self.config_stage_dir
 | 
					                        # ones with the same name since there is a risk of
 | 
				
			||||||
                    if basename.endswith(".yaml"):
 | 
					                        # losing changes (e.g., from 'spack config update').
 | 
				
			||||||
                        config_path = os.path.join(config_path, basename)
 | 
					                        tty.warn(
 | 
				
			||||||
                else:
 | 
					                            "Will not re-stage configuration from {0} to avoid "
 | 
				
			||||||
                    staged_path = spack.config.fetch_remote_configs(
 | 
					                            "losing changes to the already staged file of the "
 | 
				
			||||||
                        config_path, str(self.config_stage_dir), skip_existing=True
 | 
					                            "same name.".format(remote_path)
 | 
				
			||||||
                    )
 | 
					 | 
				
			||||||
                    if not staged_path:
 | 
					 | 
				
			||||||
                        raise SpackEnvironmentError(
 | 
					 | 
				
			||||||
                            "Unable to fetch remote configuration {0}".format(config_path)
 | 
					 | 
				
			||||||
                        )
 | 
					                        )
 | 
				
			||||||
                    config_path = staged_path
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            elif include_url.scheme:
 | 
					                        # Recognize the configuration stage directory
 | 
				
			||||||
                raise ValueError(
 | 
					                        # is flattened to ensure a single copy of each
 | 
				
			||||||
                    f"Unsupported URL scheme ({include_url.scheme}) for "
 | 
					                        # configuration file.
 | 
				
			||||||
                    f"environment include: {config_path}"
 | 
					                        config_path = self.config_stage_dir
 | 
				
			||||||
                )
 | 
					                        if basename.endswith(".yaml"):
 | 
				
			||||||
 | 
					                            config_path = os.path.join(config_path, basename)
 | 
				
			||||||
 | 
					                    else:
 | 
				
			||||||
 | 
					                        staged_path = spack.config.fetch_remote_configs(
 | 
				
			||||||
 | 
					                            config_path, str(self.config_stage_dir), skip_existing=True
 | 
				
			||||||
 | 
					                        )
 | 
				
			||||||
 | 
					                        if not staged_path:
 | 
				
			||||||
 | 
					                            raise SpackEnvironmentError(
 | 
				
			||||||
 | 
					                                "Unable to fetch remote configuration {0}".format(config_path)
 | 
				
			||||||
 | 
					                            )
 | 
				
			||||||
 | 
					                        config_path = staged_path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                elif include_url.scheme:
 | 
				
			||||||
 | 
					                    raise ValueError(
 | 
				
			||||||
 | 
					                        f"Unsupported URL scheme ({include_url.scheme}) for "
 | 
				
			||||||
 | 
					                        f"environment include: {config_path}"
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            # treat relative paths as relative to the environment
 | 
					            # treat relative paths as relative to the environment
 | 
				
			||||||
            if not os.path.isabs(config_path):
 | 
					            if not os.path.isabs(config_path):
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -760,7 +760,6 @@ def test_ci_rebuild_mock_success(
 | 
				
			|||||||
    rebuild_env = create_rebuild_env(tmpdir, pkg_name, broken_tests)
 | 
					    rebuild_env = create_rebuild_env(tmpdir, pkg_name, broken_tests)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    monkeypatch.setattr(spack.cmd.ci, "SPACK_COMMAND", "echo")
 | 
					    monkeypatch.setattr(spack.cmd.ci, "SPACK_COMMAND", "echo")
 | 
				
			||||||
    monkeypatch.setattr(spack.cmd.ci, "MAKE_COMMAND", "echo")
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    with rebuild_env.env_dir.as_cwd():
 | 
					    with rebuild_env.env_dir.as_cwd():
 | 
				
			||||||
        activate_rebuild_env(tmpdir, pkg_name, rebuild_env)
 | 
					        activate_rebuild_env(tmpdir, pkg_name, rebuild_env)
 | 
				
			||||||
@@ -843,7 +842,6 @@ def test_ci_rebuild(
 | 
				
			|||||||
        ci_cmd("rebuild", "--tests", fail_on_error=False)
 | 
					        ci_cmd("rebuild", "--tests", fail_on_error=False)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    monkeypatch.setattr(spack.cmd.ci, "SPACK_COMMAND", "notcommand")
 | 
					    monkeypatch.setattr(spack.cmd.ci, "SPACK_COMMAND", "notcommand")
 | 
				
			||||||
    monkeypatch.setattr(spack.cmd.ci, "MAKE_COMMAND", "notcommand")
 | 
					 | 
				
			||||||
    monkeypatch.setattr(spack.cmd.ci, "INSTALL_FAIL_CODE", 127)
 | 
					    monkeypatch.setattr(spack.cmd.ci, "INSTALL_FAIL_CODE", 127)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    with rebuild_env.env_dir.as_cwd():
 | 
					    with rebuild_env.env_dir.as_cwd():
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,6 +8,8 @@
 | 
				
			|||||||
import os
 | 
					import os
 | 
				
			||||||
import re
 | 
					import re
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import llnl.util.filesystem
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import spack.error
 | 
					import spack.error
 | 
				
			||||||
import spack.paths
 | 
					import spack.paths
 | 
				
			||||||
import spack.util.executable
 | 
					import spack.util.executable
 | 
				
			||||||
@@ -385,7 +387,7 @@ def _socket_dir(gpgconf):
 | 
				
			|||||||
                os.mkdir(var_run_user)
 | 
					                os.mkdir(var_run_user)
 | 
				
			||||||
                os.chmod(var_run_user, 0o777)
 | 
					                os.chmod(var_run_user, 0o777)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            user_dir = os.path.join(var_run_user, str(os.getuid()))
 | 
					            user_dir = os.path.join(var_run_user, str(llnl.util.filesystem.getuid()))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if not os.path.exists(user_dir):
 | 
					            if not os.path.exists(user_dir):
 | 
				
			||||||
                os.mkdir(user_dir)
 | 
					                os.mkdir(user_dir)
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -76,14 +76,7 @@ def is_path_instead_of_url(path_or_url):
 | 
				
			|||||||
    """Historically some config files and spack commands used paths
 | 
					    """Historically some config files and spack commands used paths
 | 
				
			||||||
    where urls should be used. This utility can be used to validate
 | 
					    where urls should be used. This utility can be used to validate
 | 
				
			||||||
    and promote paths to urls."""
 | 
					    and promote paths to urls."""
 | 
				
			||||||
    scheme = urllib.parse.urlparse(path_or_url).scheme
 | 
					    return not validate_scheme(urllib.parse.urlparse(path_or_url).scheme)
 | 
				
			||||||
 | 
					 | 
				
			||||||
    # On non-Windows, no scheme means it's likely a path
 | 
					 | 
				
			||||||
    if not sys.platform == "win32":
 | 
					 | 
				
			||||||
        return not scheme
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    # On Windows, we may have drive letters.
 | 
					 | 
				
			||||||
    return "A" <= scheme <= "Z"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def format(parsed_url):
 | 
					def format(parsed_url):
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,6 +4,8 @@
 | 
				
			|||||||
# SPDX-License-Identifier: (Apache-2.0 OR MIT)
 | 
					# SPDX-License-Identifier: (Apache-2.0 OR MIT)
 | 
				
			||||||
import os
 | 
					import os
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import llnl.util.filesystem as fs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import spack.builder
 | 
					import spack.builder
 | 
				
			||||||
from spack.build_systems import autotools, nmake
 | 
					from spack.build_systems import autotools, nmake
 | 
				
			||||||
from spack.package import *
 | 
					from spack.package import *
 | 
				
			||||||
@@ -244,19 +246,30 @@ def makefile_name(self):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    @property
 | 
					    @property
 | 
				
			||||||
    def build_directory(self):
 | 
					    def build_directory(self):
 | 
				
			||||||
        return os.path.join(self.stage.source_path, "win32")
 | 
					        return fs.windows_sfn(os.path.join(self.stage.source_path, "win32"))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def configure(self, pkg, spec, prefix):
 | 
					    def configure(self, pkg, spec, prefix):
 | 
				
			||||||
        with working_dir(self.build_directory):
 | 
					        with working_dir(self.build_directory):
 | 
				
			||||||
            opts = [
 | 
					            opts = [
 | 
				
			||||||
                "prefix=%s" % prefix,
 | 
					                "prefix=%s" % fs.windows_sfn(prefix),
 | 
				
			||||||
                "compiler=msvc",
 | 
					                "compiler=msvc",
 | 
				
			||||||
                "iconv=no",
 | 
					                "iconv=no",
 | 
				
			||||||
                "zlib=yes",
 | 
					                "zlib=yes",
 | 
				
			||||||
                "lzma=yes",
 | 
					                "lzma=yes",
 | 
				
			||||||
                "lib=%s" % ";".join((spec["zlib-api"].prefix.lib, spec["xz"].prefix.lib)),
 | 
					                "lib=%s"
 | 
				
			||||||
 | 
					                % ";".join(
 | 
				
			||||||
 | 
					                    (
 | 
				
			||||||
 | 
					                        fs.windows_sfn(spec["zlib-api"].prefix.lib),
 | 
				
			||||||
 | 
					                        fs.windows_sfn(spec["xz"].prefix.lib),
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
                "include=%s"
 | 
					                "include=%s"
 | 
				
			||||||
                % ";".join((spec["zlib-api"].prefix.include, spec["xz"].prefix.include)),
 | 
					                % ";".join(
 | 
				
			||||||
 | 
					                    (
 | 
				
			||||||
 | 
					                        fs.windows_sfn(spec["zlib-api"].prefix.include),
 | 
				
			||||||
 | 
					                        fs.windows_sfn(spec["xz"].prefix.include),
 | 
				
			||||||
 | 
					                    )
 | 
				
			||||||
 | 
					                ),
 | 
				
			||||||
            ]
 | 
					            ]
 | 
				
			||||||
            if "+python" in spec:
 | 
					            if "+python" in spec:
 | 
				
			||||||
                opts.append("python=yes")
 | 
					                opts.append("python=yes")
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user