patches.mappings: support prefix-strip in addition to exact match

Lets patches be laid out as android/<version>/<real-aosp-path>/*.patch
and still land in the correct project, instead of every patch under a
mapped folder going to one fixed target.
This commit is contained in:
2026-07-04 06:30:46 -07:00
parent b33843feb4
commit 53f3bc95c7
3 changed files with 64 additions and 23 deletions
+20 -8
View File
@@ -37,12 +37,12 @@ repo:
# `repo sync` — `repo` merges every *.xml in that directory into the manifest
# (adding projects, removing projects, overriding revisions, etc).
#
# Each value is either:
# - a single URL string -> downloaded as-is to "<key>.xml"
# - a YAML list of URLs -> all downloaded and merged into one "<key>.xml",
# combining child elements and de-duplicating ones that share the same
# tag + name attribute (first occurrence wins). Handy for splitting a
# long <remove-project> list across a common file and a device-specific one.
# Every key's value is normally a single URL string, downloaded as-is to
# "<key>.xml". The "remove_projects" key is the one exception: it may instead
# be a YAML list of URLs, all downloaded and merged into one "remove_projects.xml",
# combining child elements and de-duplicating ones that share the same tag +
# name attribute (first occurrence wins). Handy for splitting a long
# <remove-project> list across a common file and a device-specific one.
local_manifests:
device_manifest: "https://raw.githubusercontent.com/example/device-manifest/main/manifest.xml"
vendor_manifest: "https://raw.githubusercontent.com/example/vendor-manifest/main/manifest.xml"
@@ -60,10 +60,22 @@ patches:
- patches
# Optional: maps a patch subdirectory to a different AOSP project path, for
# layouts that don't/shouldn't mirror the AOSP tree directly (e.g. grouping
# patches by Android version instead of by project path).
# layouts that don't/shouldn't mirror the AOSP tree directly. Two forms:
#
# - Exact match -> replace the whole subdir: every patch found under it
# applies to the one given project.
# android/36: frameworks/base
# patches/android/36/*.patch -> applied at frameworks/base/
#
# - Prefix match (map to "") -> strip the matched prefix and use the rest
# of the path as-is. Lets you group patches by Android version while
# still targeting multiple different AOSP projects underneath:
# android/37: ""
# patches/android/37/frameworks/base/*.patch -> applied at frameworks/base/
# patches/android/37/packages/apps/Settings/*.patch -> applied at packages/apps/Settings/
mappings:
android/36: frameworks/base
android/37: ""
```
### Command Line Options
+26 -6
View File
@@ -212,18 +212,30 @@ def find_patches(patch_dirs, mappings=None):
Returns a list of (patch_path, target_subdir) tuples where target_subdir
is the AOSP project path the patch should be applied into.
mappings (optional dict) translates patch subdirectory paths to AOSP paths,
e.g. {"android/36": "frameworks/base"}. Without a mapping the subdirectory
structure must mirror the AOSP project layout directly:
mappings (optional dict) translates patch subdirectory paths to AOSP paths.
Without a mapping the subdirectory structure must mirror the AOSP project
layout directly:
patches/
frameworks/base/0001-sig-spoof.patch -> <source>/frameworks/base/
0001-root-level.patch -> <source>/
With mappings from repo.yml:
A mapping key can match a subdirectory path exactly:
mappings: {"android/36": "frameworks/base"}
patches/
android/36/android_frameworks_base-*.patch -> <source>/frameworks/base/
android/36/*.patch -> <source>/frameworks/base/ (all patches in this dir go to one project)
Or match as a *prefix*, stripping it and using the rest of the path as-is
(map to "" to strip with no replacement) - handy for grouping patches by
Android version while still targeting multiple different AOSP projects:
mappings: {"android/36": ""}
patches/
android/36/frameworks/base/0001-sig-spoof.patch -> <source>/frameworks/base/
android/36/packages/apps/Settings/0001-toggle.patch -> <source>/packages/apps/Settings/
"""
if mappings is None:
mappings = {}
@@ -250,9 +262,17 @@ def find_patches(patch_dirs, mappings=None):
rel_str = str(rel_parent).replace("\\", "/") # normalise on Windows
target_subdir = rel_str if rel_str != "." else "."
# Apply mapping if one is configured for this subdirectory
# Apply mapping if one is configured for this subdirectory: exact
# match first, then fall back to a prefix match (e.g. a version
# folder like "android/36" containing multiple AOSP project paths).
if target_subdir in mappings:
target_subdir = mappings[target_subdir]
else:
for prefix, replacement in mappings.items():
if target_subdir.startswith(prefix + "/"):
remainder = target_subdir[len(prefix) + 1:]
target_subdir = f"{replacement}/{remainder}" if replacement else remainder
break
patches.append((patch_file, target_subdir))
+18 -9
View File
@@ -17,12 +17,12 @@ repo:
# `repo` reads every *.xml file in that directory and layers them on top of
# the upstream manifest (adding projects, removing projects, overriding revisions).
#
# Each value is either:
# - a single URL string -> downloaded as-is to "<key>.xml"
# - a YAML list of URLs -> all downloaded and merged into one "<key>.xml",
# combining their child elements and de-duplicating entries that share the
# same tag + name attribute (first occurrence wins). Useful for splitting a
# long <remove-project> list across a common file and a device-specific one.
# Every key's value is normally a single URL string, downloaded as-is to
# "<key>.xml". The "remove_projects" key is the one exception: it may instead
# be a YAML list of URLs, all downloaded and merged into one "remove_projects.xml",
# combining their child elements and de-duplicating entries that share the
# same tag + name attribute (first occurrence wins). Useful for splitting a
# long <remove-project> list across a common file and a device-specific one.
local_manifests:
# Adds PawletOS's own repo/project definitions common to all devices.
manifest_common_pawletos: "https://git.oxmc.me/PawletOS/android_local_manifest/raw/branch/android-16.0/common/pawletos.xml"
@@ -51,8 +51,17 @@ patches:
dirs:
- vendor/pawlet/patches
# Optional: maps a patch subdirectory name to a different AOSP project path,
# for cases where the patch directory layout can't/shouldn't mirror the AOSP
# tree directly (e.g. grouping patches by Android version instead).
# Optional: maps a patch subdirectory to a different AOSP project path, for
# layouts that don't/shouldn't mirror the AOSP tree directly. Two forms:
# - Exact match -> replace the whole subdir; every patch under it applies
# to the one given project:
# android/36: frameworks/base
# - Prefix match (map to "") -> strip the matched prefix and use the rest
# of the path as-is; groups patches by Android version while still
# targeting multiple different AOSP projects underneath:
# android/37: ""
# vendor/pawlet/patches/android/37/frameworks/base/*.patch -> frameworks/base/
# vendor/pawlet/patches/android/37/packages/apps/Settings/*.patch -> packages/apps/Settings/
# mappings:
# android/36: frameworks/base
# android/37: ""