Per app config

This commit is contained in:
Nikhil Badyal
2023-08-05 17:21:16 +05:30
parent b8c8983de8
commit bd5224c1a1
11 changed files with 222 additions and 307 deletions
+1 -1
View File
@@ -7,4 +7,4 @@ venv
/revanced-cache/
changelog.md
.idea
*patches.json
*.json
+15 -62
View File
@@ -6,86 +6,39 @@ from loguru import logger
from src.config import RevancedConfig
from src.downloader.factory import DownloaderFactory
from src.downloader.utils import download_revanced
from src.parser import Parser
from src.patches import Patches
from src.utils import AppNotFound, PatcherDownloadFailed
from src.utils import AppNotFound, PatchesJsonFailed, check_java
def main() -> None:
"""Entry point."""
from src.app import APP
env = Env()
config = RevancedConfig(env)
check_java(config.dry_run)
patcher = Patches(config)
try:
download_revanced(config, patcher)
except PatcherDownloadFailed as e:
logger.error(f"Failed to download {e}")
sys.exit(1)
logger.info(f"Will Patch only {patcher.config.apps}")
for app in patcher.config.apps:
logger.info(f"Will Patch only {config.apps}")
for app in config.apps:
logger.info("Trying to build %s" % app)
try:
logger.info("Trying to build %s" % app)
app = APP(app_name=app, config=config)
patcher = Patches(config, app)
parser = Parser(patcher, config)
app_all_patches, version, is_experimental = patcher.get_app_configs(app)
app_all_patches = patcher.get_app_configs(app)
patcher.include_exclude_patch(app, parser, app_all_patches)
downloader = DownloaderFactory.create_downloader(
app=app, patcher=patcher, config=config
app=app.app_name, patcher=patcher, config=config
)
downloader.download(version, app)
config.app_versions[app] = version
logger.info(f"Downloaded {app}, version {version}")
parser.patch_app(app=app, version=version, is_experimental=is_experimental)
downloader.download(app.app_version, app.app_name)
parser.patch_app(app)
except AppNotFound as e:
logger.info(f"Invalid app requested to build {e}")
except PatchesJsonFailed:
logger.exception("Patches.json not found")
except Exception as e:
logger.exception(f"Failed to build {app} because of {e}")
if len(config.alternative_youtube_patches) and "youtube" in config.apps:
for alternative_patch in config.alternative_youtube_patches:
parser = Parser(patcher, config)
app_all_patches, version, is_experimental = patcher.get_app_configs(
"youtube"
)
patcher.include_exclude_patch("youtube", parser, app_all_patches)
was_inverted = parser.invert_patch(alternative_patch)
if was_inverted:
logger.info(
f"Rebuilding youtube with inverted {alternative_patch} patch."
)
parser.patch_app(
app="youtube",
version=config.app_versions.get("youtube", "latest"),
is_experimental=is_experimental,
output_prefix="-" + alternative_patch + "-",
)
else:
logger.info(
f"Skipping Rebuilding youtube as {alternative_patch} patch was not found."
)
if len(config.alternative_youtube_music_patches) and "youtube_music" in config.apps:
for alternative_patch in config.alternative_youtube_music_patches:
parser = Parser(patcher, config)
app_all_patches, version, is_experimental = patcher.get_app_configs(
"youtube_music"
)
patcher.include_exclude_patch("youtube_music", parser, app_all_patches)
was_inverted = parser.invert_patch(alternative_patch)
if was_inverted:
logger.info(
f"Rebuilding youtube music with inverted {alternative_patch} patch."
)
parser.patch_app(
app="youtube_music",
version=config.app_versions.get("youtube_music", "latest"),
is_experimental=is_experimental,
output_prefix="-" + alternative_patch + "-",
)
else:
logger.info(
f"Skipping Rebuilding youtube music as {alternative_patch} patch was not found."
)
if __name__ == "__main__":
+94
View File
@@ -0,0 +1,94 @@
"""Class to represent apk to be patched."""
import concurrent
import hashlib
import pathlib
from concurrent.futures import ThreadPoolExecutor
from typing import Dict
from loguru import logger
from src.config import RevancedConfig
from src.utils import PatcherDownloadFailed, slugify
class APP(object):
"""Patched APK."""
def __init__(self, app_name: str, config: RevancedConfig):
self.app_name = app_name
self.app_version = config.env.str(f"{app_name}_VERSION".upper(), None)
self.experiment = False
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
)
self.integrations_dl = config.env.str(
f"{app_name}_INTEGRATION_DL".upper(), config.global_integrations_dl
)
self.exclude_request = config.env.list(f"EXCLUDE_PATCH_{app_name}".upper(), [])
self.include_request = config.env.list(f"INCLUDE_PATCH_{app_name}".upper(), [])
self.resource: Dict[str, str] = {}
self.no_of_patches = 0
self.download_patch_resources(config)
def get_output_file_name(self) -> str:
"""Get output file appended with version."""
return f"Re-{self.app_name}-{slugify(self.app_version)}.apk"
def set_recommended_version(self, version: str, exp: bool = False) -> None:
"""Update if cooking non-recommended."""
self.app_version = version
self.experiment = exp
def __str__(self: "APP") -> str:
attrs = vars(self)
return ", ".join("%s: %s" % item for item in attrs.items())
@staticmethod
def download(url: str, config: RevancedConfig, assets_filter: str = None) -> str: # type: ignore
"""Downloader."""
from src.downloader.download import Downloader
url = url.strip()
if url.startswith("https://github"):
from src.downloader.github import Github
url = Github.patch_resource(url, assets_filter)[0]
extension = pathlib.Path(url).suffix
file_name = APP.generate_filename(url) + extension
Downloader(None, config).direct_download(url, file_name) # type: ignore
return file_name
def download_patch_resources(self, config: RevancedConfig) -> None:
"""Download resource for patching."""
logger.info("Downloading resources for patching.")
# Create a list of resource download tasks
download_tasks = [
("cli", self.cli_dl, config),
("integrations", self.integrations_dl, config),
("patches", self.patches_dl, config, ".*jar"),
("patches_json", self.patches_dl, config, ".*json"),
]
# Using a ThreadPoolExecutor for parallelism
with ThreadPoolExecutor() as executor:
futures = {
resource_name: executor.submit(self.download, *args)
for resource_name, *args in download_tasks
}
# Wait for all tasks to complete
concurrent.futures.wait(futures.values())
# Retrieve results from completed tasks
for resource_name, future in futures.items():
try:
self.resource[resource_name] = future.result()
except Exception as e:
raise PatcherDownloadFailed(f"An exception occurred: {e}")
@staticmethod
def generate_filename(url: str) -> str:
"""Get file name from url."""
encoded_url: str = hashlib.sha256(url.encode()).hexdigest()
return encoded_url
+11 -24
View File
@@ -1,23 +1,27 @@
"""Revanced Configurations."""
from pathlib import Path
from typing import Dict, List
from typing import List
from environs import Env
from requests import Session
from src.utils import default_build
default_cli = "https://github.com/revanced/revanced-cli/releases/latest"
default_patches = "https://github.com/revanced/revanced-patches/releases/latest"
default_integrations = (
"https://github.com/revanced/revanced-integrations/releases/latest"
)
class RevancedConfig(object):
"""Revanced Configurations."""
def __init__(self, env: Env) -> None:
self.app_versions: Dict[str, str] = {}
self.env = env
self.temp_folder = Path("apks")
self.session = Session()
self.session.headers["User-Agent"] = "anything"
self.build_extended = env.bool("BUILD_EXTENDED", False)
self.apk_mirror = "https://www.apkmirror.com"
self.upto_down = [
"spotify",
@@ -34,27 +38,7 @@ class RevancedConfig(object):
self.keystore_name = env.str("KEYSTORE_FILE_NAME", "revanced.keystore")
self.ci_test = env.bool("CI_TEST", False)
self.apps = env.list("PATCH_APPS", default_build)
self.extended_apps: List[str] = ["youtube", "youtube_music", "microg", "reddit"]
self.rip_libs_apps: List[str] = ["youtube"]
self.normal_cli_jar = "revanced-cli.jar"
self.normal_patches_jar = "revanced-patches.jar"
self.normal_integrations_apk = "revanced-integrations.apk"
self.normal_options_json = "options.json"
self.cli_jar = (
f"inotia00-{self.normal_cli_jar}"
if self.build_extended
else self.normal_cli_jar
)
self.patches_jar = (
f"inotia00-{self.normal_patches_jar}"
if self.build_extended
else self.normal_patches_jar
)
self.integrations_apk = (
f"inotia00-{self.normal_integrations_apk}"
if self.build_extended
else self.normal_integrations_apk
)
self.rip_libs_apps: List[str] = []
self.apk_mirror_urls = {
"reddit": f"{self.apk_mirror}/apk/redditinc/reddit/",
"twitter": f"{self.apk_mirror}/apk/x-corp/twitter/",
@@ -97,3 +81,6 @@ class RevancedConfig(object):
self.existing_downloaded_apks = env.list("EXISTING_DOWNLOADED_APKS", [])
self.personal_access_token = env.str("PERSONAL_ACCESS_TOKEN", None)
self.dry_run = env.bool("DRY_RUN", False)
self.global_cli_dl = env.str("GLOBAL_CLI_DL", default_cli)
self.global_patches_dl = env.str("GLOBAL_CLI_DL", default_patches)
self.global_integrations_dl = env.str("GLOBAL_CLI_DL", default_integrations)
-4
View File
@@ -30,7 +30,6 @@ class ApkMirror(Downloader):
"p.notes:nth-child(3) > span:nth-child(1) > a:nth-child(1)"
).attributes["href"]
self._download(self.config.apk_mirror + href, f"{app}.apk")
logger.debug("Finished Extracting link and downloading")
def get_download_page(self, parser: LexborHTMLParser, main_page: str) -> str:
"""Function to get the download page in apk_mirror.
@@ -67,7 +66,6 @@ class ApkMirror(Downloader):
:param version: Version of the application to download
:return: Version of downloaded apk
"""
logger.debug(f"Trying to download {app},specific version {version}")
version = version.replace(".", "-")
main_page = f"{self.config.apk_mirror_version_urls.get(app)}-{version}-release/"
parser = LexborHTMLParser(
@@ -75,7 +73,6 @@ class ApkMirror(Downloader):
)
download_page = self.get_download_page(parser, main_page)
self.extract_download_link(download_page, app)
logger.debug(f"Downloaded {app} apk from apkmirror_specific_version")
def latest_version(self, app: str, **kwargs: Any) -> None:
"""Function to download whatever the latest version of app from
@@ -105,4 +102,3 @@ class ApkMirror(Downloader):
parser = LexborHTMLParser(self.config.session.get(main_page).text)
download_page = self.get_download_page(parser, main_page)
self.extract_download_link(download_page, app)
logger.debug(f"Downloaded {app} apk from apkmirror_specific_version in rt")
+17 -6
View File
@@ -1,5 +1,6 @@
"""Downloader Class."""
import os
from pathlib import Path
from queue import PriorityQueue
from time import perf_counter
from typing import Any, Tuple
@@ -23,14 +24,20 @@ class Downloader(object):
self.config = config
self.patcher = patcher
def _download(self, url: str, file_name: str) -> None:
if (
os.path.exists(self.config.temp_folder.joinpath(file_name))
or self.config.dry_run
):
@staticmethod
def file_status_check(file_name: Path, dry_run: bool, url: str) -> bool:
"""Check if file already exists."""
if os.path.exists(file_name) or dry_run:
logger.debug(
f"Skipping download of {file_name}. File already exists or dry running."
f"Skipping download of {file_name} from {url}. File already exists or dry running."
)
return True
return False
def _download(self, url: str, file_name: str) -> None:
if self.file_status_check(
self.config.temp_folder.joinpath(file_name), self.config.dry_run, url
):
return
logger.info(f"Trying to download {file_name} from {url}")
self._QUEUE_LENGTH += 1
@@ -99,3 +106,7 @@ class Downloader(object):
self.specific_version(app, version)
else:
self.latest_version(app, **kwargs)
def direct_download(self, dl: str, file_name: str) -> None:
"""Download from DL."""
self._download(dl, file_name)
+10 -1
View File
@@ -1,7 +1,8 @@
"""Github Downloader."""
from typing import Dict
from typing import Dict, List
import requests
from lastversion import latest
from loguru import logger
from src.downloader.download import Downloader
@@ -41,3 +42,11 @@ class Github(Downloader):
download_url = response.json()["assets"][0]["browser_download_url"]
update_changelog(f"{owner}/{repo_name}", response.json())
self._download(download_url, file_name=app)
@staticmethod
def patch_resource(repo_url: str, assets_filter: str) -> list[str]:
"""Fetch patch resource from repo url."""
latest_resource_version: List[str] = latest(
repo_url, assets_filter=assets_filter, output_format="assets"
)
return latest_resource_version
-59
View File
@@ -1,63 +1,4 @@
"""Utility class."""
import os
from concurrent.futures import ThreadPoolExecutor, as_completed
from loguru import logger
from src.config import RevancedConfig
from src.patches import Patches
from src.utils import PatcherDownloadFailed
implement_method = "Please implement the method"
def download_revanced(config: RevancedConfig, patcher: Patches) -> None:
"""Download Revanced and Extended Patches, Integration and CLI."""
from src.downloader.factory import DownloaderFactory
if os.path.exists("changelog.md") and not config.dry_run:
logger.debug("Deleting old changelog.md")
os.remove("changelog.md")
assets = [
["revanced", "revanced-cli", config.normal_cli_jar],
["revanced", "revanced-integrations", config.normal_integrations_apk],
["revanced", "revanced-patches", config.normal_patches_jar],
]
if config.build_extended:
assets += [
["inotia00", "revanced-cli", config.cli_jar],
["inotia00", "revanced-integrations", config.integrations_apk],
["inotia00", "revanced-patches", config.patches_jar],
]
if (
"youtube" in config.apps
or "youtube_music" in config.apps
or "microg" in config.apps
):
if config.build_extended and "microg" in config.apps:
assets += [
["inotia00", "mMicroG", "microg.apk"],
]
else:
assets += [
["inotia00", "mMicroG", "microg-output.apk"],
]
downloader = DownloaderFactory.create_downloader(
app="patches", patcher=patcher, config=config
)
with ThreadPoolExecutor(7) as executor:
futures = [
executor.submit(
downloader.download,
version="latest",
app=repo[2],
**{"owner": repo[0], "name": repo[1]},
)
for repo in assets
]
for future in as_completed(futures):
try:
future.result()
except Exception as e:
raise PatcherDownloadFailed(f"An exception occurred: {e}")
logger.info("Downloaded revanced microG ,cli, integrations and patches.")
+13 -29
View File
@@ -6,9 +6,10 @@ from typing import List
from loguru import logger
from src.app import APP
from src.config import RevancedConfig
from src.patches import Patches
from src.utils import possible_archs, slugify
from src.utils import possible_archs
class Parser(object):
@@ -70,43 +71,29 @@ class Parser(object):
# noinspection IncorrectFormatting
def patch_app(
self,
app: str,
version: str,
is_experimental: bool = False,
output_prefix: str = "-",
app: APP,
) -> None:
"""Revanced APP Patcher.
:param app: Name of the app
:param version: Version of the application
:param is_experimental: Whether to enable experimental support
:param output_prefix: Prefix to add to the output apks file name
"""
cli = self.config.normal_cli_jar
patches = self.config.normal_patches_jar
integrations = self.config.normal_integrations_apk
options = self.config.normal_options_json
if self.config.build_extended and app in self.config.extended_apps:
cli = self.config.cli_jar
patches = self.config.patches_jar
integrations = self.config.integrations_apk
args = [
"-jar",
cli,
app.resource["cli"],
"-a",
app + ".apk",
app.app_name + ".apk",
"-b",
patches,
app.resource["patches"],
"-m",
integrations,
app.resource["integrations"],
"-o",
f"Re-{app}-{slugify(version)}{output_prefix}output.apk",
app.get_output_file_name(),
"--keystore",
self.config.keystore_name,
"--options",
options,
"options.json",
]
if is_experimental:
if app.experiment:
logger.debug("Using experimental features")
args.append("--experimental")
args[1::2] = map(lambda i: self.config.temp_folder.joinpath(i), args[1::2])
@@ -114,11 +101,7 @@ class Parser(object):
self.exclude_all_patches()
if self._PATCHES:
args.extend(self._PATCHES)
if (
self.config.build_extended
and len(self.config.archs_to_build) > 0
and app in self.config.rip_libs_apps
):
if app.app_name in self.config.rip_libs_apps:
excluded = set(possible_archs) - set(self.config.archs_to_build)
for arch in excluded:
args.append("--rip-lib")
@@ -126,8 +109,9 @@ class Parser(object):
start = perf_counter()
logger.debug(
f"Sending request to revanced cli for building {app} revanced with args java {args}"
f"Sending request to revanced cli for building with args java {args}"
)
return
process = Popen(["java", *args], stdout=PIPE)
output = process.stdout
if not output:
+35 -121
View File
@@ -1,13 +1,13 @@
"""Revanced Patches."""
import json
import subprocess
import os
from typing import Any, Dict, List, Tuple
from loguru import logger
from requests import Session
from src.app import APP
from src.config import RevancedConfig
from src.utils import AppNotFound, handle_response
from src.utils import AppNotFound, PatchesJsonFailed
class Patches(object):
@@ -50,59 +50,28 @@ class Patches(object):
"ml.docilealligator.infinityforreddit": "infinity",
"me.ccrama.redditslide": "slide",
"com.onelouder.baconreader": "bacon",
"com.google.android.youtube": "youtube",
"com.google.android.apps.youtube.music": "youtube_music",
"com.mgoogle.android.gms": "microg",
}
revanced_app_ids = {
key: (value, "_" + value) for key, value in _revanced_app_ids.items()
}
_revanced_extended_app_ids = {
"com.google.android.youtube": "youtube",
"com.google.android.apps.youtube.music": "youtube_music",
"com.mgoogle.android.gms": "microg",
"com.reddit.frontpage": "reddit",
}
revanced_extended_app_ids = {
key: (value, "_" + value) for key, value in _revanced_extended_app_ids.items()
}
@staticmethod
def support_app() -> Dict[str, str]:
"""Return supported apps."""
return Patches._revanced_app_ids
@staticmethod
def check_java(dry_run: bool) -> None:
"""Check if Java17 is installed."""
try:
if dry_run:
return
jd = subprocess.check_output(
["java", "-version"], stderr=subprocess.STDOUT
).decode("utf-8")
jd = jd[1:-1]
if "Runtime Environment" not in jd:
raise subprocess.CalledProcessError(-1, "java -version")
if "17" not in jd and "20" not in jd:
raise subprocess.CalledProcessError(-1, "java -version")
logger.debug("Cool!! Java is available")
except subprocess.CalledProcessError:
logger.debug("Java>= 17 Must be installed")
exit(-1)
def scrap_patches(self, file_name: str) -> Any:
"""Scrap Patches."""
if os.path.exists(file_name):
with open(file_name) as f:
patches = json.load(f)
return patches
raise PatchesJsonFailed()
# noinspection DuplicatedCode
def fetch_patches(self) -> None:
def fetch_patches(self, config: RevancedConfig, app: APP) -> None:
"""Function to fetch all patches."""
session = Session()
if self.config.dry_run:
logger.debug("fetching all patches from local file")
with open("patches.json") as f:
patches = json.load(f)
else:
url = "https://raw.githubusercontent.com/revanced/revanced-patches/main/patches.json"
logger.debug(f"fetching all patches from {url}")
response = session.get(url)
handle_response(response)
patches = response.json()
patches = self.scrap_patches(
f'{config.temp_folder}/{app.resource["patches_json"]}'
)
for app_name in (self.revanced_app_ids[x][1] for x in self.revanced_app_ids):
setattr(self, app_name, [])
setattr(self, "universal_patch", [])
@@ -122,47 +91,11 @@ class Patches(object):
p["app"] = compatible_package
p["version"] = version[-1] if version else "all"
getattr(self, app_name).append(p)
if self.config.dry_run:
extended_patches = patches
else:
if self.config.build_extended:
url = "https://raw.githubusercontent.com/inotia00/revanced-patches/revanced-extended/patches.json"
else:
url = "https://raw.githubusercontent.com/revanced/revanced-patches/main/patches.json"
response = session.get(url)
handle_response(response)
extended_patches = response.json()
for app_name in (
self.revanced_extended_app_ids[x][1] for x in self.revanced_extended_app_ids
):
setattr(self, app_name, [])
n_patches = len(getattr(self, f"_{app.app_name}"))
app.no_of_patches = n_patches
for patch in extended_patches:
for compatible_package, version in [
(x["name"], x["versions"]) for x in patch["compatiblePackages"]
]:
if compatible_package in self.revanced_extended_app_ids:
app_name = self.revanced_extended_app_ids[compatible_package][1]
p = {x: patch[x] for x in ["name", "description"]}
p["app"] = compatible_package
p["version"] = version[-1] if version else "all"
getattr(self, app_name).append(p)
for app_name, app_id in self.revanced_extended_app_ids.values():
n_patches = len(getattr(self, app_id))
logger.debug(f"Total patches in {app_name} are {n_patches}")
for app_name, app_id in self.revanced_app_ids.values():
n_patches = len(getattr(self, app_id))
logger.debug(f"Total patches in {app_name} are {n_patches}")
n_patches = len(getattr(self, "universal_patch"))
logger.debug(f"Total universal patches are {n_patches}")
def __init__(self, config: RevancedConfig) -> None:
self.config = config
self.check_java(self.config.dry_run)
self.fetch_patches()
if self.config.dry_run:
self.config.apps = list(self._revanced_app_ids.values())
def __init__(self, config: RevancedConfig, app: APP) -> None:
self.fetch_patches(config, app)
def get(self, app: str) -> Tuple[List[Dict[str, str]], str]:
"""Get all patches for the given app.
@@ -170,11 +103,7 @@ class Patches(object):
:param app: Name of the application
:return: Patches
"""
logger.debug("Getting patches for %s" % app)
app_names = {value[0]: value[1] for value in self.revanced_app_ids.values()}
app_names.update(
{value[0]: value[1] for value in self.revanced_extended_app_ids.values()}
)
if not (app_name := app_names.get(app)):
raise AppNotFound(app)
@@ -182,14 +111,13 @@ class Patches(object):
version = "latest"
try:
version = next(i["version"] for i in patches if i["version"] != "all")
logger.debug(f"Recommended Version for patching {app} is {version}")
except StopIteration:
pass
return patches, version
# noinspection IncorrectFormatting
def include_exclude_patch(
self, app: str, parser: Any, patches: List[Dict[str, str]]
self, app: APP, parser: Any, patches: List[Dict[str, str]]
) -> None:
"""Include and exclude patches for a given app.
@@ -197,34 +125,20 @@ class Patches(object):
:param parser: Parser Obj
:param patches: All the patches of a given app
"""
if self.config.build_extended and app in self.config.extended_apps:
excluded_patches = self.config.env.list(
f"EXCLUDE_PATCH_{app}_EXTENDED".upper(), []
)
included_patches = self.config.env.list(
f"INCLUDE_PATCH_{app}_EXTENDED".upper(), []
)
else:
excluded_patches = self.config.env.list(f"EXCLUDE_PATCH_{app}".upper(), [])
included_patches = self.config.env.list(f"INCLUDE_PATCH_{app}".upper(), [])
for patch in patches:
normalized_patch = patch["name"].lower().replace(" ", "-")
parser.include(
normalized_patch
) if normalized_patch not in excluded_patches else parser.exclude(
) if normalized_patch not in app.exclude_request else parser.exclude(
normalized_patch
)
for normalized_patch in included_patches:
for normalized_patch in app.include_request:
parser.include(normalized_patch) if normalized_patch not in getattr(
self, "universal_patch", []
) else ()
excluded = parser.get_excluded_patches()
if excluded:
logger.debug(f"Excluded patches {excluded} for {app}")
else:
logger.debug(f"No excluded patches for {app}")
logger.info(app)
def get_app_configs(self, app: str) -> Tuple[List[Dict[str, str]], str, bool]:
def get_app_configs(self, app: "APP") -> List[Dict[str, str]]:
"""Get Configurations for a given app.
:param app: Name of the application
@@ -232,15 +146,15 @@ class Patches(object):
experimental
"""
experiment = False
total_patches, recommended_version = self.get(app=app)
env_version = self.config.env.str(f"{app}_VERSION".upper(), None)
if env_version:
logger.debug(f"Picked {app} version {env_version} from env.")
total_patches, recommended_version = self.get(app=app.app_name)
if app.app_version:
logger.debug(f"Picked {app} version {app.app_version:} from env.")
if (
env_version == "latest"
or env_version > recommended_version
or env_version < recommended_version
app.app_version == "latest"
or app.app_version > recommended_version
or app.app_version < recommended_version
):
experiment = True
recommended_version = env_version
return total_patches, recommended_version, experiment
recommended_version = app.app_version
app.set_recommended_version(recommended_version, experiment)
return total_patches
+26
View File
@@ -1,5 +1,6 @@
"""Utilities."""
import re
import subprocess
from typing import Dict
from loguru import logger
@@ -50,6 +51,12 @@ class PatcherDownloadFailed(Exception):
pass
class PatchesJsonFailed(ValueError):
"""Patches failed."""
pass
def handle_response(response: Response) -> None:
"""Handle Get Request Response."""
response_code = response.status_code
@@ -76,3 +83,22 @@ def slugify(string: str) -> str:
string = string.strip("-")
return string
def check_java(dry_run: bool) -> None:
"""Check if Java17 is installed."""
try:
if dry_run:
return
jd = subprocess.check_output(
["java", "-version"], stderr=subprocess.STDOUT
).decode("utf-8")
jd = jd[1:-1]
if "Runtime Environment" not in jd:
raise subprocess.CalledProcessError(-1, "java -version")
if "17" not in jd and "20" not in jd:
raise subprocess.CalledProcessError(-1, "java -version")
logger.debug("Cool!! Java is available")
except subprocess.CalledProcessError:
logger.debug("Java>= 17 Must be installed")
exit(-1)