Files
swvscode-porter/swvscode-porter.py
2025-04-17 14:43:22 +08:00

145 lines
4.6 KiB
Python

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()