From ac17dccc820282ded7266ba73b34416b48f20a6d Mon Sep 17 00:00:00 2001 From: Yingchi Long Date: Thu, 17 Apr 2025 14:43:22 +0800 Subject: [PATCH] swvscode-porter.py: init --- swvscode-porter.py | 144 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 144 insertions(+) create mode 100644 swvscode-porter.py diff --git a/swvscode-porter.py b/swvscode-porter.py new file mode 100644 index 0000000..1d01f40 --- /dev/null +++ b/swvscode-porter.py @@ -0,0 +1,144 @@ +import json +import os +import shutil +import subprocess +import urllib.request +from functools import partial +from pathlib import Path +from tarfile import TarFile + +NODE_MODULES = "node_modules" + + +def replace(target_path, link_target): + # Ensure the parent directory of target_path exists + target_path.parent.mkdir(parents=True, exist_ok=True) + + if target_path.is_symlink(): + if target_path.resolve() == link_target.resolve(): + print(f"Symlink already correct: {target_path} -> {link_target}") + else: + print(f"Symlink points to the wrong target. Updating: {target_path}") + target_path.unlink() + os.symlink(link_target, target_path) + elif target_path.exists(): + print( + f"Path exists but is not a symlink. Removing and replacing: {target_path}" + ) + if target_path.is_dir(): + shutil.rmtree(target_path) + else: + target_path.unlink() + os.symlink(link_target, target_path) + else: + print(f"Creating new symlink: {target_path} -> {link_target}") + os.symlink(link_target, target_path) + +def replace_node_modules(vscode_path, native_path, name): + replace(target_path=vscode_path / NODE_MODULES / name, link_target=native_path / NODE_MODULES / name) + + + +native_modules = [ + "node-pty", + "native-watchdog", + "@vscode/spdlog", + "@parcel/watcher", +] + + +def replace_natives(vscode_path, native_path): + replace = partial(replace_node_modules, vscode_path, native_path) + for name in native_modules: + replace(name) + +def mk_native_modules(vscode_path: Path, native_path: Path): + """ + For each native module: + 1. Read VSCode's node_modules package/package.json to retrieve version info + 2. Use npm to install specific versions of the native modules + """ + native_path.mkdir(parents=True, exist_ok=True) + + # Create package.json if it doesn't exist + package_json_path = native_path / "package.json" + if not package_json_path.exists(): + with open(package_json_path, "w") as f: + json.dump({ + "name": "vscode-native-modules", + "version": "1.0.0", + "private": True, + "dependencies": {} + }, f, indent=2) + + # Read the existing package.json + with open(package_json_path, "r") as f: + package_json = json.load(f) + + # Ensure dependencies object exists + if "dependencies" not in package_json: + package_json["dependencies"] = {} + + # For each native module, get its version and add to dependencies + modules_to_install = [] + for module_name in native_modules: + module_package_json = vscode_path / NODE_MODULES / module_name / "package.json" + if module_package_json.exists(): + with open(module_package_json, "r") as f: + module_info = json.load(f) + version = module_info.get("version", "latest") + package_json["dependencies"][module_name] = version + modules_to_install.append(f"{module_name}@{version}") + + # Write updated package.json + with open(package_json_path, "w") as f: + json.dump(package_json, f, indent=2) + + # Install the native modules + if modules_to_install: + print(f"Installing native modules: {', '.join(modules_to_install)}") + subprocess.run(["npm", "install"], cwd=str(native_path), check=True) + +def replace_node(vscode_path, node_path): + """ + Replace the node binary in vscode_path with the one from node_path. + """ + vscode_node_path = vscode_path / "node" + + # Ensure the parent directory of vscode_node_path exists + vscode_node_path.parent.mkdir(parents=True, exist_ok=True) + + replace( + target_path=vscode_node_path, + link_target=node_path, + ) + +def main(): + # Download vscode server + + url = "https://github.com/VSCodium/vscodium/releases/download/1.99.32562/vscodium-reh-web-linux-x64-1.99.32562.tar.gz" # Replace with the actual URL + tar_path = "vscode-server.tar.gz" # Replace with your tar.gz file path + + with urllib.request.urlopen(url) as response: + with open(tar_path, "wb") as file: + file.write(response.read()) + + vscode_path = (Path(".") / "vscode-server-linux-x64-web").absolute() + # Extract it (tar.gz) + with TarFile.open(tar_path, "r:gz") as tar: + tar.extractall(path=vscode_path) + + + native_path = (Path(".") / "native_modules").absolute() + mk_native_modules( + vscode_path=vscode_path, + native_path=native_path, + ) + + replace_natives(vscode_path, native_path) + replace_node(vscode_path, Path(shutil.which("node"))) + + +if __name__ == "__main__": + main() +