Compare commits

...

24 Commits

Author SHA1 Message Date
oSumAtrIX
e87ee9c5b8 chore: Add click-to-run scripts 2024-10-19 06:35:25 +02:00
semantic-release-bot
504c6c1ea5 chore: Release v5.0.0-dev.8 [skip ci]
# [5.0.0-dev.8](https://github.com/ReVanced/revanced-cli/compare/v5.0.0-dev.7...v5.0.0-dev.8) (2024-10-17)
2024-10-17 18:06:32 +00:00
oSumAtrIX
f58b101636 build(Needs bump): Bump ReVanced Patcher 2024-10-17 20:02:26 +02:00
cyberboh
292b93b609 docs: Use correct option name in command example (#342) 2024-10-16 15:27:58 +02:00
semantic-release-bot
e60a61b098 chore: Release v5.0.0-dev.7 [skip ci]
# [5.0.0-dev.7](https://github.com/ReVanced/revanced-cli/compare/v5.0.0-dev.6...v5.0.0-dev.7) (2024-10-16)

### Bug Fixes

* Check for null when no device serial was specified ([1da8ae9](1da8ae9e46))
2024-10-16 02:57:57 +00:00
oSumAtrIX
1da8ae9e46 fix: Check for null when no device serial was specified 2024-10-16 04:55:52 +02:00
semantic-release-bot
a9f2538827 chore: Release v5.0.0-dev.6 [skip ci]
# [5.0.0-dev.6](https://github.com/ReVanced/revanced-cli/compare/v5.0.0-dev.5...v5.0.0-dev.6) (2024-10-10)

### Bug Fixes

* Use the first connected device when no ADB device is specified ([5f952f3](5f952f35f5))
2024-10-10 21:05:17 +00:00
oSumAtrIX
5f952f35f5 fix: Use the first connected device when no ADB device is specified 2024-10-10 23:03:20 +02:00
oSumAtrIX
280ded2281 ci: Adjust release commit message 2024-10-01 17:30:15 +02:00
semantic-release-bot
bb6bc1ba9a chore: Release 5.0.0-dev.5 [skip ci]
# [5.0.0-dev.5](https://github.com/ReVanced/revanced-cli/compare/v5.0.0-dev.4...v5.0.0-dev.5) (2024-09-30)
2024-09-30 20:27:43 +00:00
oSumAtrIX
04b178b701 build(Needs bump): Update dependencies 2024-09-30 22:25:06 +02:00
oSumAtrIX
32e6aae132 ci: Adjust release commit message 2024-09-30 22:24:40 +02:00
oSumAtrIX
7ee4f15ab9 ci: Use permissions and regular GitHub token instead of PAT 2024-09-30 22:24:18 +02:00
oSumAtrIX
a7af611ef0 docs: Use correct option keys in command examples [skip ci] 2024-09-21 23:08:32 +02:00
semantic-release-bot
9440dc769e chore(release): 5.0.0-dev.4 [skip ci]
# [5.0.0-dev.4](https://github.com/ReVanced/revanced-cli/compare/v5.0.0-dev.3...v5.0.0-dev.4) (2024-09-17)

### Bug Fixes

* Make patches selectable by using a mutable collection for the selection option ([751fa1d](751fa1d889))
* Make the patch command work without specifying any selection ([ba159a3](ba159a35a9))

### Features

* Show error about no installation device found at the beginning ([3300e6b](3300e6b433))
2024-09-17 23:18:07 +00:00
oSumAtrIX
751fa1d889 fix: Make patches selectable by using a mutable collection for the selection option 2024-09-05 23:08:18 +04:00
oSumAtrIX
3300e6b433 feat: Show error about no installation device found at the beginning 2024-09-05 23:00:22 +04:00
oSumAtrIX
ba159a35a9 fix: Make the patch command work without specifying any selection 2024-09-05 22:54:09 +04:00
kitadai31
74ff94037e docs: List supported ABIs correctly and add a mention how to use other ones
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
2024-09-01 16:36:34 +02:00
oSumAtrIX
7e8fb5722a docs: Link to JRE downloads instead of JDK 2024-08-23 13:21:27 +04:00
semantic-release-bot
7b4af46c94 chore(release): 5.0.0-dev.3 [skip ci]
# [5.0.0-dev.3](https://github.com/ReVanced/revanced-cli/compare/v5.0.0-dev.2...v5.0.0-dev.3) (2024-08-14)

### Features

* Simplify option descriptions ([45c998b](45c998b335))
2024-08-14 13:36:05 +00:00
oSumAtrIX
45c998b335 feat: Simplify option descriptions 2024-08-14 15:34:02 +02:00
semantic-release-bot
9b03963687 chore(release): 5.0.0-dev.2 [skip ci]
# [5.0.0-dev.2](https://github.com/ReVanced/revanced-cli/compare/v5.0.0-dev.1...v5.0.0-dev.2) (2024-08-14)

### Features

* Simplify command and option names and descriptions ([#338](https://github.com/ReVanced/revanced-cli/issues/338)) ([6e7797a](6e7797a3f0))

### BREAKING CHANGES

* Options have been renamed.
2024-08-14 12:08:47 +00:00
oSumAtrIX
6e7797a3f0 feat: Simplify command and option names and descriptions (#338)
BREAKING CHANGE: Options have been renamed.
2024-08-14 14:06:58 +02:00
32 changed files with 1391 additions and 1589 deletions

View File

@@ -10,6 +10,8 @@ on:
jobs:
release:
name: Release
permissions:
contents: write
runs-on: ubuntu-latest
steps:
- name: Checkout
@@ -46,5 +48,5 @@ jobs:
- name: Release
env:
GITHUB_TOKEN: ${{ secrets.REPOSITORY_PUSH_ACCESS }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: npm exec semantic-release

5
.gitignore vendored
View File

@@ -122,4 +122,7 @@ revanced-cache/
options.toml
# Generated by Android projects
local.properties
local.properties
# Generated by scripts
scripts/workspace

View File

@@ -23,7 +23,8 @@
"assets": [
"CHANGELOG.md",
"gradle.properties"
]
],
"message": "chore: Release v${nextRelease.version} [skip ci]\n\n${nextRelease.notes}"
}
],
[

View File

@@ -1,3 +1,53 @@
# [5.0.0-dev.8](https://github.com/ReVanced/revanced-cli/compare/v5.0.0-dev.7...v5.0.0-dev.8) (2024-10-17)
# [5.0.0-dev.7](https://github.com/ReVanced/revanced-cli/compare/v5.0.0-dev.6...v5.0.0-dev.7) (2024-10-16)
### Bug Fixes
* Check for null when no device serial was specified ([1da8ae9](https://github.com/ReVanced/revanced-cli/commit/1da8ae9e46000dd3c4eecd793c559e75012cf535))
# [5.0.0-dev.6](https://github.com/ReVanced/revanced-cli/compare/v5.0.0-dev.5...v5.0.0-dev.6) (2024-10-10)
### Bug Fixes
* Use the first connected device when no ADB device is specified ([5f952f3](https://github.com/ReVanced/revanced-cli/commit/5f952f35f5cb388b6509b2b4d905b8143ebc7996))
# [5.0.0-dev.5](https://github.com/ReVanced/revanced-cli/compare/v5.0.0-dev.4...v5.0.0-dev.5) (2024-09-30)
# [5.0.0-dev.4](https://github.com/ReVanced/revanced-cli/compare/v5.0.0-dev.3...v5.0.0-dev.4) (2024-09-17)
### Bug Fixes
* Make patches selectable by using a mutable collection for the selection option ([751fa1d](https://github.com/ReVanced/revanced-cli/commit/751fa1d889f40c51b291116029fd84f2b051f2f0))
* Make the patch command work without specifying any selection ([ba159a3](https://github.com/ReVanced/revanced-cli/commit/ba159a35a9a99d18a4c1e04128b08ae336a49b3e))
### Features
* Show error about no installation device found at the beginning ([3300e6b](https://github.com/ReVanced/revanced-cli/commit/3300e6b4333ed1c4e6785cb82eca9016fc6d4a20))
# [5.0.0-dev.3](https://github.com/ReVanced/revanced-cli/compare/v5.0.0-dev.2...v5.0.0-dev.3) (2024-08-14)
### Features
* Simplify option descriptions ([45c998b](https://github.com/ReVanced/revanced-cli/commit/45c998b335b65ac233fece8b804dc7410142691c))
# [5.0.0-dev.2](https://github.com/ReVanced/revanced-cli/compare/v5.0.0-dev.1...v5.0.0-dev.2) (2024-08-14)
### Features
* Simplify command and option names and descriptions ([#338](https://github.com/ReVanced/revanced-cli/issues/338)) ([6e7797a](https://github.com/ReVanced/revanced-cli/commit/6e7797a3f0525a8f48af7182157da0d045600ac2))
### BREAKING CHANGES
* Options have been renamed.
# [5.0.0-dev.1](https://github.com/ReVanced/revanced-cli/compare/v4.6.0...v5.0.0-dev.1) (2024-08-12)

View File

@@ -4,9 +4,9 @@ To use ReVanced CLI, you will need to fulfill specific requirements.
## 🤝 Requirements
- Java Runtime Environment 11 ([Azul Zulu JRE](https://www.azul.com/downloads/?version=java-11-lts&package=jdk#zulu) or [OpenJDK](https://jdk.java.net/archive/))
- Java Runtime Environment 11 or higher ([Eclipse Temurin JRE](https://adoptium.net/temurin/releases/?package=jre) or [OpenJDK](https://jdk.java.net/archive/))
- [Android Debug Bridge (ADB)](https://developer.android.com/studio/command-line/adb) if you want to install the patched APK file on your device
- An ABI other than ARMv7 such as x86 or x86-64 (or a custom AAPT binary that supports ARMv7)
- x86 or x86-64 (For [other architectures](https://github.com/ReVanced/revanced-manager/tree/main/android/app/src/main/jniLibs) use the `--custom-aapt2-binary` option)
## ⏭️ Whats next

View File

@@ -13,7 +13,7 @@ java -jar revanced-cli.jar -h
## 📃 List patches
```bash
java -jar revanced-cli.jar list-patches --with-packages --with-versions --with-options revanced-patches.rvp
java -jar revanced-cli.jar list-patches --with-packages --with-versions --with-options patches.rvp
```
## 💉 Patch an app
@@ -21,48 +21,48 @@ java -jar revanced-cli.jar list-patches --with-packages --with-versions --with-o
To patch an app using the default list of patches, use the `patch` command:
```bash
java -jar revanced-cli.jar patch -b revanced-patches.rvp input.apk
java -jar revanced-cli.jar patch -p patches.rvp input.apk
```
You can also use multiple patch bundles:
You can also use multiple RVP files:
```bash
java -jar revanced-cli.jar patch -b revanced-patches.rvp -b another-patches.rvp input.apk
java -jar revanced-cli.jar patch -p patches.rvp -p another-patches.rvp input.apk
```
To change the default set of used patches, use the option `-i` or `-e` to use or disuse specific patches.
You can use the `list-patches` command to see which patches are used by default.
To change the default set of enabled or disabled patches, use the option `-e` or `-d` to enable or disable specific patches.
You can use the `list-patches` command to see which patches are enabled by default.
To only use specific patches, you can use the option `--exclusive` combined with `-i`.
Remember that the options `-i` and `-e` match the patch's name exactly. Here is an example:
To only enable specific patches, you can use the option `--exclusive` combined with `-e`.
Remember that the options `-e` and `-d` match the patch's name exactly. Here is an example:
```bash
java -jar revanced-cli.jar patch -b revanced-patches.rvp --exclusive -i "Patch name" -i "Another patch name" input.apk
java -jar revanced-cli.jar patch -p patches.rvp --exclusive -e "Patch name" -e "Another patch name" input.apk
```
You can also use the options `--ii` and `--ie` to use or disuse patches by their index.
This is useful, if two patches happen to have the same name.
You can also use the options `--ei` or `--di` to enable or disable patches by their index.
This is useful, if two patches happen to have the same name, or if typing the names is too cumbersome.
To know the indices of patches, use the command `list-patches`:
```bash
java -jar revanced-cli.jar list-patches revanced-patches.rvp
java -jar revanced-cli.jar list-patches patches.rvp
```
Then you can use the indices to use or disuse patches:
Then you can use the indices to enable or disable patches:
```bash
java -jar revanced-cli.jar patch -b revanced-patches.rvp --ii 123 --ie 456 input.apk
java -jar revanced-cli.jar patch -p patches.rvp --ei 123 --di 456 input.apk
```
You can combine the option `-i`, `-e`, `--ii`, `--ie` and `--exclusive`. Here is an example:
You can combine the option `-e`, `-d`, `--ei`, `--di` and `--exclusive`. Here is an example:
```bash
java -jar revanced-cli.jar patch -b revanced-patches.rvp --exclusive -i "Patch name" --ii 123 input.apk
java -jar revanced-cli.jar patch -p patches.rvp --exclusive -e "Patch name" --ei 123 input.apk
```
> [!TIP]
> You can use the option `-d` to automatically install the patched app after patching.
> You can use the option `-i` to automatically install the patched app after patching.
> Make sure ADB is working:
>
> ```bash
@@ -83,7 +83,7 @@ Patches can have options you can set using the option `-O` alongside the option
To know the options of a patch, use the option `--with-options` when listing patches:
```bash
java -jar revanced-cli.jar list-patches --with-options revanced-patches.rvp
java -jar revanced-cli.jar list-patches --with-options patches.rvp
```
Each patch can have multiple options. You can set them using the option `-O`.
@@ -91,18 +91,18 @@ For example, to set the options for the patch with the name `Patch name`
with the key `key1` and `key2` to `value1` and `value2` respectively, use the following command:
```bash
java -jar revanced-cli.jar patch -b revanced-patches.rvp -i "Patch name" -Okey1=value1 -Okey2=value2 input.apk
java -jar revanced-cli.jar patch -p patches.rvp -e "Patch name" -Okey1=value1 -Okey2=value2 input.apk
```
If you want to set a value to `null`, you can omit the value:
If you want to set the option value to `null`, you can omit the value:
```bash
java -jar revanced-cli.jar patch -b revanced-patches.rvp -i "Patch name" -Okey1 input.apk
java -jar revanced-cli.jar patch -p patches.rvp -i "Patch name" -Okey1 input.apk
```
> [!WARNING]
> Option values are usually typed. If you set a value with the wrong type, the patch can fail.
> Option value types can be seen when listing patches with the option `--with-options`.
> The value types can be seen when listing patches with the option `--with-options`.
>
> Example option values:
>
@@ -131,7 +131,7 @@ java -jar revanced-cli.jar patch -b revanced-patches.rvp -i "Patch name" -Okey1
> Example command with an escaped integer as a string:
>
> ```bash
> java -jar revanced-cli.jar -b revanced-patches.rvp -i "Patch name" -OstringKey=\'1\' input.apk
> java -jar revanced-cli.jar -p patches.rvp -e "Patch name" -OstringKey=\'1\' input.apk
> ```
## 📦 Install an app manually

View File

@@ -1,4 +1,4 @@
org.gradle.parallel = true
org.gradle.caching = true
kotlin.code.style = official
version = 5.0.0-dev.1
version = 5.0.0-dev.8

View File

@@ -1,9 +1,9 @@
[versions]
shadow = "8.1.1"
kotlin = "2.0.0"
kotlin = "2.0.20"
kotlinx = "1.8.1"
picocli = "4.7.6"
revanced-patcher = "20.0.0"
revanced-patcher = "20.0.2"
revanced-library = "3.0.0"
[libraries]

2387
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -3,7 +3,7 @@
"@saithodev/semantic-release-backmerge": "^4.0.1",
"@semantic-release/changelog": "^6.0.3",
"@semantic-release/git": "^10.0.1",
"gradle-semantic-release-plugin": "^1.9.1",
"semantic-release": "^23.0.8"
"gradle-semantic-release-plugin": "^1.10.1",
"semantic-release": "^24.1.2"
}
}

View File

@@ -0,0 +1,29 @@
@echo off
echo Check, if OpenJDK/ Eclipse Temurin 11 or newer is installed.
pause
echo:
cd modules
call run java -version
cd ..
echo:
set /P INSTALLED_JAVA=Can you see OpenJDK/ Eclipse Temurin 11 or newer? (y/n)
if "%INSTALLED_JAVA%"=="y" (
echo The environment is set up.
pause
exit
)
cls
echo Install Eclipse Temurin JRE 21.
pause
cd modules
call install-java
cd ..
echo The environment is set up. Rerun this script to check your environment.
pause

11
scripts/2-download.bat Normal file
View File

@@ -0,0 +1,11 @@
@echo off
echo Download necessary files from GitHub.
pause
cd modules
call composite download %~dp0\workspace
cd ..
echo Files downloaded.
pause

14
scripts/3-patch.bat Normal file
View File

@@ -0,0 +1,14 @@
@echo off
setlocal
echo Patch an APK with the patches in the workspace.
pause
cd modules
call composite patch %~dp0\workspace
cd ..
mv %~dp0\workspace\patched.apk %~dp0\patched.apk
echo Patched APK saved at %~dp0\patched.apk.
pause

11
scripts/4-cleanup.bat Normal file
View File

@@ -0,0 +1,11 @@
@echo off
echo Clean the workspace.
pause
cd modules
call composite clean %~dp0\workspace
cd ..
echo Cleaned workspace.
pause

8
scripts/README.md Normal file
View File

@@ -0,0 +1,8 @@
# 📜 Scripts
This directory contain click-to-run scripts to use ReVanced CLI.
## Prerequisites
- [cURL](https://curl.haxx.se/)
- [WinGet](https://aka.ms/getwinget), if you are on Windows

1
scripts/customize.bat Normal file
View File

@@ -0,0 +1 @@
notepad modules\env.bat

View File

@@ -0,0 +1,12 @@
@echo off
setlocal
for /f "tokens=8 delims=. " %%a in ('java --version 2^>nul ^| findstr /r "build"') do (
set JAVA_VERSION_MAJOR=%%a
goto :break
)
:break
if %JAVA_VERSION_MAJOR% LSS 11 (
echo It looks like Java version is less than 11. Install OpenJDK/ Eclipse Temurin 11 or newer.
)

View File

@@ -0,0 +1,51 @@
@echo off
setlocal EnableDelayedExpansion
if "%~1"=="" (
set INVALID_ARGS=true
)
if "%~2"=="" (
set INVALID_ARGS=true
)
if defined INVALID_ARGS (
echo Runs curated compositions of scripts.
echo:
echo Usage: composite ^<script^> ^<workspace^>
echo Example: composite patch C:/revanced
echo:
echo Available commands:
echo: download - Download files
echo: patch - Patches an application
echo: clean - Cleans the workspace
echo: env - Check for a valid environment setup
exit /b 1
)
call env
set WORKSPACE=%2
if "%~1"=="download" (
call create %WORKSPACE%
if not exist %WORKSPACE%/revanced-cli.jar (
echo Downloading ReVanced CLI...
call download %CLI_REPO% jar %WORKSPACE%/revanced-cli.jar
)
if not exist %WORKSPACE%/patches.rvp (
echo Downloading ReVanced patches...
call download %PATCHES_REPO% jar %WORKSPACE%/patches.rvp
)
)
if "%~1"=="patch" (
set /p APK="Path to the APK file: "
call patch !APK! %WORKSPACE%
)
if "%~1"=="clean" (
call delete %WORKSPACE%
)
if "%~1"=="env" (
call check-java
)

View File

@@ -0,0 +1,19 @@
@echo off
setlocal
if "%~1"=="" (
set INVALID_ARGS=true
)
if defined INVALID_ARGS (
echo Creates a directory using the mkdir command.
echo:
echo Usage: create ^<path^>
echo Example: create C:/revanced
exit /b 1
)
set DIRECTORY=%1
if not exist %DIRECTORY% (
run "mkdir.exe" -p %DIRECTORY%
)

View File

@@ -0,0 +1,20 @@
@echo off
setlocal
if "%~1"=="" (
set INVALID_ARGS=true
)
if defined INVALID_ARGS (
echo Deletes a directory relative to the current directory using the rmdir command.
echo:
echo Usage: delete ^<path^>
echo Example: delete C:/revanced
exit /b 1
)
set DIRECTORY=%1
if exist %DIRECTORY% (
echo Confirm deletion of
run rmdir /s %DIRECTORY%
)

View File

@@ -0,0 +1,30 @@
@echo off
setlocal
if "%~1"=="" (
set INVALID_ARGS=true
)
if "%~2"=="" (
set INVALID_ARGS=true
)
if "%~3"=="" (
set INVALID_ARGS=true
)
if defined INVALID_ARGS (
echo Downloads a file from a GitHub repository release.
echo:
echo Usage: download ^<repo^> ^<asset-extension^> ^<out^>
echo Example: download revanced/revanced-cli jar C:/revanced/revanced-cli.jar
exit /b 1
)
set REPO=%1
set ASSET_EXTENSION=%2
set OUT=%3
set URL=https://api.github.com/repos/%REPO%/releases/latest
for /f "delims=" %%i in ('curl -s %URL% ^| jq -r ".assets[] | select(.name | endswith(\"%ASSET_EXTENSION%\")) | .browser_download_url"') do (
set JAR_URL=%%i
)
run curl --silent --location --output %OUT% %JAR_URL%

6
scripts/modules/env.bat Normal file
View File

@@ -0,0 +1,6 @@
@echo off
:: Customize your environment.
set CLI_REPO=revanced/revanced-cli
set PATCHES_REPO=revanced/revanced-patches

View File

@@ -0,0 +1 @@
run install EclipseAdoptium.Temurin.21.JRE

View File

@@ -0,0 +1 @@
run install jqlang.jq

View File

@@ -0,0 +1,14 @@
@echo off
if "%~1"=="" (
set INVALID_ARGS=true
)
if defined INVALID_ARGS (
echo Installs a package using winget.
echo:
echo Usage: install ^<id^>
echo Example: install jqlang.jq
exit /b 1
)
run winget install -e --id=%1

28
scripts/modules/patch.bat Normal file
View File

@@ -0,0 +1,28 @@
@echo off
setlocal
if "%~1"=="" (
set INVALID_ARGS=true
)
if "%~2"=="" (
set INVALID_ARGS=true
)
if defined INVALID_ARGS (
echo Patches an application using the specified patches.
echo:
echo Usage: patch ^<apk^> ^<workspace^>
echo Example: patch C:/app.apk C:/workspace
exit /b 1
)
set APK=%1
set WORKSPACE=%2
call run java -jar %WORKSPACE%/revanced-cli.jar patch ^
--patch-bundle %WORKSPACE%/patches.rvp ^
--temporary-files-path %WORKSPACE%/temporary-files ^
--out %WORKSPACE%/patched.apk ^
--purge ^
%APK%
mv %WORKSPACE%/patched.apk

23
scripts/modules/run.bat Normal file
View File

@@ -0,0 +1,23 @@
@echo off
if "%~1"=="" (
set INVALID_ARGS=true
)
if defined INVALID_ARGS (
echo Run a command with arguments.
echo:
echo Usage: run.bat ^<command^> [arguments]
echo Example: run.bat echo Hello, World!
exit /b 1
)
%*
if %ERRORLEVEL% NEQ 0 (
echo:
echo Failed to run command with exit code %ERRORLEVEL%.
echo Failed command: %*
echo:
pause
exit /b %ERRORLEVEL%
)

View File

@@ -12,17 +12,17 @@ import java.util.logging.Logger
name = "list-versions",
description = [
"List the most common compatible versions of apps that are compatible " +
"with the patches in the supplied patch bundles.",
"with the patches from RVP files.",
],
)
internal class ListCompatibleVersions : Runnable {
private val logger = Logger.getLogger(this::class.java.name)
@CommandLine.Parameters(
description = ["Paths to patch bundles."],
description = ["Paths to RVP files."],
arity = "1..*",
)
private lateinit var patchBundles: Set<File>
private lateinit var patchesFiles: Set<File>
@CommandLine.Option(
names = ["-f", "--filter-package-names"],
@@ -56,7 +56,7 @@ internal class ListCompatibleVersions : Runnable {
appendLine(versions.buildVersionsString().prependIndent("\t"))
}
val patches = loadPatchesFromJar(patchBundles)
val patches = loadPatchesFromJar(patchesFiles)
patches.mostCommonCompatibleVersions(
packageNames,

View File

@@ -11,16 +11,16 @@ import app.revanced.patcher.patch.Option as PatchOption
@Command(
name = "list-patches",
description = ["List patches from supplied patch bundles."],
description = ["List patches from supplied RVP files."],
)
internal object ListPatchesCommand : Runnable {
private val logger = Logger.getLogger(this::class.java.name)
@Parameters(
description = ["Paths to patch bundles."],
description = ["Paths to RVP files."],
arity = "1..*",
)
private lateinit var patchBundles: Set<File>
private lateinit var patchesFiles: Set<File>
@Option(
names = ["-d", "--with-descriptions"],
@@ -59,7 +59,7 @@ internal object ListPatchesCommand : Runnable {
@Option(
names = ["-i", "--index"],
description = ["List the index of each patch in relation to the supplied patch bundles."],
description = ["List the index of each patch in relation to the supplied RVP files."],
showDefaultValue = ALWAYS,
)
private var withIndex: Boolean = true
@@ -111,6 +111,8 @@ internal object ListPatchesCommand : Runnable {
if (withDescriptions) append("\nDescription: ${patch.description}")
append("Enabled: ${patch.use}")
if (withOptions && patch.options.isNotEmpty()) {
appendLine("\nOptions:")
append(
@@ -135,7 +137,7 @@ internal object ListPatchesCommand : Runnable {
compatiblePackages?.any { (compatiblePackageName, _) -> compatiblePackageName == name }
?: withUniversalPatches
val patches = loadPatchesFromJar(patchBundles).withIndex().toList()
val patches = loadPatchesFromJar(patchesFiles).withIndex().toList()
val filtered =
packageName?.let { patches.filter { (_, patch) -> patch.filterCompatiblePackages(it) } } ?: patches

View File

@@ -30,27 +30,27 @@ internal object PatchCommand : Runnable {
private lateinit var spec: CommandSpec
@ArgGroup(multiplicity = "0..*")
private lateinit var selection: Set<Selection>
private var selection = mutableSetOf<Selection>()
internal class Selection {
@ArgGroup(exclusive = false, multiplicity = "1")
internal var include: IncludeSelection? = null
internal var enabled: EnableSelection? = null
internal class IncludeSelection {
internal class EnableSelection {
@ArgGroup(multiplicity = "1")
internal lateinit var selector: IncludeSelector
internal lateinit var selector: EnableSelector
internal class IncludeSelector {
internal class EnableSelector {
@CommandLine.Option(
names = ["-i", "--include"],
description = ["The name of the patch."],
names = ["-e", "--enable"],
description = ["Name of the patch."],
required = true,
)
internal var name: String? = null
@CommandLine.Option(
names = ["--ii"],
description = ["The index of the patch in the combined list of all supplied patch bundles."],
names = ["--ei"],
description = ["Index of the patch in the combined list of the supplied RVP files."],
required = true,
)
internal var index: Int? = null
@@ -58,7 +58,7 @@ internal object PatchCommand : Runnable {
@CommandLine.Option(
names = ["-O", "--options"],
description = ["The option values keyed by the option keys."],
description = ["Option values keyed by option keys."],
mapFallbackValue = CommandLine.Option.NULL_VALUE,
converter = [OptionKeyConverter::class, OptionValueConverter::class],
)
@@ -66,23 +66,23 @@ internal object PatchCommand : Runnable {
}
@ArgGroup(exclusive = false, multiplicity = "1")
internal var exclude: ExcludeSelection? = null
internal var disable: DisableSelection? = null
internal class ExcludeSelection {
internal class DisableSelection {
@ArgGroup(multiplicity = "1")
internal lateinit var selector: ExcludeSelector
internal lateinit var selector: DisableSelector
internal class ExcludeSelector {
internal class DisableSelector {
@CommandLine.Option(
names = ["-e", "--exclude"],
description = ["The name of the patch."],
names = ["-d", "--disable"],
description = ["Name of the patch."],
required = true,
)
internal var name: String? = null
@CommandLine.Option(
names = ["--ie"],
description = ["The index of the patch in the combined list of all supplied patch bundles."],
names = ["--di"],
description = ["Index of the patch in the combined list of the supplied RVP files."],
required = true,
)
internal var index: Int? = null
@@ -92,14 +92,14 @@ internal object PatchCommand : Runnable {
@CommandLine.Option(
names = ["--exclusive"],
description = ["Only include patches that are explicitly specified to be included."],
description = ["Disable all patches except the ones enabled."],
showDefaultValue = ALWAYS,
)
private var exclusive = false
@CommandLine.Option(
names = ["-f", "--force"],
description = ["Bypass compatibility checks for the supplied APK's version."],
description = ["Don't check for compatibility with the supplied APK's version."],
showDefaultValue = ALWAYS,
)
private var force: Boolean = false
@@ -108,7 +108,7 @@ internal object PatchCommand : Runnable {
@CommandLine.Option(
names = ["-o", "--out"],
description = ["Path to save the patched APK file to. Defaults to the same directory as the supplied APK file."],
description = ["Path to save the patched APK file to. Defaults to the same path as the supplied APK file."],
)
@Suppress("unused")
private fun setOutputFilePath(outputFilePath: File?) {
@@ -116,8 +116,8 @@ internal object PatchCommand : Runnable {
}
@CommandLine.Option(
names = ["-d", "--device-serial"],
description = ["ADB device serial to install to. If not supplied, the first connected device will be used."],
names = ["-i", "--install"],
description = ["Serial of the ADB device to install to. If not specified, the first connected device will be used."],
// Empty string to indicate that the first connected device should be used.
fallbackValue = "",
arity = "0..1",
@@ -126,7 +126,7 @@ internal object PatchCommand : Runnable {
@CommandLine.Option(
names = ["--mount"],
description = ["Install by mounting the patched APK file."],
description = ["Install the patched APK file by mounting."],
showDefaultValue = ALWAYS,
)
private var mount: Boolean = false
@@ -134,28 +134,28 @@ internal object PatchCommand : Runnable {
@CommandLine.Option(
names = ["--keystore"],
description = [
"Path to the keystore to sign the patched APK file with. " +
"Path to the keystore file containing a private key and certificate pair to sign the patched APK file with. " +
"Defaults to the same directory as the supplied APK file.",
],
)
private var keystoreFilePath: File? = null
private var keyStoreFilePath: File? = null
@CommandLine.Option(
names = ["--keystore-password"],
description = ["The password of the keystore to sign the patched APK file with. Empty password by default."],
description = ["Password of the keystore. Empty password by default."],
)
private var keyStorePassword: String? = null // Empty password by default
@CommandLine.Option(
names = ["--keystore-entry-alias"],
description = ["The alias of the keystore entry to sign the patched APK file with."],
description = ["Alias of the private key and certificate pair keystore entry."],
showDefaultValue = ALWAYS,
)
private var keyStoreEntryAlias = "ReVanced Key"
@CommandLine.Option(
names = ["--keystore-entry-password"],
description = ["The password of the entry from the keystore for the key to sign the patched APK file with."],
description = ["Password of the keystore entry."],
)
private var keyStoreEntryPassword = "" // Empty password by default
@@ -175,15 +175,15 @@ internal object PatchCommand : Runnable {
private var aaptBinaryPath: File? = null
@CommandLine.Option(
names = ["-p", "--purge"],
description = ["Purge the temporary resource cache directory after patching."],
names = ["--purge"],
description = ["Purge temporary files directory after patching."],
showDefaultValue = ALWAYS,
)
private var purge: Boolean = false
@CommandLine.Parameters(
description = ["APK file to be patched."],
arity = "1..1",
description = ["APK file to patch."],
arity = "1",
)
@Suppress("unused")
private fun setApk(apk: File) {
@@ -199,19 +199,19 @@ internal object PatchCommand : Runnable {
private lateinit var apk: File
@CommandLine.Option(
names = ["-b", "--patch-bundle"],
description = ["One or more bundles of patches."],
names = ["-p", "--patches"],
description = ["One or more path to RVP files."],
required = true,
)
@Suppress("unused")
private fun setPatchBundles(patchBundles: Set<File>) {
patchBundles.firstOrNull { !it.exists() }?.let {
throw CommandLine.ParameterException(spec.commandLine(), "Patch bundle ${it.name} does not exist")
private fun setPatchesFile(patchesFiles: Set<File>) {
patchesFiles.firstOrNull { !it.exists() }?.let {
throw CommandLine.ParameterException(spec.commandLine(), "${it.name} can't be found")
}
this.patchBundles = patchBundles
this.patchesFiles = patchesFiles
}
private var patchBundles = emptySet<File>()
private var patchesFiles = emptySet<File>()
@CommandLine.Option(
names = ["--custom-aapt2-binary"],
@@ -242,16 +242,44 @@ internal object PatchCommand : Runnable {
)
val keystoreFilePath =
keystoreFilePath ?: outputFilePath.parentFile
keyStoreFilePath ?: outputFilePath.parentFile
.resolve("${outputFilePath.nameWithoutExtension}.keystore")
val installer = if (deviceSerial != null) {
val deviceSerial = deviceSerial!!.ifEmpty { null }
try {
if (mount) {
AdbRootInstaller(deviceSerial)
} else {
AdbInstaller(deviceSerial)
}
} catch (e: DeviceNotFoundException) {
if (deviceSerial?.isNotEmpty() == true) {
logger.severe(
"Device with serial $deviceSerial not found to install to. " +
"Ensure the device is connected and the serial is correct when using the --install option.",
)
} else {
logger.severe(
"No device has been found to install to. " +
"Ensure a device is connected when using the --install option.",
)
}
return
}
} else {
null
}
// endregion
// region Load patches
logger.info("Loading patches")
val patches = loadPatchesFromJar(patchBundles)
val patches = loadPatchesFromJar(patchesFiles)
// endregion
@@ -274,11 +302,11 @@ internal object PatchCommand : Runnable {
logger.info("Setting patch options")
val patchesList = patches.toList()
selection.filter { it.include != null }.associate {
val includeSelection = it.include!!
selection.filter { it.enabled != null }.associate {
val enabledSelection = it.enabled!!
(includeSelection.selector.name ?: patchesList[includeSelection.selector.index!!].name!!) to
includeSelection.options
(enabledSelection.selector.name ?: patchesList[enabledSelection.selector.index!!].name!!) to
enabledSelection.options
}.let(filteredPatches::setOptions)
patcher += filteredPatches
@@ -332,13 +360,7 @@ internal object PatchCommand : Runnable {
val deviceSerial = it.ifEmpty { null }
runBlocking {
val result = if (mount) {
AdbRootInstaller(deviceSerial)
} else {
AdbInstaller(deviceSerial)
}.install(Installer.Apk(outputFilePath, packageName))
when (result) {
when (val result = installer!!.install(Installer.Apk(outputFilePath, packageName))) {
RootInstallerResult.FAILURE -> logger.severe("Failed to mount the patched APK file")
is AdbInstallerResult.Failure -> logger.severe(result.exception.toString())
else -> logger.info("Installed the patched APK file")
@@ -365,21 +387,21 @@ internal object PatchCommand : Runnable {
packageName: String,
packageVersion: String,
): Set<Patch<*>> = buildSet {
val includedPatchesByName =
selection.asSequence().mapNotNull { it.include?.selector?.name }.toSet()
val includedPatchesByIndex =
selection.asSequence().mapNotNull { it.include?.selector?.index }.toSet()
val enabledPatchesByName =
selection.mapNotNull { it.enabled?.selector?.name }.toSet()
val enabledPatchesByIndex =
selection.mapNotNull { it.enabled?.selector?.index }.toSet()
val excludedPatches =
selection.asSequence().mapNotNull { it.exclude?.selector?.name }.toSet()
val excludedPatchesByIndex =
selection.asSequence().mapNotNull { it.exclude?.selector?.index }.toSet()
val disabledPatches =
selection.mapNotNull { it.disable?.selector?.name }.toSet()
val disabledPatchesByIndex =
selection.mapNotNull { it.disable?.selector?.index }.toSet()
this@filterPatchSelection.withIndex().forEach patchLoop@{ (i, patch) ->
val patchName = patch.name!!
val isManuallyExcluded = patchName in excludedPatches || i in excludedPatchesByIndex
if (isManuallyExcluded) return@patchLoop logger.info("\"$patchName\" excluded manually")
val isManuallyDisabled = patchName in disabledPatches || i in disabledPatchesByIndex
if (isManuallyDisabled) return@patchLoop logger.info("\"$patchName\" disabled manually")
// Make sure the patch is compatible with the supplied APK files package name and version.
patch.compatiblePackages?.let { packages ->
@@ -409,11 +431,11 @@ internal object PatchCommand : Runnable {
return@let
} ?: logger.fine("\"$patchName\" has no package constraints")
val isIncluded = !exclusive && patch.use
val isManuallyIncluded = patchName in includedPatchesByName || i in includedPatchesByIndex
val isEnabled = !exclusive && patch.use
val isManuallyEnabled = patchName in enabledPatchesByName || i in enabledPatchesByIndex
if (!(isIncluded || isManuallyIncluded)) {
return@patchLoop logger.info("\"$patchName\" excluded")
if (!(isEnabled || isManuallyEnabled)) {
return@patchLoop logger.info("\"$patchName\" disabled")
}
add(patch)

View File

@@ -10,27 +10,27 @@ import java.util.logging.Logger
@Command(
name = "install",
description = ["Install an APK file to devices with the supplied ADB device serials"],
description = ["Install an APK file."],
)
internal object InstallCommand : Runnable {
private val logger = Logger.getLogger(this::class.java.name)
@Parameters(
description = ["ADB device serials. If not supplied, the first connected device will be used."],
description = ["Serial of ADB devices. If not supplied, the first connected device will be used."],
arity = "0..*",
)
private var deviceSerials: Array<String>? = null
@Option(
names = ["-a", "--apk"],
description = ["APK file to be installed"],
description = ["APK file to be installed."],
required = true,
)
private lateinit var apk: File
@Option(
names = ["-m", "--mount"],
description = ["Mount the supplied APK file over the app with the supplied package name"],
description = ["Mount the supplied APK file over the app with the supplied package name."],
)
private var packageName: String? = null

View File

@@ -13,27 +13,27 @@ import java.util.logging.Logger
@Command(
name = "uninstall",
description = ["Uninstall a patched app from the devices with the supplied ADB device serials"],
description = ["Uninstall a patched app."],
)
internal object UninstallCommand : Runnable {
private val logger = Logger.getLogger(this::class.java.name)
@Parameters(
description = ["ADB device serials. If not supplied, the first connected device will be used."],
description = ["Serial of ADB devices. If not supplied, the first connected device will be used."],
arity = "0..*",
)
private var deviceSerials: Array<String>? = null
@Option(
names = ["-p", "--package-name"],
description = ["Package name of the app to uninstall"],
description = ["Package name of the app to uninstall."],
required = true,
)
private lateinit var packageName: String
@Option(
names = ["-u", "--unmount"],
description = ["Uninstall by unmounting the patched APK file"],
description = ["Uninstall the patched APK file by unmounting."],
showDefaultValue = ALWAYS,
)
private var unmount: Boolean = false