Compare commits

...

287 Commits

Author SHA1 Message Date
semantic-release-bot
f7fcbc55bb chore(release): 3.0.2-dev.2 [skip ci]
## [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](9fe5a0b6d9))
2023-08-28 16:38:55 +00:00
oSumAtrIX
9fe5a0b6d9 fix: check for package compatibility at first 2023-08-28 18:37:11 +02:00
semantic-release-bot
4f2d2568d3 chore(release): 3.0.2-dev.1 [skip ci]
## [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](a3d8f004ec))
2023-08-28 15:59:00 +00:00
semantic-release-bot
a3d8f004ec fix: do not filter explicitly included patches 2023-08-28 17:56:47 +02:00
semantic-release-bot
41ffc99ad0 chore(release): 3.0.1 [skip ci]
## [3.0.1](https://github.com/ReVanced/revanced-cli/compare/v3.0.0...v3.0.1) (2023-08-28)
2023-08-28 13:23:57 +00:00
oSumAtrIX
1121376018 chore: merge branch dev to main (#254) 2023-08-28 15:21:55 +02:00
semantic-release-bot
48e1689223 chore(release): 3.0.1-dev.1 [skip ci]
## [3.0.1-dev.1](https://github.com/ReVanced/revanced-cli/compare/v3.0.0...v3.0.1-dev.1) (2023-08-28)
2023-08-28 13:18:00 +00:00
oSumAtrIX
7580f5c2fc build(Needs bump): bump dependencies
This fixes an issue with flagging the resource table with sparse incorrectly.
2023-08-28 15:14:53 +02:00
semantic-release-bot
dd6c1392eb chore(release): 3.0.0 [skip ci]
# [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](52c3be23f2))
* delete temporary files after root installation ([a3d8705](a3d8705e89))
* do not delete output file ([0f3e090](0f3e090418))
* do not use absolute path from custom AAPT2 binary option ([a9c2a5f](a9c2a5f096))
* filtration of patches malfunctioning ([2d5a7fd](2d5a7fdf1e))
* fix running commands not running ([2c7fcaf](2c7fcaf4ad))
* only check once for patch options ([11c3a6c](11c3a6cfd4))
* print original instead of kebab cased names ([5eaad33](5eaad33dc1))
* print stack trace when a patch failed ([924c1f8](924c1f80ec))
* specify correct class containing entry-point ([1fcc591](1fcc591222))
* use correct option name ([f8972ea](f8972eac3e))

* refactor!: restructure code ([07da528](07da528ce2))

### Features

* add install command ([0350b7f](0350b7f1a2))
* add options command ([9edbbf3](9edbbf3163))
* Check for missing integrations ([c93186f](c93186fb97))
* Improve command line argument descriptions ([f9cf7d2](f9cf7d21b7))
* properly make use of logging facade ([41898d7](41898d7547))
* show full package name when listing patches ([#240](https://github.com/ReVanced/revanced-cli/issues/240)) ([7174364](7174364ef8))
* use better logging text ([b0e748d](b0e748daff))
* use friendly descriptions ([3dd875d](3dd875d14c))
* use separate command to list patches ([b74213f](b74213f66e))
* use separate command to patch ([32da961](32da961d57))
* use separate command to uninstall ([c0cc909](c0cc909626))
* use simpler log ([ba758f0](ba758f00f4))

### BREAKING CHANGES

* This introduces major changes to how ReVanced CLI is used from the command line.
2023-08-26 23:23:34 +00:00
oSumAtrIX
2a3dbafd17 chore: merge branch dev to main (#236) 2023-08-27 01:21:45 +02:00
semantic-release-bot
9e39a6f8e4 chore(release): 3.0.0-dev.10 [skip ci]
# [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](2d5a7fdf1e))
2023-08-25 21:48:59 +00:00
oSumAtrIX
2d5a7fdf1e fix: filtration of patches malfunctioning
Apparently, you were not able to include patches explicitly
2023-08-25 23:47:18 +02:00
semantic-release-bot
be5d812dff chore(release): 3.0.0-dev.9 [skip ci]
# [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](c93186fb97))
2023-08-25 00:28:57 +00:00
oSumAtrIX
c93186fb97 feat: Check for missing integrations
Check, if the integrations file exists at first.
2023-08-25 02:26:38 +02:00
semantic-release-bot
3a198052bb chore(release): 3.0.0-dev.8 [skip ci]
# [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](0f3e090418))
2023-08-24 23:32:29 +00:00
oSumAtrIX
0f3e090418 fix: do not delete output file
This fixes the output file to be deleted when the option `--purge` was used.
2023-08-25 01:30:28 +02:00
semantic-release-bot
6aed946183 chore(release): 3.0.0-dev.7 [skip ci]
# [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](924c1f80ec))
2023-08-24 21:47:17 +00:00
oSumAtrIX
924c1f80ec fix: print stack trace when a patch failed 2023-08-24 23:45:10 +02:00
semantic-release-bot
8dd709b6ef chore(release): 3.0.0-dev.6 [skip ci]
# [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)
2023-08-24 16:11:51 +00:00
oSumAtrIX
139e7facac build(Needs bump): depend on build task when publishing
This fixes the issue that no builds are generated
2023-08-24 18:09:35 +02:00
semantic-release-bot
1d26e572f7 chore(release): 3.0.0-dev.5 [skip ci]
# [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](52c3be23f2))
* delete temporary files after root installation ([a3d8705](a3d8705e89))
* fix running commands not running ([2c7fcaf](2c7fcaf4ad))
* only check once for patch options ([11c3a6c](11c3a6cfd4))

### Features

* add install command ([0350b7f](0350b7f1a2))
* use friendly descriptions ([3dd875d](3dd875d14c))
2023-08-24 15:53:09 +00:00
oSumAtrIX
2c7fcaf4ad fix: fix running commands not running 2023-08-24 17:51:31 +02:00
oSumAtrIX
52c3be23f2 fix: also delete temporary files when uninstalling 2023-08-24 16:54:08 +02:00
oSumAtrIX
3dd875d14c feat: use friendly descriptions 2023-08-24 16:53:31 +02:00
oSumAtrIX
0350b7f1a2 feat: add install command
This introduces a separate utility subcommand.
2023-08-24 16:50:10 +02:00
oSumAtrIX
a3d8705e89 fix: delete temporary files after root installation 2023-08-24 16:24:33 +02:00
oSumAtrIX
a536c9f815 refactor: use better identifiers 2023-08-24 16:24:18 +02:00
oSumAtrIX
11c3a6cfd4 fix: only check once for patch options
This prevents checking for the same patches options multiple times when it is already determined to not have any options
2023-08-24 15:52:12 +02:00
oSumAtrIX
a5851f0c1a build: clean after building 2023-08-24 15:35:27 +02:00
oSumAtrIX
963ae3a5fa docs: add missing inline docs 2023-08-24 15:35:27 +02:00
semantic-release-bot
93f338a731 chore(release): 3.0.0-dev.4 [skip ci]
# [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](41898d7547))
2023-08-24 02:56:08 +00:00
oSumAtrIX
7dcf15e03b build: bump dependencies 2023-08-24 04:52:53 +02:00
oSumAtrIX
41898d7547 feat: properly make use of logging facade 2023-08-24 04:41:44 +02:00
oSumAtrIX
45dd15f679 build: do not use a daemon when building
This decreases build times
2023-08-23 16:43:57 +02:00
semantic-release-bot
c2da04a834 chore(release): 3.0.0-dev.3 [skip ci]
# [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)
2023-08-23 14:40:41 +00:00
oSumAtrIX
f556909b9e build(Needs bump): run build task when dummy publication task is executed
This fixes issues with semantic-release not being able to upload release assets
2023-08-23 16:38:14 +02:00
semantic-release-bot
1fa3dd7b8c chore(release): 3.0.0-dev.2 [skip ci]
# [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](1fcc591222))
2023-08-23 12:53:55 +00:00
oSumAtrIX
1fcc591222 fix: specify correct class containing entry-point 2023-08-23 14:51:44 +02:00
oSumAtrIX
1fd3b83d46 docs: fix incorrect title 2023-08-23 05:39:31 +02:00
oSumAtrIX
7ec9040d41 docs: remove invalid codeblock 2023-08-23 05:37:19 +02:00
semantic-release-bot
44cc88b25d chore(release): 3.0.0-dev.1 [skip ci]
# [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](a9c2a5f096))
* use correct option name ([f8972ea](f8972eac3e))

* refactor!: restructure code ([07da528](07da528ce2))

### Features

* add options command ([9edbbf3](9edbbf3163))
* use better logging text ([b0e748d](b0e748daff))
* use separate command to list patches ([b74213f](b74213f66e))
* use separate command to patch ([32da961](32da961d57))
* use separate command to uninstall ([c0cc909](c0cc909626))
* use simpler log ([ba758f0](ba758f00f4))

### BREAKING CHANGES

* This introduces major changes to how ReVanced CLI is used from the command line.
2023-08-23 03:17:57 +00:00
oSumAtrIX
97548f80b3 build: fix dummy publish task 2023-08-23 05:16:17 +02:00
oSumAtrIX
d766f0e229 refactor!: restructure code (#242) 2023-08-23 04:57:46 +02:00
oSumAtrIX
b0e748daff feat: use better logging text 2023-08-23 04:46:42 +02:00
oSumAtrIX
ba758f00f4 feat: use simpler log 2023-08-23 04:32:28 +02:00
oSumAtrIX
a9c2a5f096 fix: do not use absolute path from custom AAPT2 binary option 2023-08-23 04:29:58 +02:00
oSumAtrIX
0dcd838de3 build: migrate dependencies to version catalogs 2023-08-23 04:28:12 +02:00
oSumAtrIX
a7290353bf build: make sure to add use all necessary repositories 2023-08-23 03:56:31 +02:00
oSumAtrIX
47a20afd2d docs: improve correctness 2023-08-23 03:53:24 +02:00
oSumAtrIX
f8972eac3e fix: use correct option name 2023-08-23 03:40:42 +02:00
oSumAtrIX
9edbbf3163 feat: add options command 2023-08-23 03:35:38 +02:00
oSumAtrIX
32da961d57 feat: use separate command to patch 2023-08-23 03:32:39 +02:00
oSumAtrIX
8a5daab2a3 build: add properties resource file 2023-08-23 03:30:13 +02:00
oSumAtrIX
c0cc909626 feat: use separate command to uninstall 2023-08-23 03:30:04 +02:00
oSumAtrIX
b74213f66e feat: use separate command to list patches 2023-08-22 23:41:32 +02:00
oSumAtrIX
fe75d4ab87 docs: use correct description 2023-08-22 23:41:32 +02:00
oSumAtrIX
07da528ce2 refactor!: restructure code
This commit focuses on improving code quality in a couple of places and bumping the dependency to ReVanced Patcher.

BREAKING CHANGE: This introduces major changes to how ReVanced CLI is used from the command line.
2023-08-22 23:41:31 +02:00
semantic-release-bot
ef5fa9b4c9 chore(release): 2.23.0-dev.5 [skip ci]
# [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)
2023-08-14 02:14:18 +00:00
oSumAtrIX
fc359923e3 build(Needs bump): Bump dependencies 2023-08-14 04:12:10 +02:00
semantic-release-bot
2e3cd90537 chore(release): 2.23.0-dev.4 [skip ci]
# [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](7174364ef8))
2023-08-13 11:44:20 +00:00
programminghoch10
7174364ef8 feat: show full package name when listing patches (#240) 2023-08-13 13:42:16 +02:00
oSumAtrIX
4c9d414228 docs: fix some mistakes 2023-08-10 02:06:13 +02:00
taku
5e73e6d2de docs: add missing prerequisites (#239)
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
2023-08-07 02:51:01 +02:00
semantic-release-bot
667ca3051c chore(release): 2.23.0-dev.3 [skip ci]
# [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)
2023-08-03 18:41:14 +00:00
oSumAtrIX
9220642a7b build(Needs bump): Bump compatibility 2023-08-03 20:38:48 +02:00
semantic-release-bot
3f47235c64 chore(release): 2.23.0-dev.2 [skip ci]
# [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)
2023-08-03 02:22:52 +00:00
oSumAtrIX
83b475c2e3 build(Needs bump): Update dependencies 2023-08-03 04:21:02 +02:00
semantic-release-bot
4105b638c0 chore(release): 2.23.0-dev.1 [skip ci]
# [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](f9cf7d21b7))
2023-07-30 00:52:33 +00:00
oSumAtrIX
f9cf7d21b7 feat: Improve command line argument descriptions 2023-07-30 02:49:49 +02:00
oSumAtrIX
0a758d86df build(Needs bump): Bump dependencies 2023-07-30 02:49:48 +02:00
oSumAtrIX
83f99e29ec ci: Change bumping commit scope 2023-07-30 02:49:39 +02:00
semantic-release-bot
00410d54c0 chore(release): 2.22.1-dev.1 [skip ci]
## [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](5eaad33dc1))
2023-07-24 12:20:19 +00:00
oSumAtrIX
5eaad33dc1 fix: print original instead of kebab cased names 2023-07-24 14:18:15 +02:00
semantic-release-bot
fa85482c4a chore(release): 2.22.0 [skip ci]
# [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](f6c221d72d))
2023-07-11 03:14:04 +00:00
oSumAtrIX
caed39af7f chore: merge branch dev to main (#233) 2023-07-11 05:12:30 +02:00
oSumAtrIX
20e1fdc18d chore: add notice to move option 2023-07-11 05:11:24 +02:00
semantic-release-bot
19cd541e9a chore(release): 2.22.0-dev.1 [skip ci]
# [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](e4908c7105))
2023-07-11 05:06:46 +02:00
oSumAtrIX
f6c221d72d feat: use new patch naming convention 2023-07-11 05:06:46 +02:00
oSumAtrIX
9c148c96bf chore: add README file 2023-07-06 20:19:19 +02:00
oSumAtrIX
2c5b53c7e9 build: update gradle 2023-07-05 23:07:31 +02:00
semantic-release-bot
77d9cb98d1 chore(release): 2.21.5 [skip ci]
## [2.21.5](https://github.com/revanced/revanced-cli/compare/v2.21.4...v2.21.5) (2023-07-01)
2023-07-01 12:45:44 +00:00
oSumAtrIX
38677e2319 chore: merge branch dev to main (#230) 2023-07-01 14:43:45 +02:00
semantic-release-bot
e5e768fa34 chore(release): 2.21.5-dev.2 [skip ci]
## [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)
2023-07-01 00:00:31 +00:00
oSumAtrIX
9082181ce5 build(revanced-patcher): bump version 2023-07-01 01:58:28 +02:00
oSumAtrIX
542580ecff docs: add section for patch options 2023-06-30 19:40:52 +02:00
semantic-release-bot
26112a4fd2 chore(release): 2.21.5-dev.1 [skip ci]
## [2.21.5-dev.1](https://github.com/revanced/revanced-cli/compare/v2.21.4...v2.21.5-dev.1) (2023-06-27)
2023-06-27 02:36:32 +00:00
oSumAtrIX
553fbdbb8f build(revanced-patcher): bump version 2023-06-27 04:10:34 +02:00
semantic-release-bot
be429a4770 chore(release): 2.21.4 [skip ci]
## [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](d0fc886428))
2023-06-21 23:31:29 +00:00
oSumAtrIX
8c391cecce chore: merge branch dev to main (#229) 2023-06-22 01:29:31 +02:00
semantic-release-bot
bd14bdb5ea chore(release): 2.21.4-dev.1 [skip ci]
## [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](d0fc886428))
2023-06-18 00:20:12 +00:00
oSumAtrIX
d0fc886428 fix: remove duplicate options entries. 2023-06-18 02:18:28 +02:00
semantic-release-bot
1ccbed8d17 chore(release): 2.21.3 [skip ci]
## [2.21.3](https://github.com/revanced/revanced-cli/compare/v2.21.2...v2.21.3) (2023-06-12)
2023-06-12 01:45:08 +00:00
oSumAtrIX
3b89fb7bc2 chore: merge branch dev to main (#228) 2023-06-12 03:43:20 +02:00
oSumAtrIX
16bb1a60fc ci: add cache step 2023-06-12 02:33:21 +02:00
oSumAtrIX
5f1843771e ci: build before running semantic-release 2023-06-12 01:52:53 +02:00
oSumAtrIX
9de90703c8 ci: remove unnecessary steps 2023-06-12 01:49:18 +02:00
semantic-release-bot
1201f9edc5 chore(release): 2.21.3-dev.1 [skip ci]
## [2.21.3-dev.1](https://github.com/revanced/revanced-cli/compare/v2.21.2...v2.21.3-dev.1) (2023-06-07)
2023-06-07 01:48:39 +00:00
oSumAtrIX
9c8f9608b2 build(revanced-patcher): bump version 2023-06-07 03:46:32 +02:00
semantic-release-bot
be90d2e360 chore(release): 2.21.2 [skip ci]
## [2.21.2](https://github.com/revanced/revanced-cli/compare/v2.21.1...v2.21.2) (2023-05-24)
2023-05-24 19:19:03 +00:00
oSumAtrIX
79dc99aa9b chore: merge branch dev to main (#225) 2023-05-24 21:17:06 +02:00
semantic-release-bot
260ff00951 chore(release): 2.21.2-dev.2 [skip ci]
## [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)
2023-05-24 01:57:56 +02:00
LisoUseInAIKyrios
cfe4c5ed0e build(revanced-patcher): bump version (#226) 2023-05-24 01:57:56 +02:00
oSumAtrIX
7133242691 build: use Java SDK 17 for building 2023-05-09 07:13:17 +02:00
semantic-release-bot
55750ce16a chore(release): 2.21.2-dev.1 [skip ci]
## [2.21.2-dev.1](https://github.com/revanced/revanced-cli/compare/v2.21.1...v2.21.2-dev.1) (2023-05-07)
2023-05-07 23:24:29 +00:00
oSumAtrIX
6003e68d47 docs: remove "the" in front of ReVanced names 2023-05-08 01:20:20 +02:00
oSumAtrIX
9f8c2aeedf build: downgrade to JDK version 11 2023-05-08 01:15:27 +02:00
oSumAtrIX
0a16bc849b build(revanced-patcher): bump version 2023-05-08 01:15:07 +02:00
semantic-release-bot
ecd5147590 chore(release): 2.21.1 [skip ci]
## [2.21.1](https://github.com/revanced/revanced-cli/compare/v2.21.0...v2.21.1) (2023-05-06)
2023-05-06 22:21:27 +00:00
oSumAtrIX
ca255c9e1b chore: merge branch dev to main (#224) 2023-05-07 00:19:48 +02:00
semantic-release-bot
e9aa490355 chore(release): 2.21.1-dev.1 [skip ci]
## [2.21.1-dev.1](https://github.com/revanced/revanced-cli/compare/v2.21.0...v2.21.1-dev.1) (2023-05-06)
2023-05-06 21:23:52 +00:00
oSumAtrIX
69fe59f97b ci: release when bumping ReVanced Patcher
This is required when two projects bump ReVanced Patcher, but one does not release a new version, resulting them to get out of sync. For that reason, commits of type `build` and scope `revanced-patcher` are treated as releasing commits.
2023-05-06 23:22:53 +02:00
oSumAtrIX
995e1712bc build(revanced-patcher): bump version 2023-05-06 23:22:52 +02:00
semantic-release-bot
a236f10bb0 chore(release): 2.21.0 [skip ci]
# [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](2ef48af1b3))
* use working JADB dependency version ([#222](https://github.com/revanced/revanced-cli/issues/222)) ([da2c918](da2c91874d))

### Features

* add appreciation message for new contributors ([6962fc2](6962fc2f4c))
2023-05-04 00:33:50 +00:00
oSumAtrIX
4a6134ea60 chore: merge branch dev to main (#219) 2023-05-04 02:32:03 +02:00
semantic-release-bot
b084024742 chore(release): 2.21.0-dev.1 [skip ci]
# [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](2ef48af1b3))
* use working JADB dependency version ([#222](https://github.com/revanced/revanced-cli/issues/222)) ([da2c918](da2c91874d))

### Features

* add appreciation message for new contributors ([6962fc2](6962fc2f4c))
2023-05-04 00:31:04 +00:00
oSumAtrIX
2ef48af1b3 fix(tests): set order of tests 2023-05-04 02:30:11 +02:00
bogadana
da2c91874d fix: use working JADB dependency version (#222)
This fixes a current issue with CI/CD failing
2023-05-04 02:30:10 +02:00
oSumAtrIX
379687c814 fix!: support null as option value (#221)
BREAKING-CHANGE: serialize options as JSON instead of TOML
2023-05-04 02:30:10 +02:00
oSumAtrIX
2f5577e464 chore: update gradle and dependencies 2023-05-04 02:30:10 +02:00
oSumAtrIX
6962fc2f4c feat: add appreciation message for new contributors 2023-05-04 02:30:09 +02:00
semantic-release-bot
a6cef26210 chore(release): 2.20.2 [skip ci]
## [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](31fb3166d9))
2023-04-30 01:00:27 +00:00
oSumAtrIX
b4892c4413 chore: merge branch dev to main (#210) 2023-04-30 02:58:45 +02:00
bitingsock
90368405ad docs: update name of example patch (#218) 2023-04-30 02:55:27 +02:00
oSumAtrIX
26967959e2 ci: only dispatch documentation update event if on branch main 2023-04-30 02:53:24 +02:00
oSumAtrIX
eac6f6fbe3 docs: fix spelling (#213) 2023-04-21 17:14:09 +02:00
EvadeMaster
af4ec43352 docs: fix misspelling word 2023-04-21 21:23:41 +07:00
semantic-release-bot
4f5644b62c chore(release): 2.20.2-dev.1 [skip ci]
## [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](31fb3166d9))
2023-04-03 03:08:42 +00:00
oSumAtrIX
31fb3166d9 fix: correct spelling mistake 2023-04-03 05:07:45 +02:00
oSumAtrIX
a76bd0ad35 chore: bump dependencies 2023-04-03 03:04:07 +02:00
oSumAtrIX
ba07ab1ac2 build: update Kotlin to 1.8.10 2023-03-31 17:20:15 +02:00
oSumAtrIX
92bf57f279 docs: remove unnecessary option 2023-03-19 22:48:37 +01:00
semantic-release-bot
886d501026 chore(release): 2.20.1 [skip ci]
## [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](ac3a8f66f7))
2023-03-14 15:00:44 +00:00
oSumAtrIX
4b04cc4b59 chore: merge branch dev to main (#205) 2023-03-14 15:59:14 +01:00
semantic-release-bot
75d237058f chore(release): 2.20.1-dev.1 [skip ci]
## [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](ac3a8f66f7))
2023-03-05 01:06:31 +00:00
oSumAtrIX
40026fe300 docs: fix output file name 2023-03-05 02:05:40 +01:00
semantic-release-bot
dbec559ed7 chore(release): 2.20.1-dev.1 [skip ci]
## [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](ac3a8f66f7))
2023-03-03 13:09:06 +00:00
Professsional
00e49719ca docs: fix invalid grammar (#206)
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
2023-03-03 14:08:13 +01:00
semantic-release-bot
df276846e1 chore(release): 2.20.1-dev.1 [skip ci]
## [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](ac3a8f66f7))
2023-03-02 19:39:20 +00:00
oSumAtrIX
ac3a8f66f7 fix: correctly word option descriptions
Signed-off-by: oSumAtrIX <johan.melkonyan1@web.de>
2023-03-02 20:38:02 +01:00
oSumAtrIX
e900ce8486 chore: remove project files 2023-03-02 20:37:57 +01:00
oSumAtrIX
ee6dd5a57c docs: update options usage
Signed-off-by: oSumAtrIX <johan.melkonyan1@web.de>
2023-02-27 01:07:57 +01:00
oSumAtrIX
23d9e1e841 ci: fix usage of backmergeBranches option
Signed-off-by: oSumAtrIX <johan.melkonyan1@web.de>
2023-02-27 00:57:46 +01:00
oSumAtrIX
3718b7992c build: update dependencies
Signed-off-by: oSumAtrIX <johan.melkonyan1@web.de>
2023-02-27 00:53:27 +01:00
oSumAtrIX
bce5e86874 ci: fix backmerge direction
Signed-off-by: oSumAtrIX <johan.melkonyan1@web.de>
2023-02-22 16:39:51 +01:00
oSumAtrIX
cda6df6238 ci: add backmerge target branch
Signed-off-by: oSumAtrIX <johan.melkonyan1@web.de>
2023-02-22 06:46:23 +01:00
oSumAtrIX
0dc230292a ci: use new semantic-release-backmerge option
Signed-off-by: oSumAtrIX <johan.melkonyan1@web.de>
2023-02-18 21:55:41 +01:00
oSumAtrIX
695cd1ba41 docs: correct note on excluding patches 2023-02-14 23:27:28 +01:00
Palm
d08bbf8664 ci: update actions (#204) 2023-02-13 22:35:05 +01:00
oSumAtrIX
d55dd0a1fc chore: merge branch dev to main (#201) 2023-02-10 05:36:19 +01:00
oSumAtrIX
a53d3482de build: bump patcher dependency version
Signed-off-by: oSumAtrIX <johan.melkonyan1@web.de>
2023-02-10 05:28:35 +01:00
semantic-release-bot
7a3d0420f7 chore(release): 2.20.0 [skip ci]
# [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](51c04b7b16))
* do not list compatible packages if patches do not define them ([31e4a41](31e4a41dd2))

### Features

* connect to first device if given device was not found ([6485e47](6485e477a1))
* remove option `--with-descriptions` ([07a423b](07a423b19e))
2023-01-18 20:36:39 +00:00
semantic-release-bot
5cddf5004e chore(release): 2.20.0 [skip ci]
# [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](51c04b7b16))
* do not list compatible packages if patches do not define them ([31e4a41](31e4a41dd2))

### Features

* connect to first device if given device was not found ([6485e47](6485e477a1))
* remove option `--with-descriptions` ([07a423b](07a423b19e))
2023-01-17 23:48:27 +00:00
oSumAtrIX
6393a5016a chore: merge branch dev to main (#196) 2023-01-18 00:47:01 +01:00
oSumAtrIX
cad38ca3bd ci: use PAT in step Release 2023-01-18 00:44:39 +01:00
oSumAtrIX
6c1169b433 chore: merge branch dev to main (#195) 2023-01-18 00:39:15 +01:00
oSumAtrIX
bf2bb72ce0 build: update dependencies
Signed-off-by: oSumAtrIX <johan.melkonyan1@web.de>
2023-01-18 00:33:00 +01:00
oSumAtrIX
567bdee887 chore: merge branch dev to main (#194) 2023-01-15 06:16:46 +01:00
semantic-release-bot
9888b0e08e chore(release): 2.20.0-dev.3 [skip ci]
# [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](51c04b7b16))
2023-01-15 04:36:31 +00:00
oSumAtrIX
51c04b7b16 fix: bump patcher dependency version
This commit addresses https://github.com/revanced/multidexlib2/issues/2.
2023-01-15 05:34:52 +01:00
semantic-release-bot
a39cf893d6 chore(release): 2.20.0-dev.2 [skip ci]
# [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](6485e477a1))
2023-01-15 04:25:04 +00:00
oSumAtrIX
6485e477a1 feat: connect to first device if given device was not found 2023-01-15 05:17:38 +01:00
oSumAtrIX
f99d340534 chore: merge branch dev to main (#193) 2023-01-13 22:33:19 +01:00
oSumAtrIX
4edc325978 ci: use PAT in step Release 2023-01-13 22:31:11 +01:00
oSumAtrIX
cffa1ea3a4 chore: merge branch dev to main (#192) 2023-01-13 16:04:32 +01:00
oSumAtrIX
d15505adaa ci: downgrade semantic release and plugins to v19 2023-01-13 15:50:39 +01:00
oSumAtrIX
aaf452a103 refactor: fix formatting 2023-01-13 14:41:38 +01:00
oSumAtrIX
1753a1aa3e ci: give jobs names 2023-01-13 14:41:18 +01:00
oSumAtrIX
f4e74cb4f2 docs: improve CLI usage commands 2023-01-13 00:13:45 +01:00
oSumAtrIX
50df4e117e docs: improve wording and accuracy 2023-01-09 10:11:15 +01:00
oSumAtrIX
9fcd2b4cd1 Merge branch 'main' into dev 2023-01-08 16:43:59 +01:00
oSumAtrIX
e6bb05c0b9 docs: init (#191) 2023-01-08 16:43:19 +01:00
oSumAtrIX
6bd7d42e32 ci: dispatch event to revanced/revanced-documentation on push to /docs 2023-01-08 14:46:13 +01:00
oSumAtrIX
19200eacc1 docs: init 2023-01-08 14:37:41 +01:00
semantic-release-bot
666738ee57 chore(release): 2.20.0 [skip ci]
# [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](31e4a41dd2))

### Features

* remove option `--with-descriptions` ([07a423b](07a423b19e))
2023-01-02 08:15:31 +00:00
oSumAtrIX
961267b8cd chore: merge branch dev to main (#190) 2023-01-02 09:13:55 +01:00
oSumAtrIX
6b7314a399 build: bump patcher dependency version (#189) 2023-01-02 09:11:19 +01:00
semantic-release-bot
c8a47c51df chore(release): 2.20.0 [skip ci]
# [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](31e4a41dd2))

### Features

* remove option `--with-descriptions` ([07a423b](07a423b19e))
2023-01-01 17:15:28 +00:00
oSumAtrIX
72d8f73d7f chore: merge branch dev to main (#188) 2023-01-01 18:14:36 +01:00
semantic-release-bot
1957a2c4ff chore(release): 2.20.0-dev.1 [skip ci]
# [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](31e4a41dd2))

### Features

* remove option `--with-descriptions` ([07a423b](07a423b19e))
2023-01-01 17:12:07 +00:00
oSumAtrIX
07a423b19e feat: remove option --with-descriptions 2023-01-01 18:11:10 +01:00
oSumAtrIX
31e4a41dd2 fix: do not list compatible packages if patches do not define them 2023-01-01 18:11:10 +01:00
semantic-release-bot
8284c1048f chore(release): 2.19.0 [skip ci]
# [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](b69e784785))
2022-12-31 18:22:25 +00:00
oSumAtrIX
9c64f5ec3e chore: merge branch dev to main (#184) 2022-12-31 19:20:26 +01:00
semantic-release-bot
f4c447e71b chore(release): 2.19.0-dev.1 [skip ci]
# [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](b69e784785))
2022-12-31 18:19:03 +00:00
oSumAtrIX
b69e784785 feat: improve description of options (#185) 2022-12-31 19:17:57 +01:00
oSumAtrIX
ccce9c926d ci: do not escape in environment variable MESSAGE 2022-12-29 19:07:33 +01:00
oSumAtrIX
dc4ab22f41 chore: bump patcher dependency version 2022-12-18 22:20:20 +01:00
semantic-release-bot
25d8ad4aaf chore(release): 2.18.2 [skip ci]
## [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](d5794b94ca))
2022-12-16 16:10:17 +00:00
oSumAtrIX
3d9436e691 chore: merge branch dev to main (#180) 2022-12-16 17:08:38 +01:00
semantic-release-bot
ee70423527 chore(release): 2.18.2-dev.1 [skip ci]
## [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](d5794b94ca))
2022-12-16 15:54:28 +00:00
oSumAtrIX
d5794b94ca fix: exclude patcher dependency from minimizing 2022-12-16 16:53:01 +01:00
oSumAtrIX
3160d894da chore: merge branch dev to main (#179) 2022-12-16 01:25:15 +01:00
oSumAtrIX
545597959a refactor: remove unused class ZipFileUtils 2022-12-16 01:23:37 +01:00
semantic-release-bot
a6db0edc70 chore(release): 2.18.1 [skip ci]
## [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](ad81a1b656))
2022-12-15 23:50:16 +00:00
oSumAtrIX
ff0d3dd224 chore: merge branch dev to main (#178) 2022-12-15 23:43:46 +01:00
semantic-release-bot
d9a1fd33ed chore(release): 2.18.1-dev.1 [skip ci]
## [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](ad81a1b656))
2022-12-15 22:43:16 +00:00
oSumAtrIX
ad81a1b656 fix: don't log when package is incompatible and exclusive option is used 2022-12-15 23:41:42 +01:00
oSumAtrIX
8c2aeff2cf build: exclude Bouncy Castle dependency from minimizing 2022-12-15 23:41:42 +01:00
semantic-release-bot
eb6c659f5b chore(release): 2.18.0 [skip ci]
# [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](ae91b0d597))
* use correct prefix in log message ([1a67cd8](1a67cd81da))

### Features

* simplify log message ([74d73ca](74d73ca3a7))
2022-12-15 21:11:11 +00:00
semantic-release-bot
bac4f839c9 chore(release): 2.18.0 [skip ci]
# [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](ae91b0d597))
* use correct prefix in log message ([1a67cd8](1a67cd81da))

### Features

* simplify log message ([74d73ca](74d73ca3a7))
2022-12-15 21:06:50 +00:00
oSumAtrIX
c1e7215d31 chore: merge branch dev to main (#176) 2022-12-15 22:05:59 +01:00
semantic-release-bot
18d132123f chore(release): 2.18.0-dev.1 [skip ci]
# [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](ae91b0d597))
* use correct prefix in log message ([1a67cd8](1a67cd81da))

### Features

* simplify log message ([74d73ca](74d73ca3a7))
2022-12-15 21:04:58 +00:00
oSumAtrIX
74d73ca3a7 feat: simplify log message 2022-12-15 22:03:47 +01:00
oSumAtrIX
ae91b0d597 fix: start with uppercase in log message 2022-12-15 22:03:29 +01:00
oSumAtrIX
1a67cd81da fix: use correct prefix in log message 2022-12-15 22:00:08 +01:00
oSumAtrIX
9b9fad7cc0 chore: merge branch dev to main (#174) 2022-12-15 21:46:55 +01:00
oSumAtrIX
1620305b4a ci: do not release on build commit type 2022-12-15 19:47:48 +01:00
semantic-release-bot
d906edbe78 chore(release): 2.17.1-dev.2 [skip ci]
## [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)
2022-12-15 18:34:01 +00:00
oSumAtrIX
4e53638cb9 build: exclude Kotlin standard library dependencies from minimizing 2022-12-15 19:32:08 +01:00
semantic-release-bot
7d1f200621 chore(release): 2.17.1-dev.1 [skip ci]
## [2.17.1-dev.1](https://github.com/revanced/revanced-cli/compare/v2.17.0...v2.17.1-dev.1) (2022-12-15)
2022-12-15 00:01:17 +00:00
oSumAtrIX
a7db6cb8f1 build: do not comment on successful releases 2022-12-15 01:00:22 +01:00
semantic-release-bot
d61ab058da chore(release): 2.17.0 [skip ci]
# [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](6e703eb8e8))

### Features

* improve missing compatibility annotation tracing log ([2c7eb72](2c7eb7274c))
* trace logs when compatibility annotation is missing ([#166](https://github.com/revanced/revanced-cli/issues/166)) ([c590bf5](c590bf559c))
2022-12-14 23:48:26 +00:00
oSumAtrIX
235c2742ec chore: merge branch dev to main (#173) 2022-12-15 00:39:03 +01:00
semantic-release-bot
8a964efd00 chore(release): 2.17.0-dev.3 [skip ci]
# [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](2c7eb7274c))
2022-12-14 23:37:35 +00:00
oSumAtrIX
8114d1dca0 build: remove unnecessary step 2022-12-15 00:32:48 +01:00
oSumAtrIX
5a7cadd96d build: remove manifest attributes 2022-12-15 00:32:47 +01:00
oSumAtrIX
1c5983b803 build: minimize shadow jar 2022-12-15 00:32:47 +01:00
oSumAtrIX
2c7eb7274c feat: improve missing compatibility annotation tracing log 2022-12-15 00:32:47 +01:00
oSumAtrIX
512152fb66 ci: stash before rebasing 2022-12-15 00:32:47 +01:00
oSumAtrIX
8793b5fc65 chore: merge branch dev to main (#167) 2022-12-14 01:18:05 +01:00
semantic-release-bot
39c490d6b7 chore(release): 2.17.0-dev.2 [skip ci]
# [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](6e703eb8e8))
2022-12-14 00:16:38 +00:00
oSumAtrIX
6e703eb8e8 fix: invalid header when writing a ZipFile (#169) 2022-12-14 01:14:00 +01:00
oSumAtrIX
c677eb9792 ci: back-merge releases back into dev branch 2022-12-14 01:13:45 +01:00
oSumAtrIX
75c8ea4639 chore: bump patcher dependency version 2022-12-14 01:13:00 +01:00
semantic-release-bot
b69dd52ca9 chore(release): 2.17.0-dev.1 [skip ci]
# [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](c590bf559c))
2022-12-11 19:10:19 +00:00
oSumAtrIX
c590bf559c feat: trace logs when compatibility annotation is missing (#166) 2022-12-11 20:08:52 +01:00
oSumAtrIX
ec0b847419 chore: merge branch dev to main (#165) 2022-12-11 05:19:08 +01:00
oSumAtrIX
b3cf32e89d ci: open pull requests to merge dev to main (#164) 2022-12-11 05:16:51 +01:00
oSumAtrIX
8a1199ba9a ci: refactor release workflow 2022-12-11 05:14:23 +01:00
oSumAtrIX
25b45800a1 chore: bump patcher dependency version 2022-12-02 04:04:25 +01:00
oSumAtrIX
2fe3303a27 chore: bump patcher dependency version 2022-12-02 02:35:35 +01:00
semantic-release-bot
04339f0654 chore(release): 2.16.1 [skip ci]
## [2.16.1](https://github.com/revanced/revanced-cli/compare/v2.16.0...v2.16.1) (2022-11-22)
2022-11-22 23:37:24 +00:00
oSumAtrIX
456428a836 build: bump dependencies 2022-11-23 00:33:45 +01:00
oSumAtrIX
c9ae379c77 feat!: apply changes from ReVanced Patcher 2022-11-23 00:20:48 +01:00
semantic-release-bot
81d702949c chore(release): 2.16.0 [skip ci]
# [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](39e377bc48))
2022-11-20 01:50:38 +00:00
oSumAtrIX
39e377bc48 feat: do not warn on incompatible packages 2022-11-20 00:34:00 +01:00
oSumAtrIX
fce40421e9 chore: ignore file vcs.xml from version control [skip ci] 2022-11-19 19:56:46 +01:00
semantic-release-bot
cb554c8bdf chore(release): 2.15.1 [skip ci]
## [2.15.1](https://github.com/revanced/revanced-cli/compare/v2.15.0...v2.15.1) (2022-11-18)
2022-11-18 01:37:14 +00:00
oSumAtrIX
269c753dfa build: bump picocli dependency version 2022-11-18 02:34:28 +01:00
oSumAtrIX
6403e34712 build: bump patcher dependency version 2022-11-18 02:27:33 +01:00
Nico Mexis
f68e7697ff build: update workflow actions (#161) [skip ci] 2022-11-05 15:28:42 +01:00
semantic-release-bot
64b7e86252 chore(release): 2.15.0 [skip ci]
# [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](7be9af0942))

### Features

* use `am` instead of `monkey` to launch the app ([#159](https://github.com/revanced/revanced-cli/issues/159)) ([6a35cf7](6a35cf7ea4))
2022-10-31 13:19:05 +00:00
OxrxL
7be9af0942 fix(gitignore): ignore options.toml (#158) 2022-10-31 14:16:00 +01:00
decipher
6a35cf7ea4 feat: use am instead of monkey to launch the app (#159) 2022-10-31 14:15:34 +01:00
SriBalaji
4914fd37bc build: update checkout actions to v3 [skip ci] (#155) 2022-10-13 17:35:24 +02:00
semantic-release-bot
38052b6ecf chore(release): 2.14.0 [skip ci]
# [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](6e21d81964))

### Features

* handle unmounting deleted files ([#148](https://github.com/revanced/revanced-cli/issues/148)) ([3a733e5](3a733e5137))
* unmount all occurrences in `/proc/mounts` ([#131](https://github.com/revanced/revanced-cli/issues/131)) ([4f4e1f9](4f4e1f9834))
2022-10-05 18:27:53 +00:00
oSumAtrIX
6e21d81964 fix: escape quotation mark in string 2022-10-05 20:26:15 +02:00
decipher
3a733e5137 feat: handle unmounting deleted files (#148) 2022-10-05 14:47:23 +02:00
decipher
4f4e1f9834 feat: unmount all occurrences in /proc/mounts (#131) 2022-10-05 14:20:41 +02:00
oSumAtrIX
e035d93d2c chore: migrate to new changes from the patcher 2022-10-05 04:12:46 +02:00
oSumAtrIX
839854d890 refactor: remove unused variable 2022-10-04 08:30:53 +02:00
semantic-release-bot
43c772c98d chore(release): 2.13.0 [skip ci]
# [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](b6dff6d832))
2022-10-01 03:21:30 +00:00
oSumAtrIX
b6dff6d832 feat: check, if input file exists 2022-10-01 05:19:42 +02:00
OxrxL
29b057dead chore: do not commit revanced-cache (#144) 2022-09-30 00:33:17 +02:00
oSumAtrIX
7df4a7e7da chore: bump patcher dependency version 2022-09-29 21:32:39 +02:00
semantic-release-bot
07c09f092c chore(release): 2.12.0 [skip ci]
# [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](467d8387e6))
2022-09-26 07:02:22 +00:00
oSumAtrIX
e8c9c80349 chore: bump patcher dependency version 2022-09-26 09:00:29 +02:00
oSumAtrIX
467d8387e6 feat: remove unused option -r 2022-09-26 09:00:14 +02:00
oSumAtrIX
65637c8b3a chore: bump patcher dependency version 2022-09-26 04:29:35 +02:00
semantic-release-bot
aa21137e99 chore(release): 2.11.2 [skip ci]
## [2.11.2](https://github.com/revanced/revanced-cli/compare/v2.11.1...v2.11.2) (2022-09-23)
2022-09-23 04:46:47 +00:00
oSumAtrIX
b35302094a build: update patcher dependency 2022-09-23 06:35:32 +02:00
semantic-release-bot
dfb527fc29 chore(release): 2.11.1 [skip ci]
## [2.11.1](https://github.com/revanced/revanced-cli/compare/v2.11.0...v2.11.1) (2022-09-21)
2022-09-21 02:16:24 +00:00
oSumAtrIX
ac2332a592 build: bump patcher dependency version to v5.0.0 2022-09-21 04:14:45 +02:00
semantic-release-bot
a530624fb2 chore(release): 2.11.0 [skip ci]
# [2.11.0](https://github.com/revanced/revanced-cli/compare/v2.10.2...v2.11.0) (2022-09-20)

### Features

* section `acknowledgements` for issue templates ([0e3ecc3](0e3ecc3a51))
2022-09-20 22:37:23 +00:00
oSumAtrIX
0e3ecc3a51 feat: section acknowledgements for issue templates
Signed-off-by: oSumAtrIX <johan.melkonyan1@web.de>
2022-09-21 00:35:56 +02:00
semantic-release-bot
7fac75c6b6 chore(release): 2.10.2 [skip ci]
## [2.10.2](https://github.com/revanced/revanced-cli/compare/v2.10.1...v2.10.2) (2022-09-18)
2022-09-18 06:29:07 +00:00
oSumAtrIX
7ca0b35e45 build: bump patcher dependency version
Signed-off-by: oSumAtrIX <johan.melkonyan1@web.de>
2022-09-18 08:27:20 +02:00
Sculas
cb0fde4908 refactor: clarify config header 2022-09-12 12:24:36 +02:00
Sculas
75e810e42e chore: remove broken dir mappings
cc @oSumAtrIX: if you need this, don't push this file to remote.
2022-09-12 11:47:35 +02:00
semantic-release-bot
37cc77dfc5 chore(release): 2.10.1 [skip ci]
## [2.10.1](https://github.com/revanced/revanced-cli/compare/v2.10.0...v2.10.1) (2022-09-09)
2022-09-09 20:51:44 +00:00
Sculas
075bf406fd refactor: improve OptionsLoader a lot 2022-09-09 22:50:15 +02:00
Sculas
71c81510f7 build: update patcher dependency 2022-09-09 20:59:10 +02:00
semantic-release-bot
51fd16409f chore(release): 2.10.0 [skip ci]
# [2.10.0](https://github.com/revanced/revanced-cli/compare/v2.9.10...v2.10.0) (2022-09-08)

### Features

* Patch Options CLI implementation ([#132](https://github.com/revanced/revanced-cli/issues/132)) ([3f5345a](3f5345af6e))
2022-09-08 20:36:40 +00:00
Sculas
3f5345af6e feat: Patch Options CLI implementation (#132)
* feat: Patch Options CLI implementation

* fix: remove leftover log message
2022-09-08 22:35:09 +02:00
semantic-release-bot
649d9bdb2a chore(release): 2.9.10 [skip ci]
## [2.9.10](https://github.com/revanced/revanced-cli/compare/v2.9.9...v2.9.10) (2022-09-08)

### Bug Fixes

* don't print same patch multiple times ([f4b0469](f4b04698d8))
2022-09-08 20:21:12 +00:00
Sculas
f4b04698d8 fix: don't print same patch multiple times 2022-09-08 22:19:53 +02:00
semantic-release-bot
240ab18eaf chore(release): 2.9.9 [skip ci]
## [2.9.9](https://github.com/revanced/revanced-cli/compare/v2.9.8...v2.9.9) (2022-09-08)
2022-09-08 15:03:24 +00:00
Sculas
096dba2337 build: update patcher dependency 2022-09-08 17:02:02 +02:00
semantic-release-bot
26780f94e5 chore(release): 2.9.8 [skip ci]
## [2.9.8](https://github.com/revanced/revanced-cli/compare/v2.9.7...v2.9.8) (2022-09-08)

### Bug Fixes

* broken deprecation message ([e3e74ac](e3e74ac0e9))
2022-09-08 11:51:01 +00:00
Sculas
faa52e2c68 Merge remote-tracking branch 'origin/main' into main 2022-09-08 13:49:18 +02:00
Sculas
e3e74ac0e9 fix: broken deprecation message 2022-09-08 13:49:03 +02:00
Sculas
de1bdb708c build: update patcher 2022-09-08 13:46:23 +02:00
semantic-release-bot
9b2b933998 chore(release): 2.9.7 [skip ci]
## [2.9.7](https://github.com/revanced/revanced-cli/compare/v2.9.6...v2.9.7) (2022-09-08)
2022-09-08 10:55:29 +00:00
Sculas
fb5a72fdc0 build: remove useless stdlib 2022-09-08 12:53:38 +02:00
Sculas
86c5992630 build: update patcher 2022-09-08 12:53:08 +02:00
Sculas
06d2139ebf refactor: handle deprecation & cleanup 2022-09-08 12:52:00 +02:00
Sculas
15ba4f40cd chore: ignore kotlinc 2022-09-08 12:45:14 +02:00
62 changed files with 8951 additions and 1135 deletions

9
.gitattributes vendored Normal file
View 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

View File

@@ -59,3 +59,15 @@ body:
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

View File

@@ -43,4 +43,16 @@ body:
label: Additional context
description: Add additional context here.
validations:
required: false
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

2
.github/config.yml vendored Normal file
View File

@@ -0,0 +1,2 @@
firstPRMergeComment: >
Thank you for contributing to ReVanced. Join us on [Discord](https://revanced.app/discord) if you want to receive a contributor role.

25
.github/workflows/pull_request.yml vendored Normal file
View File

@@ -0,0 +1,25 @@
name: 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@v3
- 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

View File

@@ -1,4 +1,5 @@
name: Release
on:
workflow_dispatch:
push:
@@ -9,32 +10,37 @@ on:
branches:
- main
- dev
jobs:
release:
name: Release
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v3
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
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: |
${{ runner.home }}/.gradle/caches
${{ runner.home }}/.gradle/wrapper
.gradle
build
node_modules
key: ${{ runner.os }}-gradle-npm-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties', 'package-lock.json') }}
- 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

View 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
View File

@@ -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

8
.idea/.gitignore generated vendored
View File

@@ -1,8 +0,0 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

7
.idea/discord.xml generated
View File

@@ -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>

View File

@@ -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
View File

@@ -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>

14
.idea/vcs.xml generated
View File

@@ -1,14 +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" />
<mapping directory="$PROJECT_DIR$/../revanced-patcher" vcs="Git" />
<mapping directory="$PROJECT_DIR$/../revanced-patches" vcs="Git" />
</component>
</project>

View File

@@ -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
}
]
]

View File

@@ -1,3 +1,580 @@
## [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)
# [2.11.0](https://github.com/revanced/revanced-cli/compare/v2.10.2...v2.11.0) (2022-09-20)
### Features
* section `acknowledgements` for issue templates ([0e3ecc3](https://github.com/revanced/revanced-cli/commit/0e3ecc3a51540b71072ae0be0eb94d115a5b1f92))
## [2.10.2](https://github.com/revanced/revanced-cli/compare/v2.10.1...v2.10.2) (2022-09-18)
## [2.10.1](https://github.com/revanced/revanced-cli/compare/v2.10.0...v2.10.1) (2022-09-09)
# [2.10.0](https://github.com/revanced/revanced-cli/compare/v2.9.10...v2.10.0) (2022-09-08)
### Features
* Patch Options CLI implementation ([#132](https://github.com/revanced/revanced-cli/issues/132)) ([3f5345a](https://github.com/revanced/revanced-cli/commit/3f5345af6e45bfb6c91d52fc089ab18d81fdc998))
## [2.9.10](https://github.com/revanced/revanced-cli/compare/v2.9.9...v2.9.10) (2022-09-08)
### Bug Fixes
* don't print same patch multiple times ([f4b0469](https://github.com/revanced/revanced-cli/commit/f4b04698d8c1717824e86f91da5e01c5021612da))
## [2.9.9](https://github.com/revanced/revanced-cli/compare/v2.9.8...v2.9.9) (2022-09-08)
## [2.9.8](https://github.com/revanced/revanced-cli/compare/v2.9.7...v2.9.8) (2022-09-08)
### Bug Fixes
* broken deprecation message ([e3e74ac](https://github.com/revanced/revanced-cli/commit/e3e74ac0e9a844f9d717a499bca09e575dd90435))
## [2.9.7](https://github.com/revanced/revanced-cli/compare/v2.9.6...v2.9.7) (2022-09-08)
## [2.9.6](https://github.com/revanced/revanced-cli/compare/v2.9.5...v2.9.6) (2022-09-07)
## [2.9.5](https://github.com/revanced/revanced-cli/compare/v2.9.4...v2.9.5) (2022-09-01)

3
README.md Normal file
View File

@@ -0,0 +1,3 @@
# 💻 ReVanced CLI
Command line application to use ReVanced.

View File

@@ -1,49 +1,51 @@
plugins {
kotlin("jvm") version "1.7.0"
id("com.github.johnrengelman.shadow") version "7.1.2"
kotlin("jvm") version "1.8.20"
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()
}
dependencies {
implementation(kotlin("stdlib"))
implementation(kotlin("reflect"))
implementation("app.revanced:revanced-patcher:4.1.0")
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(libs.revanced.patcher)
implementation(libs.kotlin.reflect)
implementation(libs.kotlinx.coroutines.core)
implementation(libs.picocli)
implementation(libs.jadb) // Updated fork
implementation(libs.apksig)
implementation(libs.bcpkix.jdk15on)
implementation(libs.jackson.module.kotlin)
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

17
docs/0_prerequisites.md Normal file
View File

@@ -0,0 +1,17 @@
# 💼 Prerequisites
To use ReVanced CLI, you will need to fulfil 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)
- ReVanced Patches
- ReVanced Integrations, if the patches require it
## ⏭️ Whats next
The following section will show you how to use ReVanced CLI.
Continue: [🛠️ Using ReVanced CLI](1_usage.md)

111
docs/1_usage.md Normal file
View File

@@ -0,0 +1,111 @@
# 🛠️ Using ReVanced CLI
Learn how to ReVanced CLI.
## ⚡ Setup ADB
1. Ensure that ADB is working
```bash
adb shell exit
```
Optionally, you can install the patched APK file on your device by mounting it on top of the original APK file.
You will need root permissions for this. Check if you have root permissions by running the following command:
```bash
adb shell su -c exit
```
2. Get your device's serial
```bash
adb devices
```
## 🔨 Using ReVanced CLI
- ### ⚙️ Show all available options for ReVanced CLI
```bash
java -jar revanced-cli.jar -h
```
- ### 📃 List patches from supplied patch bundles
```bash
java -jar revanced-cli.jar list-patches \
--with-packages \
--with-versions \
--with-options \
revanced-patches.jar [<patch-bundle> ...]
```
- ### ⚙️ Generate options from patches using ReVanced CLI
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 generated, if it does not exist
without any need for intervention when using the `patch` command.
- ### 💉 Use ReVanced CLI to patch an APK file but install without root permissions
This will install the patched APK file regularly on your device.
```bash
java -jar revanced-cli.jar patch \
--patch-bundle revanced-patches.jar \
--out output.apk \
--device-serial <device-serial> \
input.apk
```
- ### 👾 Use ReVanced CLI to patch an APK file but install with root permissions
This will install the patched APK file on your device by mounting it on top of the original APK file.
```bash
adb install input.apk
java -jar revanced-cli.jar patch \
--patch-bundle revanced-patches.jar \
--include some-other-patch \
--exclude some-patch \
--out patched-output.apk \
--device-serial <device-serial> \
--mount \
input.apk
```
> **Note**: Some patches may require integrations
such as [ReVanced Integrations](https://github.com/revanced/revanced-integrations).
Supply them with the option `--merge`. If any patches accepted by ReVanced Patcher require ReVanced Integrations,
they will be merged into the APK file automatically.
- ### 🗑️ Uninstall a patched APK file
```bash
java -jar revanced-cli.jar utility uninstall \
--package-name <package-name> \
<device-serial>
```
> **Note**: You can unmount an APK file
with the option `--unmount`.
- ### ⚙️ Manually install an APK file
```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
View 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)

View File

@@ -1,2 +1,4 @@
org.gradle.parallel = true
org.gradle.caching = true
kotlin.code.style = official
version = 2.9.6
version = 3.0.2-dev.2

25
gradle/libs.versions.toml Normal file
View File

@@ -0,0 +1,25 @@
[versions]
shadow = "8.1.1"
apksig = "8.1.1"
bcpkix-jdk15on = "1.70"
jackson-module-kotlin = "2.14.3"
jadb = "2531a28109"
kotlin-reflect = "1.9.0"
kotlin-test = "1.8.20-RC"
kotlinx-coroutines-core = "1.7.1"
picocli = "4.7.3"
revanced-patcher = "14.2.1"
[libraries]
apksig = { module = "com.android.tools.build:apksig", version.ref = "apksig" }
bcpkix-jdk15on = { module = "org.bouncycastle:bcpkix-jdk15on", version.ref = "bcpkix-jdk15on" }
jackson-module-kotlin = { module = "com.fasterxml.jackson.module:jackson-module-kotlin", version.ref = "jackson-module-kotlin" }
jadb = { module = "com.github.revanced:jadb", version.ref = "jadb" }
kotlin-reflect = { module = "org.jetbrains.kotlin:kotlin-reflect", version.ref = "kotlin-reflect" }
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" }
[plugins]
shadow = { id = "com.github.johnrengelman.shadow", version.ref = "shadow" }

Binary file not shown.

View File

@@ -1,5 +1,7 @@
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.2-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

293
gradlew vendored
View File

@@ -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
View File

@@ -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

6580
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

9
package.json Normal file
View File

@@ -0,0 +1,9 @@
{
"devDependencies": {
"@saithodev/semantic-release-backmerge": "^3.1.0",
"@semantic-release/changelog": "^6.0.2",
"@semantic-release/git": "^10.0.1",
"gradle-semantic-release-plugin": "^1.7.6",
"semantic-release": "^20.1.0"
}
}

View File

@@ -1 +1,23 @@
val githubUsername: String = providers.gradleProperty("gpr.user").orNull ?: System.getenv("GITHUB_ACTOR")
val githubPassword: String = providers.gradleProperty("gpr.key").orNull ?: System.getenv("GITHUB_TOKEN")
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
mavenCentral()
mavenLocal()
google()
maven { url = uri("https://jitpack.io") }
listOf("revanced-patcher", "jadb").forEach { repo ->
maven {
url = uri("https://maven.pkg.github.com/revanced/$repo")
credentials {
username = githubUsername
password = githubPassword
}
}
}
}
}
rootProject.name = "revanced-cli"

View File

@@ -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)
}
}

View File

@@ -0,0 +1,91 @@
package app.revanced.cli.command
import app.revanced.patcher.PatchBundleLoader
import app.revanced.patcher.annotation.Package
import app.revanced.patcher.extensions.PatchExtensions.compatiblePackages
import app.revanced.patcher.extensions.PatchExtensions.description
import app.revanced.patcher.extensions.PatchExtensions.options
import app.revanced.patcher.extensions.PatchExtensions.patchName
import app.revanced.patcher.patch.PatchClass
import app.revanced.patcher.patch.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
override fun run() {
fun Package.buildString() = buildString {
if (withVersions && versions.isNotEmpty()) {
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")
appendLine("Description: $description")
value?.let {
appendLine("Key: $key")
append("Value: $it")
} ?: append("Key: $key")
}
fun PatchClass.buildString() = buildString {
append("Name: $patchName")
if (withDescriptions) append("\nDescription: $description")
if (withOptions && options != null) {
appendLine("\nOptions:")
append(
options!!.joinToString("\n\n") { option -> option.buildString() }.prependIndent("\t")
)
}
if (withPackages && compatiblePackages != null) {
appendLine("\nCompatible packages:")
append(
compatiblePackages!!.joinToString("\n") { it.buildString() }.prependIndent("\t")
)
}
}
logger.info(PatchBundleLoader.Jar(*patchBundles).joinToString("\n\n") { it.buildString() })
}
}

View File

@@ -1,259 +1,67 @@
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.adb.Adb
import picocli.CommandLine.*
import java.io.File
import java.nio.file.Files
import app.revanced.cli.command.utility.UtilityCommand
import app.revanced.patcher.patch.PatchClass
import picocli.CommandLine
import picocli.CommandLine.Command
import picocli.CommandLine.IVersionProvider
import java.util.*
import java.util.logging.*
private class CLIVersionProvider : IVersionProvider {
override fun getVersion() = arrayOf(
MainCommand::class.java.`package`.implementationVersion ?: "unknown"
)
fun main(args: Array<String>) {
System.setProperty("java.util.logging.SimpleFormatter.format", "%4\$s: %5\$s %n")
Logger.getLogger("").apply {
handlers.forEach {
it.close()
removeHandler(it)
}
object : Handler() {
override fun publish(record: LogRecord) = formatter.format(record).toByteArray().let {
if (record.level.intValue() > Level.INFO.intValue())
System.err.write(it)
else
System.out.write(it)
}
override fun flush() {
System.out.flush()
System.err.flush()
}
override fun close() = flush()
}.also {
it.level = Level.ALL
it.formatter = SimpleFormatter()
}.let(::addHandler)
}
CommandLine(MainCommand).execute(*args)
}
internal typealias PatchList = List<PatchClass>
private object CLIVersionProvider : IVersionProvider {
override fun getVersion(): Array<String> {
Properties().apply {
load(MainCommand::class.java.getResourceAsStream("/app/revanced/cli/version.properties"))
}.let {
return arrayOf("ReVanced CLI v${it.getProperty("version")}")
}
}
}
@Command(
name = "ReVanced-CLI",
name = "revanced-cli",
description = ["Command line application to use ReVanced"],
mixinStandardHelpOptions = true,
versionProvider = CLIVersionProvider::class
versionProvider = CLIVersionProvider::class,
subcommands = [
ListPatchesCommand::class,
PatchCommand::class,
OptionsCommand::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>()
@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) {
printListOfPatches()
return
}
if (args.uninstall) {
uninstall()
return
}
val pArgs = this.args.patchArgs?.patchingArgs ?: return
// the file to write to
val outputFile = File(pArgs.outputPath)
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)
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() {
for (patchBundlePath in args.patchArgs?.patchBundles!!) for (patch in JarPatchBundle(patchBundlePath).loadPatches()) {
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)
}
}
logger.info(packageEntryStr)
}
}
}
}
private object MainCommand

View File

@@ -0,0 +1,46 @@
package app.revanced.cli.command
import app.revanced.patcher.PatchBundleLoader
import app.revanced.utils.Options
import app.revanced.utils.Options.setOptions
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 path: 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() = if (!path.exists() || overwrite) with(PatchBundleLoader.Jar(*patchBundles)) {
if (update) setOptions(path)
Options.serialize(this, prettyPrint = true).let(path::writeText)
}
else logger.severe("Options file already exists, use --override to override it")
}

View File

@@ -0,0 +1,341 @@
package app.revanced.cli.command
import app.revanced.patcher.PatchBundleLoader
import app.revanced.patcher.Patcher
import app.revanced.patcher.PatcherOptions
import app.revanced.patcher.PatcherResult
import app.revanced.patcher.extensions.PatchExtensions.compatiblePackages
import app.revanced.patcher.extensions.PatchExtensions.include
import app.revanced.patcher.extensions.PatchExtensions.patchName
import app.revanced.utils.Options
import app.revanced.utils.Options.setOptions
import app.revanced.utils.adb.AdbManager
import app.revanced.utils.align.ZipAligner
import app.revanced.utils.align.zip.ZipFile
import app.revanced.utils.align.zip.structures.ZipEntry
import app.revanced.utils.signing.ApkSigner
import app.revanced.utils.signing.SigningOptions
import kotlinx.coroutines.runBlocking
import picocli.CommandLine
import picocli.CommandLine.Help.Visibility.ALWAYS
import java.io.File
import java.io.PrintWriter
import java.io.StringWriter
import java.util.logging.Logger
@CommandLine.Command(
name = "patch", description = ["Patch the supplied APK file with the supplied patches and integrations"]
)
internal object PatchCommand : Runnable {
private val logger = Logger.getLogger(PatchCommand::class.java.name)
@CommandLine.Parameters(
description = ["APK file to be patched"], arity = "1..1"
)
private lateinit var apk: File
@CommandLine.Option(
names = ["-b", "--patch-bundle"], description = ["One or more bundles of patches"], required = true
)
private var patchBundles = emptyList<File>()
@CommandLine.Option(
names = ["-m", "--merge"], description = ["One or more DEX files or containers to merge into the APK"]
)
private var integrations = listOf<File>()
@CommandLine.Option(
names = ["-i", "--include"], description = ["List of patches to include"]
)
private var includedPatches = arrayOf<String>()
@CommandLine.Option(
names = ["-e", "--exclude"], description = ["List of patches to exclude"]
)
private var excludedPatches = arrayOf<String>()
@CommandLine.Option(
names = ["--options"], description = ["Path to patch options JSON file"], showDefaultValue = ALWAYS
)
private var optionsFile: File = File("options.json")
@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 = ["Force inclusion of patches that are incompatible with the supplied APK file's version"],
showDefaultValue = ALWAYS
)
private var force: Boolean = false
@CommandLine.Option(
names = ["-o", "--out"], description = ["Path to save the patched APK file to"], required = true
)
private lateinit var outputFilePath: File
@CommandLine.Option(
names = ["-d", "--device-serial"], description = ["ADB device serial to install to"], showDefaultValue = ALWAYS
)
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 = ["--common-name"],
description = ["The common name of the signer of the patched APK file"],
showDefaultValue = ALWAYS
)
private var commonName = "ReVanced"
@CommandLine.Option(
names = ["--keystore"], description = ["Path to the keystore to sign the patched APK file with"]
)
private var keystorePath: String? = null
@CommandLine.Option(
names = ["--password"], description = ["The password of the keystore to sign the patched APK file with"]
)
private var password = "ReVanced"
@CommandLine.Option(
names = ["-r", "--resource-cache"],
description = ["Path to temporary resource cache directory"],
showDefaultValue = ALWAYS
)
private var resourceCachePath = File("revanced-resource-cache")
@CommandLine.Option(
names = ["--custom-aapt2-binary"], description = ["Path to a custom AAPT binary to compile resources with"]
)
private var aaptBinaryPath = File("")
@CommandLine.Option(
names = ["-p", "--purge"],
description = ["Purge the temporary resource cache directory after patching"],
showDefaultValue = ALWAYS
)
private var purge: Boolean = false
override fun run() {
// region Prepare
if (!apk.exists()) {
logger.severe("APK file ${apk.name} does not exist")
return
}
integrations.filter { !it.exists() }.let {
if (it.isEmpty()) return@let
it.forEach { integration ->
logger.severe("Integration file ${integration.name} does not exist")
}
return
}
val adbManager = deviceSerial?.let { serial ->
if (mount) AdbManager.RootAdbManager(serial)
else AdbManager.UserAdbManager(serial)
}
// endregion
// region Load patches
logger.info("Loading patches")
val patches = PatchBundleLoader.Jar(*patchBundles.toTypedArray())
val integrations = integrations
logger.info("Setting patch options")
optionsFile.let {
if (it.exists()) patches.setOptions(it)
else Options.serialize(patches, prettyPrint = true).let(it::writeText)
}
// endregion
// region Patch
val patcher = Patcher(
PatcherOptions(
apk,
resourceCachePath,
aaptBinaryPath.path,
resourceCachePath.absolutePath,
)
)
val result = patcher.apply {
acceptIntegrations(integrations)
acceptPatches(filterPatchSelection(patches))
// Execute patches.
runBlocking {
apply(false).collect { patchResult ->
patchResult.exception?.let {
StringWriter().use { writer ->
it.printStackTrace(PrintWriter(writer))
logger.severe("${patchResult.patchName} failed: $writer")
}
} ?: logger.info("${patchResult.patchName} succeeded")
}
}
}.get()
patcher.close()
// endregion
// region Finish
val alignAndSignedFile = sign(
apk.newAlignedFile(
result, resourceCachePath.resolve("${outputFilePath.nameWithoutExtension}_aligned.apk")
)
)
logger.info("Copying to ${outputFilePath.name}")
alignAndSignedFile.copyTo(outputFilePath, overwrite = true)
adbManager?.install(AdbManager.Apk(outputFilePath, patcher.context.packageMetadata.packageName))
if (purge) {
logger.info("Purging temporary files")
purge(resourceCachePath)
}
// endregion
}
/**
* Filter the patches to be added to the patcher. The filter is based on the following:
* - [includedPatches] (explicitly included)
* - [excludedPatches] (explicitly excluded)
* - [exclusive] (only include patches that are explicitly included)
* - [force] (ignore patches incompatibility to versions)
* - Package name and version of the input APK file (if [force] is false)
*
* @param patches The patches to filter.
* @return The filtered patches.
*/
private fun Patcher.filterPatchSelection(patches: PatchList) = buildList {
val packageName = context.packageMetadata.packageName
val packageVersion = context.packageMetadata.packageVersion
patches.forEach patch@{ patch ->
val formattedPatchName = patch.patchName.lowercase().replace(" ", "-")
val explicitlyExcluded = excludedPatches.contains(formattedPatchName)
if (explicitlyExcluded) return@patch logger.info("Excluding ${patch.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.isEmpty() || it.any { version -> version == packageVersion }
}
if (!matchesVersion) return@patch logger.warning("${patch.patchName} is incompatible with version $packageVersion. " + "This patch is only compatible with version " + packages.joinToString(
";"
) { pkg ->
"${pkg.name}: ${pkg.versions.joinToString(", ")}"
})
} ?: return@patch logger.fine("${patch.patchName} is incompatible with $packageName. "
+ "This patch is only compatible with "
+ packages.joinToString(", ") { `package` -> `package`.name })
return@let
} ?: logger.fine("$formattedPatchName: No constraint on packages.")
// If the patch is implicitly included, it will be only included if [exclusive] is false.
val implicitlyIncluded = !exclusive && patch.include
// If the patch is explicitly included, it will be included even if [exclusive] is false.
val explicitlyIncluded = includedPatches.contains(formattedPatchName)
val included = implicitlyIncluded || explicitlyIncluded
if (!included) return@patch logger.info("${patch.patchName} excluded by default") // Case 1.
logger.fine("Adding $formattedPatchName")
add(patch)
}
}
/**
* Create a new aligned APK file.
*
* @param result The result of the patching process.
* @param outputFile The file to save the aligned APK to.
*/
private fun File.newAlignedFile(
result: PatcherResult, outputFile: File
): File {
logger.info("Aligning $name")
if (outputFile.exists()) outputFile.delete()
ZipFile(outputFile).use { file ->
result.dexFiles.forEach {
file.addEntryCompressData(
ZipEntry.createWithName(it.name), it.stream.readBytes()
)
}
result.resourceFile?.let {
file.copyEntriesFromFileAligned(
ZipFile(it), ZipAligner::getEntryAlignment
)
}
// TODO: Do not compress result.doNotCompress
file.copyEntriesFromFileAligned(
ZipFile(this), ZipAligner::getEntryAlignment
)
}
return outputFile
}
/**
* Sign the APK file.
*
* @param inputFile The APK file to sign.
* @return The signed APK file. If [mount] is true, the input file will be returned.
*/
private fun sign(inputFile: File) = if (mount) inputFile
else {
logger.info("Signing ${inputFile.name}")
val keyStoreFilePath = keystorePath
?: outputFilePath.absoluteFile.parentFile.resolve("${outputFilePath.nameWithoutExtension}.keystore").canonicalPath
val options = SigningOptions(
commonName, password, keyStoreFilePath
)
ApkSigner(options).signApk(
inputFile, resourceCachePath.resolve("${outputFilePath.nameWithoutExtension}_signed.apk")
)
}
private fun purge(resourceCachePath: File) {
val result = if (resourceCachePath.deleteRecursively()) "Purged resource cache directory"
else "Failed to purge resource cache directory"
logger.info(result)
}
}

View File

@@ -0,0 +1,42 @@
package app.revanced.cli.command.utility
import app.revanced.utils.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"], arity = "1..*"
)
private lateinit var deviceSerials: Array<String>
@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() = try {
deviceSerials.forEach { deviceSerial ->
if (packageName != null) {
AdbManager.RootAdbManager(deviceSerial)
} else {
AdbManager.UserAdbManager(deviceSerial)
}.install(AdbManager.Apk(apk, packageName))
}
} catch (e: AdbManager.DeviceNotFoundException) {
logger.severe(e.toString())
}
}

View File

@@ -0,0 +1,40 @@
package app.revanced.cli.command.utility
import app.revanced.utils.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"], arity = "1..*")
private lateinit var deviceSerials: Array<String>
@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() = try {
deviceSerials.forEach { deviceSerial ->
if (unmount) {
AdbManager.RootAdbManager(deviceSerial)
} else {
AdbManager.UserAdbManager(deviceSerial)
}.uninstall(packageName)
}
} catch (e: AdbManager.DeviceNotFoundException) {
logger.severe(e.toString())
}
}

View File

@@ -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

View File

@@ -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)
}

View File

@@ -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)
}

View File

@@ -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()
}
}

View File

@@ -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)
}

View File

@@ -1,48 +0,0 @@
package app.revanced.cli.patcher
import app.revanced.cli.command.MainCommand.args
import app.revanced.cli.command.MainCommand.logger
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) {
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()
// 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()) }
}
}
}

View File

@@ -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)
}

View File

@@ -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)
}
}

View File

@@ -0,0 +1,110 @@
package app.revanced.utils
import app.revanced.cli.command.PatchList
import app.revanced.patcher.extensions.PatchExtensions.options
import app.revanced.patcher.extensions.PatchExtensions.patchName
import app.revanced.patcher.patch.NoSuchOptionException
import app.revanced.utils.Options.PatchOption.Option
import com.fasterxml.jackson.module.kotlin.jacksonObjectMapper
import java.io.File
import java.util.logging.Logger
internal object Options {
private val logger = Logger.getLogger(Options::class.java.name)
private var mapper = jacksonObjectMapper()
/**
* Serializes the options for the patches in the list.
*
* @param patches The list of patches to serialize.
* @param prettyPrint Whether to pretty print the JSON.
* @return The JSON string containing the options.
* @see PatchList
*/
fun serialize(patches: PatchList, prettyPrint: Boolean = false): String = patches
.filter { it.options?.any() == true }
.map { patch ->
PatchOption(
patch.patchName,
patch.options!!.map { option -> Option(option.key, option.value) }
)
}
// See https://github.com/revanced/revanced-patches/pull/2434/commits/60e550550b7641705e81aa72acfc4faaebb225e7.
.distinctBy { it.patchName }
.let {
if (prettyPrint)
mapper.writerWithDefaultPrettyPrinter().writeValueAsString(it)
else
mapper.writeValueAsString(it)
}
/**
* Deserializes the options for the patches in the list.
*
* @param json The JSON string containing the options.
* @return The list of [PatchOption]s.
* @see PatchOption
* @see PatchList
*/
@Suppress("MemberVisibilityCanBePrivate")
fun deserialize(json: String): Array<PatchOption> = mapper.readValue(json, Array<PatchOption>::class.java)
/**
* Sets the options for the patches in the list.
*
* @param json The JSON string containing the options.
*/
fun PatchList.setOptions(json: String) {
filter { it.options?.any() == true }.let { patches ->
if (patches.isEmpty()) return
val patchOptions = deserialize(json)
patches.forEach patch@{ patch ->
patchOptions.find { option -> option.patchName == patch.patchName }?.let {
it.options.forEach { option ->
try {
patch.options?.set(option.key, option.value)
?: run{
logger.warning("${patch.patchName} has no options")
return@patch
}
} catch (e: NoSuchOptionException) {
logger.info(e.toString())
}
}
}
}
}
}
/**
* Sets the options for the patches in the list.
*
* @param file The file containing the JSON string containing the options.
* @see setOptions
*/
fun PatchList.setOptions(file: File) = setOptions(file.readText())
/**
* Data class for a patch and its [Option]s.
*
* @property patchName The name of the patch.
* @property options The [Option]s for the patch.
*/
internal data class PatchOption(
val patchName: String,
val options: List<Option>
) {
/**
* Data class for patch option.
*
* @property key The name of the option.
* @property value The value of the option.
*/
internal data class Option(val key: String, val value: Any?)
}
}

View File

@@ -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()
}
}

View File

@@ -0,0 +1,140 @@
package app.revanced.utils.adb
import app.revanced.utils.adb.AdbManager.Apk
import app.revanced.utils.adb.Constants.CREATE_DIR
import app.revanced.utils.adb.Constants.DELETE
import app.revanced.utils.adb.Constants.INSTALLATION_PATH
import app.revanced.utils.adb.Constants.INSTALL_MOUNT
import app.revanced.utils.adb.Constants.INSTALL_PATCHED_APK
import app.revanced.utils.adb.Constants.MOUNT_PATH
import app.revanced.utils.adb.Constants.MOUNT_SCRIPT
import app.revanced.utils.adb.Constants.PATCHED_APK_PATH
import app.revanced.utils.adb.Constants.PLACEHOLDER
import app.revanced.utils.adb.Constants.RESTART
import app.revanced.utils.adb.Constants.TMP_PATH
import app.revanced.utils.adb.Constants.UMOUNT
import se.vidstige.jadb.JadbConnection
import se.vidstige.jadb.managers.Package
import se.vidstige.jadb.managers.PackageManager
import java.io.Closeable
import java.io.File
import java.util.logging.Logger
/**
* Adb manager. Used to install and uninstall [Apk] files.
*
* @param deviceSerial The serial of the device.
*/
internal sealed class AdbManager(deviceSerial: String? = null) : Closeable {
protected val logger: Logger = Logger.getLogger(AdbManager::class.java.name)
protected val device = JadbConnection().devices.find { device -> device.serial == deviceSerial }
?: throw DeviceNotFoundException(deviceSerial)
init {
logger.fine("Established connection to $deviceSerial")
}
/**
* Installs the [Apk] file.
*
* @param apk The [Apk] file.
*/
open fun install(apk: Apk) {
logger.info("Finished installing ${apk.file.name}")
}
/**
* Uninstalls the package.
*
* @param packageName The package name.
*/
open fun uninstall(packageName: String) {
logger.info("Finished uninstalling $packageName")
}
/**
* Closes the [AdbManager] instance.
*/
override fun close() {
logger.fine("Closed")
}
class RootAdbManager(deviceSerial: String) : AdbManager(deviceSerial) {
init {
if (!device.hasSu()) throw IllegalArgumentException("Root required on $deviceSerial. Task failed")
}
override fun install(apk: Apk) {
logger.info("Installing by mounting")
val applyReplacement = getPlaceholderReplacement(
apk.packageName ?: throw IllegalArgumentException("Package name is required")
)
device.push(apk.file, TMP_PATH)
device.run("$CREATE_DIR $INSTALLATION_PATH")
device.run(INSTALL_PATCHED_APK.applyReplacement())
device.createFile(TMP_PATH, MOUNT_SCRIPT.applyReplacement())
device.run(INSTALL_MOUNT.applyReplacement())
device.run(UMOUNT.applyReplacement()) // Sanity check.
device.run(MOUNT_PATH.applyReplacement())
device.run(RESTART.applyReplacement())
device.run(DELETE.applyReplacement(TMP_PATH).applyReplacement())
super.install(apk)
}
override fun uninstall(packageName: String) {
logger.info("Uninstalling $packageName by unmounting")
val applyReplacement = getPlaceholderReplacement(packageName)
device.run(UMOUNT.applyReplacement(packageName))
device.run(DELETE.applyReplacement(PATCHED_APK_PATH).applyReplacement())
device.run(DELETE.applyReplacement(MOUNT_PATH).applyReplacement())
device.run(DELETE.applyReplacement(TMP_PATH).applyReplacement())
super.uninstall(packageName)
}
companion object Utils {
private fun getPlaceholderReplacement(with: String): String.() -> String = { replace(PLACEHOLDER, with) }
private fun String.applyReplacement(with: String) = replace(PLACEHOLDER, with)
}
}
class UserAdbManager(deviceSerial: String) : AdbManager(deviceSerial) {
private val packageManager = PackageManager(device)
override fun install(apk: Apk) {
PackageManager(device).install(apk.file)
super.install(apk)
}
override fun uninstall(packageName: String) {
logger.info("Uninstalling $packageName")
packageManager.uninstall(Package(packageName))
super.uninstall(packageName)
}
}
/**
* Apk file for [AdbManager].
*
* @param file The [Apk] file.
* @param packageName The package name of the [Apk] file.
*/
internal class Apk(val file: File, val packageName: String? = null)
internal class DeviceNotFoundException(deviceSerial: String?) :
Exception(deviceSerial?.let {
"The device with the ADB device serial \"$deviceSerial\" can not be found"
} ?: "No ADB device found")
}

View File

@@ -5,10 +5,9 @@ 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\'")
}
if (su) return shellProcessBuilder("su -c \'$command\'")
val args = command.split(" ") as ArrayList<String>
val cmd = args.removeFirst()
@@ -20,10 +19,15 @@ 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.hasSu() =
this.startCommand("su -h", false).waitFor() == 0
internal fun JadbDevice.createFile(targetFile: String, content: String) {
internal fun JadbDevice.push(file: File, targetFilePath: String) =
push(file, RemoteFile(targetFilePath))
internal fun JadbDevice.createFile(targetFile: String, content: String) =
push(content.byteInputStream(), System.currentTimeMillis(), 644, RemoteFile(targetFile))
}
private fun JadbDevice.startCommand(command: String, su: Boolean) =
shellProcessBuilder(if (su) "su -c '$command'" else command).start()

View File

@@ -1,54 +1,37 @@
package app.revanced.utils.adb
internal object Constants {
// template placeholder to replace a string in commands
internal const val PLACEHOLDER = "TEMPLATE_PACKAGE_NAME"
internal const val PLACEHOLDER = "PLACEHOLDER"
// 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)"
internal const val TMP_PATH = "/data/local/tmp/revanced.tmp"
internal const val INSTALLATION_PATH = "/data/adb/revanced/"
internal const val PATCHED_APK_PATH = "$INSTALLATION_PATH$PLACEHOLDER.apk"
internal const val MOUNT_PATH = "/data/adb/service.d/mount_revanced_$PLACEHOLDER.sh"
// default mount file name
private const val NAME_MOUNT_SCRIPT = "mount_revanced_$PLACEHOLDER.sh"
internal const val DELETE = "rm -rf $PLACEHOLDER"
internal const val CREATE_DIR = "mkdir -p"
internal const val RESTART = "pm resolve-activity --brief $PLACEHOLDER | tail -n 1 | " +
"xargs am start -n && kill ${'$'}(pidof -s $PLACEHOLDER)"
// initial directory to push files to via adb push
internal const val PATH_INIT_PUSH = "/data/local/tmp/revanced.delete"
internal const val INSTALL_PATCHED_APK = "base_path=\"$PATCHED_APK_PATH\" && " +
"mv $TMP_PATH ${'$'}base_path && " +
"chmod 644 ${'$'}base_path && " +
"chown system:system ${'$'}base_path && " +
"chcon u:object_r:apk_data_file:s0 ${'$'}base_path"
// revanced path
internal const val PATH_REVANCED = "/data/adb/revanced/"
internal const val UMOUNT =
"grep $PLACEHOLDER /proc/mounts | while read -r line; do echo ${'$'}line | cut -d \" \" -f 2 | sed 's/apk.*/apk/' | xargs -r umount -l; done"
// revanced apk path
internal const val PATH_REVANCED_APP = "$PATH_REVANCED$PLACEHOLDER.apk"
internal const val INSTALL_MOUNT = "mv $TMP_PATH $MOUNT_PATH && chmod +x $MOUNT_PATH"
// 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 =
internal val 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"
base_path="$PATCHED_APK_PATH"
stock_path=${'$'}( pm path $PLACEHOLDER | grep base | sed 's/package://g' )
chcon u:object_r:apk_data_file:s0 ${'$'}base_path

View File

@@ -0,0 +1,11 @@
package app.revanced.utils.align
import app.revanced.utils.align.zip.structures.ZipEntry
internal object ZipAligner {
private const val DEFAULT_ALIGNMENT = 4
private const val LIBRARY_ALIGNMENT = 4096
fun getEntryAlignment(entry: ZipEntry): Int? =
if (entry.compression.toUInt() != 0u) null else if (entry.fileName.endsWith(".so")) LIBRARY_ALIGNMENT else DEFAULT_ALIGNMENT
}

View File

@@ -1,4 +1,4 @@
package app.revanced.utils.signing.align.zip
package app.revanced.utils.align.zip
import java.io.DataInput
import java.io.DataOutput

View File

@@ -0,0 +1,181 @@
package app.revanced.utils.align.zip
import app.revanced.utils.align.zip.structures.ZipEndRecord
import app.revanced.utils.align.zip.structures.ZipEntry
import java.io.Closeable
import java.io.File
import java.io.RandomAccessFile
import java.nio.ByteBuffer
import java.nio.channels.FileChannel
import java.util.zip.CRC32
import java.util.zip.Deflater
class ZipFile(file: File) : Closeable {
private var entries: MutableList<ZipEntry> = mutableListOf()
private val filePointer: RandomAccessFile = RandomAccessFile(file, "rw")
private var centralDirectoryNeedsRewrite = false
private val compressionLevel = 5
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 writeCD() {
val centralDirectoryStartOffset = 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() - centralDirectoryStartOffset,
centralDirectoryStartOffset,
""
)
filePointer.channel.write(endRecord.toECD())
}
private fun addEntry(entry: ZipEntry, data: ByteBuffer) {
centralDirectoryNeedsRewrite = true
entry.localHeaderOffset = filePointer.channel.position().toUInt()
filePointer.channel.write(entry.toLFH())
filePointer.channel.write(data)
entries.add(entry)
}
fun addEntryCompressData(entry: ZipEntry, data: ByteArray) {
val compressor = Deflater(compressionLevel, true)
compressor.setInput(data)
compressor.finish()
val uncompressedSize = data.size
val compressedData = ByteArray(uncompressedSize) // I'm guessing compression won't make the data bigger.
val compressedDataLength = compressor.deflate(compressedData)
val compressedBuffer =
ByteBuffer.wrap(compressedData.take(compressedDataLength).toByteArray())
compressor.end()
val crc = CRC32()
crc.update(data)
entry.compression = 8u // Deflate compression.
entry.uncompressedSize = uncompressedSize.toUInt()
entry.compressedSize = compressedDataLength.toUInt()
entry.crc32 = crc.value.toUInt()
addEntry(entry, compressedBuffer)
}
private fun addEntryCopyData(entry: ZipEntry, data: ByteBuffer, alignment: Int? = null) {
alignment?.let {
// 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)
}
private fun getDataForEntry(entry: ZipEntry): ByteBuffer {
return filePointer.channel.map(
FileChannel.MapMode.READ_ONLY,
entry.dataOffset.toLong(),
entry.compressedSize.toLong()
)
}
/**
* Copies all entries from [file] to this file but skip already existing entries.
*
* @param file The file to copy entries from.
* @param entryAlignment A function that returns the alignment for a given entry.
*/
fun copyEntriesFromFileAligned(file: ZipFile, entryAlignment: (entry: ZipEntry) -> Int?) {
for (entry in file.entries) {
if (entries.any { it.fileName == entry.fileName }) continue // Skip duplicates
val data = file.getDataForEntry(entry)
addEntryCopyData(entry, data, entryAlignment(entry))
}
}
override fun close() {
if (centralDirectoryNeedsRewrite) writeCD()
filePointer.close()
}
}

View File

@@ -1,9 +1,9 @@
package app.revanced.utils.signing.align.zip.structures
package app.revanced.utils.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 app.revanced.utils.align.zip.putUInt
import app.revanced.utils.align.zip.putUShort
import app.revanced.utils.align.zip.readUIntLE
import app.revanced.utils.align.zip.readUShortLE
import java.io.DataInput
import java.nio.ByteBuffer
import java.nio.ByteOrder

View File

@@ -1,10 +1,6 @@
package app.revanced.utils.signing.align.zip.structures
package app.revanced.utils.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 app.revanced.utils.align.zip.*
import java.io.DataInput
import java.nio.ByteBuffer
import java.nio.ByteOrder
@@ -13,12 +9,12 @@ data class ZipEntry(
val version: UShort,
val versionNeeded: UShort,
val flags: UShort,
val compression: UShort,
var compression: UShort,
val modificationTime: UShort,
val modificationDate: UShort,
val crc32: UInt,
val compressedSize: UInt,
val uncompressedSize: UInt,
var crc32: UInt,
var compressedSize: UInt,
var uncompressedSize: UInt,
val diskNumber: UShort,
val internalAttributes: UShort,
val externalAttributes: UInt,
@@ -26,7 +22,7 @@ data class ZipEntry(
val fileName: String,
val extraField: ByteArray,
val fileComment: String,
var localExtraField: ByteArray = ByteArray(0), //seperate for alignment
var localExtraField: ByteArray = ByteArray(0), //separate for alignment
) {
val LFHSize: Int
get() = LFH_HEADER_SIZE + fileName.toByteArray(Charsets.UTF_8).size + localExtraField.size
@@ -41,6 +37,27 @@ data class ZipEntry(
const val LFH_HEADER_SIZE = 30
const val LFH_SIGNATURE = 0x04034b50u
fun createWithName(fileName: String): ZipEntry {
return ZipEntry(
0x1403u, //made by unix, version 20
0u,
0u,
0u,
0x0821u, //seems to be static time google uses, no idea
0x0221u, //same as above
0u,
0u,
0u,
0u,
0u,
0u,
0u,
fileName,
ByteArray(0),
""
)
}
fun fromCDE(input: DataInput): ZipEntry {
val signature = input.readUIntLE()
@@ -59,7 +76,7 @@ data class ZipEntry(
val fileNameLength = input.readUShortLE()
var fileName = ""
val extraFieldLength = input.readUShortLE()
var extraField = ByteArray(extraFieldLength.toInt())
val extraField = ByteArray(extraFieldLength.toInt())
val fileCommentLength = input.readUShortLE()
var fileComment = ""
val diskNumber = input.readUShortLE()
@@ -67,7 +84,8 @@ data class ZipEntry(
val externalAttributes = input.readUIntLE()
val localHeaderOffset = input.readUIntLE()
val variableFieldsLength = fileNameLength.toInt() + extraFieldLength.toInt() + fileCommentLength.toInt()
val variableFieldsLength =
fileNameLength.toInt() + extraFieldLength.toInt() + fileCommentLength.toInt()
if (variableFieldsLength > 0) {
val fileNameBytes = ByteArray(fileNameLength.toInt())
@@ -81,7 +99,8 @@ data class ZipEntry(
fileComment = fileCommentBytes.toString(Charsets.UTF_8)
}
flags = (flags and 0b1000u.inv().toUShort()) //disable data descriptor flag as they are not used
flags = (flags and 0b1000u.inv()
.toUShort()) //disable data descriptor flag as they are not used
return ZipEntry(
version,
@@ -138,8 +157,9 @@ data class ZipEntry(
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) }
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)
@@ -166,5 +186,4 @@ data class ZipEntry(
buffer.flip()
return buffer
}
}
}

View File

@@ -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()
}

View File

@@ -1,78 +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.include
import app.revanced.patcher.extensions.PatchExtensions.patchName
import app.revanced.patcher.patch.Patch
import app.revanced.patcher.util.patch.impl.JarPatchBundle
fun Patcher.addPatchesFiltered() {
val packageName = this.data.packageMetadata.packageName
val packageVersion = this.data.packageMetadata.packageVersion
args.patchArgs?.patchBundles!!.forEach { bundle ->
val includedPatches = mutableListOf<Class<out Patch<Data>>>()
JarPatchBundle(bundle).loadPatches().forEach patch@{ patch ->
val compatiblePackages = patch.compatiblePackages
val patchName = patch.patchName
val prefix = "Skipping $patchName"
val args = MainCommand.args.patchArgs?.patchingArgs!!
if (args.excludedPatches.contains(patchName)) {
logger.info("$prefix: Explicitly excluded")
return@patch
} else if ((!patch.include || args.defaultExclude) && !args.includedPatches.contains(patchName)) {
logger.info("$prefix: Not explicitly included")
return@patch
}
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@patch
}
if (!(args.experimental || compatiblePackages.any { it.versions.isEmpty() || it.versions.any { version -> version == packageVersion } })) {
val compatibleWith = compatiblePackages.map { _package ->
"${_package.name}: ${_package.versions.joinToString(", ")}"
}.joinToString(";")
logger.warn("$prefix: Incompatible with version $packageVersion. This patch is only compatible with version $compatibleWith")
return@patch
}
}
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")
}
}

View File

@@ -1,7 +1,5 @@
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
@@ -17,11 +15,44 @@ import java.math.BigInteger
import java.security.*
import java.security.cert.X509Certificate
import java.util.*
import java.util.logging.Logger
internal class Signer(
internal class ApkSigner(
private val signingOptions: SigningOptions
) {
private val logger = Logger.getLogger(ApkSigner::class.java.name)
private val signer: ApkSigner.Builder
private val passwordCharArray = signingOptions.password.toCharArray()
init {
Security.addProvider(BouncyCastleProvider())
val keyStore = KeyStore.getInstance("BKS", "BC")
val alias = keyStore.let { store ->
FileInputStream(File(signingOptions.keyStoreFilePath).also {
if (!it.exists()) {
logger.info("Creating keystore at ${it.absolutePath}")
newKeystore(it)
} else {
logger.info("Using keystore at ${it.absolutePath}")
}
}).use { fis -> store.load(fis, null) }
store.aliases().nextElement()
}
with(
ApkSigner.SignerConfig.Builder(
signingOptions.cn,
keyStore.getKey(alias, passwordCharArray) as PrivateKey,
listOf(keyStore.getCertificate(alias) as X509Certificate)
).build()
) {
this@ApkSigner.signer = ApkSigner.Builder(listOf(this))
signer.setCreatedBy(signingOptions.cn)
}
}
private fun newKeystore(out: File) {
val (publicKey, privateKey) = createKey()
val privateKS = KeyStore.getInstance("BKS", "BC")
@@ -50,30 +81,12 @@ internal class Signer(
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)
fun signApk(input: File, output: File): File {
signer.setInputApk(input)
signer.setOutputApk(output)
signer.build().sign()
return output
}
}

View File

@@ -1,4 +1,4 @@
package app.revanced.cli.signing
package app.revanced.utils.signing
data class SigningOptions(
val cn: String,

View File

@@ -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()
}
}

View File

@@ -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()
}
}

View File

@@ -0,0 +1 @@
version=${projectVersion}

View File

@@ -0,0 +1,60 @@
package app.revanced.patcher.options
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.data.Context
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.OptionsContainer
import app.revanced.patcher.patch.Patch
import app.revanced.patcher.patch.PatchOption
import app.revanced.utils.Options
import app.revanced.utils.Options.setOptions
import org.junit.jupiter.api.MethodOrderer
import org.junit.jupiter.api.Order
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.TestMethodOrder
class PatchOptionsTestPatch : BytecodePatch() {
override fun execute(context: BytecodeContext) {
// Do nothing
}
companion object : OptionsContainer() {
var key1 by option(
PatchOption.StringOption(
"key1", null, "title1", "description1"
)
)
var key2 by option(
PatchOption.BooleanOption(
"key2", true, "title2", "description2"
)
)
}
}
@TestMethodOrder(MethodOrderer.OrderAnnotation::class)
internal object PatchOptionOptionsTest {
private var patches = listOf(PatchOptionsTestPatch::class.java as Class<out Patch<Context<*>>>)
@Test
@Order(1)
fun serializeTest() {
assert(SERIALIZED_JSON == Options.serialize(patches))
}
@Test
@Order(2)
fun loadOptionsTest() {
patches.setOptions(CHANGED_JSON)
assert(PatchOptionsTestPatch.key1 == "test")
assert(PatchOptionsTestPatch.key2 == false)
}
private const val SERIALIZED_JSON =
"[{\"patchName\":\"PatchOptionsTestPatch\",\"options\":[{\"key\":\"key1\",\"value\":null},{\"key\":\"key2\",\"value\":true}]}]"
private const val CHANGED_JSON =
"[{\"patchName\":\"PatchOptionsTestPatch\",\"options\":[{\"key\":\"key1\",\"value\":\"test\"},{\"key\":\"key2\",\"value\":false}]}]"
}