Patch Module
Transformations for applying patch files to the working directory.
patch.apply
Section titled “patch.apply”Applies one or more patch files. Patches that reference non-existent paths are ignored.
patch.apply( patches = ["patches/fix-build.patch", "patches/update-deps.patch"], strip = 1,)Parameters
Section titled “Parameters”| Parameter | Type | Description |
|---|---|---|
patches | list[string] | Patch files relative to config file |
excluded_patch_paths | list[string] | Paths to exclude from patches |
series | string | File containing list of patches to apply |
strip | int | Path components to strip (-p flag). Default: 1 |
directory | string | Directory to apply patches from (-d flag) |
Using a Series File
Section titled “Using a Series File”A series file lists patches one per line:
# Comments start with #001-fix-typo.patch002-add-feature.patch003-update-api.patch # inline comments work toopatch.apply(series = "patches/series")Generate a series file with:
find . -name "*.patch" | sort > patches/seriesCombining Patches and Series
Section titled “Combining Patches and Series”When both are specified, patches are applied first:
patch.apply( patches = ["urgent-fix.patch"], series = "patches/series",)Excluding Paths
Section titled “Excluding Paths”Skip specific files within patches:
patch.apply( patches = ["upstream.patch"], excluded_patch_paths = ["Makefile", "configure.ac"],)When excluded_patch_paths is non-empty, Copybara uses git apply instead of GNU patch.
Custom Strip Level
Section titled “Custom Strip Level”# Patch has paths like a/src/file.c, b/src/file.cpatch.apply( patches = ["changes.patch"], strip = 1, # Removes 'a/' and 'b/' prefixes)
# Patch has full paths like /home/user/project/src/file.cpatch.apply( patches = ["absolute.patch"], strip = 0, # Keep full paths)Applying to Subdirectory
Section titled “Applying to Subdirectory”patch.apply( patches = ["component.patch"], directory = "src/components",)patch.quilt_apply
Section titled “patch.quilt_apply”Applies patches using Quilt, which supports automatic patch updating when applied with fuzz.
patch.quilt_apply(series = "patches/series")How It Works
Section titled “How It Works”Copybara runs quilt import, quilt push, and quilt refresh for each patch. This means patches can be automatically updated if they apply with minor offsets.
Requirements
Section titled “Requirements”- All patches and the series file must be in a
patches/subdirectory - The
patches/directory must be at the root of the migrated code - The migrated code cannot contain its own
patches/directory
Example Directory Structure
Section titled “Example Directory Structure”source_root/├── BUILD├── copy.bara.sky├── migrated_file1├── migrated_file2└── patches/ ├── series └── patch1.patchWorkflow Configuration
Section titled “Workflow Configuration”core.workflow( name = "sync", origin = git.origin( url = "https://github.com/upstream/project", ), destination = git.destination( url = "https://github.com/myorg/fork", ), transformations = [ patch.quilt_apply(series = "patches/series"), core.move("", "source_root"), ], destination_files = glob(["source_root/**"]),)Include patches/** in destination_files to have patches updated during migration.
Use Cases
Section titled “Use Cases”Maintaining Local Patches
Section titled “Maintaining Local Patches”Keep local modifications when syncing from upstream:
core.workflow( name = "import", origin = git.origin(url = "https://upstream/repo"), destination = git.destination(url = "https://myorg/repo"), transformations = [ patch.apply(series = "patches/series"), ], destination_files = glob(["**"], exclude = ["patches/**"]),)Conditional Patches
Section titled “Conditional Patches”Apply different patches based on workflow:
def patches_for_env(env): base = ["patches/common.patch"] if env == "prod": return base + ["patches/prod-config.patch"] return base + ["patches/dev-config.patch"]