Skip to content

Patch Module

Transformations for applying patch files to the working directory.

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,
)
ParameterTypeDescription
patcheslist[string]Patch files relative to config file
excluded_patch_pathslist[string]Paths to exclude from patches
seriesstringFile containing list of patches to apply
stripintPath components to strip (-p flag). Default: 1
directorystringDirectory to apply patches from (-d flag)

A series file lists patches one per line:

patches/series
# Comments start with #
001-fix-typo.patch
002-add-feature.patch
003-update-api.patch # inline comments work too
patch.apply(series = "patches/series")

Generate a series file with:

Terminal window
find . -name "*.patch" | sort > patches/series

When both are specified, patches are applied first:

patch.apply(
patches = ["urgent-fix.patch"],
series = "patches/series",
)

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.

# Patch has paths like a/src/file.c, b/src/file.c
patch.apply(
patches = ["changes.patch"],
strip = 1, # Removes 'a/' and 'b/' prefixes
)
# Patch has full paths like /home/user/project/src/file.c
patch.apply(
patches = ["absolute.patch"],
strip = 0, # Keep full paths
)
patch.apply(
patches = ["component.patch"],
directory = "src/components",
)

Applies patches using Quilt, which supports automatic patch updating when applied with fuzz.

patch.quilt_apply(series = "patches/series")

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.

  • 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
source_root/
├── BUILD
├── copy.bara.sky
├── migrated_file1
├── migrated_file2
└── patches/
├── series
└── patch1.patch
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.

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/**"]),
)

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"]