#!/usr/bin/env python3 """ Version injection module for manifest.json files Injects nxtscape browser version into extension manifests """ import json from pathlib import Path from typing import List, Dict, Any from context import BuildContext from utils import log_info, log_error, log_success, join_paths def inject_version(ctx: BuildContext) -> bool: """Inject browser version into manifest.json files""" log_info("\n๐Ÿ’‰ Injecting browser version into extension manifests...") # Hardcoded paths to manifest files manifest_paths = [ join_paths( ctx.root_dir, "resources", "files", "ai_side_panel", "manifest.json" ), join_paths(ctx.root_dir, "resources", "files", "bug_reporter", "manifest.json"), ] success = True for manifest_path in manifest_paths: if not inject_version_to_manifest( manifest_path, ctx.get_nxtscape_chromium_version(), ctx.get_nxtscape_version(), ): success = False if success: log_success("Browser version injected into all manifests") else: log_error("Failed to inject version into some manifests") return success def inject_version_to_manifest( manifest_path: Path, browser_version: str, nxtscape_version: str ) -> bool: """Inject browser version and increment version into a single manifest.json file""" try: if not manifest_path.exists(): log_error(f"Manifest not found: {manifest_path}") return False # Read existing manifest with open(manifest_path, "r", encoding="utf-8") as f: manifest_data = json.load(f) # Set version to NXTSCAPE_VERSION formatted as X.0.0.0 if "version" in manifest_data: current_version = manifest_data["version"] # Format version as X.0.0.0 formatted_version = f"{nxtscape_version}.0.0.0" manifest_data["version"] = formatted_version log_info( f" Manifest version updated: {current_version} โ†’ {formatted_version}" ) # Add browser_version field manifest_data["browser_version"] = browser_version # Write back with proper formatting with open(manifest_path, "w", encoding="utf-8") as f: json.dump(manifest_data, f, indent=2, ensure_ascii=False) f.write("\n") # Add trailing newline # Validate the written JSON if validate_json_file(manifest_path): log_success(f"โœ“ Updated: {manifest_path.name}") return True else: log_error(f"โœ— Invalid JSON after injection: {manifest_path.name}") return False except json.JSONDecodeError as e: log_error(f"Failed to parse JSON in {manifest_path}: {e}") return False except Exception as e: log_error(f"Failed to inject version into {manifest_path}: {e}") return False def increment_version(version: str) -> str: """Increment version string by 1 in the last component""" parts = version.split(".") if not parts: return "0.0.1" # Try to increment the last numeric part for i in range(len(parts) - 1, -1, -1): try: # Convert to int, increment, and convert back incremented = int(parts[i]) + 1 parts[i] = str(incremented) return ".".join(parts) except ValueError: # If this part is not numeric, continue to the previous part continue # If no numeric part found, append .1 return version + ".1" def validate_json_file(file_path: Path) -> bool: """Validate that a file contains valid JSON""" try: with open(file_path, "r", encoding="utf-8") as f: json.load(f) return True except json.JSONDecodeError: return False except Exception: return False def remove_browser_version(ctx: BuildContext) -> bool: """Remove browser version from manifest.json files (for cleanup)""" log_info("\n๐Ÿงน Removing browser version from extension manifests...") # Hardcoded paths to manifest files manifest_paths = [ join_paths( ctx.root_dir, "resources", "files", "ai_side_panel", "manifest.json" ), join_paths(ctx.root_dir, "resources", "files", "bug_reporter", "manifest.json"), ] success = True for manifest_path in manifest_paths: if not remove_version_from_manifest(manifest_path): success = False return success def remove_version_from_manifest(manifest_path: Path) -> bool: """Remove browser version from a single manifest.json file""" try: if not manifest_path.exists(): return True # Nothing to remove # Read existing manifest with open(manifest_path, "r", encoding="utf-8") as f: manifest_data = json.load(f) # Remove browser_version field if it exists if "browser_version" in manifest_data: del manifest_data["browser_version"] # Write back with proper formatting with open(manifest_path, "w", encoding="utf-8") as f: json.dump(manifest_data, f, indent=2, ensure_ascii=False) f.write("\n") # Add trailing newline log_info(f"Removed browser_version from: {manifest_path.name}") return True except Exception as e: log_error(f"Failed to remove version from {manifest_path}: {e}") return False def get_manifest_version(manifest_path: Path) -> str: """Get the current version from a manifest.json file""" try: with open(manifest_path, "r", encoding="utf-8") as f: manifest_data = json.load(f) return manifest_data.get("version", "unknown") except Exception: return "unknown"