Files
BrowserOS/packages/browseros/build/modules/extract/extract_patch.py
Nikhil 24e9cfd8f2 chromium 142 upgrade, new cli (#214)
* refactor 1: new typer based cli and browseros cli module

* refactor 2: fixes to context.py

* refactor 3: common/ and notify

* new sign and package module

* update .gitignore

* refactor 5: dev.py and modules for each

* refactor 6: clean-up old files

* refactor 7: organise modules fruther

* refactor 8: renaming nxtscape to browseros

* refactor 9: dev.py remove cli load

* fix: pyproject.toml

* fix: typer pretty exception disable

* refactor 10: cli/build.py set to primary

* refactor 10: cli/build.py set to primary, move OS detection

* refactor: context split, env and module dataclass

* reactor: clean and git moved ot new module type

* refactor: compile and configure

* reactor: sign and package module update

* refactor: new build.py cli

* 'refactor: remove reducant OS checks

* refactor: rename BuildContext to Context

* refactor: rename BuildModule to CommandModule

* refactor: dev.py to use the new modules

* build.py: improve help output

* remove old patching way

* clean-up: remove old build.py stuff

* refactor: move to proper yaml parsing

* clean-up: remove legacy args gating

* fix: patches issues

* fix: clean-up build.py and ars resolver

* minor: gitignore

* fix: patches.py issue

* support universal build

* fix: ENV variable and YAMLs

* fix: move compile to folder to avoid compflics

* fixes: more env fixes

* fix: build_type override in CLI fix

* fix: universal clean all archs before starting

* fix: universal build type constants

* fix: linter, extract options

* fix: linter

* fix: remove chromium_src as a not a conflicting flag

* fix: support chromium_src from cli in config mode

* fix: notify with better messages

* feat: new apply patch with --reset-to feature

* feat: refactor apply and extract into separate sub modules

* 142 patches working (#211)

* updates to build.py apply/patch

* removed all old patches

* 142 build update

* fix: get updated patches from main to 142

* fix: correct patches dir

* fix: import path

* add pyright

* fix: setup pyright

* fix: new updated patches from 137 rebased on 142

* feat: new extract_patch command

* fix: add mising side_panel build patch

* fix: extension uninstall for browseros

* fix: prefs fix

* fix: ota extension updater patch fix

* fix: llm hub and chat

* feat: unvisersal module also package individual archs

* fix: add browseros-server binaries

* fix: attach color for notify

* fix: attachment for slack

* fix: update chromium version to 142.0.7444.175

* feat: add new icons needed

* fix: disable settings in menu

* fix: uv add build-backend

* minor: chromium version bump

* clean-up: removed old files of extnesion and sidepanel

* fix: product logo generate and assets.car and appicon.icns

* feat: few chromium UI fixes

* fix: update features.yaml

* fix: features.yaml path in context

* refactor: rename to get_patches_dir()

* feat: show browserOS version in about page

* fix: copy browseros_version on the build time and rename other to offset

* bump offset

* fix: update features.yaml

* feat: load env from .env files too

* fix: enable split view

* clean-up: removed old prefs

* fix: minor import issue

* fix: linux flag update
2025-12-03 13:09:23 -08:00

121 lines
4.0 KiB
Python

"""
Extract Patch - Extract patch for a single chromium file.
"""
from typing import Tuple, Optional
from ...common.context import Context
from ...common.utils import log_info, log_warning
from .utils import (
run_git_command,
parse_diff_output,
write_patch_file,
create_deletion_marker,
validate_commit_exists,
FileOperation,
GitError,
)
def extract_single_file_patch(
build_ctx: Context,
chromium_path: str,
base: str,
force: bool = False,
) -> Tuple[bool, Optional[str]]:
"""Extract patch for a single chromium file.
Extracts the diff from base commit to current working directory
(including unstaged changes) for the specified file.
Args:
build_ctx: Build context
chromium_path: Path to file in chromium (e.g., chrome/common/foo.h)
base: Base commit to diff against
force: If True, overwrite existing patch without prompting
Returns:
Tuple of (success: bool, error_message: Optional[str])
"""
if not validate_commit_exists(base, build_ctx.chromium_src):
return False, f"Base commit not found: {base}"
log_info(f"Extracting patch for: {chromium_path}")
log_info(f" Base: {base[:12]}")
# Get diff from base to working directory for this file
diff_cmd = ["git", "diff", base, "--", chromium_path]
result = run_git_command(diff_cmd, cwd=build_ctx.chromium_src)
if result.returncode != 0:
return False, f"Failed to get diff: {result.stderr}"
if not result.stdout.strip():
# No diff - check if file exists in base vs working directory
base_exists = (
run_git_command(
["git", "cat-file", "-e", f"{base}:{chromium_path}"],
cwd=build_ctx.chromium_src,
).returncode
== 0
)
working_file = build_ctx.chromium_src / chromium_path
working_exists = working_file.exists()
if not base_exists and not working_exists:
return False, f"File does not exist in base or working directory: {chromium_path}"
if base_exists and working_exists:
return False, f"No changes found for: {chromium_path}"
if not base_exists and working_exists:
# New file - get full content as diff
diff_cmd = ["git", "diff", "--no-index", "/dev/null", chromium_path]
result = run_git_command(diff_cmd, cwd=build_ctx.chromium_src)
# --no-index returns 1 when files differ, which is expected
if not result.stdout.strip():
return False, f"Failed to generate diff for new file: {chromium_path}"
# Parse the diff
file_patches = parse_diff_output(result.stdout)
if not file_patches:
return False, f"Failed to parse diff for: {chromium_path}"
if chromium_path not in file_patches:
# The file might be in the patches under a different key
if len(file_patches) == 1:
patch = list(file_patches.values())[0]
else:
return False, f"Unexpected diff output for: {chromium_path}"
else:
patch = file_patches[chromium_path]
# Check for existing patch
patch_path = build_ctx.get_patch_path_for_file(chromium_path)
if patch_path.exists() and not force:
import click
if not click.confirm(f"Patch already exists: {chromium_path}. Overwrite?", default=False):
log_info("Extraction cancelled")
return False, "Cancelled by user"
# Handle different operations
if patch.operation == FileOperation.DELETE:
if create_deletion_marker(build_ctx, chromium_path):
return True, None
return False, f"Failed to create deletion marker for: {chromium_path}"
if patch.is_binary:
return False, f"Binary files not supported: {chromium_path}"
if not patch.patch_content:
return False, f"No patch content for: {chromium_path}"
# Write the patch
if write_patch_file(build_ctx, chromium_path, patch.patch_content):
return True, None
return False, f"Failed to write patch for: {chromium_path}"