From 1d03fcf6ea66b8e5af97c520318ab6b408621fbb Mon Sep 17 00:00:00 2001 From: Sli Date: Tue, 7 Jan 2025 17:10:06 +0100 Subject: [PATCH] Fix windows path and shell calls issues --- core/management/commands/install_xapian.py | 64 +++++++++++----------- staticfiles/processors.py | 7 ++- vite.config.mts | 6 +- 3 files changed, 38 insertions(+), 39 deletions(-) diff --git a/core/management/commands/install_xapian.py b/core/management/commands/install_xapian.py index af175f1b..70ecf24b 100644 --- a/core/management/commands/install_xapian.py +++ b/core/management/commands/install_xapian.py @@ -113,6 +113,10 @@ class XapianInstaller: self._core = f"xapian-core-{self._version}" self._bindings = f"xapian-bindings-{self._version}" + @property + def _is_windows(self) -> bool: + return platform.system() == "Windows" + def _util_download(self, url: str, dest: Path, sha1_hash: str) -> None: resp = urllib3.request("GET", url) if resp.status != 200: @@ -137,32 +141,7 @@ class XapianInstaller: def _prepare_dest_folder(self): shutil.rmtree(self._dest_dir, ignore_errors=True) - self._dest_dir.mkdir(parents=True) - - def _setup_windows(self): - if "64bit" not in platform.architecture(): - raise OSError("Only windows 64bit is supported") - - extractor = self._dest_dir / "" - installer = self._dest_dir / "w64devkit-x64-2.0.0.exe" - - self._util_download( - "https://github.com/ip7z/7zip/releases/download/24.08/7zr.exe", - extractor, - "d99de792fd08db53bb552cd28f0080137274f897", - ) - - self._util_download( - "https://github.com/skeeto/w64devkit/releases/download/v2.0.0/w64devkit-x64-2.0.0.exe", - installer, - "b5190c3ca9b06abe2b5cf329d99255a0be3a61ee", - ) - - subprocess.run( - [str(extractor), "x", str(installer), f"-o{self._dest_dir}"], check=False - ).check_returncode() - - sys.path.insert(0, str(self._dest_dir / "w64devkit" / "bin")) + self._dest_dir.mkdir(parents=True, exist_ok=True) def _download(self): self._stdout.write("Downloading source…") @@ -190,11 +169,24 @@ class XapianInstaller: def _install(self): self._stdout.write("Installing Xapian-core…") + def configure() -> list[str]: + if self._is_windows: + return ["sh", "configure"] + return ["./configure"] + def enable_static() -> list[str]: + if self._is_windows: + return ["--enable-shared", "--disable-static"] + return [] + + # Make sure that xapian finds the correct executable + os.environ["PYTHON3"] = str(Path(sys.executable).as_posix()) + subprocess.run( - ["./configure", "--prefix", str(self._virtual_env)], + [*configure(), "--prefix", str(self._virtual_env.as_posix()), *enable_static(),], env=dict(os.environ), cwd=self._dest_dir / self._core, check=False, + shell=self._is_windows, ).check_returncode() subprocess.run( [ @@ -205,26 +197,32 @@ class XapianInstaller: env=dict(os.environ), cwd=self._dest_dir / self._core, check=False, + shell=self._is_windows, ).check_returncode() subprocess.run( ["make", "install"], env=dict(os.environ), cwd=self._dest_dir / self._core, check=False, + shell=self._is_windows, + ).check_returncode() + self._stdout.write("Installing Xapian-bindings") subprocess.run( [ - "./configure", + *configure(), "--prefix", - str(self._virtual_env), + str(self._virtual_env.as_posix()), "--with-python3", - f"XAPIAN_CONFIG={self._virtual_env / 'bin'/'xapian-config'}", + f"XAPIAN_CONFIG={(self._virtual_env / 'bin'/'xapian-config').as_posix()}", + *enable_static(), ], env=dict(os.environ), cwd=self._dest_dir / self._bindings, check=False, + shell=self._is_windows, ).check_returncode() subprocess.run( [ @@ -235,12 +233,14 @@ class XapianInstaller: env=dict(os.environ), cwd=self._dest_dir / self._bindings, check=False, + shell=self._is_windows, ).check_returncode() subprocess.run( ["make", "install"], env=dict(os.environ), cwd=self._dest_dir / self._bindings, check=False, + shell=self._is_windows, ).check_returncode() def _post_clean(self): @@ -248,14 +248,12 @@ class XapianInstaller: def _test(self): subprocess.run( - [sys.executable, "-c", "import xapian"], check=False + [sys.executable, "-c", "import xapian"], check=False, shell=self._is_windows, ).check_returncode() def run(self): self._setup_env() self._prepare_dest_folder() - if platform.system() == "Windows": - self._setup_windows() self._download() self._install() self._post_clean() diff --git a/staticfiles/processors.py b/staticfiles/processors.py index 3a0df243..9766601a 100644 --- a/staticfiles/processors.py +++ b/staticfiles/processors.py @@ -1,6 +1,7 @@ import json import logging import subprocess +import platform from dataclasses import dataclass from hashlib import sha1 from itertools import chain @@ -94,7 +95,7 @@ class JSBundler: @staticmethod def compile(): """Bundle js files with the javascript bundler for production.""" - process = subprocess.Popen(["npm", "run", "compile"]) + process = subprocess.Popen(["npm", "run", "compile"], shell=platform.system() == "Windows") process.wait() if process.returncode: raise RuntimeError(f"Bundler failed with returncode {process.returncode}") @@ -103,7 +104,7 @@ class JSBundler: def runserver() -> subprocess.Popen: """Bundle js files automatically in background when called in debug mode.""" logging.getLogger("django").info("Running javascript bundling server") - return subprocess.Popen(["npm", "run", "serve"]) + return subprocess.Popen(["npm", "run", "serve"], shell=platform.system() == "Windows") @staticmethod def get_manifest() -> JSBundlerManifest: @@ -197,4 +198,4 @@ class OpenApi: with open(out, "w") as f: _ = f.write(schema) - subprocess.run(["npx", "openapi-ts"], check=True) + subprocess.run(["npx", "openapi-ts"], check=True, shell=platform.system() == "Windows") diff --git a/vite.config.mts b/vite.config.mts index 955590b7..14c859e7 100644 --- a/vite.config.mts +++ b/vite.config.mts @@ -1,5 +1,5 @@ // biome-ignore lint/correctness/noNodejsModules: this is backend side -import { parse, resolve } from "node:path"; +import { parse, resolve, sep } from "node:path"; import inject from "@rollup/plugin-inject"; import { glob } from "glob"; import { type AliasOptions, type UserConfig, defineConfig } from "vite"; @@ -31,7 +31,7 @@ function getAliases(): AliasOptions { function getRelativeAssetPath(path: string): string { let relativePath: string[] = []; const fullPath = parse(path); - for (const dir of fullPath.dir.split("/").reverse()) { + for (const dir of fullPath.dir.split(sep).reverse()) { if (dir === "bundled") { break; } @@ -40,7 +40,7 @@ function getRelativeAssetPath(path: string): string { // We collected folders in reverse order, we put them back in the original order relativePath = relativePath.reverse(); relativePath.push(fullPath.name); - return relativePath.join("/"); + return relativePath.join(sep); } // biome-ignore lint/style/noDefaultExport: this is recommended by documentation