mirror of
https://github.com/ChuckBuilds/LEDMatrix.git
synced 2026-04-10 13:02:59 +00:00
* refactor: migrate from submodules to multi-root workspace for plugins - Updated LEDMatrix.code-workspace to include all plugin repos as root folders - Removed symlinks from plugin-repos/ and plugins/ directories - Updated .gitignore to reflect new plugin management approach - Added setup_plugin_repos.py script for managing plugin symlinks (if needed) - Added MULTI_ROOT_WORKSPACE_SETUP.md documentation Plugins are now managed as independent repositories via multi-root workspace, allowing for easier development and independent updates without modifying the LEDMatrix project structure. * Fix MULTI_ROOT_WORKSPACE_SETUP.md and add JSON error handling - Remove deprecated clone_plugin_repos.py command reference - Add language tag to directory tree code fence (fixes MD040) - Add JSONDecodeError handling in setup_plugin_repos.py with user-friendly error messages --------- Co-authored-by: Chuck <chuck@example.com>
152 lines
4.8 KiB
Python
Executable File
152 lines
4.8 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""
|
|
Setup plugin repository references for multi-root workspace.
|
|
|
|
This script creates symlinks in plugin-repos/ pointing to the actual
|
|
plugin repositories in the parent directory, allowing the system to
|
|
find plugins without modifying the LEDMatrix project structure.
|
|
"""
|
|
|
|
import json
|
|
import os
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
# Paths
|
|
PROJECT_ROOT = Path(__file__).parent.parent
|
|
PLUGIN_REPOS_DIR = PROJECT_ROOT / "plugin-repos"
|
|
GITHUB_DIR = PROJECT_ROOT.parent
|
|
CONFIG_FILE = PROJECT_ROOT / "config" / "config.json"
|
|
|
|
|
|
def get_workspace_plugins():
|
|
"""Get list of plugins from workspace file."""
|
|
workspace_file = PROJECT_ROOT / "LEDMatrix.code-workspace"
|
|
if not workspace_file.exists():
|
|
return []
|
|
|
|
try:
|
|
with open(workspace_file, 'r') as f:
|
|
workspace = json.load(f)
|
|
except json.JSONDecodeError as e:
|
|
print(f"Error: Failed to parse workspace file {workspace_file}: {e}")
|
|
print("Please check that the workspace file contains valid JSON.")
|
|
return []
|
|
|
|
plugins = []
|
|
for folder in workspace.get('folders', []):
|
|
path = folder.get('path', '')
|
|
if path.startswith('../') and path != '../ledmatrix-plugins':
|
|
plugin_name = path.replace('../', '')
|
|
plugins.append({
|
|
'name': plugin_name,
|
|
'workspace_path': path,
|
|
'actual_path': GITHUB_DIR / plugin_name,
|
|
'link_path': PLUGIN_REPOS_DIR / plugin_name
|
|
})
|
|
|
|
return plugins
|
|
|
|
|
|
def create_symlinks():
|
|
"""Create symlinks in plugin-repos/ pointing to actual repos."""
|
|
plugins = get_workspace_plugins()
|
|
|
|
if not plugins:
|
|
print("No plugins found in workspace configuration")
|
|
return False
|
|
|
|
# Ensure plugin-repos directory exists
|
|
PLUGIN_REPOS_DIR.mkdir(exist_ok=True)
|
|
|
|
created = 0
|
|
skipped = 0
|
|
errors = 0
|
|
|
|
print(f"Setting up plugin repository links...")
|
|
print(f" Source: {GITHUB_DIR}")
|
|
print(f" Links: {PLUGIN_REPOS_DIR}")
|
|
print()
|
|
|
|
for plugin in plugins:
|
|
actual_path = plugin['actual_path']
|
|
link_path = plugin['link_path']
|
|
|
|
if not actual_path.exists():
|
|
print(f" ⚠️ {plugin['name']} - source not found: {actual_path}")
|
|
errors += 1
|
|
continue
|
|
|
|
# Remove existing link/file if it exists
|
|
if link_path.exists() or link_path.is_symlink():
|
|
if link_path.is_symlink():
|
|
# Check if it points to the right place
|
|
try:
|
|
if link_path.resolve() == actual_path.resolve():
|
|
print(f" ✓ {plugin['name']} - link already exists")
|
|
skipped += 1
|
|
continue
|
|
else:
|
|
# Remove old symlink pointing elsewhere
|
|
link_path.unlink()
|
|
except Exception as e:
|
|
print(f" ⚠️ {plugin['name']} - error checking link: {e}")
|
|
link_path.unlink()
|
|
else:
|
|
# It's a directory/file, not a symlink
|
|
print(f" ⚠️ {plugin['name']} - {link_path.name} exists but is not a symlink")
|
|
print(f" Skipping (manual cleanup required)")
|
|
skipped += 1
|
|
continue
|
|
|
|
# Create symlink
|
|
try:
|
|
# Use relative path for symlink portability
|
|
relative_path = os.path.relpath(actual_path, link_path.parent)
|
|
link_path.symlink_to(relative_path)
|
|
print(f" ✓ {plugin['name']} - linked")
|
|
created += 1
|
|
except Exception as e:
|
|
print(f" ✗ {plugin['name']} - failed to create link: {e}")
|
|
errors += 1
|
|
|
|
print()
|
|
print(f"✅ Created {created} links, skipped {skipped}, errors {errors}")
|
|
|
|
return errors == 0
|
|
|
|
|
|
def update_config_path():
|
|
"""Update config to use absolute path to parent directory (alternative approach)."""
|
|
# This is an alternative - set plugins_directory to absolute path
|
|
# Currently not implemented as symlinks are preferred
|
|
pass
|
|
|
|
|
|
def main():
|
|
"""Main function."""
|
|
print("🔗 Setting up plugin repository symlinks...")
|
|
print()
|
|
|
|
if not GITHUB_DIR.exists():
|
|
print(f"Error: GitHub directory not found: {GITHUB_DIR}")
|
|
return 1
|
|
|
|
success = create_symlinks()
|
|
|
|
if success:
|
|
print()
|
|
print("✅ Plugin repository setup complete!")
|
|
print()
|
|
print("Plugins are now accessible via symlinks in plugin-repos/")
|
|
print("You can update plugins independently in their git repos.")
|
|
return 0
|
|
else:
|
|
print()
|
|
print("⚠️ Setup completed with some errors. Check output above.")
|
|
return 1
|
|
|
|
|
|
if __name__ == '__main__':
|
|
sys.exit(main())
|