blob: 36cb91ac771e3b8f0b7f7e6cf93f6d1e2e98b5f0 [file] [log] [blame]
#!/usr/bin/env python3
# Copyright 2025 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import json
import os
import shutil
import stat
import sys
# The directory where CIPD downloads the binary
SRC_DIR = os.path.join('third_party', 'rollup_libs')
# The root of the node_modules directory
NODE_MODULES_ROOT = 'node_modules'
def on_rm_error(func, path, exc_info):
# This error handler is for shutil.rmtree.
# On Windows, rmtree can fail with PermissionError if a file is read-only.
# To fix this, we make the file writable and retry the deletion.
os.chmod(path, stat.S_IWRITE)
func(path)
def main():
if not os.path.exists(SRC_DIR):
print(
f"Source directory {SRC_DIR} does not exist. Skipping Rollup libs sync."
)
return 0
# Ensure node_modules exists (in case npm install hasn't run yet)
if not os.path.exists(NODE_MODULES_ROOT):
os.makedirs(NODE_MODULES_ROOT)
# 1. Find the binary file recursively
# We look for .node (Mac/Linux) or .exe (Windows)
# This handles cases where the CIPD package might have a nested directory.
binary_file_name = None
binary_full_path = None
for root, dirs, files in os.walk(SRC_DIR):
for f in files:
if f.endswith('.node') or f.endswith('.exe'):
binary_file_name = f
binary_full_path = os.path.join(root, f)
break
if binary_full_path:
break
if not binary_full_path:
print(
f"No native binary found in {SRC_DIR}. This is expected if the platform doesn't need one."
)
return 0
# 2. Derive the package name
# Input: "rollup.linux-x64-gnu.node"
# Step A: Remove extension -> "rollup.linux-x64-gnu"
base_name = os.path.splitext(binary_file_name)[0]
# Step B: Replace dots with dashes
# Rollup expects "@rollup/rollup-linux-x64-gnu"
# But the binary is often named "rollup.linux-x64-gnu"
sanitized_name = base_name.replace('.', '-')
package_name = f"@rollup/{sanitized_name}"
# 3. Prepare the destination directory: node_modules/@rollup/rollup-linux-x64-gnu/
dest_dir = os.path.join(NODE_MODULES_ROOT, '@rollup', sanitized_name)
if os.path.exists(dest_dir):
shutil.rmtree(dest_dir, onerror=on_rm_error)
os.makedirs(dest_dir)
# 4. Copy the binary
# We rename it to match the sanitized name to be safe, though Rollup
# mainly cares that 'main' in package.json points to the file on disk.
dest_file_name = f"{sanitized_name}{os.path.splitext(binary_file_name)[1]}"
dest_path = os.path.join(dest_dir, dest_file_name)
shutil.copy2(binary_full_path, dest_path)
# 5. Create a minimal package.json
# This is CRITICAL. Without this, Node.js resolution ("require('@rollup/...')")
# will fail because it won't know that .node file is the entry point.
pkg_json = {
"name": package_name,
"version":
"4.53.5", # This can be generic, Rollup checks the existence mostly
"main": dest_file_name,
"files": [dest_file_name]
}
with open(os.path.join(dest_dir, 'package.json'), 'w') as f:
json.dump(pkg_json, f, indent=2)
print(f"Synced Rollup native dependency: {package_name} -> {dest_dir}")
return 0
if __name__ == '__main__':
sys.exit(main())