Files
BrowserOS/packages/browseros/build/modules/annotate/annotate.py
Nikhil 63cbbeaa86 feat: mac sparkle fixes and browseros path refactor (#258)
* patch: fix sparkle build

* fix: update browseros_server binary path after refactor

* fix: sparkle + browseros server build patch

* fix: build.py --prep dont apply series patches

* fix: build cli -- in prep configure too

* fix: cli annotate -- only add description

* fix: features.yaml update for new paths

* fix: more patch fixes

* fix: sparkle pointer exclusion

* fix: remove su-updater

* fix: sparkle update notification
2025-12-18 16:26:34 -08:00

240 lines
6.9 KiB
Python
Generated

"""
Annotate - Create git commits organized by features from features.yaml
For each feature, checks which files have modifications and creates a commit
with the feature name and description.
"""
import yaml
from pathlib import Path
from typing import List, Tuple, Optional, Dict
from ..apply.utils import run_git_command
from ...common.context import Context
from ...common.module import CommandModule, ValidationError
from ...common.utils import log_info, log_error, log_success, log_warning
def load_features(features_file: Path) -> Dict:
"""Load features from YAML file."""
try:
with open(features_file, "r") as f:
data = yaml.safe_load(f)
return data.get("features", {})
except Exception as e:
log_error(f"Failed to load features file: {e}")
return {}
def get_modified_files(chromium_src: Path, files: List[str]) -> List[str]:
"""Get list of files that have modifications or are untracked.
Args:
chromium_src: Chromium source directory
files: List of file paths to check
Returns:
List of file paths that have modifications
"""
modified = []
for file_path in files:
full_path = chromium_src / file_path
if not full_path.exists():
continue
result = run_git_command(
["git", "status", "--porcelain", str(file_path)],
cwd=chromium_src,
)
if result.returncode == 0 and result.stdout.strip():
modified.append(file_path)
return modified
def git_add_and_commit(
chromium_src: Path, files: List[str], commit_message: str
) -> bool:
"""Add files and create commit.
Args:
chromium_src: Chromium source directory
files: List of file paths to add
commit_message: Commit message
Returns:
True if commit was created successfully
"""
# Add all specified files
for file_path in files:
result = run_git_command(
["git", "add", str(file_path)],
cwd=chromium_src,
)
if result.returncode != 0:
log_error(f"Failed to add file: {file_path}")
return False
# Create commit
result = run_git_command(
["git", "commit", "-m", commit_message],
cwd=chromium_src,
)
if result.returncode != 0:
stderr = result.stderr or ""
if "nothing to commit" in stderr or "nothing added to commit" in stderr:
return False
log_error(f"Failed to commit: {stderr}")
return False
return True
def annotate_features(
ctx: Context,
feature_filter: Optional[str] = None,
) -> Tuple[int, int]:
"""Create commits for features with modified files.
Iterates through features.yaml and creates a commit for each feature
that has modified files in the working tree.
Args:
ctx: Build context
feature_filter: If specified, only process this feature
Returns:
Tuple of (commits_created, features_skipped)
"""
features_file = ctx.get_features_yaml_path()
if not features_file.exists():
log_error(f"Features file not found: {features_file}")
return 0, 0
features = load_features(features_file)
if not features:
log_error("No features found in features.yaml")
return 0, 0
# Filter to specific feature if requested
if feature_filter:
if feature_filter not in features:
log_error(f"Feature '{feature_filter}' not found in features.yaml")
return 0, 0
features = {feature_filter: features[feature_filter]}
log_info(f"📋 Processing {len(features)} feature(s)")
log_info("=" * 60)
commits_created = 0
features_skipped = 0
for feature_name, feature_data in features.items():
description = feature_data.get("description", feature_name)
files = feature_data.get("files", [])
log_info(f"\n🔧 {feature_name}")
log_info(f" {description}")
if not files:
log_warning(" No files specified, skipping")
features_skipped += 1
continue
# Find files with modifications
modified_files = get_modified_files(ctx.chromium_src, files)
if not modified_files:
log_warning(f" No modified files ({len(files)} files checked)")
features_skipped += 1
continue
log_info(f" Found {len(modified_files)} modified file(s)")
# Create commit (use description only from features.yaml)
commit_message = description
if git_add_and_commit(ctx.chromium_src, modified_files, commit_message):
log_success(f" ✓ Committed {len(modified_files)} file(s)")
commits_created += 1
else:
log_warning(" No changes staged, skipping commit")
features_skipped += 1
return commits_created, features_skipped
def annotate_single_feature(
ctx: Context,
feature_name: str,
) -> bool:
"""Create a commit for a single feature.
Args:
ctx: Build context
feature_name: Name of the feature to commit
Returns:
True if commit was created successfully
"""
commits, _ = annotate_features(ctx, feature_filter=feature_name)
return commits > 0
class AnnotateModule(CommandModule):
"""Create git commits organized by features from features.yaml"""
produces = []
requires = []
description = "Create git commits organized by features"
def validate(self, ctx: Context) -> None:
"""Validate git is available and chromium_src exists."""
import shutil
if not shutil.which("git"):
raise ValidationError("Git is not available in PATH")
if not ctx.chromium_src.exists():
raise ValidationError(f"Chromium source not found: {ctx.chromium_src}")
# Check if it's a git repository
git_dir = ctx.chromium_src / ".git"
if not git_dir.exists():
raise ValidationError(f"Not a git repository: {ctx.chromium_src}")
def execute(
self,
ctx: Context,
feature_name: Optional[str] = None,
**kwargs,
) -> None:
"""Execute annotate.
Args:
ctx: Build context
feature_name: If specified, only annotate this feature
"""
log_info("🏗️ Annotate Features")
log_info("=" * 60)
log_info(f"📁 Chromium source: {ctx.chromium_src}")
log_info(f"📄 Features file: {ctx.get_features_yaml_path()}")
commits_created, features_skipped = annotate_features(
ctx, feature_filter=feature_name
)
log_info("\n" + "=" * 60)
if commits_created > 0:
log_success(f"✓ Created {commits_created} commit(s)")
else:
log_info("No commits created (no modified files found)")
if features_skipped > 0:
log_info(f" Skipped {features_skipped} feature(s) with no changes")
log_info("=" * 60)