mirror of
https://github.com/ReVanced/revanced-cli.git
synced 2026-01-11 13:56:18 +00:00
Compare commits
397 Commits
v2.11.2
...
v4.4.0-dev
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2d17459fa3 | ||
|
|
16109bd8bc | ||
|
|
09bc652317 | ||
|
|
1d051365f3 | ||
|
|
ab7d9d8e1e | ||
|
|
5e089ea9af | ||
|
|
06c6a97915 | ||
|
|
a974b8ea80 | ||
|
|
89c35ee21b | ||
|
|
41bdb04ab0 | ||
|
|
a5542467c8 | ||
|
|
5fd205f77d | ||
|
|
e7c3d64bf1 | ||
|
|
3765957043 | ||
|
|
5e63e0a276 | ||
|
|
36c6a6a5f7 | ||
|
|
860fb7b957 | ||
|
|
9d96bb7b4c | ||
|
|
3afa590616 | ||
|
|
db0b943ad3 | ||
|
|
8c3d4d3aa1 | ||
|
|
04d312df31 | ||
|
|
158f59ab88 | ||
|
|
a078b53a21 | ||
|
|
fb75b0f115 | ||
|
|
c52383eca0 | ||
|
|
0562ee85c5 | ||
|
|
1cde672a05 | ||
|
|
d5419dbb6b | ||
|
|
d29016b428 | ||
|
|
1eb51e9d4f | ||
|
|
86b8415ac6 | ||
|
|
8f4aebc60b | ||
|
|
bd3171c7c5 | ||
|
|
6481ba68db | ||
|
|
799882e6a6 | ||
|
|
616d14f009 | ||
|
|
b2055ce07d | ||
|
|
4fc42089a5 | ||
|
|
0139dfe0bf | ||
|
|
7d1c0e663f | ||
|
|
6cc6960493 | ||
|
|
9f15ac6ec5 | ||
|
|
6670d89c74 | ||
|
|
a60d07fc5d | ||
|
|
362e6f5904 | ||
|
|
51402ab8a7 | ||
|
|
a8c8682116 | ||
|
|
a86919eb71 | ||
|
|
8b04b6790b | ||
|
|
59dfc988e3 | ||
|
|
b01fef730a | ||
|
|
a564aaa1b5 | ||
|
|
f315485713 | ||
|
|
28648a1c53 | ||
|
|
daac98817f | ||
|
|
9328475e11 | ||
|
|
6507b5fe8a | ||
|
|
349ff5749a | ||
|
|
495735f44c | ||
|
|
f48da18e37 | ||
|
|
cf58f55b38 | ||
|
|
da4469f402 | ||
|
|
df2c137ae9 | ||
|
|
8a2f219f8b | ||
|
|
719d9fcfa3 | ||
|
|
6c44a730c3 | ||
|
|
ba573f73d0 | ||
|
|
e95a392016 | ||
|
|
fc62f7f475 | ||
|
|
ff2e10dbe6 | ||
|
|
7ff433860d | ||
|
|
7121e5fa4c | ||
|
|
23b5e8b7f9 | ||
|
|
d1c4d8df3e | ||
|
|
89acffe788 | ||
|
|
64d9127291 | ||
|
|
e3c55507cf | ||
|
|
64afc95a81 | ||
|
|
022fd230f6 | ||
|
|
a177693ece | ||
|
|
4b6dbffd7b | ||
|
|
78e89dd3bf | ||
|
|
a08530d47b | ||
|
|
eec2234226 | ||
|
|
d5ea5a0ab1 | ||
|
|
6fc3eebc21 | ||
|
|
c84041f942 | ||
|
|
995f2ec99b | ||
|
|
84b24f1b6f | ||
|
|
95a974a5ac | ||
|
|
ee6d883777 | ||
|
|
b65e4083d6 | ||
|
|
e46d855643 | ||
|
|
80a8d88406 | ||
|
|
50c0f98ce5 | ||
|
|
77d91735ff | ||
|
|
3846f721ca | ||
|
|
f199298317 | ||
|
|
592dc1c64a | ||
|
|
8da0c2bdfe | ||
|
|
e8e69aaf5a | ||
|
|
157278c9ba | ||
|
|
049a385473 | ||
|
|
e7c9da7c33 | ||
|
|
67bf8c1849 | ||
|
|
075f6ad565 | ||
|
|
6942b22a68 | ||
|
|
ac5742dd6c | ||
|
|
a022febd0c | ||
|
|
978032cce1 | ||
|
|
52c5259451 | ||
|
|
43fc20d90e | ||
|
|
e3851d58c8 | ||
|
|
3e13fb5d56 | ||
|
|
db50cee12c | ||
|
|
578e16b099 | ||
|
|
1319ab7629 | ||
|
|
2a08af3cb9 | ||
|
|
7794327a11 | ||
|
|
2b77608651 | ||
|
|
d09aca65df | ||
|
|
c8d4f56d61 | ||
|
|
c67e3c70c7 | ||
|
|
05878a6e06 | ||
|
|
29bc0e8df8 | ||
|
|
c4a89e39b9 | ||
|
|
847e384d9e | ||
|
|
96c196dcb1 | ||
|
|
dfd535c201 | ||
|
|
2b6051e7f3 | ||
|
|
0304988733 | ||
|
|
ca809f0948 | ||
|
|
5d50d1a622 | ||
|
|
83c28d9f71 | ||
|
|
93cbcc28aa | ||
|
|
3b3f7c7a7a | ||
|
|
bbb1a63abd | ||
|
|
f7fcbc55bb | ||
|
|
9fe5a0b6d9 | ||
|
|
4f2d2568d3 | ||
|
|
a3d8f004ec | ||
|
|
41ffc99ad0 | ||
|
|
1121376018 | ||
|
|
48e1689223 | ||
|
|
7580f5c2fc | ||
|
|
dd6c1392eb | ||
|
|
2a3dbafd17 | ||
|
|
9e39a6f8e4 | ||
|
|
2d5a7fdf1e | ||
|
|
be5d812dff | ||
|
|
c93186fb97 | ||
|
|
3a198052bb | ||
|
|
0f3e090418 | ||
|
|
6aed946183 | ||
|
|
924c1f80ec | ||
|
|
8dd709b6ef | ||
|
|
139e7facac | ||
|
|
1d26e572f7 | ||
|
|
2c7fcaf4ad | ||
|
|
52c3be23f2 | ||
|
|
3dd875d14c | ||
|
|
0350b7f1a2 | ||
|
|
a3d8705e89 | ||
|
|
a536c9f815 | ||
|
|
11c3a6cfd4 | ||
|
|
a5851f0c1a | ||
|
|
963ae3a5fa | ||
|
|
93f338a731 | ||
|
|
7dcf15e03b | ||
|
|
41898d7547 | ||
|
|
45dd15f679 | ||
|
|
c2da04a834 | ||
|
|
f556909b9e | ||
|
|
1fa3dd7b8c | ||
|
|
1fcc591222 | ||
|
|
1fd3b83d46 | ||
|
|
7ec9040d41 | ||
|
|
44cc88b25d | ||
|
|
97548f80b3 | ||
|
|
d766f0e229 | ||
|
|
b0e748daff | ||
|
|
ba758f00f4 | ||
|
|
a9c2a5f096 | ||
|
|
0dcd838de3 | ||
|
|
a7290353bf | ||
|
|
47a20afd2d | ||
|
|
f8972eac3e | ||
|
|
9edbbf3163 | ||
|
|
32da961d57 | ||
|
|
8a5daab2a3 | ||
|
|
c0cc909626 | ||
|
|
b74213f66e | ||
|
|
fe75d4ab87 | ||
|
|
07da528ce2 | ||
|
|
ef5fa9b4c9 | ||
|
|
fc359923e3 | ||
|
|
2e3cd90537 | ||
|
|
7174364ef8 | ||
|
|
4c9d414228 | ||
|
|
5e73e6d2de | ||
|
|
667ca3051c | ||
|
|
9220642a7b | ||
|
|
3f47235c64 | ||
|
|
83b475c2e3 | ||
|
|
4105b638c0 | ||
|
|
f9cf7d21b7 | ||
|
|
0a758d86df | ||
|
|
83f99e29ec | ||
|
|
00410d54c0 | ||
|
|
5eaad33dc1 | ||
|
|
fa85482c4a | ||
|
|
caed39af7f | ||
|
|
20e1fdc18d | ||
|
|
19cd541e9a | ||
|
|
f6c221d72d | ||
|
|
9c148c96bf | ||
|
|
2c5b53c7e9 | ||
|
|
77d9cb98d1 | ||
|
|
38677e2319 | ||
|
|
e5e768fa34 | ||
|
|
9082181ce5 | ||
|
|
542580ecff | ||
|
|
26112a4fd2 | ||
|
|
553fbdbb8f | ||
|
|
be429a4770 | ||
|
|
8c391cecce | ||
|
|
bd14bdb5ea | ||
|
|
d0fc886428 | ||
|
|
1ccbed8d17 | ||
|
|
3b89fb7bc2 | ||
|
|
16bb1a60fc | ||
|
|
5f1843771e | ||
|
|
9de90703c8 | ||
|
|
1201f9edc5 | ||
|
|
9c8f9608b2 | ||
|
|
be90d2e360 | ||
|
|
79dc99aa9b | ||
|
|
260ff00951 | ||
|
|
cfe4c5ed0e | ||
|
|
7133242691 | ||
|
|
55750ce16a | ||
|
|
6003e68d47 | ||
|
|
9f8c2aeedf | ||
|
|
0a16bc849b | ||
|
|
ecd5147590 | ||
|
|
ca255c9e1b | ||
|
|
e9aa490355 | ||
|
|
69fe59f97b | ||
|
|
995e1712bc | ||
|
|
a236f10bb0 | ||
|
|
4a6134ea60 | ||
|
|
b084024742 | ||
|
|
2ef48af1b3 | ||
|
|
da2c91874d | ||
|
|
379687c814 | ||
|
|
2f5577e464 | ||
|
|
6962fc2f4c | ||
|
|
a6cef26210 | ||
|
|
b4892c4413 | ||
|
|
90368405ad | ||
|
|
26967959e2 | ||
|
|
eac6f6fbe3 | ||
|
|
af4ec43352 | ||
|
|
4f5644b62c | ||
|
|
31fb3166d9 | ||
|
|
a76bd0ad35 | ||
|
|
ba07ab1ac2 | ||
|
|
92bf57f279 | ||
|
|
886d501026 | ||
|
|
4b04cc4b59 | ||
|
|
75d237058f | ||
|
|
40026fe300 | ||
|
|
dbec559ed7 | ||
|
|
00e49719ca | ||
|
|
df276846e1 | ||
|
|
ac3a8f66f7 | ||
|
|
e900ce8486 | ||
|
|
ee6dd5a57c | ||
|
|
23d9e1e841 | ||
|
|
3718b7992c | ||
|
|
bce5e86874 | ||
|
|
cda6df6238 | ||
|
|
0dc230292a | ||
|
|
695cd1ba41 | ||
|
|
d08bbf8664 | ||
|
|
d55dd0a1fc | ||
|
|
a53d3482de | ||
|
|
7a3d0420f7 | ||
|
|
5cddf5004e | ||
|
|
6393a5016a | ||
|
|
cad38ca3bd | ||
|
|
6c1169b433 | ||
|
|
bf2bb72ce0 | ||
|
|
567bdee887 | ||
|
|
9888b0e08e | ||
|
|
51c04b7b16 | ||
|
|
a39cf893d6 | ||
|
|
6485e477a1 | ||
|
|
f99d340534 | ||
|
|
4edc325978 | ||
|
|
cffa1ea3a4 | ||
|
|
d15505adaa | ||
|
|
aaf452a103 | ||
|
|
1753a1aa3e | ||
|
|
f4e74cb4f2 | ||
|
|
50df4e117e | ||
|
|
9fcd2b4cd1 | ||
|
|
e6bb05c0b9 | ||
|
|
6bd7d42e32 | ||
|
|
19200eacc1 | ||
|
|
666738ee57 | ||
|
|
961267b8cd | ||
|
|
6b7314a399 | ||
|
|
c8a47c51df | ||
|
|
72d8f73d7f | ||
|
|
1957a2c4ff | ||
|
|
07a423b19e | ||
|
|
31e4a41dd2 | ||
|
|
8284c1048f | ||
|
|
9c64f5ec3e | ||
|
|
f4c447e71b | ||
|
|
b69e784785 | ||
|
|
ccce9c926d | ||
|
|
dc4ab22f41 | ||
|
|
25d8ad4aaf | ||
|
|
3d9436e691 | ||
|
|
ee70423527 | ||
|
|
d5794b94ca | ||
|
|
3160d894da | ||
|
|
545597959a | ||
|
|
a6db0edc70 | ||
|
|
ff0d3dd224 | ||
|
|
d9a1fd33ed | ||
|
|
ad81a1b656 | ||
|
|
8c2aeff2cf | ||
|
|
eb6c659f5b | ||
|
|
bac4f839c9 | ||
|
|
c1e7215d31 | ||
|
|
18d132123f | ||
|
|
74d73ca3a7 | ||
|
|
ae91b0d597 | ||
|
|
1a67cd81da | ||
|
|
9b9fad7cc0 | ||
|
|
1620305b4a | ||
|
|
d906edbe78 | ||
|
|
4e53638cb9 | ||
|
|
7d1f200621 | ||
|
|
a7db6cb8f1 | ||
|
|
d61ab058da | ||
|
|
235c2742ec | ||
|
|
8a964efd00 | ||
|
|
8114d1dca0 | ||
|
|
5a7cadd96d | ||
|
|
1c5983b803 | ||
|
|
2c7eb7274c | ||
|
|
512152fb66 | ||
|
|
8793b5fc65 | ||
|
|
39c490d6b7 | ||
|
|
6e703eb8e8 | ||
|
|
c677eb9792 | ||
|
|
75c8ea4639 | ||
|
|
b69dd52ca9 | ||
|
|
c590bf559c | ||
|
|
ec0b847419 | ||
|
|
b3cf32e89d | ||
|
|
8a1199ba9a | ||
|
|
25b45800a1 | ||
|
|
2fe3303a27 | ||
|
|
04339f0654 | ||
|
|
456428a836 | ||
|
|
c9ae379c77 | ||
|
|
81d702949c | ||
|
|
39e377bc48 | ||
|
|
fce40421e9 | ||
|
|
cb554c8bdf | ||
|
|
269c753dfa | ||
|
|
6403e34712 | ||
|
|
f68e7697ff | ||
|
|
64b7e86252 | ||
|
|
7be9af0942 | ||
|
|
6a35cf7ea4 | ||
|
|
4914fd37bc | ||
|
|
38052b6ecf | ||
|
|
6e21d81964 | ||
|
|
3a733e5137 | ||
|
|
4f4e1f9834 | ||
|
|
e035d93d2c | ||
|
|
839854d890 | ||
|
|
43c772c98d | ||
|
|
b6dff6d832 | ||
|
|
29b057dead | ||
|
|
7df4a7e7da | ||
|
|
07c09f092c | ||
|
|
e8c9c80349 | ||
|
|
467d8387e6 | ||
|
|
65637c8b3a |
9
.gitattributes
vendored
Normal file
9
.gitattributes
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
#
|
||||
# https://help.github.com/articles/dealing-with-line-endings/
|
||||
#
|
||||
# Linux start script should use lf
|
||||
/gradlew text eol=lf
|
||||
|
||||
# These are Windows script files and should use crlf
|
||||
*.bat text eol=crlf
|
||||
|
||||
73
.github/ISSUE_TEMPLATE/bug-issue.yml
vendored
73
.github/ISSUE_TEMPLATE/bug-issue.yml
vendored
@@ -1,73 +0,0 @@
|
||||
name: 🐞 Bug report
|
||||
description: Report a very clearly broken issue.
|
||||
title: 'bug: <title>'
|
||||
labels: [bug]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
# ReVanced bug report
|
||||
|
||||
Important to note that your issue may have already been reported before. Please check for existing issues [here](https://github.com/revanced/revanced-cli/labels/bug).
|
||||
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: Type
|
||||
options:
|
||||
- Error while running the CLI
|
||||
- Error at runtime
|
||||
- Cosmetic
|
||||
- Other
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Bug description
|
||||
description: How did you find the bug? Any additional details that might help?
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Steps to reproduce
|
||||
description: Add the steps to reproduce this bug including your environment.
|
||||
placeholder: Step 1. Download some files. Step 2. ...
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Relevant log output
|
||||
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
|
||||
render: shell
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Screenshots or videos
|
||||
description: Add screenshots or videos that show the bug here.
|
||||
placeholder: Drag and drop the screenshots/videos into this box.
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Solution
|
||||
description: If applicable, add a possible solution.
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Additional context
|
||||
description: Add additional context here.
|
||||
validations:
|
||||
required: false
|
||||
- type: checkboxes
|
||||
id: acknowledgements
|
||||
attributes:
|
||||
label: Acknowledgements
|
||||
description: Your issue will be closed if you haven't done these steps.
|
||||
options:
|
||||
- label: I have searched the existing issues and this is a new and no duplicate or related to another open issue.
|
||||
required: true
|
||||
- label: I have written a short but informative title.
|
||||
required: true
|
||||
- label: I filled out all of the requested information in this issue properly.
|
||||
required: true
|
||||
110
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
Normal file
110
.github/ISSUE_TEMPLATE/bug-report.yml
vendored
Normal file
@@ -0,0 +1,110 @@
|
||||
name: 🐞 Bug report
|
||||
description: Report a bug or an issue.
|
||||
title: 'bug: '
|
||||
labels: ['Bug report']
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
<p align="center">
|
||||
<picture>
|
||||
<source
|
||||
width="256px"
|
||||
media="(prefers-color-scheme: dark)"
|
||||
srcset="https://raw.githubusercontent.com/revanced/revanced-cli/main/assets/revanced-headline/revanced-headline-vertical-dark.svg"
|
||||
>
|
||||
<img
|
||||
width="256px"
|
||||
src="https://raw.githubusercontent.com/revanced/revanced-cli/main/assets/revanced-headline/revanced-headline-vertical-light.svg"
|
||||
>
|
||||
</picture>
|
||||
<br>
|
||||
<a href="https://revanced.app/">
|
||||
<picture>
|
||||
<source height="24px" media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/revanced/revanced-cli/main/assets/revanced-logo/revanced-logo.svg" />
|
||||
<img height="24px" src="https://raw.githubusercontent.com/revanced/revanced-cli/main/assets/revanced-logo/revanced-logo.svg" />
|
||||
</picture>
|
||||
</a>
|
||||
<a href="https://github.com/ReVanced">
|
||||
<picture>
|
||||
<source height="24px" media="(prefers-color-scheme: dark)" srcset="https://i.ibb.co/dMMmCrW/Git-Hub-Mark.png" />
|
||||
<img height="24px" src="https://i.ibb.co/9wV3HGF/Git-Hub-Mark-Light.png" />
|
||||
</picture>
|
||||
</a>
|
||||
<a href="http://revanced.app/discord">
|
||||
<picture>
|
||||
<source height="24px" media="(prefers-color-scheme: dark)" srcset="https://user-images.githubusercontent.com/13122796/178032563-d4e084b7-244e-4358-af50-26bde6dd4996.png" />
|
||||
<img height="24px" src="https://user-images.githubusercontent.com/13122796/178032563-d4e084b7-244e-4358-af50-26bde6dd4996.png" />
|
||||
</picture>
|
||||
</a>
|
||||
<a href="https://reddit.com/r/revancedapp">
|
||||
<picture>
|
||||
<source height="24px" media="(prefers-color-scheme: dark)" srcset="https://user-images.githubusercontent.com/13122796/178032351-9d9d5619-8ef7-470a-9eec-2744ece54553.png" />
|
||||
<img height="24px" src="https://user-images.githubusercontent.com/13122796/178032351-9d9d5619-8ef7-470a-9eec-2744ece54553.png" />
|
||||
</picture>
|
||||
</a>
|
||||
<a href="https://t.me/app_revanced">
|
||||
<picture>
|
||||
<source height="24px" media="(prefers-color-scheme: dark)" srcset="https://user-images.githubusercontent.com/13122796/178032213-faf25ab8-0bc3-4a94-a730-b524c96df124.png" />
|
||||
<img height="24px" src="https://user-images.githubusercontent.com/13122796/178032213-faf25ab8-0bc3-4a94-a730-b524c96df124.png" />
|
||||
</picture>
|
||||
</a>
|
||||
<a href="https://x.com/revancedapp">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://user-images.githubusercontent.com/93124920/270180600-7c1b38bf-889b-4d68-bd5e-b9d86f91421a.png">
|
||||
<img height="24px" src="https://user-images.githubusercontent.com/93124920/270108715-d80743fa-b330-4809-b1e6-79fbdc60d09c.png" />
|
||||
</picture>
|
||||
</a>
|
||||
<a href="https://www.youtube.com/@ReVanced">
|
||||
<picture>
|
||||
<source height="24px" media="(prefers-color-scheme: dark)" srcset="https://user-images.githubusercontent.com/13122796/178032714-c51c7492-0666-44ac-99c2-f003a695ab50.png" />
|
||||
<img height="24px" src="https://user-images.githubusercontent.com/13122796/178032714-c51c7492-0666-44ac-99c2-f003a695ab50.png" />
|
||||
</picture>
|
||||
</a>
|
||||
<br>
|
||||
<br>
|
||||
Continuing the legacy of Vanced
|
||||
</p>
|
||||
|
||||
# ReVanced CLI bug report
|
||||
|
||||
Before creating a new bug report, please keep the following in mind:
|
||||
|
||||
- **Do not submit a duplicate bug report**: You can review existing bug reports [here](https://github.com/ReVanced/revanced-cli/labels/Bug%20report).
|
||||
- **Review the contribution guidelines**: Make sure your bug report adheres to it. You can find the guidelines [here](https://github.com/ReVanced/revanced-cli/blob/main/CONTRIBUTING.md).
|
||||
- **Do not use the issue page for support**: If you need help or have questions, check out other platforms on [revanced.app](https://revanced.app).
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Bug description
|
||||
description: |
|
||||
- Describe your bug in detail
|
||||
- Add steps to reproduce the bug if possible (Step 1. ... Step 2. ...)
|
||||
- Add images and videos if possible
|
||||
- List used patches if applicable
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Error logs
|
||||
description: Exceptions can be captured by running `logcat | grep AndroidRuntime` in a shell.
|
||||
render: shell
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Solution
|
||||
description: If applicable, add a possible solution to the bug.
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Additional context
|
||||
description: Add additional context here.
|
||||
- type: checkboxes
|
||||
id: acknowledgements
|
||||
attributes:
|
||||
label: Acknowledgements
|
||||
description: Your bug report will be closed if you don't follow the checklist below.
|
||||
options:
|
||||
- label: This issue is not a duplicate of an existing bug report.
|
||||
required: true
|
||||
- label: I have chosen an appropriate title.
|
||||
required: true
|
||||
- label: All requested information has been provided properly.
|
||||
required: true
|
||||
5
.github/ISSUE_TEMPLATE/config.yml
vendored
5
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -1,8 +1,5 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: 📃 Documentation
|
||||
url: https://github.com/revanced/revanced-documentation/
|
||||
about: Don't know how or where to start? Check out our documentation!
|
||||
- name: 🗨 Discussions
|
||||
url: https://github.com/revanced/revanced-suggestions/discussions
|
||||
about: Got something you think should change or be added? Search for or start a new discussion!
|
||||
about: Have something unspecific to ReVanced CLI in mind? Search for or start a new discussion!
|
||||
58
.github/ISSUE_TEMPLATE/feature-issue.yml
vendored
58
.github/ISSUE_TEMPLATE/feature-issue.yml
vendored
@@ -1,58 +0,0 @@
|
||||
name: ⭐ Feature request
|
||||
description: Create a detailed feature request.
|
||||
title: 'feat: <title>'
|
||||
labels: [feature-request]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
# ReVanced feature request
|
||||
|
||||
Do not submit requests for patches here. Please submit them [here](https://github.com/orgs/revanced/discussions/categories/patches) instead.
|
||||
Important to note that your feature request may have already been made before. Please check for existing feature requests [here](https://github.com/revanced/revanced-cli/labels/feature-request).
|
||||
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: Type
|
||||
options:
|
||||
- Functionality
|
||||
- Cosmetic
|
||||
- Other
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Issue
|
||||
description: What is the current problem. Why does it require a feature request?
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Feature
|
||||
description: Describe your feature in detail. How does it solve the issue?
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Motivation
|
||||
description: Why should your feature should be considered?
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Additional context
|
||||
description: Add additional context here.
|
||||
validations:
|
||||
required: false
|
||||
- type: checkboxes
|
||||
id: acknowledgements
|
||||
attributes:
|
||||
label: Acknowledgements
|
||||
description: Your issue will be closed if you haven't done these steps.
|
||||
options:
|
||||
- label: I have searched the existing issues and this is a new and no duplicate or related to another open issue.
|
||||
required: true
|
||||
- label: I have written a short but informative title.
|
||||
required: true
|
||||
- label: I filled out all of the requested information in this issue properly.
|
||||
required: true
|
||||
106
.github/ISSUE_TEMPLATE/feature-request.yml
vendored
Normal file
106
.github/ISSUE_TEMPLATE/feature-request.yml
vendored
Normal file
@@ -0,0 +1,106 @@
|
||||
name: ⭐ Feature request
|
||||
description: Create a detailed request for a new feature.
|
||||
title: 'feat: '
|
||||
labels: ['Feature request']
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
<p align="center">
|
||||
<picture>
|
||||
<source
|
||||
width="256px"
|
||||
media="(prefers-color-scheme: dark)"
|
||||
srcset="https://raw.githubusercontent.com/revanced/revanced-cli/main/assets/revanced-headline/revanced-headline-vertical-dark.svg"
|
||||
>
|
||||
<img
|
||||
width="256px"
|
||||
src="https://raw.githubusercontent.com/revanced/revanced-cli/main/assets/revanced-headline/revanced-headline-vertical-light.svg"
|
||||
>
|
||||
</picture>
|
||||
<br>
|
||||
<a href="https://revanced.app/">
|
||||
<picture>
|
||||
<source height="24px" media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/revanced/revanced-cli/main/assets/revanced-logo/revanced-logo.svg" />
|
||||
<img height="24px" src="https://raw.githubusercontent.com/revanced/revanced-cli/main/assets/revanced-logo/revanced-logo.svg" />
|
||||
</picture>
|
||||
</a>
|
||||
<a href="https://github.com/ReVanced">
|
||||
<picture>
|
||||
<source height="24px" media="(prefers-color-scheme: dark)" srcset="https://i.ibb.co/dMMmCrW/Git-Hub-Mark.png" />
|
||||
<img height="24px" src="https://i.ibb.co/9wV3HGF/Git-Hub-Mark-Light.png" />
|
||||
</picture>
|
||||
</a>
|
||||
<a href="http://revanced.app/discord">
|
||||
<picture>
|
||||
<source height="24px" media="(prefers-color-scheme: dark)" srcset="https://user-images.githubusercontent.com/13122796/178032563-d4e084b7-244e-4358-af50-26bde6dd4996.png" />
|
||||
<img height="24px" src="https://user-images.githubusercontent.com/13122796/178032563-d4e084b7-244e-4358-af50-26bde6dd4996.png" />
|
||||
</picture>
|
||||
</a>
|
||||
<a href="https://reddit.com/r/revancedapp">
|
||||
<picture>
|
||||
<source height="24px" media="(prefers-color-scheme: dark)" srcset="https://user-images.githubusercontent.com/13122796/178032351-9d9d5619-8ef7-470a-9eec-2744ece54553.png" />
|
||||
<img height="24px" src="https://user-images.githubusercontent.com/13122796/178032351-9d9d5619-8ef7-470a-9eec-2744ece54553.png" />
|
||||
</picture>
|
||||
</a>
|
||||
<a href="https://t.me/app_revanced">
|
||||
<picture>
|
||||
<source height="24px" media="(prefers-color-scheme: dark)" srcset="https://user-images.githubusercontent.com/13122796/178032213-faf25ab8-0bc3-4a94-a730-b524c96df124.png" />
|
||||
<img height="24px" src="https://user-images.githubusercontent.com/13122796/178032213-faf25ab8-0bc3-4a94-a730-b524c96df124.png" />
|
||||
</picture>
|
||||
</a>
|
||||
<a href="https://x.com/revancedapp">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://user-images.githubusercontent.com/93124920/270180600-7c1b38bf-889b-4d68-bd5e-b9d86f91421a.png">
|
||||
<img height="24px" src="https://user-images.githubusercontent.com/93124920/270108715-d80743fa-b330-4809-b1e6-79fbdc60d09c.png" />
|
||||
</picture>
|
||||
</a>
|
||||
<a href="https://www.youtube.com/@ReVanced">
|
||||
<picture>
|
||||
<source height="24px" media="(prefers-color-scheme: dark)" srcset="https://user-images.githubusercontent.com/13122796/178032714-c51c7492-0666-44ac-99c2-f003a695ab50.png" />
|
||||
<img height="24px" src="https://user-images.githubusercontent.com/13122796/178032714-c51c7492-0666-44ac-99c2-f003a695ab50.png" />
|
||||
</picture>
|
||||
</a>
|
||||
<br>
|
||||
<br>
|
||||
Continuing the legacy of Vanced
|
||||
</p>
|
||||
|
||||
# ReVanced CLI feature request
|
||||
|
||||
Before creating a new feature request, please keep the following in mind:
|
||||
|
||||
- **Do not submit a duplicate feature request**: You can review existing feature requests [here](https://github.com/ReVanced/revanced-cli//labels/Feature%20request).
|
||||
- **Review the contribution guidelines**: Make sure your bug report adheres to it. You can find the guidelines [here](https://github.com/ReVanced/revanced-cli//blob/main/CONTRIBUTING.md).
|
||||
- **Do not use the issue page for support**: If you need help or have questions, check out other platforms on [revanced.app](https://revanced.app).
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Feature description
|
||||
description: |
|
||||
- Describe your feature in detail
|
||||
- Add images, videos, links, examples, references, etc. if possible
|
||||
- Add the target application name in case you request a new patch
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Motivation
|
||||
description: |
|
||||
A strong motivation is necessary for a feature request to be considered.
|
||||
|
||||
- Why should this feature be implemented?
|
||||
- What is the explicit use case?
|
||||
- What are the benefits?
|
||||
- What makes this feature important?
|
||||
validations:
|
||||
required: true
|
||||
- type: checkboxes
|
||||
id: acknowledgements
|
||||
attributes:
|
||||
label: Acknowledgements
|
||||
description: Your feature request will be closed if you don't follow the checklist below.
|
||||
options:
|
||||
- label: This issue is not a duplicate of an existing feature request.
|
||||
required: true
|
||||
- label: I have chosen an appropriate title.
|
||||
required: true
|
||||
- label: All requested information has been provided properly.
|
||||
required: true
|
||||
2
.github/config.yml
vendored
Normal file
2
.github/config.yml
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
firstPRMergeComment: >
|
||||
Thank you for contributing to ReVanced. Join us on [Discord](https://revanced.app/discord) to receive a role for your contribution.
|
||||
26
.github/workflows/pull_request.yml
vendored
Normal file
26
.github/workflows/pull_request.yml
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
name: Open a PR to main
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- dev
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
MESSAGE: Merge branch `${{ github.head_ref || github.ref_name }}` to `main`
|
||||
|
||||
jobs:
|
||||
pull-request:
|
||||
name: Open pull request
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Open pull request
|
||||
uses: repo-sync/pull-request@v2
|
||||
with:
|
||||
destination_branch: 'main'
|
||||
pr_title: 'chore: ${{ env.MESSAGE }}'
|
||||
pr_body: 'This pull request will ${{ env.MESSAGE }}.'
|
||||
pr_draft: true
|
||||
39
.github/workflows/release.yml
vendored
39
.github/workflows/release.yml
vendored
@@ -1,4 +1,5 @@
|
||||
name: Release
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
@@ -9,32 +10,40 @@ on:
|
||||
branches:
|
||||
- main
|
||||
- dev
|
||||
|
||||
jobs:
|
||||
release:
|
||||
name: Release
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
# Make sure the release step uses its own credentials:
|
||||
# https://github.com/cycjimmy/semantic-release-action#private-packages
|
||||
persist-credentials: false
|
||||
fetch-depth: 0
|
||||
- name: Setup JDK
|
||||
uses: actions/setup-java@v2
|
||||
|
||||
- name: Cache Node modules
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
java-version: '17'
|
||||
distribution: 'adopt'
|
||||
cache: gradle
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v2
|
||||
with:
|
||||
node-version: "lts/*"
|
||||
- name: Build with Gradle
|
||||
path: |
|
||||
node_modules
|
||||
key: npm-${{ hashFiles('package-lock.json') }}
|
||||
|
||||
- name: Cache Gradle
|
||||
uses: burrunan/gradle-cache-action@v1
|
||||
|
||||
- name: Build
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: ./gradlew build clean
|
||||
# Cleaning is necessary to avoid uploading two identical artifacts with different versions
|
||||
run: ./gradlew clean --no-daemon
|
||||
|
||||
- name: Setup semantic-release
|
||||
run: npm install -g semantic-release @semantic-release/git @semantic-release/changelog gradle-semantic-release-plugin -D
|
||||
run: npm install
|
||||
|
||||
- name: Release
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: npx semantic-release
|
||||
GITHUB_TOKEN: ${{ secrets.REPOSITORY_PUSH_ACCESS }}
|
||||
run: npm exec semantic-release
|
||||
|
||||
19
.github/workflows/update-documentation.yml
vendored
Normal file
19
.github/workflows/update-documentation.yml
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
name: Update documentation
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- docs/**
|
||||
|
||||
jobs:
|
||||
trigger:
|
||||
runs-on: ubuntu-latest
|
||||
name: Dispatch event to documentation repository
|
||||
if: github.ref == 'refs/heads/main'
|
||||
steps:
|
||||
- uses: peter-evans/repository-dispatch@v2
|
||||
with:
|
||||
token: ${{ secrets.DOCUMENTATION_REPO_ACCESS_TOKEN }}
|
||||
repository: revanced/revanced-documentation
|
||||
event-type: update-documentation
|
||||
client-payload: '{"repo": "${{ github.event.repository.name }}", "ref": "${{ github.ref }}"}'
|
||||
10
.gitignore
vendored
10
.gitignore
vendored
@@ -74,6 +74,7 @@ cmake-build-*/
|
||||
|
||||
# IntelliJ
|
||||
out/
|
||||
.idea
|
||||
|
||||
# mpeltonen/sbt-idea plugin
|
||||
.idea_modules/
|
||||
@@ -111,4 +112,11 @@ gradle-app.setting
|
||||
.gradletasknamecache
|
||||
|
||||
# # Work around https://youtrack.jetbrains.com/issue/IDEA-116898
|
||||
# gradle/wrapper/gradle-wrapper.properties
|
||||
# gradle/wrapper/gradle-wrapper.properties
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
|
||||
# ReVanced CLI
|
||||
revanced-cache/
|
||||
options.toml
|
||||
9
.idea/.gitignore
generated
vendored
9
.idea/.gitignore
generated
vendored
@@ -1,9 +0,0 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
||||
/kotlinc.xml
|
||||
7
.idea/discord.xml
generated
7
.idea/discord.xml
generated
@@ -1,7 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="DiscordProjectSettings">
|
||||
<option name="show" value="PROJECT_FILES" />
|
||||
<option name="description" value="" />
|
||||
</component>
|
||||
</project>
|
||||
15
.idea/git_toolbox_prj.xml
generated
15
.idea/git_toolbox_prj.xml
generated
@@ -1,15 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="GitToolBoxProjectSettings">
|
||||
<option name="commitMessageIssueKeyValidationOverride">
|
||||
<BoolValueOverride>
|
||||
<option name="enabled" value="true" />
|
||||
</BoolValueOverride>
|
||||
</option>
|
||||
<option name="commitMessageValidationEnabledOverride">
|
||||
<BoolValueOverride>
|
||||
<option name="enabled" value="true" />
|
||||
</BoolValueOverride>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
||||
10
.idea/misc.xml
generated
10
.idea/misc.xml
generated
@@ -1,10 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="FrameworkDetectionExcludesConfiguration">
|
||||
<file type="web" url="file://$PROJECT_DIR$" />
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="azul-17" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
||||
12
.idea/vcs.xml
generated
12
.idea/vcs.xml
generated
@@ -1,12 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CommitMessageInspectionProfile">
|
||||
<profile version="1.0">
|
||||
<inspection_tool class="CommitFormat" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="CommitNamingConvention" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
</profile>
|
||||
</component>
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
22
.releaserc
22
.releaserc
@@ -7,11 +7,13 @@
|
||||
}
|
||||
],
|
||||
"plugins": [
|
||||
["@semantic-release/commit-analyzer", {
|
||||
"releaseRules": [
|
||||
{"type": "build", "release": "patch"}
|
||||
]
|
||||
}],
|
||||
[
|
||||
"@semantic-release/commit-analyzer", {
|
||||
"releaseRules": [
|
||||
{ "type": "build", "scope": "Needs bump", "release": "patch" }
|
||||
]
|
||||
}
|
||||
],
|
||||
"@semantic-release/release-notes-generator",
|
||||
"@semantic-release/changelog",
|
||||
"gradle-semantic-release-plugin",
|
||||
@@ -31,7 +33,15 @@
|
||||
{
|
||||
"path": "build/libs/*all.jar"
|
||||
}
|
||||
]
|
||||
],
|
||||
successComment: false
|
||||
}
|
||||
],
|
||||
[
|
||||
"@saithodev/semantic-release-backmerge",
|
||||
{
|
||||
backmergeBranches: [{"from": "main", "to": "dev"}],
|
||||
clearWorkspace: true
|
||||
}
|
||||
]
|
||||
]
|
||||
|
||||
821
CHANGELOG.md
821
CHANGELOG.md
@@ -1,3 +1,824 @@
|
||||
# [4.4.0-dev.1](https://github.com/ReVanced/revanced-cli/compare/v4.3.0...v4.4.0-dev.1) (2023-12-01)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Log saved patched APK file path ([16109bd](https://github.com/ReVanced/revanced-cli/commit/16109bd8bc6236debf71cbc8db78fe452b2ed00d))
|
||||
|
||||
# [4.3.0](https://github.com/ReVanced/revanced-cli/compare/v4.2.0...v4.3.0) (2023-12-01)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Add `list-versions` command ([a974b8e](https://github.com/ReVanced/revanced-cli/commit/a974b8ea80acd85f8dc472a3f93b8fd7bea08007))
|
||||
|
||||
# [4.3.0-dev.1](https://github.com/ReVanced/revanced-cli/compare/v4.2.0...v4.3.0-dev.1) (2023-11-27)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Add `list-versions` command ([a974b8e](https://github.com/ReVanced/revanced-cli/commit/a974b8ea80acd85f8dc472a3f93b8fd7bea08007))
|
||||
|
||||
# [4.2.0](https://github.com/ReVanced/revanced-cli/compare/v4.1.0...v4.2.0) (2023-11-26)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Fix typo ([#300](https://github.com/ReVanced/revanced-cli/issues/300)) ([9d96bb7](https://github.com/ReVanced/revanced-cli/commit/9d96bb7b4cc4538da416db50bd689af1a632fc45))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Allow selecting first Adb device, if none supplied automatically by updating dependencies ([e7c3d64](https://github.com/ReVanced/revanced-cli/commit/e7c3d64bf15bf84f3853e7ef699511bf72c13767))
|
||||
* Exit application with CLI exit code ([36c6a6a](https://github.com/ReVanced/revanced-cli/commit/36c6a6a5f75f2e770a7941b3f83f430f62de13de))
|
||||
* Make `--out´ option optional ([3765957](https://github.com/ReVanced/revanced-cli/commit/3765957043989fe7a8932a0c548566a78d04fc41))
|
||||
|
||||
# [4.2.0-dev.1](https://github.com/ReVanced/revanced-cli/compare/v4.1.1-dev.1...v4.2.0-dev.1) (2023-11-26)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Allow selecting first Adb device, if none supplied automatically by updating dependencies ([e7c3d64](https://github.com/ReVanced/revanced-cli/commit/e7c3d64bf15bf84f3853e7ef699511bf72c13767))
|
||||
* Exit application with CLI exit code ([36c6a6a](https://github.com/ReVanced/revanced-cli/commit/36c6a6a5f75f2e770a7941b3f83f430f62de13de))
|
||||
* Make `--out´ option optional ([3765957](https://github.com/ReVanced/revanced-cli/commit/3765957043989fe7a8932a0c548566a78d04fc41))
|
||||
|
||||
## [4.1.1-dev.1](https://github.com/ReVanced/revanced-cli/compare/v4.1.0...v4.1.1-dev.1) (2023-11-25)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Fix typo ([#300](https://github.com/ReVanced/revanced-cli/issues/300)) ([9d96bb7](https://github.com/ReVanced/revanced-cli/commit/9d96bb7b4cc4538da416db50bd689af1a632fc45))
|
||||
|
||||
# [4.1.0](https://github.com/ReVanced/revanced-cli/compare/v4.0.2...v4.1.0) (2023-11-04)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Include or exclude patches by their index in relation to supplied patch bundles ([b2055ce](https://github.com/ReVanced/revanced-cli/commit/b2055ce07df3ab9a9f3f73ab17d8c2cf02f2ae62))
|
||||
* List patches which are compatible with any app ([#297](https://github.com/ReVanced/revanced-cli/issues/297)) ([0139dfe](https://github.com/ReVanced/revanced-cli/commit/0139dfe0bfa06a13f56dc03e7718aaf644029614))
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* Use a `HashSet` to check for included and excluded patches ([616d14f](https://github.com/ReVanced/revanced-cli/commit/616d14f0097c1ee7ba6dc07be417590f6418e8e5))
|
||||
|
||||
# [4.1.0-dev.3](https://github.com/ReVanced/revanced-cli/compare/v4.1.0-dev.2...v4.1.0-dev.3) (2023-11-03)
|
||||
|
||||
# [4.1.0-dev.2](https://github.com/ReVanced/revanced-cli/compare/v4.1.0-dev.1...v4.1.0-dev.2) (2023-11-03)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Include or exclude patches by their index in relation to supplied patch bundles ([b2055ce](https://github.com/ReVanced/revanced-cli/commit/b2055ce07df3ab9a9f3f73ab17d8c2cf02f2ae62))
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* Use a `HashSet` to check for included and excluded patches ([616d14f](https://github.com/ReVanced/revanced-cli/commit/616d14f0097c1ee7ba6dc07be417590f6418e8e5))
|
||||
|
||||
# [4.1.0-dev.1](https://github.com/ReVanced/revanced-cli/compare/v4.0.3-dev.2...v4.1.0-dev.1) (2023-11-03)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* List patches which are compatible with any app ([#297](https://github.com/ReVanced/revanced-cli/issues/297)) ([0139dfe](https://github.com/ReVanced/revanced-cli/commit/0139dfe0bfa06a13f56dc03e7718aaf644029614))
|
||||
|
||||
## [4.0.3-dev.2](https://github.com/ReVanced/revanced-cli/compare/v4.0.3-dev.1...v4.0.3-dev.2) (2023-10-30)
|
||||
|
||||
## [4.0.3-dev.1](https://github.com/ReVanced/revanced-cli/compare/v4.0.2...v4.0.3-dev.1) (2023-10-23)
|
||||
|
||||
## [4.0.2](https://github.com/ReVanced/revanced-cli/compare/v4.0.1...v4.0.2) (2023-10-12)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Move file to output even when mounting ([59dfc98](https://github.com/ReVanced/revanced-cli/commit/59dfc988e351374eb718923d19bd9bdd94e8d3c0))
|
||||
* Use punctuation in option descriptions ([da4469f](https://github.com/ReVanced/revanced-cli/commit/da4469f402c26ad95898404236b0acf0202907e2))
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* Use multiple threads for writing dex files ([28648a1](https://github.com/ReVanced/revanced-cli/commit/28648a1c53520eef8c799504ff61a35947f878b8))
|
||||
|
||||
## [4.0.2-dev.3](https://github.com/ReVanced/revanced-cli/compare/v4.0.2-dev.2...v4.0.2-dev.3) (2023-10-10)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Move file to output even when mounting ([59dfc98](https://github.com/ReVanced/revanced-cli/commit/59dfc988e351374eb718923d19bd9bdd94e8d3c0))
|
||||
|
||||
## [4.0.2-dev.2](https://github.com/ReVanced/revanced-cli/compare/v4.0.2-dev.1...v4.0.2-dev.2) (2023-10-10)
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* Use multiple threads for writing dex files ([28648a1](https://github.com/ReVanced/revanced-cli/commit/28648a1c53520eef8c799504ff61a35947f878b8))
|
||||
|
||||
## [4.0.2-dev.1](https://github.com/ReVanced/revanced-cli/compare/v4.0.1...v4.0.2-dev.1) (2023-10-08)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Use punctuation in option descriptions ([da4469f](https://github.com/ReVanced/revanced-cli/commit/da4469f402c26ad95898404236b0acf0202907e2))
|
||||
|
||||
## [4.0.1](https://github.com/ReVanced/revanced-cli/compare/v4.0.0...v4.0.1) (2023-10-08)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Correct warning message ([ba573f7](https://github.com/ReVanced/revanced-cli/commit/ba573f73d0e310fdeb8be2831fd40a7188473fff))
|
||||
|
||||
## [4.0.1-dev.1](https://github.com/ReVanced/revanced-cli/compare/v4.0.0...v4.0.1-dev.1) (2023-10-07)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Correct warning message ([e4e339d](https://github.com/ReVanced/revanced-cli/commit/e4e339dff40542d6265de59496545c859312cf11))
|
||||
|
||||
# [4.0.0](https://github.com/ReVanced/revanced-cli/compare/v3.1.1...v4.0.0) (2023-10-04)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Check, if mounting is possible ([3e13fb5](https://github.com/ReVanced/revanced-cli/commit/3e13fb5d56eb2a90c2a4a1ddfc05852b1f70add5))
|
||||
* Delete temporal files if it exists ([a022feb](https://github.com/ReVanced/revanced-cli/commit/a022febd0c70807ddc3fa9948207a2a70d5191da))
|
||||
* Do not sign if mounting ([578e16b](https://github.com/ReVanced/revanced-cli/commit/578e16b099fddfd2bb56accb225d04dfcd409b0c))
|
||||
* Filter logs correctly ([43fc20d](https://github.com/ReVanced/revanced-cli/commit/43fc20d90e0a694b231b17bb7d9ecfa22bb5d9a0))
|
||||
* Log correct options command ([#262](https://github.com/ReVanced/revanced-cli/issues/262)) ([96c196d](https://github.com/ReVanced/revanced-cli/commit/96c196dcb14e37ad91b751af61ee8382547c1ca3))
|
||||
* Log logs with levels over warning to error output stream ([075f6ad](https://github.com/ReVanced/revanced-cli/commit/075f6ad56528a667dca1f0bed704cf7e5381026f))
|
||||
* Only open files for reading and writing if writeable ([3846f72](https://github.com/ReVanced/revanced-cli/commit/3846f721ca015ab39a7e4b8d3f3d61163a6f1650))
|
||||
* Only set options for filtered patches ([64d9127](https://github.com/ReVanced/revanced-cli/commit/64d9127291ea9a8abe21a0e82721721495094472))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Add function to get the most common compatible version ([77d9173](https://github.com/ReVanced/revanced-cli/commit/77d91735ffbbd6e733f08176f535bfd39ece0c29))
|
||||
* Add option to filter patches to be listed by package name ([50c0f98](https://github.com/ReVanced/revanced-cli/commit/50c0f98ce5927e07839437a2e550aa85f5a7e62d))
|
||||
* Add option to warn about patches not being found in supplied patch bundles ([e46d855](https://github.com/ReVanced/revanced-cli/commit/e46d85564320f46c6faa54b2d3fa7fca3fa60019))
|
||||
* Add ReVanced Library subproject ([#265](https://github.com/ReVanced/revanced-cli/issues/265)) ([157278c](https://github.com/ReVanced/revanced-cli/commit/157278c9ba25f0f786c5fe58e3e23f6890107118))
|
||||
* Do not format patch names ([80a8d88](https://github.com/ReVanced/revanced-cli/commit/80a8d88406b2b04d13dca4fb0d7d7d62e1910317))
|
||||
* Extend signing API ([592dc1c](https://github.com/ReVanced/revanced-cli/commit/592dc1c64ae4078e73bb71eba11380b301c79dea))
|
||||
* Improve option descriptions ([d5ea5a0](https://github.com/ReVanced/revanced-cli/commit/d5ea5a0ab1cc015730063e5be94ee18bd88cc906))
|
||||
* Log stacktrace in new line ([c67e3c7](https://github.com/ReVanced/revanced-cli/commit/c67e3c70c7eaa514cde1bebe775a2216bc4a6074))
|
||||
* Use ReVanced Library in ReVanced CLI ([7794327](https://github.com/ReVanced/revanced-cli/commit/7794327a11e8a0e0f28176cd45fad797b924c45f))
|
||||
* Word log message better ([6942b22](https://github.com/ReVanced/revanced-cli/commit/6942b22a68de5e991987ea89882915917aec93a3))
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* Do not check, if the options file exists twice ([e3c5550](https://github.com/ReVanced/revanced-cli/commit/e3c55507cf52e697b9ce9d59decc1cbe4cfe5b43))
|
||||
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
* This changes many signatures of existing APIs and adds new functions for signing
|
||||
* This changes the log handler signature
|
||||
|
||||
# [4.0.0-dev.5](https://github.com/ReVanced/revanced-cli/compare/v4.0.0-dev.4...v4.0.0-dev.5) (2023-10-04)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Only set options for filtered patches ([64d9127](https://github.com/ReVanced/revanced-cli/commit/64d9127291ea9a8abe21a0e82721721495094472))
|
||||
|
||||
|
||||
### Performance Improvements
|
||||
|
||||
* Do not check, if the options file exists twice ([e3c5550](https://github.com/ReVanced/revanced-cli/commit/e3c55507cf52e697b9ce9d59decc1cbe4cfe5b43))
|
||||
|
||||
# [4.0.0-dev.4](https://github.com/ReVanced/revanced-cli/compare/v4.0.0-dev.3...v4.0.0-dev.4) (2023-10-01)
|
||||
|
||||
# [4.0.0-dev.3](https://github.com/ReVanced/revanced-cli/compare/v4.0.0-dev.2...v4.0.0-dev.3) (2023-09-27)
|
||||
|
||||
# [4.0.0-dev.2](https://github.com/ReVanced/revanced-cli/compare/v4.0.0-dev.1...v4.0.0-dev.2) (2023-09-24)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Improve option descriptions ([d5ea5a0](https://github.com/ReVanced/revanced-cli/commit/d5ea5a0ab1cc015730063e5be94ee18bd88cc906))
|
||||
|
||||
# [4.0.0-dev.1](https://github.com/ReVanced/revanced-cli/compare/v3.1.2-dev.1...v4.0.0-dev.1) (2023-09-23)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Check, if mounting is possible ([3e13fb5](https://github.com/ReVanced/revanced-cli/commit/3e13fb5d56eb2a90c2a4a1ddfc05852b1f70add5))
|
||||
* Delete temporal files if it exists ([a022feb](https://github.com/ReVanced/revanced-cli/commit/a022febd0c70807ddc3fa9948207a2a70d5191da))
|
||||
* Do not sign if mounting ([578e16b](https://github.com/ReVanced/revanced-cli/commit/578e16b099fddfd2bb56accb225d04dfcd409b0c))
|
||||
* Filter logs correctly ([43fc20d](https://github.com/ReVanced/revanced-cli/commit/43fc20d90e0a694b231b17bb7d9ecfa22bb5d9a0))
|
||||
* Log logs with levels over warning to error output stream ([075f6ad](https://github.com/ReVanced/revanced-cli/commit/075f6ad56528a667dca1f0bed704cf7e5381026f))
|
||||
* Only open files for reading and writing if writeable ([3846f72](https://github.com/ReVanced/revanced-cli/commit/3846f721ca015ab39a7e4b8d3f3d61163a6f1650))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Add function to get the most common compatible version ([77d9173](https://github.com/ReVanced/revanced-cli/commit/77d91735ffbbd6e733f08176f535bfd39ece0c29))
|
||||
* Add option to filter patches to be listed by package name ([50c0f98](https://github.com/ReVanced/revanced-cli/commit/50c0f98ce5927e07839437a2e550aa85f5a7e62d))
|
||||
* Add option to warn about patches not being found in supplied patch bundles ([e46d855](https://github.com/ReVanced/revanced-cli/commit/e46d85564320f46c6faa54b2d3fa7fca3fa60019))
|
||||
* Add ReVanced Library subproject ([#265](https://github.com/ReVanced/revanced-cli/issues/265)) ([157278c](https://github.com/ReVanced/revanced-cli/commit/157278c9ba25f0f786c5fe58e3e23f6890107118))
|
||||
* Do not format patch names ([80a8d88](https://github.com/ReVanced/revanced-cli/commit/80a8d88406b2b04d13dca4fb0d7d7d62e1910317))
|
||||
* Extend signing API ([592dc1c](https://github.com/ReVanced/revanced-cli/commit/592dc1c64ae4078e73bb71eba11380b301c79dea))
|
||||
* Log stacktrace in new line ([c67e3c7](https://github.com/ReVanced/revanced-cli/commit/c67e3c70c7eaa514cde1bebe775a2216bc4a6074))
|
||||
* Use ReVanced Library in ReVanced CLI ([7794327](https://github.com/ReVanced/revanced-cli/commit/7794327a11e8a0e0f28176cd45fad797b924c45f))
|
||||
* Word log message better ([6942b22](https://github.com/ReVanced/revanced-cli/commit/6942b22a68de5e991987ea89882915917aec93a3))
|
||||
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
* This changes many signatures of existing APIs and adds new functions for signing
|
||||
* This changes the log handler signature
|
||||
|
||||
# [3.2.0-dev.1](https://github.com/ReVanced/revanced-cli/compare/v3.1.2-dev.1...v3.2.0-dev.1) (2023-09-20)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Log stacktrace in new line ([c67e3c7](https://github.com/ReVanced/revanced-cli/commit/c67e3c70c7eaa514cde1bebe775a2216bc4a6074))
|
||||
|
||||
## [3.1.2-dev.1](https://github.com/ReVanced/revanced-cli/compare/v3.1.1...v3.1.2-dev.1) (2023-09-12)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Log correct options command ([#262](https://github.com/ReVanced/revanced-cli/issues/262)) ([96c196d](https://github.com/ReVanced/revanced-cli/commit/96c196dcb14e37ad91b751af61ee8382547c1ca3))
|
||||
|
||||
## [3.1.1](https://github.com/ReVanced/revanced-cli/compare/v3.1.0...v3.1.1) (2023-09-09)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Create options if it does not exist when updating them ([ca809f0](https://github.com/ReVanced/revanced-cli/commit/ca809f0948379e3a825f24d7a49aba8b6b8767d1))
|
||||
|
||||
## [3.1.1-dev.1](https://github.com/ReVanced/revanced-cli/compare/v3.1.0...v3.1.1-dev.1) (2023-09-03)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* Create options if it does not exist when updating them ([ca809f0](https://github.com/ReVanced/revanced-cli/commit/ca809f0948379e3a825f24d7a49aba8b6b8767d1))
|
||||
|
||||
# [3.1.0](https://github.com/ReVanced/revanced-cli/compare/v3.0.1...v3.1.0) (2023-08-31)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* check for package compatibility at first ([9fe5a0b](https://github.com/ReVanced/revanced-cli/commit/9fe5a0b6d93304f630436ed0e954723d9a27b0f6))
|
||||
* do not filter explicitly included patches ([a3d8f00](https://github.com/ReVanced/revanced-cli/commit/a3d8f004ec405f696d99d96c74ca41b573ecf425))
|
||||
* format patches input ([bbb1a63](https://github.com/ReVanced/revanced-cli/commit/bbb1a63abd80dcbecdcf362158c0429cf3e6318f))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Simplify command description ([3b3f7c7](https://github.com/ReVanced/revanced-cli/commit/3b3f7c7a7a7b2795e3d1fad776f6b457f2e68c7b))
|
||||
|
||||
# [3.1.0-dev.1](https://github.com/ReVanced/revanced-cli/compare/v3.0.2-dev.2...v3.1.0-dev.1) (2023-08-28)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* format patches input ([bbb1a63](https://github.com/ReVanced/revanced-cli/commit/bbb1a63abd80dcbecdcf362158c0429cf3e6318f))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Simplify command description ([3b3f7c7](https://github.com/ReVanced/revanced-cli/commit/3b3f7c7a7a7b2795e3d1fad776f6b457f2e68c7b))
|
||||
|
||||
## [3.0.2-dev.2](https://github.com/ReVanced/revanced-cli/compare/v3.0.2-dev.1...v3.0.2-dev.2) (2023-08-28)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* check for package compatibility at first ([9fe5a0b](https://github.com/ReVanced/revanced-cli/commit/9fe5a0b6d93304f630436ed0e954723d9a27b0f6))
|
||||
|
||||
## [3.0.2-dev.1](https://github.com/ReVanced/revanced-cli/compare/v3.0.1...v3.0.2-dev.1) (2023-08-28)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* do not filter explicitly included patches ([a3d8f00](https://github.com/ReVanced/revanced-cli/commit/a3d8f004ec405f696d99d96c74ca41b573ecf425))
|
||||
|
||||
## [3.0.1](https://github.com/ReVanced/revanced-cli/compare/v3.0.0...v3.0.1) (2023-08-28)
|
||||
|
||||
## [3.0.1-dev.1](https://github.com/ReVanced/revanced-cli/compare/v3.0.0...v3.0.1-dev.1) (2023-08-28)
|
||||
|
||||
# [3.0.0](https://github.com/ReVanced/revanced-cli/compare/v2.22.0...v3.0.0) (2023-08-26)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* also delete temporary files when uninstalling ([52c3be2](https://github.com/ReVanced/revanced-cli/commit/52c3be23f2915dccaee7f9941413c8f81e14acc8))
|
||||
* delete temporary files after root installation ([a3d8705](https://github.com/ReVanced/revanced-cli/commit/a3d8705e89732a0dd4f51de28c405b6af13c8633))
|
||||
* do not delete output file ([0f3e090](https://github.com/ReVanced/revanced-cli/commit/0f3e090418771e951dfd15e5c193421f72cbe459))
|
||||
* do not use absolute path from custom AAPT2 binary option ([a9c2a5f](https://github.com/ReVanced/revanced-cli/commit/a9c2a5f096627dbbf8ab1b8da26fb14529ce6bc3))
|
||||
* filtration of patches malfunctioning ([2d5a7fd](https://github.com/ReVanced/revanced-cli/commit/2d5a7fdf1eb2e13f5013a790b03f09851b167fe0))
|
||||
* fix running commands not running ([2c7fcaf](https://github.com/ReVanced/revanced-cli/commit/2c7fcaf4add65a12052afc5bef779dbc73debd69))
|
||||
* only check once for patch options ([11c3a6c](https://github.com/ReVanced/revanced-cli/commit/11c3a6cfd4fe59ba5d703358634a1853e1cc22a5))
|
||||
* print original instead of kebab cased names ([5eaad33](https://github.com/ReVanced/revanced-cli/commit/5eaad33dc1fbd24c36e1498f04e21d068e85f53e))
|
||||
* print stack trace when a patch failed ([924c1f8](https://github.com/ReVanced/revanced-cli/commit/924c1f80ec0d17a3bdc07a0fb2015e44c49162e4))
|
||||
* specify correct class containing entry-point ([1fcc591](https://github.com/ReVanced/revanced-cli/commit/1fcc591222ab67112f2b78174a8b94106846838c))
|
||||
* use correct option name ([f8972ea](https://github.com/ReVanced/revanced-cli/commit/f8972eac3e5ee0a4a186c12cbe711925656d657b))
|
||||
|
||||
|
||||
* refactor!: restructure code ([07da528](https://github.com/ReVanced/revanced-cli/commit/07da528ce2223582f84bf64d2fec69714c647ddc))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add install command ([0350b7f](https://github.com/ReVanced/revanced-cli/commit/0350b7f1a276d9dc795b22442ba4f202855ea090))
|
||||
* add options command ([9edbbf3](https://github.com/ReVanced/revanced-cli/commit/9edbbf31635603f89fc7bc5dcc6c023d4cdbb5a6))
|
||||
* Check for missing integrations ([c93186f](https://github.com/ReVanced/revanced-cli/commit/c93186fb9700907e65f33442e88073783cc163de))
|
||||
* Improve command line argument descriptions ([f9cf7d2](https://github.com/ReVanced/revanced-cli/commit/f9cf7d21b7f1c2f11234d604a1047b9d2b165f83))
|
||||
* properly make use of logging facade ([41898d7](https://github.com/ReVanced/revanced-cli/commit/41898d7547690e3130372414515c5645e5dc2634))
|
||||
* show full package name when listing patches ([#240](https://github.com/ReVanced/revanced-cli/issues/240)) ([7174364](https://github.com/ReVanced/revanced-cli/commit/7174364ef8ef5d6ce8351a8340f9c1a5b58eac3c))
|
||||
* use better logging text ([b0e748d](https://github.com/ReVanced/revanced-cli/commit/b0e748daff527ee7f417b3069882e074896fc131))
|
||||
* use friendly descriptions ([3dd875d](https://github.com/ReVanced/revanced-cli/commit/3dd875d14cca488ade6d21bbd4cce0d481692134))
|
||||
* use separate command to list patches ([b74213f](https://github.com/ReVanced/revanced-cli/commit/b74213f66e0d04d3a0ae6197d069631388e06580))
|
||||
* use separate command to patch ([32da961](https://github.com/ReVanced/revanced-cli/commit/32da961d57537e99b39fd92b625a1c73f8314bc6))
|
||||
* use separate command to uninstall ([c0cc909](https://github.com/ReVanced/revanced-cli/commit/c0cc90962646cfffd5e2730ae556423271a7990b))
|
||||
* use simpler log ([ba758f0](https://github.com/ReVanced/revanced-cli/commit/ba758f00f4ce18791439b7e72fe1ad2e7f11f8af))
|
||||
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
* This introduces major changes to how ReVanced CLI is used from the command line.
|
||||
|
||||
# [3.0.0-dev.10](https://github.com/ReVanced/revanced-cli/compare/v3.0.0-dev.9...v3.0.0-dev.10) (2023-08-25)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* filtration of patches malfunctioning ([2d5a7fd](https://github.com/ReVanced/revanced-cli/commit/2d5a7fdf1eb2e13f5013a790b03f09851b167fe0))
|
||||
|
||||
# [3.0.0-dev.9](https://github.com/ReVanced/revanced-cli/compare/v3.0.0-dev.8...v3.0.0-dev.9) (2023-08-25)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Check for missing integrations ([c93186f](https://github.com/ReVanced/revanced-cli/commit/c93186fb9700907e65f33442e88073783cc163de))
|
||||
|
||||
# [3.0.0-dev.8](https://github.com/ReVanced/revanced-cli/compare/v3.0.0-dev.7...v3.0.0-dev.8) (2023-08-24)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* do not delete output file ([0f3e090](https://github.com/ReVanced/revanced-cli/commit/0f3e090418771e951dfd15e5c193421f72cbe459))
|
||||
|
||||
# [3.0.0-dev.7](https://github.com/ReVanced/revanced-cli/compare/v3.0.0-dev.6...v3.0.0-dev.7) (2023-08-24)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* print stack trace when a patch failed ([924c1f8](https://github.com/ReVanced/revanced-cli/commit/924c1f80ec0d17a3bdc07a0fb2015e44c49162e4))
|
||||
|
||||
# [3.0.0-dev.6](https://github.com/ReVanced/revanced-cli/compare/v3.0.0-dev.5...v3.0.0-dev.6) (2023-08-24)
|
||||
|
||||
# [3.0.0-dev.5](https://github.com/ReVanced/revanced-cli/compare/v3.0.0-dev.4...v3.0.0-dev.5) (2023-08-24)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* also delete temporary files when uninstalling ([52c3be2](https://github.com/ReVanced/revanced-cli/commit/52c3be23f2915dccaee7f9941413c8f81e14acc8))
|
||||
* delete temporary files after root installation ([a3d8705](https://github.com/ReVanced/revanced-cli/commit/a3d8705e89732a0dd4f51de28c405b6af13c8633))
|
||||
* fix running commands not running ([2c7fcaf](https://github.com/ReVanced/revanced-cli/commit/2c7fcaf4add65a12052afc5bef779dbc73debd69))
|
||||
* only check once for patch options ([11c3a6c](https://github.com/ReVanced/revanced-cli/commit/11c3a6cfd4fe59ba5d703358634a1853e1cc22a5))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add install command ([0350b7f](https://github.com/ReVanced/revanced-cli/commit/0350b7f1a276d9dc795b22442ba4f202855ea090))
|
||||
* use friendly descriptions ([3dd875d](https://github.com/ReVanced/revanced-cli/commit/3dd875d14cca488ade6d21bbd4cce0d481692134))
|
||||
|
||||
# [3.0.0-dev.4](https://github.com/ReVanced/revanced-cli/compare/v3.0.0-dev.3...v3.0.0-dev.4) (2023-08-24)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* properly make use of logging facade ([41898d7](https://github.com/ReVanced/revanced-cli/commit/41898d7547690e3130372414515c5645e5dc2634))
|
||||
|
||||
# [3.0.0-dev.3](https://github.com/ReVanced/revanced-cli/compare/v3.0.0-dev.2...v3.0.0-dev.3) (2023-08-23)
|
||||
|
||||
# [3.0.0-dev.2](https://github.com/ReVanced/revanced-cli/compare/v3.0.0-dev.1...v3.0.0-dev.2) (2023-08-23)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* specify correct class containing entry-point ([1fcc591](https://github.com/ReVanced/revanced-cli/commit/1fcc591222ab67112f2b78174a8b94106846838c))
|
||||
|
||||
# [3.0.0-dev.1](https://github.com/ReVanced/revanced-cli/compare/v2.23.0-dev.5...v3.0.0-dev.1) (2023-08-23)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* do not use absolute path from custom AAPT2 binary option ([a9c2a5f](https://github.com/ReVanced/revanced-cli/commit/a9c2a5f096627dbbf8ab1b8da26fb14529ce6bc3))
|
||||
* use correct option name ([f8972ea](https://github.com/ReVanced/revanced-cli/commit/f8972eac3e5ee0a4a186c12cbe711925656d657b))
|
||||
|
||||
|
||||
* refactor!: restructure code ([07da528](https://github.com/ReVanced/revanced-cli/commit/07da528ce2223582f84bf64d2fec69714c647ddc))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add options command ([9edbbf3](https://github.com/ReVanced/revanced-cli/commit/9edbbf31635603f89fc7bc5dcc6c023d4cdbb5a6))
|
||||
* use better logging text ([b0e748d](https://github.com/ReVanced/revanced-cli/commit/b0e748daff527ee7f417b3069882e074896fc131))
|
||||
* use separate command to list patches ([b74213f](https://github.com/ReVanced/revanced-cli/commit/b74213f66e0d04d3a0ae6197d069631388e06580))
|
||||
* use separate command to patch ([32da961](https://github.com/ReVanced/revanced-cli/commit/32da961d57537e99b39fd92b625a1c73f8314bc6))
|
||||
* use separate command to uninstall ([c0cc909](https://github.com/ReVanced/revanced-cli/commit/c0cc90962646cfffd5e2730ae556423271a7990b))
|
||||
* use simpler log ([ba758f0](https://github.com/ReVanced/revanced-cli/commit/ba758f00f4ce18791439b7e72fe1ad2e7f11f8af))
|
||||
|
||||
|
||||
### BREAKING CHANGES
|
||||
|
||||
* This introduces major changes to how ReVanced CLI is used from the command line.
|
||||
|
||||
# [2.23.0-dev.5](https://github.com/ReVanced/revanced-cli/compare/v2.23.0-dev.4...v2.23.0-dev.5) (2023-08-14)
|
||||
|
||||
# [2.23.0-dev.4](https://github.com/ReVanced/revanced-cli/compare/v2.23.0-dev.3...v2.23.0-dev.4) (2023-08-13)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* show full package name when listing patches ([#240](https://github.com/ReVanced/revanced-cli/issues/240)) ([7174364](https://github.com/ReVanced/revanced-cli/commit/7174364ef8ef5d6ce8351a8340f9c1a5b58eac3c))
|
||||
|
||||
# [2.23.0-dev.3](https://github.com/ReVanced/revanced-cli/compare/v2.23.0-dev.2...v2.23.0-dev.3) (2023-08-03)
|
||||
|
||||
# [2.23.0-dev.2](https://github.com/ReVanced/revanced-cli/compare/v2.23.0-dev.1...v2.23.0-dev.2) (2023-08-03)
|
||||
|
||||
# [2.23.0-dev.1](https://github.com/ReVanced/revanced-cli/compare/v2.22.1-dev.1...v2.23.0-dev.1) (2023-07-30)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* Improve command line argument descriptions ([f9cf7d2](https://github.com/ReVanced/revanced-cli/commit/f9cf7d21b7f1c2f11234d604a1047b9d2b165f83))
|
||||
|
||||
## [2.22.1-dev.1](https://github.com/ReVanced/revanced-cli/compare/v2.22.0...v2.22.1-dev.1) (2023-07-24)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* print original instead of kebab cased names ([5eaad33](https://github.com/ReVanced/revanced-cli/commit/5eaad33dc1fbd24c36e1498f04e21d068e85f53e))
|
||||
|
||||
# [2.22.0](https://github.com/revanced/revanced-cli/compare/v2.21.5...v2.22.0) (2023-07-11)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* use new patch naming convention ([f6c221d](https://github.com/revanced/revanced-cli/commit/f6c221d72dc43ebea00e5eba6bfa02751ae8ad77))
|
||||
|
||||
# [2.22.0-dev.1](https://github.com/revanced/revanced-cli/compare/v2.21.5...v2.22.0-dev.1) (2023-07-10)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* use new patch naming convention ([e4908c7](https://github.com/revanced/revanced-cli/commit/e4908c71051a535f8ce3406427cebbb0941464df))
|
||||
|
||||
## [2.21.5](https://github.com/revanced/revanced-cli/compare/v2.21.4...v2.21.5) (2023-07-01)
|
||||
|
||||
## [2.21.5-dev.2](https://github.com/revanced/revanced-cli/compare/v2.21.5-dev.1...v2.21.5-dev.2) (2023-07-01)
|
||||
|
||||
## [2.21.5-dev.1](https://github.com/revanced/revanced-cli/compare/v2.21.4...v2.21.5-dev.1) (2023-06-27)
|
||||
|
||||
## [2.21.4](https://github.com/revanced/revanced-cli/compare/v2.21.3...v2.21.4) (2023-06-21)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* remove duplicate options entries. ([d0fc886](https://github.com/revanced/revanced-cli/commit/d0fc8864286adc2677f91a319a11a90272c1001d))
|
||||
|
||||
## [2.21.4-dev.1](https://github.com/revanced/revanced-cli/compare/v2.21.3...v2.21.4-dev.1) (2023-06-18)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* remove duplicate options entries. ([d0fc886](https://github.com/revanced/revanced-cli/commit/d0fc8864286adc2677f91a319a11a90272c1001d))
|
||||
|
||||
## [2.21.3](https://github.com/revanced/revanced-cli/compare/v2.21.2...v2.21.3) (2023-06-12)
|
||||
|
||||
## [2.21.3-dev.1](https://github.com/revanced/revanced-cli/compare/v2.21.2...v2.21.3-dev.1) (2023-06-07)
|
||||
|
||||
## [2.21.2](https://github.com/revanced/revanced-cli/compare/v2.21.1...v2.21.2) (2023-05-24)
|
||||
|
||||
## [2.21.2-dev.2](https://github.com/revanced/revanced-cli/compare/v2.21.2-dev.1...v2.21.2-dev.2) (2023-05-15)
|
||||
|
||||
## [2.21.2-dev.1](https://github.com/revanced/revanced-cli/compare/v2.21.1...v2.21.2-dev.1) (2023-05-07)
|
||||
|
||||
## [2.21.1](https://github.com/revanced/revanced-cli/compare/v2.21.0...v2.21.1) (2023-05-06)
|
||||
|
||||
## [2.21.1-dev.1](https://github.com/revanced/revanced-cli/compare/v2.21.0...v2.21.1-dev.1) (2023-05-06)
|
||||
|
||||
# [2.21.0](https://github.com/revanced/revanced-cli/compare/v2.20.2...v2.21.0) (2023-05-04)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **tests:** set order of tests ([2ef48af](https://github.com/revanced/revanced-cli/commit/2ef48af1b339ab729a05d69cb0c8c1ee1e3ab486))
|
||||
* use working JADB dependency version ([#222](https://github.com/revanced/revanced-cli/issues/222)) ([da2c918](https://github.com/revanced/revanced-cli/commit/da2c91874d5623402febfcc0677ada3d648565e1))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add appreciation message for new contributors ([6962fc2](https://github.com/revanced/revanced-cli/commit/6962fc2f4c0f0c96e88a823be64f8ebd1312ee17))
|
||||
|
||||
# [2.21.0-dev.1](https://github.com/revanced/revanced-cli/compare/v2.20.2...v2.21.0-dev.1) (2023-05-04)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **tests:** set order of tests ([2ef48af](https://github.com/revanced/revanced-cli/commit/2ef48af1b339ab729a05d69cb0c8c1ee1e3ab486))
|
||||
* use working JADB dependency version ([#222](https://github.com/revanced/revanced-cli/issues/222)) ([da2c918](https://github.com/revanced/revanced-cli/commit/da2c91874d5623402febfcc0677ada3d648565e1))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* add appreciation message for new contributors ([6962fc2](https://github.com/revanced/revanced-cli/commit/6962fc2f4c0f0c96e88a823be64f8ebd1312ee17))
|
||||
|
||||
## [2.20.2](https://github.com/revanced/revanced-cli/compare/v2.20.1...v2.20.2) (2023-04-30)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* correct spelling mistake ([31fb316](https://github.com/revanced/revanced-cli/commit/31fb3166d922ae1f568f52e44cbe726dd1c891a4))
|
||||
|
||||
## [2.20.2-dev.1](https://github.com/revanced/revanced-cli/compare/v2.20.1...v2.20.2-dev.1) (2023-04-03)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* correct spelling mistake ([31fb316](https://github.com/revanced/revanced-cli/commit/31fb3166d922ae1f568f52e44cbe726dd1c891a4))
|
||||
|
||||
## [2.20.1](https://github.com/revanced/revanced-cli/compare/v2.20.0...v2.20.1) (2023-03-14)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* correctly word option descriptions ([ac3a8f6](https://github.com/revanced/revanced-cli/commit/ac3a8f66f77a7218974465eebbfc78a536b76d51))
|
||||
|
||||
## [2.20.1-dev.1](https://github.com/revanced/revanced-cli/compare/v2.20.0...v2.20.1-dev.1) (2023-03-05)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* correctly word option descriptions ([ac3a8f6](https://github.com/revanced/revanced-cli/commit/ac3a8f66f77a7218974465eebbfc78a536b76d51))
|
||||
|
||||
## [2.20.1-dev.1](https://github.com/revanced/revanced-cli/compare/v2.20.0...v2.20.1-dev.1) (2023-03-03)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* correctly word option descriptions ([ac3a8f6](https://github.com/revanced/revanced-cli/commit/ac3a8f66f77a7218974465eebbfc78a536b76d51))
|
||||
|
||||
## [2.20.1-dev.1](https://github.com/revanced/revanced-cli/compare/v2.20.0...v2.20.1-dev.1) (2023-03-02)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* correctly word option descriptions ([ac3a8f6](https://github.com/revanced/revanced-cli/commit/ac3a8f66f77a7218974465eebbfc78a536b76d51))
|
||||
|
||||
# [2.20.0](https://github.com/revanced/revanced-cli/compare/v2.19.0...v2.20.0) (2023-01-18)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* bump patcher dependency version ([51c04b7](https://github.com/revanced/revanced-cli/commit/51c04b7b162ad2876bbeb248b7ccddd105b5076d))
|
||||
* do not list compatible packages if patches do not define them ([31e4a41](https://github.com/revanced/revanced-cli/commit/31e4a41dd20f5fa62f840cd8e3b92fe0814eda87))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* connect to first device if given device was not found ([6485e47](https://github.com/revanced/revanced-cli/commit/6485e477a10bb89dfb2e40f3596d72b20bf23cc8))
|
||||
* remove option `--with-descriptions` ([07a423b](https://github.com/revanced/revanced-cli/commit/07a423b19ec72e9f020aeb0222f4ced571036dbe))
|
||||
|
||||
# [2.20.0](https://github.com/revanced/revanced-cli/compare/v2.19.0...v2.20.0) (2023-01-17)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* bump patcher dependency version ([51c04b7](https://github.com/revanced/revanced-cli/commit/51c04b7b162ad2876bbeb248b7ccddd105b5076d))
|
||||
* do not list compatible packages if patches do not define them ([31e4a41](https://github.com/revanced/revanced-cli/commit/31e4a41dd20f5fa62f840cd8e3b92fe0814eda87))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* connect to first device if given device was not found ([6485e47](https://github.com/revanced/revanced-cli/commit/6485e477a10bb89dfb2e40f3596d72b20bf23cc8))
|
||||
* remove option `--with-descriptions` ([07a423b](https://github.com/revanced/revanced-cli/commit/07a423b19ec72e9f020aeb0222f4ced571036dbe))
|
||||
|
||||
# [2.20.0-dev.3](https://github.com/revanced/revanced-cli/compare/v2.20.0-dev.2...v2.20.0-dev.3) (2023-01-15)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* bump patcher dependency version ([51c04b7](https://github.com/revanced/revanced-cli/commit/51c04b7b162ad2876bbeb248b7ccddd105b5076d))
|
||||
|
||||
# [2.20.0-dev.2](https://github.com/revanced/revanced-cli/compare/v2.20.0-dev.1...v2.20.0-dev.2) (2023-01-15)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* connect to first device if given device was not found ([6485e47](https://github.com/revanced/revanced-cli/commit/6485e477a10bb89dfb2e40f3596d72b20bf23cc8))
|
||||
|
||||
# [2.20.0](https://github.com/revanced/revanced-cli/compare/v2.19.0...v2.20.0) (2023-01-02)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* do not list compatible packages if patches do not define them ([31e4a41](https://github.com/revanced/revanced-cli/commit/31e4a41dd20f5fa62f840cd8e3b92fe0814eda87))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* remove option `--with-descriptions` ([07a423b](https://github.com/revanced/revanced-cli/commit/07a423b19ec72e9f020aeb0222f4ced571036dbe))
|
||||
|
||||
# [2.20.0](https://github.com/revanced/revanced-cli/compare/v2.19.0...v2.20.0) (2023-01-01)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* do not list compatible packages if patches do not define them ([31e4a41](https://github.com/revanced/revanced-cli/commit/31e4a41dd20f5fa62f840cd8e3b92fe0814eda87))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* remove option `--with-descriptions` ([07a423b](https://github.com/revanced/revanced-cli/commit/07a423b19ec72e9f020aeb0222f4ced571036dbe))
|
||||
|
||||
# [2.20.0-dev.1](https://github.com/revanced/revanced-cli/compare/v2.19.0...v2.20.0-dev.1) (2023-01-01)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* do not list compatible packages if patches do not define them ([31e4a41](https://github.com/revanced/revanced-cli/commit/31e4a41dd20f5fa62f840cd8e3b92fe0814eda87))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* remove option `--with-descriptions` ([07a423b](https://github.com/revanced/revanced-cli/commit/07a423b19ec72e9f020aeb0222f4ced571036dbe))
|
||||
|
||||
# [2.19.0](https://github.com/revanced/revanced-cli/compare/v2.18.2...v2.19.0) (2022-12-31)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* improve description of options ([#185](https://github.com/revanced/revanced-cli/issues/185)) ([b69e784](https://github.com/revanced/revanced-cli/commit/b69e784785f7f262f83b35c4f241c90036169fc7))
|
||||
|
||||
# [2.19.0-dev.1](https://github.com/revanced/revanced-cli/compare/v2.18.2...v2.19.0-dev.1) (2022-12-31)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* improve description of options ([#185](https://github.com/revanced/revanced-cli/issues/185)) ([b69e784](https://github.com/revanced/revanced-cli/commit/b69e784785f7f262f83b35c4f241c90036169fc7))
|
||||
|
||||
## [2.18.2](https://github.com/revanced/revanced-cli/compare/v2.18.1...v2.18.2) (2022-12-16)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* exclude patcher dependency from minimizing ([d5794b9](https://github.com/revanced/revanced-cli/commit/d5794b94ca19c9287190a3b863c97a089893cc07))
|
||||
|
||||
## [2.18.2-dev.1](https://github.com/revanced/revanced-cli/compare/v2.18.1...v2.18.2-dev.1) (2022-12-16)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* exclude patcher dependency from minimizing ([d5794b9](https://github.com/revanced/revanced-cli/commit/d5794b94ca19c9287190a3b863c97a089893cc07))
|
||||
|
||||
## [2.18.1](https://github.com/revanced/revanced-cli/compare/v2.18.0...v2.18.1) (2022-12-15)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* don't log when package is incompatible and `exclusive` option is used ([ad81a1b](https://github.com/revanced/revanced-cli/commit/ad81a1b656586226f8b7b8d1123c52b0f3f2e6f7))
|
||||
|
||||
## [2.18.1-dev.1](https://github.com/revanced/revanced-cli/compare/v2.18.0...v2.18.1-dev.1) (2022-12-15)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* don't log when package is incompatible and `exclusive` option is used ([ad81a1b](https://github.com/revanced/revanced-cli/commit/ad81a1b656586226f8b7b8d1123c52b0f3f2e6f7))
|
||||
|
||||
# [2.18.0](https://github.com/revanced/revanced-cli/compare/v2.17.0...v2.18.0) (2022-12-15)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* start with uppercase in log message ([ae91b0d](https://github.com/revanced/revanced-cli/commit/ae91b0d597b107a152e1b630b8c16a795a7ca3b3))
|
||||
* use correct prefix in log message ([1a67cd8](https://github.com/revanced/revanced-cli/commit/1a67cd81da5ed7f259b6dbaeb66a7eef4a113034))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* simplify log message ([74d73ca](https://github.com/revanced/revanced-cli/commit/74d73ca3a7ba2f5da872fe9a241629e1c143cd4e))
|
||||
|
||||
# [2.18.0](https://github.com/revanced/revanced-cli/compare/v2.17.0...v2.18.0) (2022-12-15)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* start with uppercase in log message ([ae91b0d](https://github.com/revanced/revanced-cli/commit/ae91b0d597b107a152e1b630b8c16a795a7ca3b3))
|
||||
* use correct prefix in log message ([1a67cd8](https://github.com/revanced/revanced-cli/commit/1a67cd81da5ed7f259b6dbaeb66a7eef4a113034))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* simplify log message ([74d73ca](https://github.com/revanced/revanced-cli/commit/74d73ca3a7ba2f5da872fe9a241629e1c143cd4e))
|
||||
|
||||
# [2.18.0-dev.1](https://github.com/revanced/revanced-cli/compare/v2.17.1-dev.2...v2.18.0-dev.1) (2022-12-15)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* start with uppercase in log message ([ae91b0d](https://github.com/revanced/revanced-cli/commit/ae91b0d597b107a152e1b630b8c16a795a7ca3b3))
|
||||
* use correct prefix in log message ([1a67cd8](https://github.com/revanced/revanced-cli/commit/1a67cd81da5ed7f259b6dbaeb66a7eef4a113034))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* simplify log message ([74d73ca](https://github.com/revanced/revanced-cli/commit/74d73ca3a7ba2f5da872fe9a241629e1c143cd4e))
|
||||
|
||||
## [2.17.1-dev.2](https://github.com/revanced/revanced-cli/compare/v2.17.1-dev.1...v2.17.1-dev.2) (2022-12-15)
|
||||
|
||||
## [2.17.1-dev.1](https://github.com/revanced/revanced-cli/compare/v2.17.0...v2.17.1-dev.1) (2022-12-15)
|
||||
|
||||
# [2.17.0](https://github.com/revanced/revanced-cli/compare/v2.16.1...v2.17.0) (2022-12-14)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* invalid header when writing a `ZipFile` ([#169](https://github.com/revanced/revanced-cli/issues/169)) ([6e703eb](https://github.com/revanced/revanced-cli/commit/6e703eb8e8d7da0e52266c4965f37bc8aafb409c))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* improve missing compatibility annotation tracing log ([2c7eb72](https://github.com/revanced/revanced-cli/commit/2c7eb7274c713dfbcb53c5f3b6a9205c751914fa))
|
||||
* trace logs when compatibility annotation is missing ([#166](https://github.com/revanced/revanced-cli/issues/166)) ([c590bf5](https://github.com/revanced/revanced-cli/commit/c590bf559c4d2d2667c2af0c0da23d4706fcd4b7))
|
||||
|
||||
# [2.17.0-dev.3](https://github.com/revanced/revanced-cli/compare/v2.17.0-dev.2...v2.17.0-dev.3) (2022-12-14)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* improve missing compatibility annotation tracing log ([2c7eb72](https://github.com/revanced/revanced-cli/commit/2c7eb7274c713dfbcb53c5f3b6a9205c751914fa))
|
||||
|
||||
# [2.17.0-dev.2](https://github.com/revanced/revanced-cli/compare/v2.17.0-dev.1...v2.17.0-dev.2) (2022-12-14)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* invalid header when writing a `ZipFile` ([#169](https://github.com/revanced/revanced-cli/issues/169)) ([6e703eb](https://github.com/revanced/revanced-cli/commit/6e703eb8e8d7da0e52266c4965f37bc8aafb409c))
|
||||
|
||||
# [2.17.0-dev.1](https://github.com/revanced/revanced-cli/compare/v2.16.1...v2.17.0-dev.1) (2022-12-11)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* trace logs when compatibility annotation is missing ([#166](https://github.com/revanced/revanced-cli/issues/166)) ([c590bf5](https://github.com/revanced/revanced-cli/commit/c590bf559c4d2d2667c2af0c0da23d4706fcd4b7))
|
||||
|
||||
## [2.16.1](https://github.com/revanced/revanced-cli/compare/v2.16.0...v2.16.1) (2022-11-22)
|
||||
|
||||
# [2.16.0](https://github.com/revanced/revanced-cli/compare/v2.15.1...v2.16.0) (2022-11-20)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* do not warn on incompatible packages ([39e377b](https://github.com/revanced/revanced-cli/commit/39e377bc485e2892422e9712d30e6ff665856ac1))
|
||||
|
||||
## [2.15.1](https://github.com/revanced/revanced-cli/compare/v2.15.0...v2.15.1) (2022-11-18)
|
||||
|
||||
# [2.15.0](https://github.com/revanced/revanced-cli/compare/v2.14.0...v2.15.0) (2022-10-31)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* **gitignore:** ignore `options.toml` ([#158](https://github.com/revanced/revanced-cli/issues/158)) ([7be9af0](https://github.com/revanced/revanced-cli/commit/7be9af0942de2a834b9e57403d46263b65f1a422))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* use `am` instead of `monkey` to launch the app ([#159](https://github.com/revanced/revanced-cli/issues/159)) ([6a35cf7](https://github.com/revanced/revanced-cli/commit/6a35cf7ea46a4474120626ce03d28490cc96bf07))
|
||||
|
||||
# [2.14.0](https://github.com/revanced/revanced-cli/compare/v2.13.0...v2.14.0) (2022-10-05)
|
||||
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
* escape quotation mark in string ([6e21d81](https://github.com/revanced/revanced-cli/commit/6e21d81964e8160e06ffda7051dd484e4aaaa432))
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* handle unmounting deleted files ([#148](https://github.com/revanced/revanced-cli/issues/148)) ([3a733e5](https://github.com/revanced/revanced-cli/commit/3a733e513717799ca0e32327e5b8be043680c556))
|
||||
* unmount all occurrences in `/proc/mounts` ([#131](https://github.com/revanced/revanced-cli/issues/131)) ([4f4e1f9](https://github.com/revanced/revanced-cli/commit/4f4e1f9834bf28d9be2efd4fd7bae19951b85258))
|
||||
|
||||
# [2.13.0](https://github.com/revanced/revanced-cli/compare/v2.12.0...v2.13.0) (2022-10-01)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* check, if input file exists ([b6dff6d](https://github.com/revanced/revanced-cli/commit/b6dff6d832de4a513a6d86b0a59b2458eddd23c2))
|
||||
|
||||
# [2.12.0](https://github.com/revanced/revanced-cli/compare/v2.11.2...v2.12.0) (2022-09-26)
|
||||
|
||||
|
||||
### Features
|
||||
|
||||
* remove unused option `-r` ([467d838](https://github.com/revanced/revanced-cli/commit/467d8387e646c88d24a30406a5b2e84065ef4d54))
|
||||
|
||||
## [2.11.2](https://github.com/revanced/revanced-cli/compare/v2.11.1...v2.11.2) (2022-09-23)
|
||||
|
||||
## [2.11.1](https://github.com/revanced/revanced-cli/compare/v2.11.0...v2.11.1) (2022-09-21)
|
||||
|
||||
98
CONTRIBUTING.md
Normal file
98
CONTRIBUTING.md
Normal file
@@ -0,0 +1,98 @@
|
||||
<p align="center">
|
||||
<picture>
|
||||
<source
|
||||
width="256px"
|
||||
media="(prefers-color-scheme: dark)"
|
||||
srcset="assets/revanced-headline/revanced-headline-vertical-dark.svg"
|
||||
>
|
||||
<img
|
||||
width="256px"
|
||||
src="assets/revanced-headline/revanced-headline-vertical-light.svg"
|
||||
>
|
||||
</picture>
|
||||
<br>
|
||||
<a href="https://revanced.app/">
|
||||
<picture>
|
||||
<source height="24px" media="(prefers-color-scheme: dark)" srcset="assets/revanced-logo/revanced-logo.svg" />
|
||||
<img height="24px" src="assets/revanced-logo/revanced-logo.svg" />
|
||||
</picture>
|
||||
</a>
|
||||
<a href="https://github.com/ReVanced">
|
||||
<picture>
|
||||
<source height="24px" media="(prefers-color-scheme: dark)" srcset="https://i.ibb.co/dMMmCrW/Git-Hub-Mark.png" />
|
||||
<img height="24px" src="https://i.ibb.co/9wV3HGF/Git-Hub-Mark-Light.png" />
|
||||
</picture>
|
||||
</a>
|
||||
<a href="http://revanced.app/discord">
|
||||
<picture>
|
||||
<source height="24px" media="(prefers-color-scheme: dark)" srcset="https://user-images.githubusercontent.com/13122796/178032563-d4e084b7-244e-4358-af50-26bde6dd4996.png" />
|
||||
<img height="24px" src="https://user-images.githubusercontent.com/13122796/178032563-d4e084b7-244e-4358-af50-26bde6dd4996.png" />
|
||||
</picture>
|
||||
</a>
|
||||
<a href="https://reddit.com/r/revancedapp">
|
||||
<picture>
|
||||
<source height="24px" media="(prefers-color-scheme: dark)" srcset="https://user-images.githubusercontent.com/13122796/178032351-9d9d5619-8ef7-470a-9eec-2744ece54553.png" />
|
||||
<img height="24px" src="https://user-images.githubusercontent.com/13122796/178032351-9d9d5619-8ef7-470a-9eec-2744ece54553.png" />
|
||||
</picture>
|
||||
</a>
|
||||
<a href="https://t.me/app_revanced">
|
||||
<picture>
|
||||
<source height="24px" media="(prefers-color-scheme: dark)" srcset="https://user-images.githubusercontent.com/13122796/178032213-faf25ab8-0bc3-4a94-a730-b524c96df124.png" />
|
||||
<img height="24px" src="https://user-images.githubusercontent.com/13122796/178032213-faf25ab8-0bc3-4a94-a730-b524c96df124.png" />
|
||||
</picture>
|
||||
</a>
|
||||
<a href="https://x.com/revancedapp">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://user-images.githubusercontent.com/93124920/270180600-7c1b38bf-889b-4d68-bd5e-b9d86f91421a.png">
|
||||
<img height="24px" src="https://user-images.githubusercontent.com/93124920/270108715-d80743fa-b330-4809-b1e6-79fbdc60d09c.png" />
|
||||
</picture>
|
||||
</a>
|
||||
<a href="https://www.youtube.com/@ReVanced">
|
||||
<picture>
|
||||
<source height="24px" media="(prefers-color-scheme: dark)" srcset="https://user-images.githubusercontent.com/13122796/178032714-c51c7492-0666-44ac-99c2-f003a695ab50.png" />
|
||||
<img height="24px" src="https://user-images.githubusercontent.com/13122796/178032714-c51c7492-0666-44ac-99c2-f003a695ab50.png" />
|
||||
</picture>
|
||||
</a>
|
||||
<br>
|
||||
<br>
|
||||
Continuing the legacy of Vanced
|
||||
</p>
|
||||
|
||||
# 👋 Contribution guidelines
|
||||
|
||||
This document describes how to contribute to ReVanced CLI.
|
||||
|
||||
## 📖 Resources to help you get started
|
||||
|
||||
* The [documentation](/docs) explains how to use ReVanced CLI
|
||||
* [Our backlog](https://github.com/orgs/ReVanced/projects/12) is where we keep track of what we're working on
|
||||
* [Issues](https://github.com/ReVanced/revanced-cli/issues) are where we keep track of bugs and feature requests
|
||||
|
||||
## 🙏 Submitting a feature request
|
||||
|
||||
Features can be requested by opening an issue using the
|
||||
[Feature request issue template](https://github.com/ReVanced/revanced-cli/issues/new?assignees=&labels=Feature+request&projects=&template=feature-request.yml&title=feat%3A+).
|
||||
|
||||
> **Note**
|
||||
> Requests can be accepted or rejected at the discretion of maintainers of ReVanced CLI.
|
||||
> Good motivation has to be provided for a request to be accepted.
|
||||
|
||||
## 🐞 Submitting a bug report
|
||||
|
||||
If you encounter a bug while using ReVanced CLI, open an issue using the
|
||||
[Bug report issue template](https://github.com/ReVanced/revanced-cli/issues/new?assignees=&labels=Bug+report&projects=&template=bug-report.yml&title=bug%3A+).
|
||||
|
||||
## 📝 How to contribute
|
||||
|
||||
1. Before contributing, it is recommended to open an issue to discuss your change
|
||||
with the maintainers of ReVanced CLI. This will help you determine whether your change is acceptable
|
||||
and whether it is worth your time to implement it
|
||||
2. Development happens on the `dev` branch. Fork the repository and create your branch from `dev`
|
||||
3. Commit your changes.
|
||||
4. Submit a pull request to the `dev` branch of the repository and reference issues
|
||||
that your pull request closes in the description of your pull request
|
||||
5. Our team will review your pull request and provide feedback. Once your pull request is approved,
|
||||
it will be merged into the `dev` branch and will be included in the next release of ReVanced CLI
|
||||
|
||||
❤️ Thank you for considering contributing to ReVanced CLI,
|
||||
ReVanced
|
||||
93
README.md
Normal file
93
README.md
Normal file
@@ -0,0 +1,93 @@
|
||||
<p align="center">
|
||||
<picture>
|
||||
<source
|
||||
width="256px"
|
||||
media="(prefers-color-scheme: dark)"
|
||||
srcset="assets/revanced-headline/revanced-headline-vertical-dark.svg"
|
||||
>
|
||||
<img
|
||||
width="256px"
|
||||
src="assets/revanced-headline/revanced-headline-vertical-light.svg"
|
||||
>
|
||||
</picture>
|
||||
<br>
|
||||
<a href="https://revanced.app/">
|
||||
<picture>
|
||||
<source height="24px" media="(prefers-color-scheme: dark)" srcset="assets/revanced-logo/revanced-logo.svg" />
|
||||
<img height="24px" src="assets/revanced-logo/revanced-logo.svg" />
|
||||
</picture>
|
||||
</a>
|
||||
<a href="https://github.com/ReVanced">
|
||||
<picture>
|
||||
<source height="24px" media="(prefers-color-scheme: dark)" srcset="https://i.ibb.co/dMMmCrW/Git-Hub-Mark.png" />
|
||||
<img height="24px" src="https://i.ibb.co/9wV3HGF/Git-Hub-Mark-Light.png" />
|
||||
</picture>
|
||||
</a>
|
||||
<a href="http://revanced.app/discord">
|
||||
<picture>
|
||||
<source height="24px" media="(prefers-color-scheme: dark)" srcset="https://user-images.githubusercontent.com/13122796/178032563-d4e084b7-244e-4358-af50-26bde6dd4996.png" />
|
||||
<img height="24px" src="https://user-images.githubusercontent.com/13122796/178032563-d4e084b7-244e-4358-af50-26bde6dd4996.png" />
|
||||
</picture>
|
||||
</a>
|
||||
<a href="https://reddit.com/r/revancedapp">
|
||||
<picture>
|
||||
<source height="24px" media="(prefers-color-scheme: dark)" srcset="https://user-images.githubusercontent.com/13122796/178032351-9d9d5619-8ef7-470a-9eec-2744ece54553.png" />
|
||||
<img height="24px" src="https://user-images.githubusercontent.com/13122796/178032351-9d9d5619-8ef7-470a-9eec-2744ece54553.png" />
|
||||
</picture>
|
||||
</a>
|
||||
<a href="https://t.me/app_revanced">
|
||||
<picture>
|
||||
<source height="24px" media="(prefers-color-scheme: dark)" srcset="https://user-images.githubusercontent.com/13122796/178032213-faf25ab8-0bc3-4a94-a730-b524c96df124.png" />
|
||||
<img height="24px" src="https://user-images.githubusercontent.com/13122796/178032213-faf25ab8-0bc3-4a94-a730-b524c96df124.png" />
|
||||
</picture>
|
||||
</a>
|
||||
<a href="https://x.com/revancedapp">
|
||||
<picture>
|
||||
<source media="(prefers-color-scheme: dark)" srcset="https://user-images.githubusercontent.com/93124920/270180600-7c1b38bf-889b-4d68-bd5e-b9d86f91421a.png">
|
||||
<img height="24px" src="https://user-images.githubusercontent.com/93124920/270108715-d80743fa-b330-4809-b1e6-79fbdc60d09c.png" />
|
||||
</picture>
|
||||
</a>
|
||||
<a href="https://www.youtube.com/@ReVanced">
|
||||
<picture>
|
||||
<source height="24px" media="(prefers-color-scheme: dark)" srcset="https://user-images.githubusercontent.com/13122796/178032714-c51c7492-0666-44ac-99c2-f003a695ab50.png" />
|
||||
<img height="24px" src="https://user-images.githubusercontent.com/13122796/178032714-c51c7492-0666-44ac-99c2-f003a695ab50.png" />
|
||||
</picture>
|
||||
</a>
|
||||
<br>
|
||||
<br>
|
||||
Continuing the legacy of Vanced
|
||||
</p>
|
||||
|
||||
# 💻 ReVanced CLI
|
||||
|
||||

|
||||

|
||||
|
||||
Command line application to use ReVanced.
|
||||
|
||||
## ❓ About
|
||||
|
||||
ReVanced CLI is a command line application to patch apps using ReVanced.
|
||||
ReVanced CLI also comes with commands to uninstall or install patched apps and list patches from supplied patch bundles.
|
||||
|
||||
## 🚀 Download
|
||||
|
||||
You can download the most recent version of ReVanced CLI from
|
||||
[here](https://github.com/ReVanced/revanced-cli/releases/latest). Learn how to use ReVanced CLI by following the [documentation](/docs).
|
||||
|
||||
## 📚 Everything else
|
||||
|
||||
### 📙 Contributing
|
||||
|
||||
Thank you for considering contributing to ReVanced CLI.
|
||||
You can find the contribution guidelines [here](CONTRIBUTING.md).
|
||||
|
||||
### 🛠️ Building
|
||||
|
||||
In order to build ReVanced CLI, you can follow the [documentation](/docs).
|
||||
|
||||
## 📜 Licence
|
||||
|
||||
ReVanced CLI is licensed under the GPLv3 licence. Please see the [licence file](LICENSE) for more information.
|
||||
[tl;dr](https://www.tldrlegal.com/license/gnu-general-public-license-v3-gpl-3) you may copy, distribute and modify ReVanced CLI as long as you track changes/dates in source files.
|
||||
Any modifications to ReVanced CLI must also be made available under the GPL along with build & install instructions.
|
||||
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 11 KiB |
File diff suppressed because one or more lines are too long
|
After Width: | Height: | Size: 11 KiB |
1
assets/revanced-logo/revanced-logo.svg
Normal file
1
assets/revanced-logo/revanced-logo.svg
Normal file
@@ -0,0 +1 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg width="100%" height="100%" viewBox="0 0 800 800" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" xmlns:serif="http://www.serif.com/" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;"><g id="Logo"><g id="Ring"><circle id="Ring-Background" serif:id="Ring Background" cx="400" cy="400" r="400" style="fill:#1b1b1b;"/><path id="Ring1" serif:id="Ring" d="M400,0c220.766,0 400,179.234 400,400c-0,220.766 -179.234,400 -400,400c-220.766,-0 -400,-179.234 -400,-400c0,-220.766 179.234,-400 400,-400Zm-0,36c200.897,-0 364,163.103 364,364c0,200.897 -163.103,364 -364,364c-200.897,0 -364,-163.103 -364,-364c-0,-200.897 163.103,-364 364,-364Z" style="fill:url(#_Linear1);"/></g><g id="Shape"><path id="V-Shape" serif:id="V Shape" d="M538.74,269.872c1.481,-3.382 1.157,-7.283 -0.863,-10.373c-2.021,-3.091 -5.464,-4.954 -9.156,-4.954c-5.148,0 -10.435,0 -14.165,0c-3.1,0 -5.907,1.834 -7.153,4.672c-12.468,28.396 -78.273,178.273 -100.25,228.328c-1.246,2.838 -4.053,4.671 -7.154,4.671c-3.1,0 -5.907,-1.833 -7.153,-4.671c-21.977,-50.055 -87.782,-199.932 -100.25,-228.328c-1.246,-2.838 -4.053,-4.672 -7.153,-4.672c-3.73,0 -9.017,0 -14.164,0c-3.693,0 -7.135,1.863 -9.156,4.954c-2.02,3.09 -2.344,6.991 -0.863,10.373c23.557,53.766 101.872,232.519 117.871,269.034c1.743,3.979 5.674,6.549 10.018,6.549c6.293,-0 15.408,-0 21.701,-0c4.344,-0 8.275,-2.57 10.018,-6.549c15.999,-36.515 94.315,-215.268 117.872,-269.034Z" style="fill:#fff;"/><path id="Diamond" d="M408.119,395.312c-1.675,2.901 -4.77,4.688 -8.119,4.688c-3.349,-0 -6.444,-1.787 -8.119,-4.688c-16.997,-29.44 -56.156,-97.264 -73.153,-126.704c-1.675,-2.901 -1.675,-6.474 0,-9.375c1.675,-2.901 4.77,-4.688 8.119,-4.688c33.995,0 112.311,0 146.306,0c3.349,0 6.444,1.787 8.119,4.688c1.675,2.901 1.675,6.474 -0,9.375c-16.997,29.44 -56.156,97.264 -73.153,126.704Z" style="fill:url(#_Linear2);"/></g></g><defs><linearGradient id="_Linear1" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(4.89859e-14,800,-800,4.89859e-14,400.001,3.31681e-10)"><stop offset="0" style="stop-color:#f04e98;stop-opacity:1"/><stop offset="0.5" style="stop-color:#5f65d4;stop-opacity:1"/><stop offset="1" style="stop-color:#4e98f0;stop-opacity:1"/></linearGradient><linearGradient id="_Linear2" x1="0" y1="0" x2="1" y2="0" gradientUnits="userSpaceOnUse" gradientTransform="matrix(1.77155e-14,289.317,-282.535,1.73003e-14,400,254.545)"><stop offset="0" style="stop-color:#f04e98;stop-opacity:1"/><stop offset="0.5" style="stop-color:#5f65d4;stop-opacity:1"/><stop offset="1" style="stop-color:#4e98f0;stop-opacity:1"/></linearGradient></defs></svg>
|
||||
|
After Width: | Height: | Size: 2.8 KiB |
@@ -1,55 +1,70 @@
|
||||
plugins {
|
||||
kotlin("jvm") version "1.7.0"
|
||||
id("com.github.johnrengelman.shadow") version "7.1.2"
|
||||
kotlin("jvm") version "1.9.10"
|
||||
alias(libs.plugins.shadow)
|
||||
}
|
||||
|
||||
group = "app.revanced"
|
||||
|
||||
val githubUsername: String = project.findProperty("gpr.user") as? String ?: System.getenv("GITHUB_ACTOR")
|
||||
val githubPassword: String = project.findProperty("gpr.key") as? String ?: System.getenv("GITHUB_TOKEN")
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
mavenLocal()
|
||||
maven {
|
||||
url = uri("https://maven.pkg.github.com/revanced/revanced-patcher")
|
||||
credentials {
|
||||
username = githubUsername
|
||||
password = githubPassword
|
||||
}
|
||||
}
|
||||
maven { url = uri("https://jitpack.io") }
|
||||
google()
|
||||
maven { url = uri("https://jitpack.io") }
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(kotlin("reflect"))
|
||||
implementation(libs.revanced.patcher)
|
||||
implementation(libs.revanced.library)
|
||||
implementation(libs.kotlinx.coroutines.core)
|
||||
implementation(libs.picocli)
|
||||
|
||||
implementation("app.revanced:revanced-patcher:5.0.1")
|
||||
implementation("info.picocli:picocli:4.6.3")
|
||||
implementation("com.android.tools.build:apksig:7.2.1")
|
||||
implementation("com.github.revanced:jadb:master-SNAPSHOT") // updated fork
|
||||
implementation("org.bouncycastle:bcpkix-jdk15on:1.70")
|
||||
implementation("cc.ekblad:4koma:1.1.0")
|
||||
testImplementation(libs.kotlin.test)
|
||||
}
|
||||
|
||||
kotlin { jvmToolchain(11) }
|
||||
|
||||
tasks {
|
||||
test {
|
||||
useJUnitPlatform()
|
||||
testLogging {
|
||||
events("PASSED", "SKIPPED", "FAILED")
|
||||
}
|
||||
}
|
||||
|
||||
processResources {
|
||||
expand("projectVersion" to project.version)
|
||||
}
|
||||
|
||||
shadowJar {
|
||||
manifest {
|
||||
attributes("Main-Class" to "app.revanced.cli.command.MainCommandKt")
|
||||
}
|
||||
minimize {
|
||||
exclude(dependency("org.jetbrains.kotlin:.*"))
|
||||
exclude(dependency("org.bouncycastle:.*"))
|
||||
exclude(dependency("app.revanced:.*"))
|
||||
}
|
||||
}
|
||||
|
||||
build {
|
||||
dependsOn(shadowJar)
|
||||
}
|
||||
shadowJar {
|
||||
manifest {
|
||||
attributes("Main-Class" to "app.revanced.cli.main.MainKt")
|
||||
attributes("Implementation-Title" to project.name)
|
||||
attributes("Implementation-Version" to project.version)
|
||||
}
|
||||
}
|
||||
// Dummy task to fix the Gradle semantic-release plugin.
|
||||
// Remove this if you forked it to support building only.
|
||||
// Tracking issue: https://github.com/KengoTODA/gradle-semantic-release-plugin/issues/435
|
||||
|
||||
/*
|
||||
Dummy task to hack gradle-semantic-release-plugin to release this project.
|
||||
|
||||
Explanation:
|
||||
SemVer is a standard for versioning libraries.
|
||||
For that reason the semantic-release plugin uses the "publish" task to publish libraries.
|
||||
However, this subproject is not a library, and the "publish" task is not available for this subproject.
|
||||
Because semantic-release is not designed to handle this case, we need to hack it.
|
||||
|
||||
RE: https://github.com/KengoTODA/gradle-semantic-release-plugin/issues/435
|
||||
*/
|
||||
|
||||
register<DefaultTask>("publish") {
|
||||
group = "publish"
|
||||
description = "Dummy task"
|
||||
group = "publishing"
|
||||
description = "Dummy task to hack gradle-semantic-release-plugin to release ReVanced CLI"
|
||||
dependsOn(build)
|
||||
}
|
||||
}
|
||||
|
||||
15
docs/0_prerequisites.md
Normal file
15
docs/0_prerequisites.md
Normal file
@@ -0,0 +1,15 @@
|
||||
# 💼 Prerequisites
|
||||
|
||||
To use ReVanced CLI, you will need to fulfill specific requirements.
|
||||
|
||||
## 🤝 Requirements
|
||||
|
||||
- Java SDK 11 (Azul Zulu JDK or OpenJDK)
|
||||
- [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)
|
||||
|
||||
## ⏭️ Whats next
|
||||
|
||||
The following section will show you how to use ReVanced CLI.
|
||||
|
||||
Continue: [🛠️ Using ReVanced CLI](1_usage.md)
|
||||
136
docs/1_usage.md
Normal file
136
docs/1_usage.md
Normal file
@@ -0,0 +1,136 @@
|
||||
# 🛠️ Using ReVanced CLI
|
||||
|
||||
Learn how to ReVanced CLI.
|
||||
|
||||
## 🔨 Usage
|
||||
|
||||
ReVanced CLI is divided into the following fundamental commands:
|
||||
|
||||
- ### 🚀 Show all available options for ReVanced CLI
|
||||
|
||||
```bash
|
||||
java -jar revanced-cli.jar -h
|
||||
```
|
||||
|
||||
- ### 📃 List patches
|
||||
|
||||
```bash
|
||||
java -jar revanced-cli.jar list-patches \
|
||||
--with-packages \
|
||||
--with-versions \
|
||||
--with-options \
|
||||
revanced-patches.jar [<patch-bundle> ...]
|
||||
```
|
||||
|
||||
- ### ⚙️ Generate options
|
||||
|
||||
This will generate an `options.json` file for the patches from a list of supplied patch bundles.
|
||||
The file can be supplied to ReVanced CLI later on.
|
||||
|
||||
```bash
|
||||
java -jar revanced-cli.jar options \
|
||||
--path options.json \
|
||||
--overwrite \
|
||||
revanced-patches.jar [<patch-bundle> ...]
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> A default `options.json` file will be automatically created, if it does not exist
|
||||
without any need for intervention when using the `patch` command.
|
||||
|
||||
- ### 💉 Patch an app
|
||||
|
||||
You can patch apps by supplying patch bundles and the app to patch.
|
||||
After patching, ReVanced CLI can install the patched app on your device using two methods:
|
||||
|
||||
> [!NOTE]
|
||||
> For ReVanced CLI to be able to install the patched app on your device, make sure ADB is working:
|
||||
>
|
||||
> ```bash
|
||||
> adb shell exit
|
||||
> ```
|
||||
>
|
||||
> To get your device's serial, run the following command:
|
||||
>
|
||||
> ```bash
|
||||
> adb devices
|
||||
> ```
|
||||
>
|
||||
> If you want to mount the patched app on top of the un-patched app, make sure you have root permissions:
|
||||
>
|
||||
> ```bash
|
||||
> adb shell su -c exit
|
||||
> ```
|
||||
>
|
||||
|
||||
> [!WARNING]
|
||||
> Some patches may require integrations
|
||||
> such as [ReVanced Integrations](https://github.com/revanced/revanced-integrations).
|
||||
> Supply them with the option `--merge`. ReVanced Patcher will automatically determine if they are necessary.
|
||||
|
||||
- #### 👾 Patch an app and install it on your device regularly
|
||||
|
||||
```bash
|
||||
java -jar revanced-cli.jar patch \
|
||||
--patch-bundle revanced-patches.jar \
|
||||
--device-serial <device-serial> \
|
||||
input.apk
|
||||
```
|
||||
|
||||
- #### 👾 Patch an app and mount it on top of the un-patched app with root permissions
|
||||
|
||||
> [!IMPORTANT]
|
||||
> Ensure sure the same app you are patching and mounting over is installed on your device:
|
||||
>
|
||||
> ```bash
|
||||
> adb install app.apk
|
||||
> ```
|
||||
|
||||
> [!NOTE]
|
||||
> You can use the option `--ii` to include or `--ie` to exclude
|
||||
> patches by their index in relation to supplied patch bundles,
|
||||
> similarly to the option `--include` and `--exclude`.
|
||||
>
|
||||
> This is useful in case two patches have the same name, and you need to include or exclude one of them.
|
||||
> The index of a patch is calculated by the position of the patch in the list of patches
|
||||
> from patch bundles supplied using the option `--patch-bundle`.
|
||||
>
|
||||
> You can list all patches with their indices using the command `list-patches`.
|
||||
>
|
||||
> Keep in mind, that the indices can change based on the order of the patch bundles supplied,
|
||||
> as well if the patch bundles are updated, because patches can be added or removed.
|
||||
|
||||
```bash
|
||||
java -jar revanced-cli.jar patch \
|
||||
--patch-bundle revanced-patches.jar \
|
||||
--include "Some patch" \
|
||||
--ii 123 \
|
||||
--exclude "Some other patch" \
|
||||
--device-serial <device-serial> \
|
||||
--mount \
|
||||
app.apk
|
||||
```
|
||||
|
||||
- ### 🗑️ Uninstall an app
|
||||
|
||||
```bash
|
||||
java -jar revanced-cli.jar utility uninstall \
|
||||
--package-name <package-name> \
|
||||
[<device-serial>]
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> You can unmount an APK file
|
||||
by adding the option `--unmount`.
|
||||
|
||||
- ### ️ 📦 Install an app
|
||||
|
||||
```bash
|
||||
java -jar revanced-cli.jar utility install \
|
||||
-a input.apk \
|
||||
[<device-serial>]
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> You can mount an APK file
|
||||
> by supplying the package name of the app to mount the supplied APK file to over the option `--mount`.
|
||||
8
docs/README.md
Normal file
8
docs/README.md
Normal file
@@ -0,0 +1,8 @@
|
||||
# 💻 Documentation and guides of ReVanced CLI
|
||||
|
||||
This documentation explains how to use [ReVanced CLI](https://github.com/revanced/revanced-cli).
|
||||
|
||||
## 📖 Table of contents
|
||||
|
||||
1. [💼 Prerequisites](0_prerequisites.md)
|
||||
2. [🛠️ Using ReVanced CLI](1_usage.md)
|
||||
@@ -1,2 +1,4 @@
|
||||
org.gradle.parallel = true
|
||||
org.gradle.caching = true
|
||||
kotlin.code.style = official
|
||||
version = 2.11.2
|
||||
version = 4.4.0-dev.1
|
||||
|
||||
17
gradle/libs.versions.toml
Normal file
17
gradle/libs.versions.toml
Normal file
@@ -0,0 +1,17 @@
|
||||
[versions]
|
||||
shadow = "8.1.1"
|
||||
kotlin-test = "1.9.20"
|
||||
kotlinx-coroutines-core = "1.7.3"
|
||||
picocli = "4.7.3"
|
||||
revanced-patcher = "19.1.0"
|
||||
revanced-library = "1.4.0"
|
||||
|
||||
[libraries]
|
||||
kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin-test" }
|
||||
kotlinx-coroutines-core = { module = "org.jetbrains.kotlinx:kotlinx-coroutines-core", version.ref = "kotlinx-coroutines-core" }
|
||||
picocli = { module = "info.picocli:picocli", version.ref = "picocli" }
|
||||
revanced-patcher = { module = "app.revanced:revanced-patcher", version.ref = "revanced-patcher" }
|
||||
revanced-library = { module = "app.revanced:revanced-library", version.ref = "revanced-library" }
|
||||
|
||||
[plugins]
|
||||
shadow = { id = "com.github.johnrengelman.shadow", version.ref = "shadow" }
|
||||
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
5
gradle/wrapper/gradle-wrapper.properties
vendored
5
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,5 +1,6 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-all.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.4-bin.zip
|
||||
distributionSha256Sum=3e1af3ae886920c3ac87f7a91f816c0c7c436f276a6eefdb3da152100fef72ae
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
zipStorePath=wrapper/dist
|
||||
293
gradlew
vendored
293
gradlew
vendored
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env sh
|
||||
#!/bin/sh
|
||||
|
||||
#
|
||||
# Copyright 2015 the original author or authors.
|
||||
# Copyright © 2015-2021 the original authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
@@ -17,67 +17,98 @@
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
##
|
||||
#
|
||||
# Gradle start up script for POSIX generated by Gradle.
|
||||
#
|
||||
# Important for running:
|
||||
#
|
||||
# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
|
||||
# noncompliant, but you have some other compliant shell such as ksh or
|
||||
# bash, then to run this script, type that shell name before the whole
|
||||
# command line, like:
|
||||
#
|
||||
# ksh Gradle
|
||||
#
|
||||
# Busybox and similar reduced shells will NOT work, because this script
|
||||
# requires all of these POSIX shell features:
|
||||
# * functions;
|
||||
# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
|
||||
# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
|
||||
# * compound commands having a testable exit status, especially «case»;
|
||||
# * various built-in commands including «command», «set», and «ulimit».
|
||||
#
|
||||
# Important for patching:
|
||||
#
|
||||
# (2) This script targets any POSIX shell, so it avoids extensions provided
|
||||
# by Bash, Ksh, etc; in particular arrays are avoided.
|
||||
#
|
||||
# The "traditional" practice of packing multiple parameters into a
|
||||
# space-separated string is a well documented source of bugs and security
|
||||
# problems, so this is (mostly) avoided, by progressively accumulating
|
||||
# options in "$@", and eventually passing that to Java.
|
||||
#
|
||||
# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
|
||||
# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
|
||||
# see the in-line comments for details.
|
||||
#
|
||||
# There are tweaks for specific operating systems such as AIX, CygWin,
|
||||
# Darwin, MinGW, and NonStop.
|
||||
#
|
||||
# (3) This script is generated from the Groovy template
|
||||
# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
|
||||
# within the Gradle project.
|
||||
#
|
||||
# You can find Gradle at https://github.com/gradle/gradle/.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
# Attempt to set APP_HOME
|
||||
|
||||
# Resolve links: $0 may be a link
|
||||
PRG="$0"
|
||||
# Need this for relative symlinks.
|
||||
while [ -h "$PRG" ] ; do
|
||||
ls=`ls -ld "$PRG"`
|
||||
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||
if expr "$link" : '/.*' > /dev/null; then
|
||||
PRG="$link"
|
||||
else
|
||||
PRG=`dirname "$PRG"`"/$link"
|
||||
fi
|
||||
app_path=$0
|
||||
|
||||
# Need this for daisy-chained symlinks.
|
||||
while
|
||||
APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
|
||||
[ -h "$app_path" ]
|
||||
do
|
||||
ls=$( ls -ld "$app_path" )
|
||||
link=${ls#*' -> '}
|
||||
case $link in #(
|
||||
/*) app_path=$link ;; #(
|
||||
*) app_path=$APP_HOME$link ;;
|
||||
esac
|
||||
done
|
||||
SAVED="`pwd`"
|
||||
cd "`dirname \"$PRG\"`/" >/dev/null
|
||||
APP_HOME="`pwd -P`"
|
||||
cd "$SAVED" >/dev/null
|
||||
|
||||
APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
# This is normally unused
|
||||
# shellcheck disable=SC2034
|
||||
APP_BASE_NAME=${0##*/}
|
||||
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
MAX_FD=maximum
|
||||
|
||||
warn () {
|
||||
echo "$*"
|
||||
}
|
||||
} >&2
|
||||
|
||||
die () {
|
||||
echo
|
||||
echo "$*"
|
||||
echo
|
||||
exit 1
|
||||
}
|
||||
} >&2
|
||||
|
||||
# OS specific support (must be 'true' or 'false').
|
||||
cygwin=false
|
||||
msys=false
|
||||
darwin=false
|
||||
nonstop=false
|
||||
case "`uname`" in
|
||||
CYGWIN* )
|
||||
cygwin=true
|
||||
;;
|
||||
Darwin* )
|
||||
darwin=true
|
||||
;;
|
||||
MSYS* | MINGW* )
|
||||
msys=true
|
||||
;;
|
||||
NONSTOP* )
|
||||
nonstop=true
|
||||
;;
|
||||
case "$( uname )" in #(
|
||||
CYGWIN* ) cygwin=true ;; #(
|
||||
Darwin* ) darwin=true ;; #(
|
||||
MSYS* | MINGW* ) msys=true ;; #(
|
||||
NONSTOP* ) nonstop=true ;;
|
||||
esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
@@ -87,9 +118,9 @@ CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
# IBM's JDK on AIX uses strange locations for the executables
|
||||
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||
JAVACMD=$JAVA_HOME/jre/sh/java
|
||||
else
|
||||
JAVACMD="$JAVA_HOME/bin/java"
|
||||
JAVACMD=$JAVA_HOME/bin/java
|
||||
fi
|
||||
if [ ! -x "$JAVACMD" ] ; then
|
||||
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
|
||||
@@ -98,88 +129,120 @@ Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
else
|
||||
JAVACMD="java"
|
||||
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
JAVACMD=java
|
||||
if ! command -v java >/dev/null 2>&1
|
||||
then
|
||||
die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
|
||||
Please set the JAVA_HOME variable in your environment to match the
|
||||
location of your Java installation."
|
||||
fi
|
||||
fi
|
||||
|
||||
# Increase the maximum file descriptors if we can.
|
||||
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
|
||||
MAX_FD_LIMIT=`ulimit -H -n`
|
||||
if [ $? -eq 0 ] ; then
|
||||
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
|
||||
MAX_FD="$MAX_FD_LIMIT"
|
||||
fi
|
||||
ulimit -n $MAX_FD
|
||||
if [ $? -ne 0 ] ; then
|
||||
warn "Could not set maximum file descriptor limit: $MAX_FD"
|
||||
fi
|
||||
else
|
||||
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
|
||||
fi
|
||||
fi
|
||||
|
||||
# For Darwin, add options to specify how the application appears in the dock
|
||||
if $darwin; then
|
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
|
||||
SEP=""
|
||||
for dir in $ROOTDIRSRAW ; do
|
||||
ROOTDIRS="$ROOTDIRS$SEP$dir"
|
||||
SEP="|"
|
||||
done
|
||||
OURCYGPATTERN="(^($ROOTDIRS))"
|
||||
# Add a user-defined pattern to the cygpath arguments
|
||||
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
|
||||
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
|
||||
fi
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
i=0
|
||||
for arg in "$@" ; do
|
||||
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
|
||||
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
|
||||
|
||||
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
|
||||
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=`expr $i + 1`
|
||||
done
|
||||
case $i in
|
||||
0) set -- ;;
|
||||
1) set -- "$args0" ;;
|
||||
2) set -- "$args0" "$args1" ;;
|
||||
3) set -- "$args0" "$args1" "$args2" ;;
|
||||
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
|
||||
case $MAX_FD in #(
|
||||
max*)
|
||||
# In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC3045
|
||||
MAX_FD=$( ulimit -H -n ) ||
|
||||
warn "Could not query maximum file descriptor limit"
|
||||
esac
|
||||
case $MAX_FD in #(
|
||||
'' | soft) :;; #(
|
||||
*)
|
||||
# In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
|
||||
# shellcheck disable=SC3045
|
||||
ulimit -n "$MAX_FD" ||
|
||||
warn "Could not set maximum file descriptor limit to $MAX_FD"
|
||||
esac
|
||||
fi
|
||||
|
||||
# Escape application args
|
||||
save () {
|
||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||
echo " "
|
||||
}
|
||||
APP_ARGS=`save "$@"`
|
||||
# Collect all arguments for the java command, stacking in reverse order:
|
||||
# * args from the command line
|
||||
# * the main class name
|
||||
# * -classpath
|
||||
# * -D...appname settings
|
||||
# * --module-path (only if needed)
|
||||
# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
|
||||
|
||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if "$cygwin" || "$msys" ; then
|
||||
APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
|
||||
CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
|
||||
|
||||
JAVACMD=$( cygpath --unix "$JAVACMD" )
|
||||
|
||||
# Now convert the arguments - kludge to limit ourselves to /bin/sh
|
||||
for arg do
|
||||
if
|
||||
case $arg in #(
|
||||
-*) false ;; # don't mess with options #(
|
||||
/?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
|
||||
[ -e "$t" ] ;; #(
|
||||
*) false ;;
|
||||
esac
|
||||
then
|
||||
arg=$( cygpath --path --ignore --mixed "$arg" )
|
||||
fi
|
||||
# Roll the args list around exactly as many times as the number of
|
||||
# args, so each arg winds up back in the position where it started, but
|
||||
# possibly modified.
|
||||
#
|
||||
# NB: a `for` loop captures its iteration list before it begins, so
|
||||
# changing the positional parameters here affects neither the number of
|
||||
# iterations, nor the values presented in `arg`.
|
||||
shift # remove old arg
|
||||
set -- "$@" "$arg" # push replacement arg
|
||||
done
|
||||
fi
|
||||
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Collect all arguments for the java command;
|
||||
# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of
|
||||
# shell script including quotes and variable substitutions, so put them in
|
||||
# double quotes to make sure that they get re-expanded; and
|
||||
# * put everything else in single quotes, so that it's not re-expanded.
|
||||
|
||||
set -- \
|
||||
"-Dorg.gradle.appname=$APP_BASE_NAME" \
|
||||
-classpath "$CLASSPATH" \
|
||||
org.gradle.wrapper.GradleWrapperMain \
|
||||
"$@"
|
||||
|
||||
# Stop when "xargs" is not available.
|
||||
if ! command -v xargs >/dev/null 2>&1
|
||||
then
|
||||
die "xargs is not available"
|
||||
fi
|
||||
|
||||
# Use "xargs" to parse quoted args.
|
||||
#
|
||||
# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
|
||||
#
|
||||
# In Bash we could simply go:
|
||||
#
|
||||
# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
|
||||
# set -- "${ARGS[@]}" "$@"
|
||||
#
|
||||
# but POSIX shell has neither arrays nor command substitution, so instead we
|
||||
# post-process each arg (as a line of input to sed) to backslash-escape any
|
||||
# character that might be a shell metacharacter, then use eval to reverse
|
||||
# that process (while maintaining the separation between arguments), and wrap
|
||||
# the whole thing up as a single "set" statement.
|
||||
#
|
||||
# This will of course break if any of these variables contains a newline or
|
||||
# an unmatched quote.
|
||||
#
|
||||
|
||||
eval "set -- $(
|
||||
printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
|
||||
xargs -n1 |
|
||||
sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
|
||||
tr '\n' ' '
|
||||
)" '"$@"'
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
|
||||
15
gradlew.bat
vendored
15
gradlew.bat
vendored
@@ -14,7 +14,7 @@
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@if "%DEBUG%"=="" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@rem Gradle startup script for Windows
|
||||
@@ -25,7 +25,8 @@
|
||||
if "%OS%"=="Windows_NT" setlocal
|
||||
|
||||
set DIRNAME=%~dp0
|
||||
if "%DIRNAME%" == "" set DIRNAME=.
|
||||
if "%DIRNAME%"=="" set DIRNAME=.
|
||||
@rem This is normally unused
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@@ -40,7 +41,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto execute
|
||||
if %ERRORLEVEL% equ 0 goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
@@ -75,13 +76,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
if "%ERRORLEVEL%"=="0" goto mainEnd
|
||||
if %ERRORLEVEL% equ 0 goto mainEnd
|
||||
|
||||
:fail
|
||||
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
|
||||
rem the _cmd.exe /c_ return code!
|
||||
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
|
||||
exit /b 1
|
||||
set EXIT_CODE=%ERRORLEVEL%
|
||||
if %EXIT_CODE% equ 0 set EXIT_CODE=1
|
||||
if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
|
||||
exit /b %EXIT_CODE%
|
||||
|
||||
:mainEnd
|
||||
if "%OS%"=="Windows_NT" endlocal
|
||||
|
||||
11284
package-lock.json
generated
Normal file
11284
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
9
package.json
Normal file
9
package.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"devDependencies": {
|
||||
"@saithodev/semantic-release-backmerge": "^3.2.1",
|
||||
"@semantic-release/changelog": "^6.0.3",
|
||||
"@semantic-release/git": "^10.0.1",
|
||||
"gradle-semantic-release-plugin": "^1.8.0",
|
||||
"semantic-release": "^22.0.8"
|
||||
}
|
||||
}
|
||||
@@ -1 +1,7 @@
|
||||
rootProject.name = "revanced-cli"
|
||||
rootProject.name = "revanced-cli"
|
||||
|
||||
buildCache {
|
||||
local {
|
||||
isEnabled = !System.getenv().containsKey("CI")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
package app.revanced.cli.aligning
|
||||
|
||||
import app.revanced.cli.command.MainCommand.logger
|
||||
import app.revanced.utils.signing.align.ZipAligner
|
||||
import java.io.File
|
||||
|
||||
object Aligning {
|
||||
fun align(inputFile: File, outputFile: File) {
|
||||
logger.info("Aligning ${inputFile.name} to ${outputFile.name}")
|
||||
ZipAligner.align(inputFile, outputFile)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
package app.revanced.cli.command
|
||||
|
||||
import app.revanced.library.PackageName
|
||||
import app.revanced.library.PatchUtils
|
||||
import app.revanced.library.VersionMap
|
||||
import app.revanced.patcher.PatchBundleLoader
|
||||
import picocli.CommandLine
|
||||
import java.io.File
|
||||
import java.util.logging.Logger
|
||||
|
||||
@CommandLine.Command(
|
||||
name = "list-versions",
|
||||
description = [
|
||||
"List the most common compatible versions of apps that are compatible " +
|
||||
"with the patches in the supplied patch bundles.",
|
||||
],
|
||||
)
|
||||
internal class ListCompatibleVersions : Runnable {
|
||||
private val logger = Logger.getLogger(ListCompatibleVersions::class.java.name)
|
||||
|
||||
@CommandLine.Parameters(
|
||||
description = ["Paths to patch bundles."],
|
||||
arity = "1..*",
|
||||
)
|
||||
private lateinit var patchBundles: Array<File>
|
||||
|
||||
@CommandLine.Option(
|
||||
names = ["-f", "--filter-package-names"],
|
||||
description = ["Filter patches by package name."],
|
||||
)
|
||||
private var packageNames: Set<String>? = null
|
||||
|
||||
@CommandLine.Option(
|
||||
names = ["-u", "--count-unused-patches"],
|
||||
description = ["Count patches that are not used by default."],
|
||||
showDefaultValue = CommandLine.Help.Visibility.ALWAYS,
|
||||
)
|
||||
private var countUnusedPatches: Boolean = false
|
||||
|
||||
override fun run() {
|
||||
val patches = PatchBundleLoader.Jar(*patchBundles)
|
||||
|
||||
fun VersionMap.buildVersionsString(): String {
|
||||
if (isEmpty()) return "Any"
|
||||
|
||||
fun buildPatchesCountString(count: Int) = if (count == 1) "1 patch" else "$count patches"
|
||||
|
||||
return entries.joinToString("\n") { (version, count) ->
|
||||
"$version (${buildPatchesCountString(count)})"
|
||||
}
|
||||
}
|
||||
|
||||
fun buildString(entry: Map.Entry<PackageName, VersionMap>) =
|
||||
buildString {
|
||||
val (name, versions) = entry
|
||||
appendLine("Package name: $name")
|
||||
appendLine("Most common compatible versions:")
|
||||
appendLine(versions.buildVersionsString().prependIndent("\t"))
|
||||
}
|
||||
|
||||
PatchUtils.getMostCommonCompatibleVersions(
|
||||
patches,
|
||||
packageNames,
|
||||
countUnusedPatches,
|
||||
).entries.joinToString("\n", transform = ::buildString).let(logger::info)
|
||||
}
|
||||
}
|
||||
139
src/main/kotlin/app/revanced/cli/command/ListPatchesCommand.kt
Normal file
139
src/main/kotlin/app/revanced/cli/command/ListPatchesCommand.kt
Normal file
@@ -0,0 +1,139 @@
|
||||
package app.revanced.cli.command
|
||||
|
||||
import app.revanced.patcher.PatchBundleLoader
|
||||
import app.revanced.patcher.patch.Patch
|
||||
import app.revanced.patcher.patch.options.PatchOption
|
||||
import picocli.CommandLine.*
|
||||
import picocli.CommandLine.Help.Visibility.ALWAYS
|
||||
import java.io.File
|
||||
import java.util.logging.Logger
|
||||
|
||||
@Command(
|
||||
name = "list-patches",
|
||||
description = ["List patches from supplied patch bundles."],
|
||||
)
|
||||
internal object ListPatchesCommand : Runnable {
|
||||
private val logger = Logger.getLogger(ListPatchesCommand::class.java.name)
|
||||
|
||||
@Parameters(
|
||||
description = ["Paths to patch bundles."],
|
||||
arity = "1..*",
|
||||
)
|
||||
private lateinit var patchBundles: Array<File>
|
||||
|
||||
@Option(
|
||||
names = ["-d", "--with-descriptions"],
|
||||
description = ["List their descriptions."],
|
||||
showDefaultValue = ALWAYS,
|
||||
)
|
||||
private var withDescriptions: Boolean = true
|
||||
|
||||
@Option(
|
||||
names = ["-p", "--with-packages"],
|
||||
description = ["List the packages the patches are compatible with."],
|
||||
showDefaultValue = ALWAYS,
|
||||
)
|
||||
private var withPackages: Boolean = false
|
||||
|
||||
@Option(
|
||||
names = ["-v", "--with-versions"],
|
||||
description = ["List the versions of the apps the patches are compatible with."],
|
||||
showDefaultValue = ALWAYS,
|
||||
)
|
||||
private var withVersions: Boolean = false
|
||||
|
||||
@Option(
|
||||
names = ["-o", "--with-options"],
|
||||
description = ["List the options of the patches."],
|
||||
showDefaultValue = ALWAYS,
|
||||
)
|
||||
private var withOptions: Boolean = false
|
||||
|
||||
@Option(
|
||||
names = ["-u", "--with-universal-patches"],
|
||||
description = ["List patches which are compatible with any app."],
|
||||
showDefaultValue = ALWAYS,
|
||||
)
|
||||
private var withUniversalPatches: Boolean = true
|
||||
|
||||
@Option(
|
||||
names = ["-i", "--index"],
|
||||
description = ["List the index of each patch in relation to the supplied patch bundles."],
|
||||
showDefaultValue = ALWAYS,
|
||||
)
|
||||
private var withIndex: Boolean = true
|
||||
|
||||
@Option(
|
||||
names = ["-f", "--filter-package-name"],
|
||||
description = ["Filter patches by package name."],
|
||||
)
|
||||
private var packageName: String? = null
|
||||
|
||||
override fun run() {
|
||||
fun Patch.CompatiblePackage.buildString() =
|
||||
buildString {
|
||||
if (withVersions && versions != null) {
|
||||
appendLine("Package name: $name")
|
||||
appendLine("Compatible versions:")
|
||||
append(versions!!.joinToString("\n") { version -> version }.prependIndent("\t"))
|
||||
} else {
|
||||
append("Package name: $name")
|
||||
}
|
||||
}
|
||||
|
||||
fun PatchOption<*>.buildString() =
|
||||
buildString {
|
||||
appendLine("Title: $title")
|
||||
description?.let { appendLine("Description: $it") }
|
||||
default?.let {
|
||||
appendLine("Key: $key")
|
||||
append("Default: $it")
|
||||
} ?: append("Key: $key")
|
||||
|
||||
values?.let { values ->
|
||||
appendLine("\nValid values:")
|
||||
append(values.map { "${it.value} (${it.key})" }.joinToString("\n").prependIndent("\t"))
|
||||
}
|
||||
}
|
||||
|
||||
fun IndexedValue<Patch<*>>.buildString() =
|
||||
let { (index, patch) ->
|
||||
buildString {
|
||||
if (withIndex) appendLine("Index: $index")
|
||||
|
||||
append("Name: ${patch.name}")
|
||||
|
||||
if (withDescriptions) append("\nDescription: ${patch.description}")
|
||||
|
||||
if (withOptions && patch.options.isNotEmpty()) {
|
||||
appendLine("\nOptions:")
|
||||
append(
|
||||
patch.options.values.joinToString("\n\n") { option ->
|
||||
option.buildString()
|
||||
}.prependIndent("\t"),
|
||||
)
|
||||
}
|
||||
|
||||
if (withPackages && patch.compatiblePackages != null) {
|
||||
appendLine("\nCompatible packages:")
|
||||
append(
|
||||
patch.compatiblePackages!!.joinToString("\n") {
|
||||
it.buildString()
|
||||
}.prependIndent("\t"),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Patch<*>.filterCompatiblePackages(name: String) =
|
||||
compatiblePackages?.any { it.name == name }
|
||||
?: withUniversalPatches
|
||||
|
||||
val patches = PatchBundleLoader.Jar(*patchBundles).withIndex().toList()
|
||||
|
||||
val filtered =
|
||||
packageName?.let { patches.filter { (_, patch) -> patch.filterCompatiblePackages(it) } } ?: patches
|
||||
|
||||
if (filtered.isNotEmpty()) logger.info(filtered.joinToString("\n\n") { it.buildString() })
|
||||
}
|
||||
}
|
||||
@@ -1,263 +1,43 @@
|
||||
package app.revanced.cli.command
|
||||
|
||||
import app.revanced.cli.aligning.Aligning
|
||||
import app.revanced.cli.logging.impl.DefaultCliLogger
|
||||
import app.revanced.cli.patcher.Patcher
|
||||
import app.revanced.cli.patcher.logging.impl.PatcherLogger
|
||||
import app.revanced.cli.signing.Signing
|
||||
import app.revanced.cli.signing.SigningOptions
|
||||
import app.revanced.patcher.PatcherOptions
|
||||
import app.revanced.patcher.extensions.PatchExtensions.compatiblePackages
|
||||
import app.revanced.patcher.extensions.PatchExtensions.description
|
||||
import app.revanced.patcher.extensions.PatchExtensions.patchName
|
||||
import app.revanced.patcher.util.patch.impl.JarPatchBundle
|
||||
import app.revanced.utils.OptionsLoader
|
||||
import app.revanced.utils.adb.Adb
|
||||
import picocli.CommandLine.*
|
||||
import java.io.File
|
||||
import java.nio.file.Files
|
||||
import app.revanced.cli.command.utility.UtilityCommand
|
||||
import app.revanced.library.logging.Logger
|
||||
import picocli.CommandLine
|
||||
import picocli.CommandLine.Command
|
||||
import picocli.CommandLine.IVersionProvider
|
||||
import java.util.*
|
||||
|
||||
private class CLIVersionProvider : IVersionProvider {
|
||||
override fun getVersion() = arrayOf(
|
||||
MainCommand::class.java.`package`.implementationVersion ?: "unknown"
|
||||
)
|
||||
fun main(args: Array<String>) {
|
||||
Logger.setDefault()
|
||||
CommandLine(MainCommand).execute(*args).let(System::exit)
|
||||
}
|
||||
|
||||
private object CLIVersionProvider : IVersionProvider {
|
||||
override fun getVersion() =
|
||||
arrayOf(
|
||||
MainCommand::class.java.getResourceAsStream(
|
||||
"/app/revanced/cli/version.properties",
|
||||
)?.use { stream ->
|
||||
Properties().apply {
|
||||
load(stream)
|
||||
}.let {
|
||||
"ReVanced CLI v${it.getProperty("version")}"
|
||||
}
|
||||
} ?: "ReVanced CLI",
|
||||
)
|
||||
}
|
||||
|
||||
@Command(
|
||||
name = "ReVanced-CLI",
|
||||
name = "revanced-cli",
|
||||
description = ["Command line application to use ReVanced."],
|
||||
mixinStandardHelpOptions = true,
|
||||
versionProvider = CLIVersionProvider::class
|
||||
versionProvider = CLIVersionProvider::class,
|
||||
subcommands = [
|
||||
PatchCommand::class,
|
||||
OptionsCommand::class,
|
||||
ListPatchesCommand::class,
|
||||
ListCompatibleVersions::class,
|
||||
UtilityCommand::class,
|
||||
],
|
||||
)
|
||||
internal object MainCommand : Runnable {
|
||||
val logger = DefaultCliLogger()
|
||||
|
||||
@ArgGroup(exclusive = false, multiplicity = "1")
|
||||
lateinit var args: Args
|
||||
|
||||
class Args {
|
||||
@Option(names = ["-a", "--apk"], description = ["Input file to be patched"], required = true)
|
||||
lateinit var inputFile: File
|
||||
|
||||
@Option(names = ["--uninstall"], description = ["Uninstall the mount variant"])
|
||||
var uninstall: Boolean = false
|
||||
|
||||
@Option(names = ["-d", "--deploy-on"], description = ["If specified, deploy to adb device with given name"])
|
||||
var deploy: String? = null
|
||||
|
||||
@ArgGroup(exclusive = false)
|
||||
var patchArgs: PatchArgs? = null
|
||||
}
|
||||
|
||||
class PatchArgs {
|
||||
@Option(names = ["-b", "--bundles"], description = ["One or more bundles of patches"], required = true)
|
||||
var patchBundles = arrayOf<String>()
|
||||
|
||||
@Option(names = ["--options"], description = ["Configuration file for all patch options"])
|
||||
var options: File = File("options.toml")
|
||||
|
||||
@ArgGroup(exclusive = false)
|
||||
var listingArgs: ListingArgs? = null
|
||||
|
||||
@ArgGroup(exclusive = false)
|
||||
var patchingArgs: PatchingArgs? = null
|
||||
}
|
||||
|
||||
class ListingArgs {
|
||||
@Option(names = ["-l", "--list"], description = ["List patches only"], required = true)
|
||||
var listOnly: Boolean = false
|
||||
|
||||
@Option(names = ["--with-versions"], description = ["List patches with compatible versions"])
|
||||
var withVersions: Boolean = false
|
||||
|
||||
@Option(names = ["--with-packages"], description = ["List patches with compatible packages"])
|
||||
var withPackages: Boolean = false
|
||||
|
||||
@Option(names = ["--with-descriptions"], description = ["List patches with their descriptions"])
|
||||
var withDescriptions: Boolean = true
|
||||
}
|
||||
|
||||
class PatchingArgs {
|
||||
@Option(names = ["-o", "--out"], description = ["Output file path"], required = true)
|
||||
lateinit var outputPath: String
|
||||
|
||||
@Option(names = ["-e", "--exclude"], description = ["Explicitly exclude patches"])
|
||||
var excludedPatches = arrayOf<String>()
|
||||
|
||||
@Option(
|
||||
names = ["--exclusive"],
|
||||
description = ["Only installs the patches you include, not including any patch by default"]
|
||||
)
|
||||
var defaultExclude = false
|
||||
|
||||
@Option(names = ["-i", "--include"], description = ["Include patches"])
|
||||
var includedPatches = arrayOf<String>()
|
||||
|
||||
@Option(names = ["-r", "--resource-patcher"], description = ["Disable patching resources"])
|
||||
var disableResourcePatching: Boolean = false
|
||||
|
||||
@Option(names = ["--experimental"], description = ["Disable patch version compatibility patch"])
|
||||
var experimental: Boolean = false
|
||||
|
||||
@Option(names = ["-m", "--merge"], description = ["One or more dex file containers to merge"])
|
||||
var mergeFiles = listOf<File>()
|
||||
|
||||
@Option(names = ["--mount"], description = ["If specified, instead of installing, mount"])
|
||||
var mount: Boolean = false
|
||||
|
||||
@Option(names = ["--cn"], description = ["Overwrite the default CN for the signed file"])
|
||||
var cn = "ReVanced"
|
||||
|
||||
@Option(names = ["--keystore"], description = ["File path to your keystore"])
|
||||
var keystorePath: String? = null
|
||||
|
||||
@Option(names = ["-p", "--password"], description = ["Overwrite the default password for the signed file"])
|
||||
var password = "ReVanced"
|
||||
|
||||
@Option(names = ["-t", "--temp-dir"], description = ["Temporary resource cache directory"])
|
||||
var cacheDirectory = "revanced-cache"
|
||||
|
||||
@Option(
|
||||
names = ["-c", "--clean"],
|
||||
description = ["Clean the temporary resource cache directory. This will be done anyways when running the patcher"]
|
||||
)
|
||||
var clean: Boolean = false
|
||||
|
||||
@Option(names = ["--custom-aapt2-binary"], description = ["Path to custom aapt2 binary"])
|
||||
var aaptPath: String = ""
|
||||
}
|
||||
|
||||
override fun run() {
|
||||
if (args.patchArgs?.listingArgs?.listOnly == true) return printListOfPatches()
|
||||
if (args.uninstall) return uninstall()
|
||||
|
||||
val pArgs = this.args.patchArgs?.patchingArgs ?: return
|
||||
val outputFile = File(pArgs.outputPath) // the file to write to
|
||||
|
||||
val allPatches = args.patchArgs!!.patchBundles.flatMap { bundle ->
|
||||
JarPatchBundle(bundle).loadPatches()
|
||||
}
|
||||
|
||||
OptionsLoader.init(args.patchArgs!!.options, allPatches)
|
||||
|
||||
val patcher = app.revanced.patcher.Patcher(
|
||||
PatcherOptions(
|
||||
args.inputFile,
|
||||
pArgs.cacheDirectory,
|
||||
!pArgs.disableResourcePatching,
|
||||
pArgs.aaptPath,
|
||||
pArgs.cacheDirectory,
|
||||
PatcherLogger
|
||||
)
|
||||
)
|
||||
|
||||
// prepare adb
|
||||
val adb: Adb? = args.deploy?.let {
|
||||
Adb(outputFile, patcher.data.packageMetadata.packageName, args.deploy!!, !pArgs.mount)
|
||||
}
|
||||
|
||||
val patchedFile = File(pArgs.cacheDirectory).resolve("${outputFile.nameWithoutExtension}_raw.apk")
|
||||
|
||||
// start the patcher
|
||||
Patcher.start(patcher, patchedFile, allPatches)
|
||||
|
||||
val cacheDirectory = File(pArgs.cacheDirectory)
|
||||
|
||||
// align the file
|
||||
val alignedFile = cacheDirectory.resolve("${outputFile.nameWithoutExtension}_aligned.apk")
|
||||
Aligning.align(patchedFile, alignedFile)
|
||||
|
||||
// sign the file
|
||||
val finalFile = if (!pArgs.mount) {
|
||||
val signedOutput = cacheDirectory.resolve("${outputFile.nameWithoutExtension}_signed.apk")
|
||||
Signing.sign(
|
||||
alignedFile,
|
||||
signedOutput,
|
||||
SigningOptions(
|
||||
pArgs.cn,
|
||||
pArgs.password,
|
||||
pArgs.keystorePath ?: outputFile.absoluteFile.parentFile
|
||||
.resolve("${outputFile.nameWithoutExtension}.keystore")
|
||||
.canonicalPath
|
||||
)
|
||||
)
|
||||
|
||||
signedOutput
|
||||
} else
|
||||
alignedFile
|
||||
|
||||
// finally copy to the specified output file
|
||||
logger.info("Copying ${finalFile.name} to ${outputFile.name}")
|
||||
finalFile.copyTo(outputFile, overwrite = true)
|
||||
|
||||
// clean up the cache directory if needed
|
||||
if (pArgs.clean)
|
||||
cleanUp(pArgs.cacheDirectory)
|
||||
|
||||
// deploy if specified
|
||||
adb?.deploy()
|
||||
|
||||
if (pArgs.clean && args.deploy != null) Files.delete(outputFile.toPath())
|
||||
|
||||
logger.info("Finished")
|
||||
}
|
||||
|
||||
private fun cleanUp(cacheDirectory: String) {
|
||||
val result = if (File(cacheDirectory).deleteRecursively())
|
||||
"Cleaned up cache directory"
|
||||
else
|
||||
"Failed to clean up cache directory"
|
||||
logger.info(result)
|
||||
}
|
||||
|
||||
private fun uninstall() {
|
||||
// temporarily get package name using Patcher method
|
||||
// fix: abstract options in patcher
|
||||
val patcher = app.revanced.patcher.Patcher(
|
||||
PatcherOptions(
|
||||
args.inputFile,
|
||||
"uninstaller-cache",
|
||||
false
|
||||
)
|
||||
)
|
||||
File("uninstaller-cache").deleteRecursively()
|
||||
|
||||
val adb: Adb? = args.deploy?.let {
|
||||
Adb(File("placeholder_file"), patcher.data.packageMetadata.packageName, args.deploy!!, false)
|
||||
}
|
||||
adb?.uninstall()
|
||||
}
|
||||
|
||||
private fun printListOfPatches() {
|
||||
val logged = mutableListOf<String>()
|
||||
for (patchBundlePath in args.patchArgs?.patchBundles!!) for (patch in JarPatchBundle(patchBundlePath).loadPatches()) {
|
||||
if (patch.patchName in logged) continue
|
||||
for (compatiblePackage in patch.compatiblePackages!!) {
|
||||
val packageEntryStr = buildString {
|
||||
// Add package if flag is set
|
||||
if (args.patchArgs?.listingArgs?.withPackages == true) {
|
||||
val packageName = compatiblePackage.name.substringAfterLast(".").padStart(10)
|
||||
append(packageName)
|
||||
append("\t")
|
||||
}
|
||||
// Add patch name
|
||||
val patchName = patch.patchName.padStart(25)
|
||||
append(patchName)
|
||||
// Add description if flag is set.
|
||||
if (args.patchArgs?.listingArgs?.withDescriptions == true) {
|
||||
append("\t")
|
||||
append(patch.description)
|
||||
}
|
||||
// Add compatible versions, if flag is set
|
||||
if (args.patchArgs?.listingArgs?.withVersions == true) {
|
||||
val compatibleVersions = compatiblePackage.versions.joinToString(separator = ", ")
|
||||
append("\t")
|
||||
append(compatibleVersions)
|
||||
}
|
||||
}
|
||||
|
||||
logged.add(patch.patchName)
|
||||
logger.info(packageEntryStr)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
private object MainCommand
|
||||
|
||||
62
src/main/kotlin/app/revanced/cli/command/OptionsCommand.kt
Normal file
62
src/main/kotlin/app/revanced/cli/command/OptionsCommand.kt
Normal file
@@ -0,0 +1,62 @@
|
||||
package app.revanced.cli.command
|
||||
|
||||
import app.revanced.library.Options
|
||||
import app.revanced.library.Options.setOptions
|
||||
import app.revanced.patcher.PatchBundleLoader
|
||||
import picocli.CommandLine
|
||||
import picocli.CommandLine.Help.Visibility.ALWAYS
|
||||
import java.io.File
|
||||
import java.util.logging.Logger
|
||||
|
||||
@CommandLine.Command(
|
||||
name = "options",
|
||||
description = ["Generate options file from patches."],
|
||||
)
|
||||
internal object OptionsCommand : Runnable {
|
||||
private val logger = Logger.getLogger(OptionsCommand::class.java.name)
|
||||
|
||||
@CommandLine.Parameters(
|
||||
description = ["Paths to patch bundles."],
|
||||
arity = "1..*",
|
||||
)
|
||||
private lateinit var patchBundles: Array<File>
|
||||
|
||||
@CommandLine.Option(
|
||||
names = ["-p", "--path"],
|
||||
description = ["Path to patch options JSON file."],
|
||||
showDefaultValue = ALWAYS,
|
||||
)
|
||||
private var filePath: File = File("options.json")
|
||||
|
||||
@CommandLine.Option(
|
||||
names = ["-o", "--overwrite"],
|
||||
description = ["Overwrite existing options file."],
|
||||
showDefaultValue = ALWAYS,
|
||||
)
|
||||
private var overwrite: Boolean = false
|
||||
|
||||
@CommandLine.Option(
|
||||
names = ["-u", "--update"],
|
||||
description = ["Update existing options by adding missing and removing non-existent options."],
|
||||
showDefaultValue = ALWAYS,
|
||||
)
|
||||
private var update: Boolean = false
|
||||
|
||||
override fun run() =
|
||||
try {
|
||||
PatchBundleLoader.Jar(*patchBundles).let { patches ->
|
||||
val exists = filePath.exists()
|
||||
if (!exists || overwrite) {
|
||||
if (exists && update) patches.setOptions(filePath)
|
||||
|
||||
Options.serialize(patches, prettyPrint = true).let(filePath::writeText)
|
||||
} else {
|
||||
throw OptionsFileAlreadyExistsException()
|
||||
}
|
||||
}
|
||||
} catch (ex: OptionsFileAlreadyExistsException) {
|
||||
logger.severe("Options file already exists, use --overwrite to override it")
|
||||
}
|
||||
|
||||
class OptionsFileAlreadyExistsException : Exception()
|
||||
}
|
||||
413
src/main/kotlin/app/revanced/cli/command/PatchCommand.kt
Normal file
413
src/main/kotlin/app/revanced/cli/command/PatchCommand.kt
Normal file
@@ -0,0 +1,413 @@
|
||||
package app.revanced.cli.command
|
||||
|
||||
import app.revanced.library.ApkUtils
|
||||
import app.revanced.library.Options
|
||||
import app.revanced.library.Options.setOptions
|
||||
import app.revanced.library.adb.AdbManager
|
||||
import app.revanced.patcher.PatchBundleLoader
|
||||
import app.revanced.patcher.PatchSet
|
||||
import app.revanced.patcher.Patcher
|
||||
import app.revanced.patcher.PatcherOptions
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import picocli.CommandLine
|
||||
import picocli.CommandLine.Help.Visibility.ALWAYS
|
||||
import picocli.CommandLine.Model.CommandSpec
|
||||
import picocli.CommandLine.Spec
|
||||
import java.io.File
|
||||
import java.io.PrintWriter
|
||||
import java.io.StringWriter
|
||||
import java.util.logging.Logger
|
||||
|
||||
@CommandLine.Command(
|
||||
name = "patch",
|
||||
description = ["Patch an APK file."],
|
||||
)
|
||||
internal object PatchCommand : Runnable {
|
||||
private val logger = Logger.getLogger(PatchCommand::class.java.name)
|
||||
|
||||
@Spec
|
||||
lateinit var spec: CommandSpec // injected by picocli
|
||||
|
||||
private lateinit var apk: File
|
||||
|
||||
private var integrations = listOf<File>()
|
||||
|
||||
private var patchBundles = emptyList<File>()
|
||||
|
||||
@CommandLine.Option(
|
||||
names = ["-i", "--include"],
|
||||
description = ["List of patches to include."],
|
||||
)
|
||||
private var includedPatches = hashSetOf<String>()
|
||||
|
||||
@CommandLine.Option(
|
||||
names = ["--ii"],
|
||||
description = ["List of patches to include by their index in relation to the supplied patch bundles."],
|
||||
)
|
||||
private var includedPatchesByIndex = arrayOf<Int>()
|
||||
|
||||
@CommandLine.Option(
|
||||
names = ["-e", "--exclude"],
|
||||
description = ["List of patches to exclude."],
|
||||
)
|
||||
private var excludedPatches = hashSetOf<String>()
|
||||
|
||||
@CommandLine.Option(
|
||||
names = ["--ei"],
|
||||
description = ["List of patches to exclude by their index in relation to the supplied patch bundles."],
|
||||
)
|
||||
private var excludedPatchesByIndex = arrayOf<Int>()
|
||||
|
||||
@CommandLine.Option(
|
||||
names = ["--options"],
|
||||
description = ["Path to patch options JSON file."],
|
||||
)
|
||||
private var optionsFile: File? = null
|
||||
|
||||
@CommandLine.Option(
|
||||
names = ["--exclusive"],
|
||||
description = ["Only include patches that are explicitly specified to be included."],
|
||||
showDefaultValue = ALWAYS,
|
||||
)
|
||||
private var exclusive = false
|
||||
|
||||
@CommandLine.Option(
|
||||
names = ["-f", "--force"],
|
||||
description = ["Bypass compatibility checks for the supplied APK's version."],
|
||||
showDefaultValue = ALWAYS,
|
||||
)
|
||||
private var force: Boolean = false
|
||||
|
||||
private var outputFilePath: File? = null
|
||||
|
||||
@CommandLine.Option(
|
||||
names = ["-o", "--out"],
|
||||
description = ["Path to save the patched APK file to. Defaults to the same directory as the supplied APK file."],
|
||||
)
|
||||
private fun setOutputFilePath(outputFilePath: File?) {
|
||||
this.outputFilePath = outputFilePath?.absoluteFile
|
||||
}
|
||||
|
||||
@CommandLine.Option(
|
||||
names = ["-d", "--device-serial"],
|
||||
description = ["ADB device serial to install to. If not supplied, the first connected device will be used."],
|
||||
fallbackValue = "", // Empty string to indicate that the first connected device should be used.
|
||||
arity = "0..1",
|
||||
)
|
||||
private var deviceSerial: String? = null
|
||||
|
||||
@CommandLine.Option(
|
||||
names = ["--mount"],
|
||||
description = ["Install by mounting the patched APK file."],
|
||||
showDefaultValue = ALWAYS,
|
||||
)
|
||||
private var mount: Boolean = false
|
||||
|
||||
@CommandLine.Option(
|
||||
names = ["--keystore"],
|
||||
description = [
|
||||
"Path to the keystore to sign the patched APK file with. " +
|
||||
"Defaults to the same directory as the supplied APK file.",
|
||||
],
|
||||
)
|
||||
private var keystoreFilePath: File? = null
|
||||
|
||||
// key store password
|
||||
@CommandLine.Option(
|
||||
names = ["--keystore-password"],
|
||||
description = ["The password of the keystore to sign the patched APK file with. Empty password by default."],
|
||||
)
|
||||
private var keyStorePassword: String? = null // Empty password by default
|
||||
|
||||
@CommandLine.Option(
|
||||
names = ["--alias"],
|
||||
description = ["The alias of the key from the keystore to sign the patched APK file with."],
|
||||
showDefaultValue = ALWAYS,
|
||||
)
|
||||
private var alias = "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."],
|
||||
)
|
||||
private var password = "" // Empty password by default
|
||||
|
||||
@CommandLine.Option(
|
||||
names = ["--signer"],
|
||||
description = ["The name of the signer to sign the patched APK file with."],
|
||||
showDefaultValue = ALWAYS,
|
||||
)
|
||||
private var signer = "ReVanced"
|
||||
|
||||
@CommandLine.Option(
|
||||
names = ["-r", "--resource-cache"],
|
||||
description = ["Path to temporary resource cache directory."],
|
||||
)
|
||||
private var resourceCachePath: File? = null
|
||||
|
||||
private var aaptBinaryPath: File? = null
|
||||
|
||||
@CommandLine.Option(
|
||||
names = ["-p", "--purge"],
|
||||
description = ["Purge the temporary resource cache directory after patching."],
|
||||
showDefaultValue = ALWAYS,
|
||||
)
|
||||
private var purge: Boolean = false
|
||||
|
||||
@CommandLine.Option(
|
||||
names = ["-w", "--warn"],
|
||||
description = ["Warn if a patch can not be found in the supplied patch bundles."],
|
||||
showDefaultValue = ALWAYS,
|
||||
)
|
||||
private var warn: Boolean = false
|
||||
|
||||
@CommandLine.Parameters(
|
||||
description = ["APK file to be patched."],
|
||||
arity = "1..1",
|
||||
)
|
||||
@Suppress("unused")
|
||||
private fun setApk(apk: File) {
|
||||
if (!apk.exists()) {
|
||||
throw CommandLine.ParameterException(
|
||||
spec.commandLine(),
|
||||
"APK file ${apk.name} does not exist",
|
||||
)
|
||||
}
|
||||
this.apk = apk
|
||||
}
|
||||
|
||||
@CommandLine.Option(
|
||||
names = ["-m", "--merge"],
|
||||
description = ["One or more DEX files or containers to merge into the APK."],
|
||||
)
|
||||
@Suppress("unused")
|
||||
private fun setIntegrations(integrations: Array<File>) {
|
||||
integrations.firstOrNull { !it.exists() }?.let {
|
||||
throw CommandLine.ParameterException(spec.commandLine(), "Integrations file ${it.name} does not exist.")
|
||||
}
|
||||
this.integrations += integrations
|
||||
}
|
||||
|
||||
@CommandLine.Option(
|
||||
names = ["-b", "--patch-bundle"],
|
||||
description = ["One or more bundles of patches."],
|
||||
required = true,
|
||||
)
|
||||
@Suppress("unused")
|
||||
private fun setPatchBundles(patchBundles: Array<File>) {
|
||||
patchBundles.firstOrNull { !it.exists() }?.let {
|
||||
throw CommandLine.ParameterException(spec.commandLine(), "Patch bundle ${it.name} does not exist")
|
||||
}
|
||||
this.patchBundles = patchBundles.toList()
|
||||
}
|
||||
|
||||
@CommandLine.Option(
|
||||
names = ["--custom-aapt2-binary"],
|
||||
description = ["Path to a custom AAPT binary to compile resources with."],
|
||||
)
|
||||
@Suppress("unused")
|
||||
private fun setAaptBinaryPath(aaptBinaryPath: File) {
|
||||
if (!aaptBinaryPath.exists()) {
|
||||
throw CommandLine.ParameterException(
|
||||
spec.commandLine(),
|
||||
"AAPT binary ${aaptBinaryPath.name} does not exist",
|
||||
)
|
||||
}
|
||||
this.aaptBinaryPath = aaptBinaryPath
|
||||
}
|
||||
|
||||
override fun run() {
|
||||
// region Setup
|
||||
|
||||
val outputFilePath =
|
||||
outputFilePath ?: File("").absoluteFile.resolve(
|
||||
"${apk.nameWithoutExtension}-patched.${apk.extension}",
|
||||
)
|
||||
|
||||
val resourceCachePath =
|
||||
resourceCachePath ?: outputFilePath.parentFile.resolve(
|
||||
"${outputFilePath.nameWithoutExtension}-resource-cache",
|
||||
)
|
||||
|
||||
val optionsFile =
|
||||
optionsFile ?: outputFilePath.parentFile.resolve(
|
||||
"${outputFilePath.nameWithoutExtension}-options.json",
|
||||
)
|
||||
|
||||
val keystoreFilePath =
|
||||
keystoreFilePath ?: outputFilePath.parentFile
|
||||
.resolve("${outputFilePath.nameWithoutExtension}.keystore")
|
||||
|
||||
// endregion
|
||||
|
||||
// region Load patches
|
||||
|
||||
logger.info("Loading patches")
|
||||
|
||||
val patches = PatchBundleLoader.Jar(*patchBundles.toTypedArray())
|
||||
|
||||
// Warn if a patch can not be found in the supplied patch bundles.
|
||||
if (warn) {
|
||||
patches.map { it.name }.toHashSet().let { availableNames ->
|
||||
(includedPatches + excludedPatches).filter { name ->
|
||||
!availableNames.contains(name)
|
||||
}
|
||||
}.let { unknownPatches ->
|
||||
if (unknownPatches.isEmpty()) return@let
|
||||
logger.warning("Unknown input of patches:\n${unknownPatches.joinToString("\n")}")
|
||||
}
|
||||
}
|
||||
|
||||
// endregion
|
||||
|
||||
Patcher(
|
||||
PatcherOptions(
|
||||
apk,
|
||||
resourceCachePath,
|
||||
aaptBinaryPath?.path,
|
||||
resourceCachePath.absolutePath,
|
||||
true,
|
||||
),
|
||||
).use { patcher ->
|
||||
val filteredPatches =
|
||||
patcher.filterPatchSelection(patches).also { patches ->
|
||||
logger.info("Setting patch options")
|
||||
|
||||
if (optionsFile.exists()) {
|
||||
patches.setOptions(optionsFile)
|
||||
} else {
|
||||
Options.serialize(patches, prettyPrint = true).let(optionsFile::writeText)
|
||||
}
|
||||
}
|
||||
|
||||
// region Patch
|
||||
|
||||
val patcherResult =
|
||||
patcher.apply {
|
||||
acceptIntegrations(integrations)
|
||||
acceptPatches(filteredPatches.toList())
|
||||
|
||||
// Execute patches.
|
||||
runBlocking {
|
||||
apply(false).collect { patchResult ->
|
||||
patchResult.exception?.let {
|
||||
StringWriter().use { writer ->
|
||||
it.printStackTrace(PrintWriter(writer))
|
||||
logger.severe("${patchResult.patch.name} failed:\n$writer")
|
||||
}
|
||||
} ?: logger.info("${patchResult.patch.name} succeeded")
|
||||
}
|
||||
}
|
||||
}.get()
|
||||
|
||||
// endregion
|
||||
|
||||
// region Save
|
||||
|
||||
val alignedFile =
|
||||
resourceCachePath.resolve(apk.name).apply {
|
||||
ApkUtils.copyAligned(apk, this, patcherResult)
|
||||
}
|
||||
|
||||
if (!mount) {
|
||||
ApkUtils.sign(
|
||||
alignedFile,
|
||||
outputFilePath,
|
||||
ApkUtils.SigningOptions(
|
||||
keystoreFilePath,
|
||||
keyStorePassword,
|
||||
alias,
|
||||
password,
|
||||
signer,
|
||||
),
|
||||
)
|
||||
} else {
|
||||
alignedFile.renameTo(outputFilePath)
|
||||
}
|
||||
|
||||
logger.info("Saved to $outputFilePath")
|
||||
|
||||
// endregion
|
||||
|
||||
// region Install
|
||||
|
||||
deviceSerial?.let { serial ->
|
||||
AdbManager.getAdbManager(deviceSerial = serial.ifEmpty { null }, mount)
|
||||
}?.install(AdbManager.Apk(outputFilePath, patcher.context.packageMetadata.packageName))
|
||||
|
||||
// endregion
|
||||
}
|
||||
|
||||
if (purge) {
|
||||
logger.info("Purging temporary files")
|
||||
purge(resourceCachePath)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter the patches to be added to the patcher. The filter is based on the following:
|
||||
*
|
||||
* @param patches The patches to filter.
|
||||
* @return The filtered patches.
|
||||
*/
|
||||
private fun Patcher.filterPatchSelection(patches: PatchSet): PatchSet =
|
||||
buildSet {
|
||||
val packageName = context.packageMetadata.packageName
|
||||
val packageVersion = context.packageMetadata.packageVersion
|
||||
|
||||
patches.withIndex().forEach patch@{ (i, patch) ->
|
||||
val patchName = patch.name!!
|
||||
|
||||
val explicitlyExcluded = excludedPatches.contains(patchName) || excludedPatchesByIndex.contains(i)
|
||||
if (explicitlyExcluded) return@patch logger.info("Excluding $patchName")
|
||||
|
||||
// Make sure the patch is compatible with the supplied APK files package name and version.
|
||||
patch.compatiblePackages?.let { packages ->
|
||||
packages.singleOrNull { it.name == packageName }?.let { `package` ->
|
||||
val matchesVersion =
|
||||
force || `package`.versions?.let {
|
||||
it.any { version -> version == packageVersion }
|
||||
} ?: true
|
||||
|
||||
if (!matchesVersion) {
|
||||
return@patch logger.warning(
|
||||
"$patchName is incompatible with version $packageVersion. " +
|
||||
"This patch is only compatible with version " +
|
||||
packages.joinToString(";") { pkg ->
|
||||
pkg.versions!!.joinToString(", ")
|
||||
},
|
||||
)
|
||||
}
|
||||
} ?: return@patch logger.fine(
|
||||
"$patchName is incompatible with $packageName. " +
|
||||
"This patch is only compatible with " +
|
||||
packages.joinToString(", ") { `package` -> `package`.name },
|
||||
)
|
||||
|
||||
return@let
|
||||
} ?: logger.fine("$patchName has no constraint on packages.")
|
||||
|
||||
// If the patch is implicitly used, it will be only included if [exclusive] is false.
|
||||
val implicitlyIncluded = !exclusive && patch.use
|
||||
// If the patch is explicitly used, it will be included even if [exclusive] is false.
|
||||
val explicitlyIncluded = includedPatches.contains(patchName) || includedPatchesByIndex.contains(i)
|
||||
|
||||
val included = implicitlyIncluded || explicitlyIncluded
|
||||
if (!included) return@patch logger.info("$patchName excluded") // Case 1.
|
||||
|
||||
logger.fine("Adding $patchName")
|
||||
|
||||
add(patch)
|
||||
}
|
||||
}
|
||||
|
||||
private fun purge(resourceCachePath: File) {
|
||||
val result =
|
||||
if (resourceCachePath.deleteRecursively()) {
|
||||
"Purged resource cache directory"
|
||||
} else {
|
||||
"Failed to purge resource cache directory"
|
||||
}
|
||||
logger.info(result)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
package app.revanced.cli.command.utility
|
||||
|
||||
import app.revanced.library.adb.AdbManager
|
||||
import picocli.CommandLine.*
|
||||
import java.io.File
|
||||
import java.util.logging.Logger
|
||||
|
||||
@Command(
|
||||
name = "install",
|
||||
description = ["Install an APK file to devices with the supplied ADB device serials"],
|
||||
)
|
||||
internal object InstallCommand : Runnable {
|
||||
private val logger = Logger.getLogger(InstallCommand::class.java.name)
|
||||
|
||||
@Parameters(
|
||||
description = ["ADB device serials. 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"],
|
||||
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"],
|
||||
)
|
||||
private var packageName: String? = null
|
||||
|
||||
override fun run() {
|
||||
fun install(deviceSerial: String? = null) =
|
||||
try {
|
||||
AdbManager.getAdbManager(deviceSerial, packageName != null).install(AdbManager.Apk(apk, packageName))
|
||||
} catch (e: AdbManager.DeviceNotFoundException) {
|
||||
logger.severe(e.toString())
|
||||
}
|
||||
|
||||
deviceSerials?.forEach(::install) ?: install()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package app.revanced.cli.command.utility
|
||||
|
||||
import app.revanced.library.adb.AdbManager
|
||||
import picocli.CommandLine.*
|
||||
import picocli.CommandLine.Help.Visibility.ALWAYS
|
||||
import java.util.logging.Logger
|
||||
|
||||
@Command(
|
||||
name = "uninstall",
|
||||
description = ["Uninstall a patched app from the devices with the supplied ADB device serials"],
|
||||
)
|
||||
internal object UninstallCommand : Runnable {
|
||||
private val logger = Logger.getLogger(UninstallCommand::class.java.name)
|
||||
|
||||
@Parameters(
|
||||
description = ["ADB device serials. 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"],
|
||||
required = true,
|
||||
)
|
||||
private lateinit var packageName: String
|
||||
|
||||
@Option(
|
||||
names = ["-u", "--unmount"],
|
||||
description = ["Uninstall by unmounting the patched APK file"],
|
||||
showDefaultValue = ALWAYS,
|
||||
)
|
||||
private var unmount: Boolean = false
|
||||
|
||||
override fun run() {
|
||||
fun uninstall(deviceSerial: String? = null) =
|
||||
try {
|
||||
AdbManager.getAdbManager(deviceSerial, unmount).uninstall(packageName)
|
||||
} catch (e: AdbManager.DeviceNotFoundException) {
|
||||
logger.severe(e.toString())
|
||||
}
|
||||
|
||||
deviceSerials?.forEach { uninstall(it) } ?: uninstall()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
package app.revanced.cli.command.utility
|
||||
|
||||
import picocli.CommandLine
|
||||
|
||||
@CommandLine.Command(
|
||||
name = "utility",
|
||||
description = ["Commands for utility purposes"],
|
||||
subcommands = [InstallCommand::class, UninstallCommand::class],
|
||||
)
|
||||
internal object UtilityCommand
|
||||
@@ -1,8 +0,0 @@
|
||||
package app.revanced.cli.logging
|
||||
|
||||
internal interface CliLogger {
|
||||
fun error(msg: String)
|
||||
fun info(msg: String)
|
||||
fun trace(msg: String)
|
||||
fun warn(msg: String)
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
package app.revanced.cli.logging.impl
|
||||
|
||||
import app.revanced.cli.command.MainCommand
|
||||
import app.revanced.cli.logging.CliLogger
|
||||
import java.util.logging.Logger
|
||||
import java.util.logging.SimpleFormatter
|
||||
|
||||
internal class DefaultCliLogger(
|
||||
private val logger: Logger = Logger.getLogger(MainCommand::class.java.name),
|
||||
private val errorLogger: Logger = Logger.getLogger(logger.name + "Err")
|
||||
) : CliLogger {
|
||||
|
||||
init {
|
||||
logger.useParentHandlers = false
|
||||
if (logger.handlers.isEmpty()) {
|
||||
logger.addHandler(FlushingStreamHandler(System.out, SimpleFormatter()))
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
init {
|
||||
System.setProperty("java.util.logging.SimpleFormatter.format", "%4\$s: %5\$s %n")
|
||||
}
|
||||
}
|
||||
|
||||
override fun error(msg: String) = errorLogger.severe(msg)
|
||||
override fun info(msg: String) = logger.info(msg)
|
||||
override fun trace(msg: String) = logger.finest(msg)
|
||||
override fun warn(msg: String) = errorLogger.warning(msg)
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
package app.revanced.cli.logging.impl
|
||||
|
||||
import java.io.OutputStream
|
||||
import java.util.logging.Formatter
|
||||
import java.util.logging.LogRecord
|
||||
import java.util.logging.StreamHandler
|
||||
|
||||
internal class FlushingStreamHandler(out: OutputStream, format: Formatter) : StreamHandler(out, format) {
|
||||
override fun publish(record: LogRecord) {
|
||||
super.publish(record)
|
||||
flush()
|
||||
}
|
||||
}
|
||||
@@ -1,8 +0,0 @@
|
||||
package app.revanced.cli.main
|
||||
|
||||
import app.revanced.cli.command.MainCommand
|
||||
import picocli.CommandLine
|
||||
|
||||
internal fun main(args: Array<String>) {
|
||||
CommandLine(MainCommand).execute(*args)
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
package app.revanced.cli.patcher
|
||||
|
||||
import app.revanced.cli.command.MainCommand.args
|
||||
import app.revanced.cli.command.MainCommand.logger
|
||||
import app.revanced.patcher.data.Data
|
||||
import app.revanced.patcher.patch.Patch
|
||||
import app.revanced.utils.filesystem.ZipFileSystemUtils
|
||||
import app.revanced.utils.patcher.addPatchesFiltered
|
||||
import app.revanced.utils.patcher.applyPatchesVerbose
|
||||
import app.revanced.utils.patcher.mergeFiles
|
||||
import java.io.File
|
||||
import java.nio.file.Files
|
||||
|
||||
internal object Patcher {
|
||||
internal fun start(patcher: app.revanced.patcher.Patcher, output: File, allPatches: List<Class<out Patch<Data>>>) {
|
||||
val inputFile = args.inputFile
|
||||
val args = args.patchArgs?.patchingArgs!!
|
||||
|
||||
// merge files like necessary integrations
|
||||
patcher.mergeFiles()
|
||||
// add patches, but filter incompatible or excluded patches
|
||||
patcher.addPatchesFiltered(allPatches)
|
||||
// apply patches
|
||||
patcher.applyPatchesVerbose()
|
||||
|
||||
// write output file
|
||||
if (output.exists()) Files.delete(output.toPath())
|
||||
inputFile.copyTo(output)
|
||||
|
||||
val result = patcher.save()
|
||||
ZipFileSystemUtils(output).use { outputFileSystem ->
|
||||
// replace all dex files
|
||||
result.dexFiles.forEach {
|
||||
logger.info("Writing dex file ${it.name}")
|
||||
outputFileSystem.write(it.name, it.stream.readAllBytes())
|
||||
}
|
||||
|
||||
if (!args.disableResourcePatching) {
|
||||
logger.info("Writing resources...")
|
||||
|
||||
ZipFileSystemUtils(result.resourceFile!!).use { resourceFileSystem ->
|
||||
val resourceFiles = resourceFileSystem.getFile(File.separator)
|
||||
outputFileSystem.writePathRecursively(resourceFiles)
|
||||
}
|
||||
}
|
||||
|
||||
result.doNotCompress?.let { outputFileSystem.uncompress(*it.toTypedArray()) }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
package app.revanced.cli.patcher.logging.impl
|
||||
|
||||
import app.revanced.cli.logging.impl.DefaultCliLogger
|
||||
import java.util.logging.Logger
|
||||
|
||||
internal object PatcherLogger : app.revanced.patcher.logging.Logger{
|
||||
private val logger = DefaultCliLogger(Logger.getLogger(app.revanced.patcher.Patcher::class.java.name))
|
||||
|
||||
override fun error(msg: String) = logger.error(msg)
|
||||
override fun info(msg: String) = logger.info(msg)
|
||||
override fun warn(msg: String)= logger.warn(msg)
|
||||
override fun trace(msg: String)= logger.trace(msg)
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
package app.revanced.cli.signing
|
||||
|
||||
import app.revanced.cli.command.MainCommand.logger
|
||||
import app.revanced.utils.signing.Signer
|
||||
import java.io.File
|
||||
|
||||
object Signing {
|
||||
fun sign(alignedFile: File, signedOutput: File, signingOptions: SigningOptions) {
|
||||
logger.info("Signing ${alignedFile.name} to ${signedOutput.name}")
|
||||
Signer(signingOptions).signApk(alignedFile, signedOutput)
|
||||
}
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
package app.revanced.cli.signing
|
||||
|
||||
data class SigningOptions(
|
||||
val cn: String,
|
||||
val password: String,
|
||||
val keyStoreFilePath: String
|
||||
)
|
||||
@@ -1,77 +0,0 @@
|
||||
package app.revanced.utils
|
||||
|
||||
import app.revanced.cli.command.MainCommand.logger
|
||||
import app.revanced.patcher.Patcher
|
||||
import app.revanced.patcher.data.Data
|
||||
import app.revanced.patcher.extensions.PatchExtensions.options
|
||||
import app.revanced.patcher.extensions.PatchExtensions.patchName
|
||||
import app.revanced.patcher.patch.Patch
|
||||
import cc.ekblad.toml.encodeToString
|
||||
import cc.ekblad.toml.model.TomlValue
|
||||
import cc.ekblad.toml.serialization.from
|
||||
import cc.ekblad.toml.tomlMapper
|
||||
import java.io.File
|
||||
|
||||
private typealias PatchList = List<Class<out Patch<Data>>>
|
||||
private typealias OptionsMap = MutableMap<String, MutableMap<String, Any>>
|
||||
|
||||
object OptionsLoader {
|
||||
@JvmStatic
|
||||
private val mapper = tomlMapper {}
|
||||
|
||||
@JvmStatic
|
||||
fun init(file: File, patches: PatchList) {
|
||||
if (!file.exists()) file.createNewFile()
|
||||
val map = mapper.decodeWithDefaults(generateDefaults(patches), TomlValue.from(file.toPath()))
|
||||
readAndSet(map, patches)
|
||||
save(map, file)
|
||||
}
|
||||
|
||||
private fun readAndSet(map: OptionsMap, patches: PatchList) {
|
||||
for ((patchName, options) in map) {
|
||||
val patch = patches.find { it.patchName == patchName } ?: continue
|
||||
val patchOptions = patch.options ?: continue
|
||||
for ((key, value) in options) {
|
||||
if (value == "null") { // backwards compatibility, subject to removal
|
||||
options.remove(key)
|
||||
continue
|
||||
}
|
||||
try {
|
||||
patchOptions[key] = value
|
||||
} catch (e: Exception) {
|
||||
logger.error("Error while setting option $key for patch $patchName: ${e.message}")
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun save(map: OptionsMap, file: File) {
|
||||
val toml = mapper.encodeToString(map)
|
||||
file.writeText(
|
||||
"""
|
||||
# A list of options for each patch.
|
||||
# This file does not contain all options by default.
|
||||
# Run the CLI with the "--list --with-options" flags to see all available options.
|
||||
# You can also run the CLI with the aforementioned flags and a patch name to see all available options for that patch.
|
||||
# To set an option, add a line with the format "option = value" or set the value if the option already exists.
|
||||
# To reset an option to its default value, delete the line.
|
||||
# To reset all options to their default values, delete this file.
|
||||
#
|
||||
# This file was generated by ReVanced Patcher version ${Patcher.version}.
|
||||
""".trimIndent() + "\n\n$toml"
|
||||
)
|
||||
}
|
||||
|
||||
private fun generateDefaults(patches: PatchList) = buildMap {
|
||||
for (patch in patches) {
|
||||
val options = patch.options ?: continue
|
||||
if (!options.iterator().hasNext()) continue
|
||||
put(patch.patchName, buildMap {
|
||||
for (option in options) {
|
||||
put(option.key, option.value ?: continue)
|
||||
}
|
||||
} as MutableMap)
|
||||
}
|
||||
} as MutableMap
|
||||
}
|
||||
@@ -1,113 +0,0 @@
|
||||
package app.revanced.utils.adb
|
||||
|
||||
import app.revanced.cli.command.MainCommand.logger
|
||||
import se.vidstige.jadb.JadbConnection
|
||||
import se.vidstige.jadb.JadbDevice
|
||||
import se.vidstige.jadb.managers.PackageManager
|
||||
import java.io.File
|
||||
import java.util.concurrent.Executors
|
||||
|
||||
internal class Adb(
|
||||
private val file: File,
|
||||
private val packageName: String,
|
||||
deviceName: String,
|
||||
private val modeInstall: Boolean = false,
|
||||
private val logging: Boolean = true
|
||||
) {
|
||||
private val device: JadbDevice
|
||||
|
||||
init {
|
||||
device = JadbConnection().devices.find { it.serial == deviceName }
|
||||
?: throw IllegalArgumentException("No such device with name $deviceName")
|
||||
|
||||
if (!modeInstall && device.run("su -h", false) != 0)
|
||||
throw IllegalArgumentException("Root required on $deviceName. Task failed")
|
||||
}
|
||||
|
||||
private fun String.replacePlaceholder(with: String? = null): String {
|
||||
return this.replace(Constants.PLACEHOLDER, with ?: packageName)
|
||||
}
|
||||
|
||||
internal fun deploy() {
|
||||
if (modeInstall) {
|
||||
logger.info("Installing without mounting")
|
||||
|
||||
PackageManager(device).install(file)
|
||||
} else {
|
||||
logger.info("Installing by mounting")
|
||||
|
||||
// push patched file
|
||||
device.copy(Constants.PATH_INIT_PUSH, file)
|
||||
|
||||
// create revanced folder path
|
||||
device.run("${Constants.COMMAND_CREATE_DIR} ${Constants.PATH_REVANCED}")
|
||||
|
||||
// prepare mounting the apk
|
||||
device.run(Constants.COMMAND_PREPARE_MOUNT_APK.replacePlaceholder())
|
||||
|
||||
// push mount script
|
||||
device.createFile(
|
||||
Constants.PATH_INIT_PUSH,
|
||||
Constants.CONTENT_MOUNT_SCRIPT.replacePlaceholder()
|
||||
)
|
||||
// install mount script
|
||||
device.run(Constants.COMMAND_INSTALL_MOUNT.replacePlaceholder())
|
||||
|
||||
// unmount the apk for sanity
|
||||
device.run(Constants.COMMAND_UMOUNT.replacePlaceholder())
|
||||
// mount the apk
|
||||
device.run(Constants.PATH_MOUNT.replacePlaceholder())
|
||||
|
||||
// relaunch app
|
||||
device.run(Constants.COMMAND_RESTART.replacePlaceholder())
|
||||
|
||||
// log the app
|
||||
log()
|
||||
}
|
||||
}
|
||||
|
||||
internal fun uninstall() {
|
||||
logger.info("Uninstalling by unmounting")
|
||||
|
||||
// unmount the apk
|
||||
device.run(Constants.COMMAND_UMOUNT.replacePlaceholder())
|
||||
|
||||
// delete revanced app
|
||||
device.run(Constants.COMMAND_DELETE.replacePlaceholder(Constants.PATH_REVANCED_APP).replacePlaceholder())
|
||||
|
||||
// delete mount script
|
||||
device.run(Constants.COMMAND_DELETE.replacePlaceholder(Constants.PATH_MOUNT).replacePlaceholder())
|
||||
|
||||
logger.info("Finished uninstalling")
|
||||
}
|
||||
|
||||
private fun log() {
|
||||
val executor = Executors.newSingleThreadExecutor()
|
||||
val pipe = if (logging) {
|
||||
ProcessBuilder.Redirect.INHERIT
|
||||
} else {
|
||||
ProcessBuilder.Redirect.PIPE
|
||||
}
|
||||
|
||||
val process = device.buildCommand(Constants.COMMAND_LOGCAT.replacePlaceholder())
|
||||
.redirectOutput(pipe)
|
||||
.redirectError(pipe)
|
||||
.useExecutor(executor)
|
||||
.start()
|
||||
|
||||
Thread.sleep(500) // give the app some time to start up.
|
||||
while (true) {
|
||||
try {
|
||||
while (device.run("${Constants.COMMAND_PID_OF} $packageName") == 0) {
|
||||
Thread.sleep(1000)
|
||||
}
|
||||
break
|
||||
} catch (e: Exception) {
|
||||
throw RuntimeException("An error occurred while monitoring the state of app", e)
|
||||
}
|
||||
}
|
||||
logger.info("Stopped logging because the app was closed")
|
||||
process.destroy()
|
||||
executor.shutdown()
|
||||
}
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
package app.revanced.utils.adb
|
||||
|
||||
import se.vidstige.jadb.JadbDevice
|
||||
import se.vidstige.jadb.RemoteFile
|
||||
import se.vidstige.jadb.ShellProcessBuilder
|
||||
import java.io.File
|
||||
|
||||
internal fun JadbDevice.buildCommand(command: String, su: Boolean = true): ShellProcessBuilder {
|
||||
if (su) {
|
||||
return shellProcessBuilder("su -c \'$command\'")
|
||||
}
|
||||
|
||||
val args = command.split(" ") as ArrayList<String>
|
||||
val cmd = args.removeFirst()
|
||||
|
||||
return shellProcessBuilder(cmd, *args.toTypedArray())
|
||||
}
|
||||
|
||||
internal fun JadbDevice.run(command: String, su: Boolean = true): Int {
|
||||
return this.buildCommand(command, su).start().waitFor()
|
||||
}
|
||||
|
||||
internal fun JadbDevice.copy(targetPath: String, file: File) {
|
||||
push(file, RemoteFile(targetPath))
|
||||
}
|
||||
|
||||
internal fun JadbDevice.createFile(targetFile: String, content: String) {
|
||||
push(content.byteInputStream(), System.currentTimeMillis(), 644, RemoteFile(targetFile))
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
package app.revanced.utils.adb
|
||||
|
||||
internal object Constants {
|
||||
// template placeholder to replace a string in commands
|
||||
internal const val PLACEHOLDER = "TEMPLATE_PACKAGE_NAME"
|
||||
|
||||
// utility commands
|
||||
private const val COMMAND_CHMOD_MOUNT = "chmod +x"
|
||||
internal const val COMMAND_PID_OF = "pidof -s"
|
||||
internal const val COMMAND_CREATE_DIR = "mkdir -p"
|
||||
internal const val COMMAND_LOGCAT = "logcat -c && logcat | grep AndroidRuntime"
|
||||
internal const val COMMAND_RESTART = "monkey -p $PLACEHOLDER 1 && kill ${'$'}($COMMAND_PID_OF $PLACEHOLDER)"
|
||||
|
||||
// default mount file name
|
||||
private const val NAME_MOUNT_SCRIPT = "mount_revanced_$PLACEHOLDER.sh"
|
||||
|
||||
// initial directory to push files to via adb push
|
||||
internal const val PATH_INIT_PUSH = "/data/local/tmp/revanced.delete"
|
||||
|
||||
// revanced path
|
||||
internal const val PATH_REVANCED = "/data/adb/revanced/"
|
||||
|
||||
// revanced apk path
|
||||
internal const val PATH_REVANCED_APP = "$PATH_REVANCED$PLACEHOLDER.apk"
|
||||
|
||||
// delete command
|
||||
internal const val COMMAND_DELETE = "rm -rf $PLACEHOLDER"
|
||||
|
||||
// mount script path
|
||||
internal const val PATH_MOUNT = "/data/adb/service.d/$NAME_MOUNT_SCRIPT"
|
||||
|
||||
// move to revanced apk path & set permissions
|
||||
internal const val COMMAND_PREPARE_MOUNT_APK =
|
||||
"base_path=\"$PATH_REVANCED_APP\" && mv $PATH_INIT_PUSH ${'$'}base_path && chmod 644 ${'$'}base_path && chown system:system ${'$'}base_path && chcon u:object_r:apk_data_file:s0 ${'$'}base_path"
|
||||
|
||||
// unmount command
|
||||
internal const val COMMAND_UMOUNT =
|
||||
"stock_path=${'$'}( pm path $PLACEHOLDER | grep base | sed 's/package://g' ) && umount -l ${'$'}stock_path"
|
||||
|
||||
// install mount script & set permissions
|
||||
internal const val COMMAND_INSTALL_MOUNT = "mv $PATH_INIT_PUSH $PATH_MOUNT && $COMMAND_CHMOD_MOUNT $PATH_MOUNT"
|
||||
|
||||
// mount script
|
||||
internal val CONTENT_MOUNT_SCRIPT =
|
||||
"""
|
||||
#!/system/bin/sh
|
||||
MAGISKTMP="${'$'}(magisk --path)" || MAGISKTMP=/sbin
|
||||
MIRROR="${'$'}MAGISKTMP/.magisk/mirror"
|
||||
while [ "${'$'}(getprop sys.boot_completed | tr -d '\r')" != "1" ]; do sleep 1; done
|
||||
|
||||
base_path="$PATH_REVANCED_APP"
|
||||
stock_path=${'$'}( pm path $PLACEHOLDER | grep base | sed 's/package://g' )
|
||||
|
||||
chcon u:object_r:apk_data_file:s0 ${'$'}base_path
|
||||
mount -o bind ${'$'}MIRROR${'$'}base_path ${'$'}stock_path
|
||||
""".trimIndent()
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
package app.revanced.utils.filesystem
|
||||
|
||||
import java.io.Closeable
|
||||
import java.io.File
|
||||
import java.nio.file.FileSystems
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
import java.util.zip.ZipEntry
|
||||
|
||||
internal class ZipFileSystemUtils(
|
||||
file: File
|
||||
) : Closeable {
|
||||
private var zipFileSystem = FileSystems.newFileSystem(file.toPath(), mapOf("noCompression" to true))
|
||||
|
||||
private fun Path.deleteRecursively() {
|
||||
if (!Files.exists(this)) {
|
||||
throw IllegalStateException("File exists in real folder but not in zip file system")
|
||||
}
|
||||
|
||||
if (Files.isDirectory(this)) {
|
||||
Files.list(this).forEach { path ->
|
||||
path.deleteRecursively()
|
||||
}
|
||||
}
|
||||
|
||||
Files.delete(this)
|
||||
}
|
||||
|
||||
internal fun getFile(path: String) = zipFileSystem.getPath(path)
|
||||
|
||||
internal fun writePathRecursively(path: Path) {
|
||||
Files.list(path).use { fileStream ->
|
||||
fileStream.forEach { filePath ->
|
||||
val fileSystemPath = filePath.getRelativePath(path)
|
||||
fileSystemPath.deleteRecursively()
|
||||
}
|
||||
}
|
||||
|
||||
Files.walk(path).use { fileStream ->
|
||||
// don't include build directory
|
||||
// by skipping the root node.
|
||||
fileStream.skip(1).forEach { filePath ->
|
||||
val relativePath = filePath.getRelativePath(path)
|
||||
|
||||
if (Files.isDirectory(filePath)) {
|
||||
Files.createDirectory(relativePath)
|
||||
return@forEach
|
||||
}
|
||||
|
||||
Files.copy(filePath, relativePath)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal fun write(path: String, content: ByteArray) = Files.write(zipFileSystem.getPath(path), content)
|
||||
|
||||
private fun Path.getRelativePath(path: Path): Path = zipFileSystem.getPath(path.relativize(this).toString())
|
||||
|
||||
// TODO: figure out why the file system is uncompressed by default and how to fix it
|
||||
internal fun uncompress(vararg paths: String) =
|
||||
paths.forEach { Files.setAttribute(zipFileSystem.getPath(it), "zip:method", ZipEntry.STORED) }
|
||||
|
||||
override fun close() = zipFileSystem.close()
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
package app.revanced.utils.patcher
|
||||
|
||||
import app.revanced.cli.command.MainCommand
|
||||
import app.revanced.cli.command.MainCommand.args
|
||||
import app.revanced.cli.command.MainCommand.logger
|
||||
import app.revanced.patcher.Patcher
|
||||
import app.revanced.patcher.data.Data
|
||||
import app.revanced.patcher.extensions.PatchExtensions.compatiblePackages
|
||||
import app.revanced.patcher.extensions.PatchExtensions.deprecated
|
||||
import app.revanced.patcher.extensions.PatchExtensions.include
|
||||
import app.revanced.patcher.extensions.PatchExtensions.patchName
|
||||
import app.revanced.patcher.patch.Patch
|
||||
|
||||
fun Patcher.addPatchesFiltered(allPatches: List<Class<out Patch<Data>>>) {
|
||||
val packageName = this.data.packageMetadata.packageName
|
||||
val packageVersion = this.data.packageMetadata.packageVersion
|
||||
|
||||
val includedPatches = mutableListOf<Class<out Patch<Data>>>()
|
||||
allPatches.forEach patchLoop@{ patch ->
|
||||
val compatiblePackages = patch.compatiblePackages
|
||||
val patchName = patch.patchName
|
||||
|
||||
val prefix = "Skipping $patchName, reason"
|
||||
|
||||
val args = MainCommand.args.patchArgs?.patchingArgs!!
|
||||
|
||||
if (args.excludedPatches.contains(patchName)) {
|
||||
logger.info("$prefix: manually excluded")
|
||||
return@patchLoop
|
||||
} else if ((!patch.include || args.defaultExclude) && !args.includedPatches.contains(patchName)) {
|
||||
logger.info("$prefix: excluded by default")
|
||||
return@patchLoop
|
||||
}
|
||||
|
||||
patch.deprecated?.let { (reason, replacement) ->
|
||||
logger.warn("$prefix: deprecated: $reason")
|
||||
if (replacement != null) logger.warn("Either use ${replacement.java.patchName} instead or include it manually")
|
||||
return@patchLoop
|
||||
}
|
||||
|
||||
if (compatiblePackages == null) logger.warn("$prefix: Missing compatibility annotation. Continuing.")
|
||||
else {
|
||||
if (!compatiblePackages.any { it.name == packageName }) {
|
||||
logger.warn("$prefix: incompatible with $packageName. This patch is only compatible with ${
|
||||
compatiblePackages.joinToString(
|
||||
", "
|
||||
) { it.name }
|
||||
}")
|
||||
return@patchLoop
|
||||
}
|
||||
|
||||
if (!(args.experimental || compatiblePackages.any { it.versions.isEmpty() || it.versions.any { version -> version == packageVersion } })) {
|
||||
val compatibleWith = compatiblePackages.joinToString(";") { _package ->
|
||||
"${_package.name}: ${_package.versions.joinToString(", ")}"
|
||||
}
|
||||
logger.warn("$prefix: incompatible with version $packageVersion. This patch is only compatible with version $compatibleWith")
|
||||
return@patchLoop
|
||||
}
|
||||
}
|
||||
|
||||
logger.trace("Adding $patchName")
|
||||
includedPatches.add(patch)
|
||||
}
|
||||
|
||||
this.addPatches(includedPatches)
|
||||
}
|
||||
|
||||
fun Patcher.applyPatchesVerbose() {
|
||||
this.applyPatches().forEach { (patch, result) ->
|
||||
if (result.isSuccess) {
|
||||
logger.info("$patch succeeded")
|
||||
return@forEach
|
||||
}
|
||||
logger.error("$patch failed:")
|
||||
result.exceptionOrNull()!!.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
fun Patcher.mergeFiles() {
|
||||
this.addFiles(args.patchArgs?.patchingArgs!!.mergeFiles) { file ->
|
||||
logger.info("Merging $file")
|
||||
}
|
||||
}
|
||||
@@ -1,79 +0,0 @@
|
||||
package app.revanced.utils.signing
|
||||
|
||||
import app.revanced.cli.command.MainCommand.logger
|
||||
import app.revanced.cli.signing.SigningOptions
|
||||
import com.android.apksig.ApkSigner
|
||||
import org.bouncycastle.asn1.x500.X500Name
|
||||
import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo
|
||||
import org.bouncycastle.cert.X509v3CertificateBuilder
|
||||
import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter
|
||||
import org.bouncycastle.jce.provider.BouncyCastleProvider
|
||||
import org.bouncycastle.operator.ContentSigner
|
||||
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder
|
||||
import java.io.File
|
||||
import java.io.FileInputStream
|
||||
import java.io.FileOutputStream
|
||||
import java.math.BigInteger
|
||||
import java.security.*
|
||||
import java.security.cert.X509Certificate
|
||||
import java.util.*
|
||||
|
||||
internal class Signer(
|
||||
private val signingOptions: SigningOptions
|
||||
) {
|
||||
private val passwordCharArray = signingOptions.password.toCharArray()
|
||||
private fun newKeystore(out: File) {
|
||||
val (publicKey, privateKey) = createKey()
|
||||
val privateKS = KeyStore.getInstance("BKS", "BC")
|
||||
privateKS.load(null, passwordCharArray)
|
||||
privateKS.setKeyEntry("alias", privateKey, passwordCharArray, arrayOf(publicKey))
|
||||
privateKS.store(FileOutputStream(out), passwordCharArray)
|
||||
}
|
||||
|
||||
private fun createKey(): Pair<X509Certificate, PrivateKey> {
|
||||
val gen = KeyPairGenerator.getInstance("RSA")
|
||||
gen.initialize(2048)
|
||||
val pair = gen.generateKeyPair()
|
||||
var serialNumber: BigInteger
|
||||
do serialNumber = BigInteger.valueOf(SecureRandom().nextLong()) while (serialNumber < BigInteger.ZERO)
|
||||
val x500Name = X500Name("CN=${signingOptions.cn}")
|
||||
val builder = X509v3CertificateBuilder(
|
||||
x500Name,
|
||||
serialNumber,
|
||||
Date(System.currentTimeMillis() - 1000L * 60L * 60L * 24L * 30L),
|
||||
Date(System.currentTimeMillis() + 1000L * 60L * 60L * 24L * 366L * 30L),
|
||||
Locale.ENGLISH,
|
||||
x500Name,
|
||||
SubjectPublicKeyInfo.getInstance(pair.public.encoded)
|
||||
)
|
||||
val signer: ContentSigner = JcaContentSignerBuilder("SHA256withRSA").build(pair.private)
|
||||
return JcaX509CertificateConverter().getCertificate(builder.build(signer)) to pair.private
|
||||
}
|
||||
|
||||
fun signApk(input: File, output: File) {
|
||||
Security.addProvider(BouncyCastleProvider())
|
||||
|
||||
// TODO: keystore should be saved securely
|
||||
val ks = File(signingOptions.keyStoreFilePath)
|
||||
if (!ks.exists()) newKeystore(ks) else {
|
||||
logger.info("Found existing keystore: ${ks.name}")
|
||||
}
|
||||
|
||||
val keyStore = KeyStore.getInstance("BKS", "BC")
|
||||
FileInputStream(ks).use { fis -> keyStore.load(fis, null) }
|
||||
val alias = keyStore.aliases().nextElement()
|
||||
|
||||
val config = ApkSigner.SignerConfig.Builder(
|
||||
signingOptions.cn,
|
||||
keyStore.getKey(alias, passwordCharArray) as PrivateKey,
|
||||
listOf(keyStore.getCertificate(alias) as X509Certificate)
|
||||
).build()
|
||||
|
||||
val signer = ApkSigner.Builder(listOf(config))
|
||||
signer.setCreatedBy(signingOptions.cn)
|
||||
signer.setInputApk(input)
|
||||
signer.setOutputApk(output)
|
||||
|
||||
signer.build().sign()
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
package app.revanced.utils.signing.align
|
||||
|
||||
import app.revanced.utils.signing.align.zip.ZipFile
|
||||
import java.io.File
|
||||
|
||||
internal object ZipAligner {
|
||||
private const val DEFAULT_ALIGNMENT = 4
|
||||
private const val LIBRARY_ALIGNMENT = 4096
|
||||
|
||||
fun align(input: File, output: File) {
|
||||
val inputZip = ZipFile(input)
|
||||
val outputZip = ZipFile(output)
|
||||
|
||||
for (entry in inputZip.entries) {
|
||||
val data = inputZip.getDataForEntry(entry)
|
||||
|
||||
if (entry.compression == 0.toUShort()) {
|
||||
val alignment = if (entry.fileName.endsWith(".so")) LIBRARY_ALIGNMENT else DEFAULT_ALIGNMENT
|
||||
|
||||
outputZip.addEntryAligned(entry, data, alignment)
|
||||
} else {
|
||||
outputZip.addEntry(entry, data)
|
||||
}
|
||||
}
|
||||
|
||||
outputZip.finish()
|
||||
}
|
||||
}
|
||||
@@ -1,33 +0,0 @@
|
||||
package app.revanced.utils.signing.align.zip
|
||||
|
||||
import java.io.DataInput
|
||||
import java.io.DataOutput
|
||||
import java.nio.ByteBuffer
|
||||
|
||||
fun UInt.toLittleEndian() =
|
||||
(((this.toInt() and 0xff000000.toInt()) shr 24) or ((this.toInt() and 0x00ff0000) shr 8) or ((this.toInt() and 0x0000ff00) shl 8) or (this.toInt() shl 24)).toUInt()
|
||||
|
||||
fun UShort.toLittleEndian() = (this.toUInt() shl 16).toLittleEndian().toUShort()
|
||||
|
||||
fun UInt.toBigEndian() = (((this.toInt() and 0xff) shl 24) or ((this.toInt() and 0xff00) shl 8)
|
||||
or ((this.toInt() and 0x00ff0000) ushr 8) or (this.toInt() ushr 24)).toUInt()
|
||||
|
||||
fun UShort.toBigEndian() = (this.toUInt() shl 16).toBigEndian().toUShort()
|
||||
|
||||
fun ByteBuffer.getUShort() = this.getShort().toUShort()
|
||||
fun ByteBuffer.getUInt() = this.getInt().toUInt()
|
||||
|
||||
fun ByteBuffer.putUShort(ushort: UShort) = this.putShort(ushort.toShort())
|
||||
fun ByteBuffer.putUInt(uint: UInt) = this.putInt(uint.toInt())
|
||||
|
||||
fun DataInput.readUShort() = this.readShort().toUShort()
|
||||
fun DataInput.readUInt() = this.readInt().toUInt()
|
||||
|
||||
fun DataOutput.writeUShort(ushort: UShort) = this.writeShort(ushort.toInt())
|
||||
fun DataOutput.writeUInt(uint: UInt) = this.writeInt(uint.toInt())
|
||||
|
||||
fun DataInput.readUShortLE() = this.readUShort().toBigEndian()
|
||||
fun DataInput.readUIntLE() = this.readUInt().toBigEndian()
|
||||
|
||||
fun DataOutput.writeUShortLE(ushort: UShort) = this.writeUShort(ushort.toLittleEndian())
|
||||
fun DataOutput.writeUIntLE(uint: UInt) = this.writeUInt(uint.toLittleEndian())
|
||||
@@ -1,130 +0,0 @@
|
||||
package app.revanced.utils.signing.align.zip
|
||||
|
||||
import app.revanced.utils.signing.align.zip.structures.ZipEndRecord
|
||||
import app.revanced.utils.signing.align.zip.structures.ZipEntry
|
||||
import java.io.File
|
||||
import java.io.RandomAccessFile
|
||||
import java.nio.ByteBuffer
|
||||
import java.nio.channels.FileChannel
|
||||
|
||||
class ZipFile(val file: File) {
|
||||
var entries: MutableList<ZipEntry> = mutableListOf()
|
||||
|
||||
private val filePointer: RandomAccessFile = RandomAccessFile(file, "rw")
|
||||
|
||||
init {
|
||||
//if file isn't empty try to load entries
|
||||
if (file.length() > 0) {
|
||||
val endRecord = findEndRecord()
|
||||
|
||||
if (endRecord.diskNumber > 0u || endRecord.totalEntries != endRecord.diskEntries)
|
||||
throw IllegalArgumentException("Multi-file archives are not supported")
|
||||
|
||||
entries = readEntries(endRecord).toMutableList()
|
||||
}
|
||||
|
||||
//seek back to start for writing
|
||||
filePointer.seek(0)
|
||||
}
|
||||
|
||||
private fun findEndRecord(): ZipEndRecord {
|
||||
//look from end to start since end record is at the end
|
||||
for (i in filePointer.length() - 1 downTo 0) {
|
||||
filePointer.seek(i)
|
||||
//possible beginning of signature
|
||||
if (filePointer.readByte() == 0x50.toByte()) {
|
||||
//seek back to get the full int
|
||||
filePointer.seek(i)
|
||||
val possibleSignature = filePointer.readUIntLE()
|
||||
if (possibleSignature == ZipEndRecord.ECD_SIGNATURE) {
|
||||
filePointer.seek(i)
|
||||
return ZipEndRecord.fromECD(filePointer)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw Exception("Couldn't find end record")
|
||||
}
|
||||
|
||||
private fun readEntries(endRecord: ZipEndRecord): List<ZipEntry> {
|
||||
filePointer.seek(endRecord.centralDirectoryStartOffset.toLong())
|
||||
|
||||
val numberOfEntries = endRecord.diskEntries.toInt()
|
||||
|
||||
return buildList(numberOfEntries) {
|
||||
for (i in 1..numberOfEntries) {
|
||||
add(ZipEntry.fromCDE(filePointer).also
|
||||
{
|
||||
//for some reason the local extra field can be different from the central one
|
||||
it.readLocalExtra(
|
||||
filePointer.channel.map(
|
||||
FileChannel.MapMode.READ_ONLY,
|
||||
it.localHeaderOffset.toLong() + 28,
|
||||
2
|
||||
)
|
||||
)
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun writeCDE() {
|
||||
val CDEStart = filePointer.channel.position().toUInt()
|
||||
|
||||
entries.forEach {
|
||||
filePointer.channel.write(it.toCDE())
|
||||
}
|
||||
|
||||
val entriesCount = entries.size.toUShort()
|
||||
|
||||
val endRecord = ZipEndRecord(
|
||||
0u,
|
||||
0u,
|
||||
entriesCount,
|
||||
entriesCount,
|
||||
filePointer.channel.position().toUInt() - CDEStart,
|
||||
CDEStart,
|
||||
""
|
||||
)
|
||||
|
||||
filePointer.channel.write(endRecord.toECD())
|
||||
}
|
||||
|
||||
fun addEntry(entry: ZipEntry, data: ByteBuffer) {
|
||||
entry.localHeaderOffset = filePointer.channel.position().toUInt()
|
||||
|
||||
filePointer.channel.write(entry.toLFH())
|
||||
filePointer.channel.write(data)
|
||||
|
||||
entries.add(entry)
|
||||
}
|
||||
|
||||
fun addEntryAligned(entry: ZipEntry, data: ByteBuffer, alignment: Int) {
|
||||
//calculate where data would end up
|
||||
val dataOffset = filePointer.filePointer + entry.LFHSize
|
||||
|
||||
val mod = dataOffset % alignment
|
||||
|
||||
//wrong alignment
|
||||
if (mod != 0L) {
|
||||
//add padding at end of extra field
|
||||
entry.localExtraField =
|
||||
entry.localExtraField.copyOf((entry.localExtraField.size + (alignment - mod)).toInt())
|
||||
}
|
||||
|
||||
addEntry(entry, data)
|
||||
}
|
||||
|
||||
fun getDataForEntry(entry: ZipEntry): ByteBuffer {
|
||||
return filePointer.channel.map(
|
||||
FileChannel.MapMode.READ_ONLY,
|
||||
entry.dataOffset.toLong(),
|
||||
entry.compressedSize.toLong()
|
||||
)
|
||||
}
|
||||
|
||||
fun finish() {
|
||||
writeCDE()
|
||||
filePointer.close()
|
||||
}
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
package app.revanced.utils.signing.align.zip.structures
|
||||
|
||||
import app.revanced.utils.signing.align.zip.putUInt
|
||||
import app.revanced.utils.signing.align.zip.putUShort
|
||||
import app.revanced.utils.signing.align.zip.readUIntLE
|
||||
import app.revanced.utils.signing.align.zip.readUShortLE
|
||||
import java.io.DataInput
|
||||
import java.nio.ByteBuffer
|
||||
import java.nio.ByteOrder
|
||||
|
||||
data class ZipEndRecord(
|
||||
val diskNumber: UShort,
|
||||
val startingDiskNumber: UShort,
|
||||
val diskEntries: UShort,
|
||||
val totalEntries: UShort,
|
||||
val centralDirectorySize: UInt,
|
||||
val centralDirectoryStartOffset: UInt,
|
||||
val fileComment: String,
|
||||
) {
|
||||
|
||||
companion object {
|
||||
const val ECD_HEADER_SIZE = 22
|
||||
const val ECD_SIGNATURE = 0x06054b50u
|
||||
|
||||
fun fromECD(input: DataInput): ZipEndRecord {
|
||||
val signature = input.readUIntLE()
|
||||
|
||||
if (signature != ECD_SIGNATURE)
|
||||
throw IllegalArgumentException("Input doesn't start with end record signature")
|
||||
|
||||
val diskNumber = input.readUShortLE()
|
||||
val startingDiskNumber = input.readUShortLE()
|
||||
val diskEntries = input.readUShortLE()
|
||||
val totalEntries = input.readUShortLE()
|
||||
val centralDirectorySize = input.readUIntLE()
|
||||
val centralDirectoryStartOffset = input.readUIntLE()
|
||||
val fileCommentLength = input.readUShortLE()
|
||||
var fileComment = ""
|
||||
|
||||
if (fileCommentLength > 0u) {
|
||||
val fileCommentBytes = ByteArray(fileCommentLength.toInt())
|
||||
input.readFully(fileCommentBytes)
|
||||
fileComment = fileCommentBytes.toString(Charsets.UTF_8)
|
||||
}
|
||||
|
||||
return ZipEndRecord(
|
||||
diskNumber,
|
||||
startingDiskNumber,
|
||||
diskEntries,
|
||||
totalEntries,
|
||||
centralDirectorySize,
|
||||
centralDirectoryStartOffset,
|
||||
fileComment
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun toECD(): ByteBuffer {
|
||||
val commentBytes = fileComment.toByteArray(Charsets.UTF_8)
|
||||
|
||||
val buffer = ByteBuffer.allocate(ECD_HEADER_SIZE + commentBytes.size).also { it.order(ByteOrder.LITTLE_ENDIAN) }
|
||||
|
||||
buffer.putUInt(ECD_SIGNATURE)
|
||||
buffer.putUShort(diskNumber)
|
||||
buffer.putUShort(startingDiskNumber)
|
||||
buffer.putUShort(diskEntries)
|
||||
buffer.putUShort(totalEntries)
|
||||
buffer.putUInt(centralDirectorySize)
|
||||
buffer.putUInt(centralDirectoryStartOffset)
|
||||
buffer.putUShort(commentBytes.size.toUShort())
|
||||
|
||||
buffer.put(commentBytes)
|
||||
|
||||
buffer.flip()
|
||||
return buffer
|
||||
}
|
||||
}
|
||||
@@ -1,170 +0,0 @@
|
||||
package app.revanced.utils.signing.align.zip.structures
|
||||
|
||||
import app.revanced.utils.signing.align.zip.getUShort
|
||||
import app.revanced.utils.signing.align.zip.putUInt
|
||||
import app.revanced.utils.signing.align.zip.putUShort
|
||||
import app.revanced.utils.signing.align.zip.readUIntLE
|
||||
import app.revanced.utils.signing.align.zip.readUShortLE
|
||||
import java.io.DataInput
|
||||
import java.nio.ByteBuffer
|
||||
import java.nio.ByteOrder
|
||||
|
||||
data class ZipEntry(
|
||||
val version: UShort,
|
||||
val versionNeeded: UShort,
|
||||
val flags: UShort,
|
||||
val compression: UShort,
|
||||
val modificationTime: UShort,
|
||||
val modificationDate: UShort,
|
||||
val crc32: UInt,
|
||||
val compressedSize: UInt,
|
||||
val uncompressedSize: UInt,
|
||||
val diskNumber: UShort,
|
||||
val internalAttributes: UShort,
|
||||
val externalAttributes: UInt,
|
||||
var localHeaderOffset: UInt,
|
||||
val fileName: String,
|
||||
val extraField: ByteArray,
|
||||
val fileComment: String,
|
||||
var localExtraField: ByteArray = ByteArray(0), //seperate for alignment
|
||||
) {
|
||||
val LFHSize: Int
|
||||
get() = LFH_HEADER_SIZE + fileName.toByteArray(Charsets.UTF_8).size + localExtraField.size
|
||||
|
||||
val dataOffset: UInt
|
||||
get() = localHeaderOffset + LFHSize.toUInt()
|
||||
|
||||
companion object {
|
||||
const val CDE_HEADER_SIZE = 46
|
||||
const val CDE_SIGNATURE = 0x02014b50u
|
||||
|
||||
const val LFH_HEADER_SIZE = 30
|
||||
const val LFH_SIGNATURE = 0x04034b50u
|
||||
|
||||
fun fromCDE(input: DataInput): ZipEntry {
|
||||
val signature = input.readUIntLE()
|
||||
|
||||
if (signature != CDE_SIGNATURE)
|
||||
throw IllegalArgumentException("Input doesn't start with central directory entry signature")
|
||||
|
||||
val version = input.readUShortLE()
|
||||
val versionNeeded = input.readUShortLE()
|
||||
var flags = input.readUShortLE()
|
||||
val compression = input.readUShortLE()
|
||||
val modificationTime = input.readUShortLE()
|
||||
val modificationDate = input.readUShortLE()
|
||||
val crc32 = input.readUIntLE()
|
||||
val compressedSize = input.readUIntLE()
|
||||
val uncompressedSize = input.readUIntLE()
|
||||
val fileNameLength = input.readUShortLE()
|
||||
var fileName = ""
|
||||
val extraFieldLength = input.readUShortLE()
|
||||
var extraField = ByteArray(extraFieldLength.toInt())
|
||||
val fileCommentLength = input.readUShortLE()
|
||||
var fileComment = ""
|
||||
val diskNumber = input.readUShortLE()
|
||||
val internalAttributes = input.readUShortLE()
|
||||
val externalAttributes = input.readUIntLE()
|
||||
val localHeaderOffset = input.readUIntLE()
|
||||
|
||||
val variableFieldsLength = fileNameLength.toInt() + extraFieldLength.toInt() + fileCommentLength.toInt()
|
||||
|
||||
if (variableFieldsLength > 0) {
|
||||
val fileNameBytes = ByteArray(fileNameLength.toInt())
|
||||
input.readFully(fileNameBytes)
|
||||
fileName = fileNameBytes.toString(Charsets.UTF_8)
|
||||
|
||||
input.readFully(extraField)
|
||||
|
||||
val fileCommentBytes = ByteArray(fileCommentLength.toInt())
|
||||
input.readFully(fileCommentBytes)
|
||||
fileComment = fileCommentBytes.toString(Charsets.UTF_8)
|
||||
}
|
||||
|
||||
flags = (flags and 0b1000u.inv().toUShort()) //disable data descriptor flag as they are not used
|
||||
|
||||
return ZipEntry(
|
||||
version,
|
||||
versionNeeded,
|
||||
flags,
|
||||
compression,
|
||||
modificationTime,
|
||||
modificationDate,
|
||||
crc32,
|
||||
compressedSize,
|
||||
uncompressedSize,
|
||||
diskNumber,
|
||||
internalAttributes,
|
||||
externalAttributes,
|
||||
localHeaderOffset,
|
||||
fileName,
|
||||
extraField,
|
||||
fileComment,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun readLocalExtra(buffer: ByteBuffer) {
|
||||
buffer.order(ByteOrder.LITTLE_ENDIAN)
|
||||
localExtraField = ByteArray(buffer.getUShort().toInt())
|
||||
}
|
||||
|
||||
fun toLFH(): ByteBuffer {
|
||||
val nameBytes = fileName.toByteArray(Charsets.UTF_8)
|
||||
|
||||
val buffer = ByteBuffer.allocate(LFH_HEADER_SIZE + nameBytes.size + localExtraField.size)
|
||||
.also { it.order(ByteOrder.LITTLE_ENDIAN) }
|
||||
|
||||
buffer.putUInt(LFH_SIGNATURE)
|
||||
buffer.putUShort(versionNeeded)
|
||||
buffer.putUShort(flags)
|
||||
buffer.putUShort(compression)
|
||||
buffer.putUShort(modificationTime)
|
||||
buffer.putUShort(modificationDate)
|
||||
buffer.putUInt(crc32)
|
||||
buffer.putUInt(compressedSize)
|
||||
buffer.putUInt(uncompressedSize)
|
||||
buffer.putUShort(nameBytes.size.toUShort())
|
||||
buffer.putUShort(localExtraField.size.toUShort())
|
||||
|
||||
buffer.put(nameBytes)
|
||||
buffer.put(localExtraField)
|
||||
|
||||
buffer.flip()
|
||||
return buffer
|
||||
}
|
||||
|
||||
fun toCDE(): ByteBuffer {
|
||||
val nameBytes = fileName.toByteArray(Charsets.UTF_8)
|
||||
val commentBytes = fileComment.toByteArray(Charsets.UTF_8)
|
||||
|
||||
val buffer = ByteBuffer.allocate(CDE_HEADER_SIZE + nameBytes.size + extraField.size + commentBytes.size)
|
||||
.also { it.order(ByteOrder.LITTLE_ENDIAN) }
|
||||
|
||||
buffer.putUInt(CDE_SIGNATURE)
|
||||
buffer.putUShort(version)
|
||||
buffer.putUShort(versionNeeded)
|
||||
buffer.putUShort(flags)
|
||||
buffer.putUShort(compression)
|
||||
buffer.putUShort(modificationTime)
|
||||
buffer.putUShort(modificationDate)
|
||||
buffer.putUInt(crc32)
|
||||
buffer.putUInt(compressedSize)
|
||||
buffer.putUInt(uncompressedSize)
|
||||
buffer.putUShort(nameBytes.size.toUShort())
|
||||
buffer.putUShort(extraField.size.toUShort())
|
||||
buffer.putUShort(commentBytes.size.toUShort())
|
||||
buffer.putUShort(diskNumber)
|
||||
buffer.putUShort(internalAttributes)
|
||||
buffer.putUInt(externalAttributes)
|
||||
buffer.putUInt(localHeaderOffset)
|
||||
|
||||
buffer.put(nameBytes)
|
||||
buffer.put(extraField)
|
||||
buffer.put(commentBytes)
|
||||
|
||||
buffer.flip()
|
||||
return buffer
|
||||
}
|
||||
}
|
||||
|
||||
1
src/main/resources/app/revanced/cli/version.properties
Normal file
1
src/main/resources/app/revanced/cli/version.properties
Normal file
@@ -0,0 +1 @@
|
||||
version=${projectVersion}
|
||||
Reference in New Issue
Block a user