mirror of
https://github.com/sotam0316/docker-py-revanced.git
synced 2026-04-25 03:48:37 +09:00
✨ Multi Source patch
This commit is contained in:
committed by
Nikhil Badyal
parent
a2ba0b89d1
commit
4283925f3e
@@ -47,7 +47,7 @@ You can use any of the following methods to build.
|
|||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
5. If the building process is successful, you’ll get your APKs in the<br>
|
5. If the building process is successful, you'll get your APKs in the<br>
|
||||||
<img src="https://i.imgur.com/S5d7qAO.png" width="700" style="left">
|
<img src="https://i.imgur.com/S5d7qAO.png" width="700" style="left">
|
||||||
6. Make sure to do below steps once in a while(daily or weekly) to keep the builder bug free.<br>
|
6. Make sure to do below steps once in a while(daily or weekly) to keep the builder bug free.<br>
|
||||||
<img src="https://i.imgur.com/CbdH7vM.png" width="700" style="left">
|
<img src="https://i.imgur.com/CbdH7vM.png" width="700" style="left">
|
||||||
@@ -135,9 +135,9 @@ You can use any of the following methods to build.
|
|||||||
### App Level Config
|
### App Level Config
|
||||||
|
|
||||||
| Env Name | Description | Default |
|
| Env Name | Description | Default |
|
||||||
|:--------------------------------------------------------------|:-------------------------------------------------------------------------------------------------------:|:-------------------------------|
|
|:--------------------------------------------------------------|:----------------------------------------------------------------------------------------------------:|:-------------------------------|
|
||||||
| [~~**APP_NAME**_CLI_DL~~](#global-resources) | DL for CLI to be used for patching **APP_NAME**.(Disabled Temp) | GLOBAL_CLI_DL |
|
| [~~**APP_NAME**_CLI_DL~~](#global-resources) | DL for CLI to be used for patching **APP_NAME**.(Disabled Temp) | GLOBAL_CLI_DL |
|
||||||
| [**APP_NAME**_PATCHES_DL](#global-resources) | DL for Patches to be used for patching **APP_NAME**. | GLOBAL_PATCHES_DL |
|
| [**APP_NAME**_PATCHES_DL](#global-resources) | DL for Patches to be used for patching **APP_NAME**. Supports multiple bundles via comma separation. | GLOBAL_PATCHES_DL |
|
||||||
| [**APP_NAME**_SPACE_FORMATTED_PATCHES](#global-resources) | Whether patches are space formatted. **APP_NAME**. | GLOBAL_SPACE_FORMATTED_PATCHES |
|
| [**APP_NAME**_SPACE_FORMATTED_PATCHES](#global-resources) | Whether patches are space formatted. **APP_NAME**. | GLOBAL_SPACE_FORMATTED_PATCHES |
|
||||||
| [**APP_NAME**_KEYSTORE_FILE_NAME](#global-keystore-file-name) | Key file to be used for signing **APP_NAME**. | GLOBAL_KEYSTORE_FILE_NAME |
|
| [**APP_NAME**_KEYSTORE_FILE_NAME](#global-keystore-file-name) | Key file to be used for signing **APP_NAME**. | GLOBAL_KEYSTORE_FILE_NAME |
|
||||||
| [**APP_NAME**_OLD_KEY](#global-keystore-file-name) | Whether key used was generated with cli > v4(new) <br/><br/>**APP_NAME**. <br/> <br/> | GLOBAL_OLK_KEY |
|
| [**APP_NAME**_OLD_KEY](#global-keystore-file-name) | Whether key used was generated with cli > v4(new) <br/><br/>**APP_NAME**. <br/> <br/> | GLOBAL_OLK_KEY |
|
||||||
@@ -308,10 +308,17 @@ You can use any of the following methods to build.
|
|||||||
```
|
```
|
||||||
With the config tool will try to patch YouTube with resources from inotia00 while other global resource will used
|
With the config tool will try to patch YouTube with resources from inotia00 while other global resource will used
|
||||||
for patching other apps.<br>
|
for patching other apps.<br>
|
||||||
|
|
||||||
|
**Multi-Patching Support**: You can now use multiple patch bundles from different creators for the same app:
|
||||||
|
```dotenv
|
||||||
|
# Comma-separated URLs
|
||||||
|
YOUTUBE_PATCHES_DL=https://github.com/ReVanced/revanced-patches,https://github.com/indrastorm/Dropped-patches
|
||||||
|
```
|
||||||
|
The tool will download all specified patch bundles and apply them together using the ReVanced CLI's multiple `-p` argument support.<br>
|
||||||
If you have want to provide resource locally in the apks folder. You can specify that by mentioning filename
|
If you have want to provide resource locally in the apks folder. You can specify that by mentioning filename
|
||||||
prefixed with `local://`.<br>
|
prefixed with `local://`.<br>
|
||||||
*Note* - The link provided must be DLs. Unless they are from GitHub.<br>
|
_Note_ - The link provided must be DLs. Unless they are from GitHub.<br>
|
||||||
*Note* - If your patches resource are available on GitHub and you want to select latest resource without excluding
|
_Note_ - If your patches resource are available on GitHub and you want to select latest resource without excluding
|
||||||
pre-release you can add `latest-prerelease` to the URL.
|
pre-release you can add `latest-prerelease` to the URL.
|
||||||
Example:
|
Example:
|
||||||
```dotenv
|
```dotenv
|
||||||
@@ -323,7 +330,7 @@ You can use any of the following methods to build.
|
|||||||
```
|
```
|
||||||
For above example tool while selecting latest patches will exclude any pre-release/beta ie. will consider only
|
For above example tool while selecting latest patches will exclude any pre-release/beta ie. will consider only
|
||||||
stable releases..<br>
|
stable releases..<br>
|
||||||
*Note* - Some of the patch source like inotia00 still provides **-** separated patches while revanced shifted to
|
_Note_ - Some of the patch source like inotia00 still provides **-** separated patches while revanced shifted to
|
||||||
Space formatted patches. Use `SPACE_FORMATTED_PATCHES` to define the type of patches.
|
Space formatted patches. Use `SPACE_FORMATTED_PATCHES` to define the type of patches.
|
||||||
|
|
||||||
8. <a id="global-keystore-file-name"></a>If you don't want to use default keystore. You can provide your own by
|
8. <a id="global-keystore-file-name"></a>If you don't want to use default keystore. You can provide your own by
|
||||||
@@ -371,7 +378,7 @@ You can use any of the following methods to build.
|
|||||||
```dotenv
|
```dotenv
|
||||||
YOUTUBE_ARCHS_TO_BUILD=arm64-v8a,armeabi-v7a
|
YOUTUBE_ARCHS_TO_BUILD=arm64-v8a,armeabi-v7a
|
||||||
```
|
```
|
||||||
*Note* -
|
_Note_ -
|
||||||
1. Possible values are: `armeabi-v7a`,`x86`,`x86_64`,`arm64-v8a`
|
1. Possible values are: `armeabi-v7a`,`x86`,`x86_64`,`arm64-v8a`
|
||||||
2. Make sure the patching resource(CLI) support this feature.
|
2. Make sure the patching resource(CLI) support this feature.
|
||||||
11. <a id="extra-files"></a>If you want to include any extra file to the Github upload. Set comma arguments
|
11. <a id="extra-files"></a>If you want to include any extra file to the Github upload. Set comma arguments
|
||||||
|
|||||||
+66
-16
@@ -31,10 +31,17 @@ class APP(object):
|
|||||||
self.app_version = config.env.str(f"{app_name}_VERSION".upper(), None)
|
self.app_version = config.env.str(f"{app_name}_VERSION".upper(), None)
|
||||||
self.experiment = False
|
self.experiment = False
|
||||||
self.cli_dl = config.env.str(f"{app_name}_CLI_DL".upper(), config.global_cli_dl)
|
self.cli_dl = config.env.str(f"{app_name}_CLI_DL".upper(), config.global_cli_dl)
|
||||||
self.patches_dl = config.env.str(f"{app_name}_PATCHES_DL".upper(), config.global_patches_dl)
|
|
||||||
|
# Support multiple patch bundles via comma-separated URLs
|
||||||
|
patches_dl_raw = config.env.str(f"{app_name}_PATCHES_DL".upper(), config.global_patches_dl)
|
||||||
|
self.patches_dl_list = [url.strip() for url in patches_dl_raw.split(",") if url.strip()]
|
||||||
|
# Keep backward compatibility
|
||||||
|
self.patches_dl = patches_dl_raw
|
||||||
|
|
||||||
self.exclude_request: list[str] = config.env.list(f"{app_name}_EXCLUDE_PATCH".upper(), [])
|
self.exclude_request: list[str] = config.env.list(f"{app_name}_EXCLUDE_PATCH".upper(), [])
|
||||||
self.include_request: list[str] = config.env.list(f"{app_name}_INCLUDE_PATCH".upper(), [])
|
self.include_request: list[str] = config.env.list(f"{app_name}_INCLUDE_PATCH".upper(), [])
|
||||||
self.resource: dict[str, dict[str, str]] = {}
|
self.resource: dict[str, dict[str, str]] = {}
|
||||||
|
self.patch_bundles: list[dict[str, str]] = [] # Store multiple patch bundles
|
||||||
self.no_of_patches: int = 0
|
self.no_of_patches: int = 0
|
||||||
self.keystore_name = config.env.str(f"{app_name}_KEYSTORE_FILE_NAME".upper(), config.global_keystore_name)
|
self.keystore_name = config.env.str(f"{app_name}_KEYSTORE_FILE_NAME".upper(), config.global_keystore_name)
|
||||||
self.archs_to_build = config.env.list(f"{app_name}_ARCHS_TO_BUILD".upper(), config.global_archs_to_build)
|
self.archs_to_build = config.env.list(f"{app_name}_ARCHS_TO_BUILD".upper(), config.global_archs_to_build)
|
||||||
@@ -148,6 +155,58 @@ class APP(object):
|
|||||||
Downloader(config).direct_download(url, file_name)
|
Downloader(config).direct_download(url, file_name)
|
||||||
return tag, file_name
|
return tag, file_name
|
||||||
|
|
||||||
|
def _setup_download_tasks(self: Self) -> list[tuple[str, str, None, str]]:
|
||||||
|
"""Setup download tasks for CLI and patch bundles."""
|
||||||
|
download_tasks = [
|
||||||
|
("cli", self.cli_dl, None, ".*jar"),
|
||||||
|
]
|
||||||
|
|
||||||
|
# Download multiple patch bundles
|
||||||
|
for i, patches_url in enumerate(self.patches_dl_list):
|
||||||
|
bundle_name = f"patches_{i}" if len(self.patches_dl_list) > 1 else "patches"
|
||||||
|
download_tasks.append((bundle_name, patches_url, None, ".*rvp"))
|
||||||
|
|
||||||
|
return download_tasks
|
||||||
|
|
||||||
|
def _handle_cached_resource(self: Self, resource_name: str, tag: str, file_name: str) -> None:
|
||||||
|
"""Handle cached resource and update appropriate data structures."""
|
||||||
|
if resource_name.startswith("patches"):
|
||||||
|
self.patch_bundles.append(
|
||||||
|
{
|
||||||
|
"name": resource_name,
|
||||||
|
"file_name": file_name,
|
||||||
|
"version": tag,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
# Keep backward compatibility for single bundle
|
||||||
|
if resource_name == "patches" or len(self.patches_dl_list) == 1:
|
||||||
|
self.resource["patches"] = {
|
||||||
|
"file_name": file_name,
|
||||||
|
"version": tag,
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
self.resource[resource_name] = {
|
||||||
|
"file_name": file_name,
|
||||||
|
"version": tag,
|
||||||
|
}
|
||||||
|
|
||||||
|
def _handle_downloaded_resource(
|
||||||
|
self: Self,
|
||||||
|
resource_name: str,
|
||||||
|
tag: str,
|
||||||
|
file_name: str,
|
||||||
|
download_tasks: list[tuple[str, str, RevancedConfig, str]],
|
||||||
|
resource_cache: dict[str, tuple[str, str]],
|
||||||
|
) -> None:
|
||||||
|
"""Handle newly downloaded resource and update cache."""
|
||||||
|
self._handle_cached_resource(resource_name, tag, file_name)
|
||||||
|
|
||||||
|
# Update cache for the corresponding URL
|
||||||
|
for task_name, task_url, _, _ in download_tasks:
|
||||||
|
if task_name == resource_name:
|
||||||
|
resource_cache[task_url.strip()] = (tag, file_name)
|
||||||
|
break
|
||||||
|
|
||||||
def download_patch_resources(
|
def download_patch_resources(
|
||||||
self: Self,
|
self: Self,
|
||||||
config: RevancedConfig,
|
config: RevancedConfig,
|
||||||
@@ -164,9 +223,10 @@ class APP(object):
|
|||||||
"""
|
"""
|
||||||
logger.info("Downloading resources for patching.")
|
logger.info("Downloading resources for patching.")
|
||||||
|
|
||||||
download_tasks = [
|
base_tasks = self._setup_download_tasks()
|
||||||
("cli", self.cli_dl, config, ".*jar"),
|
# Update download tasks with config
|
||||||
("patches", self.patches_dl, config, ".*rvp"),
|
download_tasks: list[tuple[str, str, RevancedConfig, str]] = [
|
||||||
|
(name, url, config, filter_pattern) for name, url, _, filter_pattern in base_tasks
|
||||||
]
|
]
|
||||||
|
|
||||||
with ThreadPoolExecutor(1) as executor:
|
with ThreadPoolExecutor(1) as executor:
|
||||||
@@ -177,10 +237,7 @@ class APP(object):
|
|||||||
if url in resource_cache:
|
if url in resource_cache:
|
||||||
logger.info(f"Skipping {resource_name} download, using cached resource: {url}")
|
logger.info(f"Skipping {resource_name} download, using cached resource: {url}")
|
||||||
tag, file_name = resource_cache[url]
|
tag, file_name = resource_cache[url]
|
||||||
self.resource[resource_name] = {
|
self._handle_cached_resource(resource_name, tag, file_name)
|
||||||
"file_name": file_name,
|
|
||||||
"version": tag,
|
|
||||||
}
|
|
||||||
continue
|
continue
|
||||||
|
|
||||||
futures[resource_name] = executor.submit(self.download, url, cfg, assets_filter)
|
futures[resource_name] = executor.submit(self.download, url, cfg, assets_filter)
|
||||||
@@ -190,14 +247,7 @@ class APP(object):
|
|||||||
for resource_name, future in futures.items():
|
for resource_name, future in futures.items():
|
||||||
try:
|
try:
|
||||||
tag, file_name = future.result()
|
tag, file_name = future.result()
|
||||||
self.resource[resource_name] = {
|
self._handle_downloaded_resource(resource_name, tag, file_name, download_tasks, resource_cache)
|
||||||
"file_name": file_name,
|
|
||||||
"version": tag,
|
|
||||||
}
|
|
||||||
resource_cache[download_tasks[["cli", "patches"].index(resource_name)][1].strip()] = (
|
|
||||||
tag,
|
|
||||||
file_name,
|
|
||||||
)
|
|
||||||
except BuilderError as e:
|
except BuilderError as e:
|
||||||
msg = f"Failed to download {resource_name} resource."
|
msg = f"Failed to download {resource_name} resource."
|
||||||
raise PatchingFailedError(msg) from e
|
raise PatchingFailedError(msg) from e
|
||||||
|
|||||||
@@ -51,7 +51,9 @@ class Github(Downloader):
|
|||||||
"""Extract repo owner and url from github url."""
|
"""Extract repo owner and url from github url."""
|
||||||
parsed_url = urlparse(url)
|
parsed_url = urlparse(url)
|
||||||
path_segments = parsed_url.path.strip("/").split("/")
|
path_segments = parsed_url.path.strip("/").split("/")
|
||||||
|
if len(path_segments) < 2:
|
||||||
|
msg = f"Invalid GitHub URL format: {url}"
|
||||||
|
raise DownloadError(msg)
|
||||||
github_repo_owner = path_segments[0]
|
github_repo_owner = path_segments[0]
|
||||||
github_repo_name = path_segments[1]
|
github_repo_name = path_segments[1]
|
||||||
tag_position = 3
|
tag_position = 3
|
||||||
|
|||||||
+1
-1
@@ -130,4 +130,4 @@ class PatchesJsonLoadError(BuilderError):
|
|||||||
def __str__(self: Self) -> str:
|
def __str__(self: Self) -> str:
|
||||||
"""Exception message."""
|
"""Exception message."""
|
||||||
base_message = super().__str__()
|
base_message = super().__str__()
|
||||||
return f"Message - {base_message} Url - {self.file_name}"
|
return f"Message - {base_message} File - {self.file_name}"
|
||||||
|
|||||||
+37
-17
@@ -24,6 +24,9 @@ class Parser(object):
|
|||||||
OUTPUT_ARG = "-o"
|
OUTPUT_ARG = "-o"
|
||||||
KEYSTORE_ARG = "--keystore"
|
KEYSTORE_ARG = "--keystore"
|
||||||
OPTIONS_ARG = "-O"
|
OPTIONS_ARG = "-O"
|
||||||
|
ENABLE_ARG = "-e"
|
||||||
|
DISABLE_ARG = "-d"
|
||||||
|
EXCLUSIVE_ARG = "--exclusive"
|
||||||
|
|
||||||
def __init__(self: Self, patcher: Patches, config: RevancedConfig) -> None:
|
def __init__(self: Self, patcher: Patches, config: RevancedConfig) -> None:
|
||||||
self._PATCHES: list[str] = []
|
self._PATCHES: list[str] = []
|
||||||
@@ -71,7 +74,7 @@ class Parser(object):
|
|||||||
for opt in options:
|
for opt in options:
|
||||||
pair = self.format_option(opt)
|
pair = self.format_option(opt)
|
||||||
self._PATCHES[:0] = [self.OPTIONS_ARG, pair]
|
self._PATCHES[:0] = [self.OPTIONS_ARG, pair]
|
||||||
self._PATCHES[:0] = ["-e", name]
|
self._PATCHES[:0] = [self.ENABLE_ARG, name]
|
||||||
|
|
||||||
def exclude(self: Self, name: str) -> None:
|
def exclude(self: Self, name: str) -> None:
|
||||||
"""The `exclude` function adds a given patch to the list of excluded patches.
|
"""The `exclude` function adds a given patch to the list of excluded patches.
|
||||||
@@ -81,7 +84,7 @@ class Parser(object):
|
|||||||
name : str
|
name : str
|
||||||
The `name` parameter is a string that represents the name of the patch to be excluded.
|
The `name` parameter is a string that represents the name of the patch to be excluded.
|
||||||
"""
|
"""
|
||||||
self._PATCHES.extend(["-d", name])
|
self._PATCHES.extend([self.DISABLE_ARG, name])
|
||||||
self._EXCLUDED.append(name)
|
self._EXCLUDED.append(name)
|
||||||
|
|
||||||
def get_excluded_patches(self: Self) -> list[str]:
|
def get_excluded_patches(self: Self) -> list[str]:
|
||||||
@@ -119,22 +122,27 @@ class Parser(object):
|
|||||||
name = name.lower().replace(" ", "-")
|
name = name.lower().replace(" ", "-")
|
||||||
indices = [i for i in range(len(self._PATCHES)) if self._PATCHES[i] == name]
|
indices = [i for i in range(len(self._PATCHES)) if self._PATCHES[i] == name]
|
||||||
for patch_index in indices:
|
for patch_index in indices:
|
||||||
if self._PATCHES[patch_index - 1] == "-e":
|
if self._PATCHES[patch_index - 1] == self.ENABLE_ARG:
|
||||||
self._PATCHES[patch_index - 1] = "-d"
|
self._PATCHES[patch_index - 1] = self.DISABLE_ARG
|
||||||
else:
|
else:
|
||||||
self._PATCHES[patch_index - 1] = "-e"
|
self._PATCHES[patch_index - 1] = self.ENABLE_ARG
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def exclude_all_patches(self: Self) -> None:
|
def enable_exclusive_mode(self: Self) -> None:
|
||||||
"""The function `exclude_all_patches` exclude all the patches."""
|
"""Enable exclusive mode - only explicitly enabled patches will run, all others disabled by default."""
|
||||||
for idx, item in enumerate(self._PATCHES):
|
logger.info("Enabling exclusive mode for fast testing - only keeping one patch enabled.")
|
||||||
if idx == 0:
|
# Clear all patches and keep only the first one enabled
|
||||||
continue
|
if self._PATCHES:
|
||||||
if item == "-e":
|
# Find the first enable argument and its patch name
|
||||||
self._PATCHES[idx] = "-d"
|
for idx in range(0, len(self._PATCHES), 2):
|
||||||
|
if idx < len(self._PATCHES) and self._PATCHES[idx] == self.ENABLE_ARG and idx + 1 < len(self._PATCHES):
|
||||||
|
first_patch = self._PATCHES[idx + 1]
|
||||||
|
# Clear all patches and set only the first one
|
||||||
|
self._PATCHES = [self.ENABLE_ARG, first_patch]
|
||||||
|
break
|
||||||
|
|
||||||
def fetch_patch_options(self: Self, name: str, options_list: list[dict[str, Any]]) -> dict[str, Any]:
|
def fetch_patch_options(self: Self, name: str, options_list: list[dict[str, Any]]) -> dict[str, Any]:
|
||||||
"""The function `fetch_patch_options` finds patch options for the patch.
|
"""The function `fetch_patch_options` finds patch options for the patch.
|
||||||
@@ -219,15 +227,27 @@ class Parser(object):
|
|||||||
app.resource["cli"]["file_name"],
|
app.resource["cli"]["file_name"],
|
||||||
apk_arg,
|
apk_arg,
|
||||||
app.download_file_name,
|
app.download_file_name,
|
||||||
self.PATCHES_ARG,
|
]
|
||||||
app.resource["patches"]["file_name"],
|
|
||||||
|
# Add multiple patch bundles using -p argument
|
||||||
|
if hasattr(app, "patch_bundles") and app.patch_bundles:
|
||||||
|
# Use multiple -p arguments for multiple bundles
|
||||||
|
for bundle in app.patch_bundles:
|
||||||
|
args.extend([self.PATCHES_ARG, bundle["file_name"]])
|
||||||
|
else:
|
||||||
|
# Fallback to single bundle for backward compatibility
|
||||||
|
args.extend([self.PATCHES_ARG, app.resource["patches"]["file_name"]])
|
||||||
|
|
||||||
|
args.extend(
|
||||||
|
[
|
||||||
self.OUTPUT_ARG,
|
self.OUTPUT_ARG,
|
||||||
app.get_output_file_name(),
|
app.get_output_file_name(),
|
||||||
self.KEYSTORE_ARG,
|
self.KEYSTORE_ARG,
|
||||||
app.keystore_name,
|
app.keystore_name,
|
||||||
exp,
|
exp,
|
||||||
]
|
],
|
||||||
args[1::2] = map(self.config.temp_folder.joinpath, args[1::2])
|
)
|
||||||
|
args[1::2] = [str(self.config.temp_folder.joinpath(arg)) for arg in args[1::2]]
|
||||||
if app.old_key:
|
if app.old_key:
|
||||||
# https://github.com/ReVanced/revanced-cli/issues/272#issuecomment-1740587534
|
# https://github.com/ReVanced/revanced-cli/issues/272#issuecomment-1740587534
|
||||||
old_key_flags = [
|
old_key_flags = [
|
||||||
@@ -237,7 +257,7 @@ class Parser(object):
|
|||||||
]
|
]
|
||||||
args.extend(old_key_flags)
|
args.extend(old_key_flags)
|
||||||
if self.config.ci_test:
|
if self.config.ci_test:
|
||||||
self.exclude_all_patches()
|
self.enable_exclusive_mode()
|
||||||
if self._PATCHES:
|
if self._PATCHES:
|
||||||
args.extend(self._PATCHES)
|
args.extend(self._PATCHES)
|
||||||
if app.app_name in self.config.rip_libs_apps:
|
if app.app_name in self.config.rip_libs_apps:
|
||||||
|
|||||||
+27
-3
@@ -1,7 +1,7 @@
|
|||||||
"""Revanced Patches."""
|
"""Revanced Patches."""
|
||||||
|
|
||||||
import contextlib
|
import contextlib
|
||||||
from typing import ClassVar, Self
|
from typing import Any, ClassVar, Self
|
||||||
|
|
||||||
from loguru import logger
|
from loguru import logger
|
||||||
|
|
||||||
@@ -125,11 +125,35 @@ class Patches(object):
|
|||||||
The `app` parameter is of type `APP`. It represents an instance of the `APP` class.
|
The `app` parameter is of type `APP`. It represents an instance of the `APP` class.
|
||||||
"""
|
"""
|
||||||
self.patches_dict[app.app_name] = []
|
self.patches_dict[app.app_name] = []
|
||||||
|
|
||||||
|
# Handle multiple patch bundles
|
||||||
|
if hasattr(app, "patch_bundles") and app.patch_bundles:
|
||||||
|
for bundle in app.patch_bundles:
|
||||||
|
patches = convert_command_output_to_json(
|
||||||
|
f"{config.temp_folder}/{app.resource["cli"]["file_name"]}",
|
||||||
|
f"{config.temp_folder}/{bundle["file_name"]}",
|
||||||
|
)
|
||||||
|
self._process_patches(patches, app)
|
||||||
|
elif "patches" in app.resource:
|
||||||
|
# Fallback to single bundle for backward compatibility
|
||||||
patches = convert_command_output_to_json(
|
patches = convert_command_output_to_json(
|
||||||
f"{config.temp_folder}/{app.resource["cli"]["file_name"]}",
|
f"{config.temp_folder}/{app.resource["cli"]["file_name"]}",
|
||||||
f"{config.temp_folder}/{app.resource["patches"]["file_name"]}",
|
f"{config.temp_folder}/{app.resource["patches"]["file_name"]}",
|
||||||
)
|
)
|
||||||
|
self._process_patches(patches, app)
|
||||||
|
|
||||||
|
app.no_of_patches = len(self.patches_dict[app.app_name])
|
||||||
|
|
||||||
|
def _process_patches(self: Self, patches: list[dict[Any, Any]], app: APP) -> None:
|
||||||
|
"""Process patches from a single bundle and add them to the patches dict.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
patches : list[dict[Any, Any]]
|
||||||
|
List of patches from a bundle
|
||||||
|
app : APP
|
||||||
|
The app instance
|
||||||
|
"""
|
||||||
for patch in patches:
|
for patch in patches:
|
||||||
if not patch["compatiblePackages"]:
|
if not patch["compatiblePackages"]:
|
||||||
p = {x: patch[x] for x in ["name", "description"]}
|
p = {x: patch[x] for x in ["name", "description"]}
|
||||||
@@ -142,10 +166,10 @@ class Patches(object):
|
|||||||
p = {x: patch[x] for x in ["name", "description"]}
|
p = {x: patch[x] for x in ["name", "description"]}
|
||||||
p["app"] = compatible_package
|
p["app"] = compatible_package
|
||||||
p["version"] = version[-1] if version else "all"
|
p["version"] = version[-1] if version else "all"
|
||||||
|
# Avoid duplicate patches from multiple bundles
|
||||||
|
if not any(existing["name"] == p["name"] for existing in self.patches_dict[app.app_name]):
|
||||||
self.patches_dict[app.app_name].append(p)
|
self.patches_dict[app.app_name].append(p)
|
||||||
|
|
||||||
app.no_of_patches = len(self.patches_dict[app.app_name])
|
|
||||||
|
|
||||||
def __init__(self: Self, config: RevancedConfig, app: APP) -> None:
|
def __init__(self: Self, config: RevancedConfig, app: APP) -> None:
|
||||||
self.patches_dict: dict[str, list[dict[str, str]]] = {"universal_patch": []}
|
self.patches_dict: dict[str, list[dict[str, str]]] = {"universal_patch": []}
|
||||||
self.fetch_patches(config, app)
|
self.fetch_patches(config, app)
|
||||||
|
|||||||
Reference in New Issue
Block a user