1
mirror of https://github.com/revanced/revanced-patcher synced 2025-09-03 03:43:05 +02:00

Compare commits

...

106 Commits

Author SHA1 Message Date
semantic-release-bot
d3721229bf chore(release): 15.0.0-dev.2 [skip ci]
# [15.0.0-dev.2](https://github.com/ReVanced/revanced-patcher/compare/v15.0.0-dev.1...v15.0.0-dev.2) (2023-09-06)
2023-09-06 03:36:03 +00:00
oSumAtrIX
86c1c9c772 build(Needs bump): Use correct Maven repository URL 2023-09-06 05:32:58 +02:00
oSumAtrIX
c299817193 feat!: Use Kotlin DSL for patch options (#234) 2023-09-06 02:53:31 +02:00
semantic-release-bot
fcc1de45ed chore(release): 15.0.0-dev.1 [skip ci]
# [15.0.0-dev.1](https://github.com/ReVanced/revanced-patcher/compare/v14.2.2...v15.0.0-dev.1) (2023-09-04)

* feat!: Add patch annotation processor ([3fc6a13](3fc6a139ee))
* feat!: Remove patch annotations ([3b4db3d](3b4db3ddb7))

### Features

* Add patch annotation processor ([#231](https://github.com/ReVanced/revanced-patcher/issues/231)) ([a29931f](a29931f2ec))

### BREAKING CHANGES

* The manifest for patches has been removed, and the properties have been added to patches. Patches are now `OptionsContainer`. The `@Patch` annotation has been removed in favour of the `@Patch` annotation from the annotation processor.
* Patch annotations have been removed. PatcherException is now thrown in various places. PatchBundleLoader is now a map of patches associated by their name. Patches are now instances.
2023-09-04 03:51:04 +00:00
oSumAtrIX
a29931f2ec feat: Add patch annotation processor (#231) 2023-09-04 05:48:20 +02:00
oSumAtrIX
3fc6a139ee feat!: Add patch annotation processor
This commit introduces an annotation processor for patches. Patches can use the `@Patch` instead of super constructor parameters.

BREAKING CHANGE: The manifest for patches has been removed, and the properties have been added to patches. Patches are now `OptionsContainer`. The `@Patch` annotation has been removed in favour of the `@Patch` annotation from the annotation processor.
2023-09-04 05:43:41 +02:00
oSumAtrIX
4dd04975d9 refactor: Move ReVanced Patcher to sub-project
This allows other sub-projects to exist.
2023-09-04 05:37:13 +02:00
oSumAtrIX
3b4db3ddb7 feat!: Remove patch annotations
Annotations required reflection and working with them turned out to be rather cumbersome. The annotations have been replaced with properties for the most part.

BREAKING CHANGE: Patch annotations have been removed. PatcherException is now thrown in various places. PatchBundleLoader is now a map of patches associated by their name. Patches are now instances.
2023-09-04 05:24:29 +02:00
semantic-release-bot
c4a7117ee8 chore(release): 14.2.2 [skip ci]
## [14.2.2](https://github.com/ReVanced/revanced-patcher/compare/v14.2.1...v14.2.2) (2023-08-30)

### Bug Fixes

* allow setting `DexClassLoader.optimizedDirectory` ([11a3378](11a3378659))
2023-08-30 17:25:12 +00:00
oSumAtrIX
b4e900fde8 chore: merge branch dev to main (#226) 2023-08-30 19:22:46 +02:00
semantic-release-bot
9818d730e4 chore(release): 14.2.2-dev.1 [skip ci]
## [14.2.2-dev.1](https://github.com/ReVanced/revanced-patcher/compare/v14.2.1...v14.2.2-dev.1) (2023-08-29)

### Bug Fixes

* allow setting `DexClassLoader.optimizedDirectory` ([11a3378](11a3378659))
2023-08-29 02:12:54 +00:00
oSumAtrIX
11a3378659 fix: allow setting DexClassLoader.optimizedDirectory
This is required for API level below 26, otherwise an NPE is thrown
2023-08-29 04:09:17 +02:00
oSumAtrIX
1bb05f22d3 chore: add initial API dump
This is necessary for the binary compatibility validation.
2023-08-29 04:05:18 +02:00
oSumAtrIX
26b70554c4 build: use binary compatibility validator
This prevents releasing breaking changes accidentally.
2023-08-29 03:47:21 +02:00
oSumAtrIX
93b29d2e83 chore: assert instead of printing in tests 2023-08-29 03:38:11 +02:00
semantic-release-bot
072986374a chore(release): 14.2.1 [skip ci]
## [14.2.1](https://github.com/ReVanced/revanced-patcher/compare/v14.2.0...v14.2.1) (2023-08-27)

### Bug Fixes

* do not flag resource table as sparse when main package is not loaded ([b832812](b832812767))
2023-08-27 20:23:09 +00:00
oSumAtrIX
2c590d212a chore: merge branch dev to main (#225) 2023-08-27 22:21:36 +02:00
semantic-release-bot
6cc863efb3 chore(release): 14.2.1-dev.1 [skip ci]
## [14.2.1-dev.1](https://github.com/ReVanced/revanced-patcher/compare/v14.2.0...v14.2.1-dev.1) (2023-08-27)

### Bug Fixes

* do not flag resource table as sparse when main package is not loaded ([b832812](b832812767))
2023-08-27 20:17:31 +00:00
oSumAtrIX
b832812767 fix: do not flag resource table as sparse when main package is not loaded 2023-08-27 22:14:43 +02:00
oSumAtrIX
c44558cacd build: bump dependencies
This fixes an issue with flagging the resource table with sparse incorrectly.
2023-08-27 22:14:11 +02:00
semantic-release-bot
6d83a720cd chore(release): 14.2.0 [skip ci]
# [14.2.0](https://github.com/ReVanced/revanced-patcher/compare/v14.1.0...v14.2.0) (2023-08-27)

### Features

* load patches in lexicographical order ([e8f2087](e8f2087a6f))
* log when merging integrations ([983563e](983563efb6))

### Performance Improvements

* compare types of classes ([55d6945](55d694579a))
2023-08-27 00:55:36 +00:00
oSumAtrIX
8d0dd9c448 chore: merge branch dev to main (#222) 2023-08-27 02:53:47 +02:00
oSumAtrIX
64020eec49 chore: add multi-threading opportunity notice 2023-08-26 20:58:19 +02:00
semantic-release-bot
4dedfb85cb chore(release): 14.2.0-dev.3 [skip ci]
# [14.2.0-dev.3](https://github.com/ReVanced/revanced-patcher/compare/v14.2.0-dev.2...v14.2.0-dev.3) (2023-08-26)

### Performance Improvements

* compare types of classes ([55d6945](55d694579a))
2023-08-26 17:44:12 +00:00
oSumAtrIX
55d694579a perf: compare types of classes 2023-08-26 19:42:33 +02:00
semantic-release-bot
86db64edff chore(release): 14.2.0-dev.2 [skip ci]
# [14.2.0-dev.2](https://github.com/ReVanced/revanced-patcher/compare/v14.2.0-dev.1...v14.2.0-dev.2) (2023-08-26)

### Features

* log when merging integrations ([983563e](983563efb6))
2023-08-26 17:16:08 +00:00
oSumAtrIX
983563efb6 feat: log when merging integrations 2023-08-26 19:14:29 +02:00
oSumAtrIX
37abb2db99 build: package the Java sources 2023-08-26 19:10:29 +02:00
semantic-release-bot
5ba0b47e60 chore(release): 14.2.0-dev.1 [skip ci]
# [14.2.0-dev.1](https://github.com/ReVanced/revanced-patcher/compare/v14.1.0...v14.2.0-dev.1) (2023-08-25)

### Features

* load patches in lexicographical order ([e8f2087](e8f2087a6f))
2023-08-25 15:12:46 +00:00
oSumAtrIX
e8f2087a6f feat: load patches in lexicographical order
This feature was lost in past commits
2023-08-25 17:10:44 +02:00
semantic-release-bot
6ce99f5cdf chore(release): 14.1.0 [skip ci]
# [14.1.0](https://github.com/ReVanced/revanced-patcher/compare/v14.0.0...v14.1.0) (2023-08-24)

### Bug Fixes

* move version properties file to correct package ([e985676](e985676c2d))

### Features

* properly make use of logging facade ([ba56a6a](ba56a6a2ee))
2023-08-24 02:50:15 +00:00
oSumAtrIX
13c0c9cdd3 chore: merge branch dev to main (#220) 2023-08-24 04:48:39 +02:00
semantic-release-bot
58ffdb60d7 chore(release): 14.1.0-dev.1 [skip ci]
# [14.1.0-dev.1](https://github.com/ReVanced/revanced-patcher/compare/v14.0.1-dev.1...v14.1.0-dev.1) (2023-08-24)

### Features

* properly make use of logging facade ([ba56a6a](ba56a6a2ee))
2023-08-24 02:45:16 +00:00
oSumAtrIX
ba56a6a2ee feat: properly make use of logging facade
This deprecates the primary constructor of `PatcherOptions` with the `logger` parameter
2023-08-24 04:43:16 +02:00
oSumAtrIX
ccccf5b1d2 build: migrate dependencies to version catalogs 2023-08-23 04:30:31 +02:00
semantic-release-bot
b507ac0a54 chore(release): 14.0.1-dev.1 [skip ci]
## [14.0.1-dev.1](https://github.com/ReVanced/revanced-patcher/compare/v14.0.0...v14.0.1-dev.1) (2023-08-23)

### Bug Fixes

* move version properties file to correct package ([e985676](e985676c2d))
2023-08-23 01:39:26 +00:00
oSumAtrIX
e985676c2d fix: move version properties file to correct package 2023-08-23 03:36:48 +02:00
oSumAtrIX
f7f4ba6c55 build: update dependencies 2023-08-23 03:36:48 +02:00
semantic-release-bot
4292f43814 chore(release): 14.0.0 [skip ci]
# [14.0.0](https://github.com/ReVanced/revanced-patcher/compare/v13.0.0...v14.0.0) (2023-08-22)

### Bug Fixes

* log decoding resources after logging deleting resource cache directory ([db62a16](db62a1607b))
* only emit closed patches that did not throw an exception with the `@Patch` annotation ([5938f6b](5938f6b7ea))
* supply the parent classloader to `DexClassLoader` ([0f15077](0f15077225))

### Code Refactoring

* improve structure and public API ([6b8977f](6b8977f178))

### Features

* do not log instantiation of ReVanced Patcher ([273dd8d](273dd8d388))

### BREAKING CHANGES

* Various public APIs have been changed. The `Version` annotation has been removed. Patches do not return anything anymore and instead throw `PatchException`. Multiple patch bundles can now be loaded in a single ClassLoader to bypass class loader isolation.
2023-08-22 17:16:51 +00:00
oSumAtrIX
30bd4fd9fe chore: merge branch dev to main (#217) 2023-08-22 19:15:09 +02:00
semantic-release-bot
76de39369d chore(release): 14.0.0-dev.4 [skip ci]
# [14.0.0-dev.4](https://github.com/ReVanced/revanced-patcher/compare/v14.0.0-dev.3...v14.0.0-dev.4) (2023-08-22)

### Bug Fixes

* only emit closed patches that did not throw an exception with the `@Patch` annotation ([5938f6b](5938f6b7ea))
2023-08-22 17:04:25 +00:00
oSumAtrIX
88a703ce36 build: bump dependencies 2023-08-22 19:01:59 +02:00
oSumAtrIX
5938f6b7ea fix: only emit closed patches that did not throw an exception with the @Patch annotation 2023-08-22 19:00:34 +02:00
semantic-release-bot
5c0c0d6c37 chore(release): 14.0.0-dev.3 [skip ci]
# [14.0.0-dev.3](https://github.com/ReVanced/revanced-patcher/compare/v14.0.0-dev.2...v14.0.0-dev.3) (2023-08-20)

### Bug Fixes

* supply the parent classloader to `DexClassLoader` ([0f15077](0f15077225))

### Features

* do not log instantiation of ReVanced Patcher ([273dd8d](273dd8d388))
2023-08-20 17:16:00 +00:00
oSumAtrIX
0f15077225 fix: supply the parent classloader to DexClassLoader 2023-08-20 19:14:10 +02:00
oSumAtrIX
273dd8d388 feat: do not log instantiation of ReVanced Patcher 2023-08-20 19:14:09 +02:00
semantic-release-bot
1795f376ef chore(release): 14.0.0-dev.2 [skip ci]
# [14.0.0-dev.2](https://github.com/ReVanced/revanced-patcher/compare/v14.0.0-dev.1...v14.0.0-dev.2) (2023-08-19)
2023-08-19 15:26:18 +00:00
oSumAtrIX
e7360a7692 build(Needs bump): Bump dependencies
This fixes an issue with a library not working on Android
2023-08-19 17:23:31 +02:00
semantic-release-bot
e1fc86934f chore(release): 14.0.0-dev.1 [skip ci]
# [14.0.0-dev.1](https://github.com/ReVanced/revanced-patcher/compare/v13.0.0...v14.0.0-dev.1) (2023-08-18)

### Bug Fixes

* log decoding resources after logging deleting resource cache directory ([db62a16](db62a1607b))

### Code Refactoring

* improve structure and public API ([6b8977f](6b8977f178))

### BREAKING CHANGES

* Various public APIs have been changed. The `Version` annotation has been removed. Patches do not return anything anymore and instead throw `PatchException`. Multiple patch bundles can now be loaded in a single ClassLoader to bypass class loader isolation.
2023-08-18 23:47:18 +00:00
oSumAtrIX
6b8977f178 refactor: improve structure and public API
This commit introduces a couple changes besides the refactor. Executing patches can be cancelled, multiple bundles loaded into the same class loader and `Patch.execute` does not have to return anymore.

BREAKING CHANGE: Various public APIs have been changed. The `Version` annotation has been removed. Patches do not return anything anymore and instead throw `PatchException`. Multiple patch bundles can now be loaded in a single ClassLoader to bypass class loader isolation.
2023-08-19 01:45:27 +02:00
oSumAtrIX
12c6c73de0 build: add mavenLocal to repositories 2023-08-16 16:53:47 +02:00
oSumAtrIX
db62a1607b fix: log decoding resources after logging deleting resource cache directory 2023-08-16 16:53:45 +02:00
semantic-release-bot
58bb879ef5 chore(release): 13.0.0 [skip ci]
# [13.0.0](https://github.com/ReVanced/revanced-patcher/compare/v12.1.1...v13.0.0) (2023-08-14)

### Bug Fixes

* decode in correct order ([8fb2f2d](8fb2f2dc1d))
* disable correct loggers ([c2d89c6](c2d89c622e))
* get framework ids to compile resources ([f2cb7ee](f2cb7ee7df))
* only enable logging for ReVanced ([783ccf8](783ccf8529))
* set package metadata correctly ([02d6ff1](02d6ff15fe))

* build(Needs bump)!: Bump dependencies ([d5f89a9](d5f89a903f))

### BREAKING CHANGES

* This bump updates smali, a crucial dependency
2023-08-14 02:11:55 +00:00
oSumAtrIX
254912438a chore: merge branch dev to main (#213) 2023-08-14 04:10:17 +02:00
semantic-release-bot
0e48918bcc chore(release): 13.0.0-dev.3 [skip ci]
# [13.0.0-dev.3](https://github.com/ReVanced/revanced-patcher/compare/v13.0.0-dev.2...v13.0.0-dev.3) (2023-08-14)

### Bug Fixes

* decode in correct order ([8fb2f2d](8fb2f2dc1d))
* only enable logging for ReVanced ([783ccf8](783ccf8529))
2023-08-14 02:04:54 +00:00
oSumAtrIX
783ccf8529 fix: only enable logging for ReVanced 2023-08-14 04:02:39 +02:00
oSumAtrIX
8fb2f2dc1d fix: decode in correct order 2023-08-14 04:02:24 +02:00
semantic-release-bot
2a8cc283c7 chore(release): 13.0.0-dev.2 [skip ci]
# [13.0.0-dev.2](https://github.com/ReVanced/revanced-patcher/compare/v13.0.0-dev.1...v13.0.0-dev.2) (2023-08-12)

### Bug Fixes

* disable correct loggers ([c2d89c6](c2d89c622e))
* get framework ids to compile resources ([f2cb7ee](f2cb7ee7df))
* set package metadata correctly ([02d6ff1](02d6ff15fe))
2023-08-12 00:25:18 +00:00
oSumAtrIX
433fe3af9f build(Needs bump): Bump dependencies 2023-08-12 02:23:03 +02:00
oSumAtrIX
c2d89c622e fix: disable correct loggers 2023-08-12 02:22:52 +02:00
oSumAtrIX
02d6ff15fe fix: set package metadata correctly 2023-08-12 02:19:28 +02:00
oSumAtrIX
f2cb7ee7df fix: get framework ids to compile resources 2023-08-12 02:18:43 +02:00
oSumAtrIX
a2ac44dcc1 chore: use more generic inline docs 2023-08-12 02:15:26 +02:00
semantic-release-bot
3cf9d74efa chore(release): 13.0.0-dev.1 [skip ci]
# [13.0.0-dev.1](https://github.com/ReVanced/revanced-patcher/compare/v12.1.1...v13.0.0-dev.1) (2023-08-11)

* build(Needs bump)!: Bump dependencies ([d5f89a9](d5f89a903f))

### BREAKING CHANGES

* This bump updates smali, a crucial dependency
2023-08-11 00:53:46 +00:00
oSumAtrIX
d5f89a903f build(Needs bump)!: Bump dependencies
BREAKING CHANGE: This bump updates smali, a crucial dependency
2023-08-11 02:51:37 +02:00
semantic-release-bot
496c2242bc chore(release): 12.1.1 [skip ci]
## [12.1.1](https://github.com/ReVanced/revanced-patcher/compare/v12.1.0...v12.1.1) (2023-08-03)

### Bug Fixes

* clear method lookup maps before initializing them ([#210](https://github.com/ReVanced/revanced-patcher/issues/210)) ([746544f](746544f9d5))
2023-08-03 18:34:22 +00:00
oSumAtrIX
98fbff87df chore: merge branch dev to main (#211) 2023-08-03 20:32:45 +02:00
semantic-release-bot
ddb51a1c45 chore(release): 12.1.1-dev.2 [skip ci]
## [12.1.1-dev.2](https://github.com/ReVanced/revanced-patcher/compare/v12.1.1-dev.1...v12.1.1-dev.2) (2023-08-03)
2023-08-03 18:16:10 +00:00
oSumAtrIX
8df1155215 build(Needs bump): Bump compatibility 2023-08-03 20:14:01 +02:00
semantic-release-bot
53f2a61409 chore(release): 12.1.1-dev.1 [skip ci]
## [12.1.1-dev.1](https://github.com/ReVanced/revanced-patcher/compare/v12.1.0...v12.1.1-dev.1) (2023-08-03)

### Bug Fixes

* clear method lookup maps before initializing them ([#210](https://github.com/ReVanced/revanced-patcher/issues/210)) ([746544f](746544f9d5))
2023-08-03 11:43:51 +00:00
aAbed
746544f9d5 fix: clear method lookup maps before initializing them (#210)
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
2023-08-03 13:42:00 +02:00
semantic-release-bot
c65c3df11c chore(release): 12.1.0 [skip ci]
# [12.1.0](https://github.com/ReVanced/revanced-patcher/compare/v12.0.0...v12.1.0) (2023-08-03)

### Features

* add `MutableMethod.getInstructions` extension function ([fae4029](fae4029cfc))
2023-08-03 02:43:21 +00:00
oSumAtrIX
b29b8f12b3 chore: merge branch dev to main (#209) 2023-08-03 04:18:23 +02:00
semantic-release-bot
d6945677c4 chore(release): 12.1.0-dev.2 [skip ci]
# [12.1.0-dev.2](https://github.com/ReVanced/revanced-patcher/compare/v12.1.0-dev.1...v12.1.0-dev.2) (2023-08-03)
2023-08-03 02:16:55 +00:00
oSumAtrIX
aedf4aea08 build(Needs bump): Update dependencies 2023-08-03 04:15:09 +02:00
semantic-release-bot
dc28d414dc chore(release): 12.1.0-dev.1 [skip ci]
# [12.1.0-dev.1](https://github.com/ReVanced/revanced-patcher/compare/v12.0.0...v12.1.0-dev.1) (2023-08-01)

### Features

* add `MutableMethod.getInstructions` extension function ([fae4029](fae4029cfc))
2023-08-01 22:14:09 +00:00
oSumAtrIX
9755bab298 refactor: remove unnecessary annotation 2023-08-02 00:12:24 +02:00
oSumAtrIX
fae4029cfc feat: add MutableMethod.getInstructions extension function 2023-08-02 00:11:56 +02:00
oSumAtrIX
1790f0d706 ci: Change bumping commit scope 2023-07-30 02:50:41 +02:00
semantic-release-bot
0ba2c51676 chore(release): 12.0.0 [skip ci]
# [12.0.0](https://github.com/ReVanced/revanced-patcher/compare/v11.0.4...v12.0.0) (2023-07-30)

### Bug Fixes

* correct access flags of `PackageMetadata` ([416d691](416d69142f))
* set resource table via resource decoder ([e0f8e1b](e0f8e1b71a))

### Features

* Deprecate `Version` annotation ([c9bbcf2](c9bbcf2bf2))
* remove `Path` option ([#202](https://github.com/ReVanced/revanced-patcher/issues/202)) ([69e4a49](69e4a49065))

### BREAKING CHANGES

* This removes the previously available `Path` option
2023-07-30 00:10:57 +00:00
oSumAtrIX
03cd97b49c chore: merge branch dev to main (#203) 2023-07-30 02:09:12 +02:00
semantic-release-bot
16a162c1dd chore(release): 12.0.0-dev.2 [skip ci]
# [12.0.0-dev.2](https://github.com/ReVanced/revanced-patcher/compare/v12.0.0-dev.1...v12.0.0-dev.2) (2023-07-28)

### Features

* Deprecate `Version` annotation ([400442f](400442f70e))
2023-07-28 20:19:02 +02:00
oSumAtrIX
c9bbcf2bf2 feat: Deprecate Version annotation 2023-07-28 20:19:01 +02:00
semantic-release-bot
86e1bf6078 chore(release): 12.0.0-dev.1 [skip ci]
# [12.0.0-dev.1](https://github.com/ReVanced/revanced-patcher/compare/v11.0.4...v12.0.0-dev.1) (2023-07-26)

### Bug Fixes

* correct access flags of `PackageMetadata` ([416d691](416d69142f))
* set resource table via resource decoder ([e0f8e1b](e0f8e1b71a))

### Features

* remove `Path` option ([#202](https://github.com/ReVanced/revanced-patcher/issues/202)) ([69e4a49](69e4a49065))

### BREAKING CHANGES

* This removes the previously available `Path` option
2023-07-26 04:30:48 +00:00
oSumAtrIX
1bca84ef0b refactor: move code out of try block 2023-07-26 06:28:48 +02:00
oSumAtrIX
e0f8e1b71a fix: set resource table via resource decoder 2023-07-26 06:28:48 +02:00
oSumAtrIX
416d69142f fix: correct access flags of PackageMetadata 2023-07-26 06:28:48 +02:00
oSumAtrIX
426807aeaa refactor: remove unnecessary changes to default config 2023-07-26 06:28:47 +02:00
oSumAtrIX
90cb075a97 build(needs-bump): update dependencies 2023-07-26 06:28:47 +02:00
oSumAtrIX
ac2ca8fbd3 ci: bump on scope needs-bump 2023-07-26 06:28:47 +02:00
Palm
69e4a49065 feat: remove Path option (#202)
BREAKING CHANGE: This removes the previously available `Path` option
2023-07-26 04:11:21 +02:00
oSumAtrIX
a4a030f2b2 build: update gradle 2023-07-06 18:15:40 +02:00
semantic-release-bot
dcc4ecd237 chore(release): 11.0.4 [skip ci]
## [11.0.4](https://github.com/revanced/revanced-patcher/compare/v11.0.3...v11.0.4) (2023-07-01)

### Bug Fixes

* clear method lookup maps ([#198](https://github.com/revanced/revanced-patcher/issues/198)) ([9d81baf](9d81baf4b4))
2023-07-01 00:42:50 +00:00
oSumAtrIX
57f3036a96 chore: merge branch dev to main (#199) 2023-07-01 02:41:21 +02:00
semantic-release-bot
753e55dfc3 chore(release): 11.0.4-dev.1 [skip ci]
## [11.0.4-dev.1](https://github.com/revanced/revanced-patcher/compare/v11.0.3...v11.0.4-dev.1) (2023-07-01)

### Bug Fixes

* clear method lookup maps ([#198](https://github.com/revanced/revanced-patcher/issues/198)) ([9d81baf](9d81baf4b4))
2023-07-01 00:37:30 +00:00
LisoUseInAIKyrios
9d81baf4b4 fix: clear method lookup maps (#198) 2023-07-01 02:35:49 +02:00
semantic-release-bot
7cb4d4c596 chore(release): 11.0.3 [skip ci]
## [11.0.3](https://github.com/revanced/revanced-patcher/compare/v11.0.2...v11.0.3) (2023-06-30)

### Bug Fixes

* NPE on method lookup ([#195](https://github.com/revanced/revanced-patcher/issues/195)) ([fcef434](fcef4342e8))
2023-06-30 23:56:27 +00:00
oSumAtrIX
2c8565508e chore: merge branch dev to main (#196) 2023-07-01 01:54:46 +02:00
semantic-release-bot
c7f156e4c9 chore(release): 11.0.3-dev.1 [skip ci]
## [11.0.3-dev.1](https://github.com/revanced/revanced-patcher/compare/v11.0.2...v11.0.3-dev.1) (2023-06-28)

### Bug Fixes

* NPE on method lookup ([#195](https://github.com/revanced/revanced-patcher/issues/195)) ([fcef434](fcef4342e8))
2023-06-28 19:57:40 +00:00
LisoUseInAIKyrios
fcef4342e8 fix: NPE on method lookup (#195) 2023-06-28 21:56:03 +02:00
semantic-release-bot
72783a5e74 chore(release): 11.0.2 [skip ci]
## [11.0.2](https://github.com/revanced/revanced-patcher/compare/v11.0.1...v11.0.2) (2023-06-27)

### Bug Fixes

* catch exceptions from closing patches ([d5d6f85](d5d6f85084))
* do not load annotations as patches ([519359a](519359a9eb))
* only close succeeded patches ([b8151eb](b8151ebccb))
* use `versionCode` if `versionName` is unavailable ([6e1b647](6e1b6479b6))

### Performance Improvements

* resolve fingerprints using method maps ([#185](https://github.com/revanced/revanced-patcher/issues/185)) ([d718134](d718134ab2))
2023-06-27 02:32:47 +00:00
oSumAtrIX
a379b69eeb chore: merge branch dev to main (#191) 2023-06-27 04:31:09 +02:00
semantic-release-bot
0a8ccba33e chore(release): 11.0.2-dev.4 [skip ci]
## [11.0.2-dev.4](https://github.com/revanced/revanced-patcher/compare/v11.0.2-dev.3...v11.0.2-dev.4) (2023-06-27)

### Bug Fixes

* do not load annotations as patches ([519359a](519359a9eb))
2023-06-27 02:11:33 +00:00
oSumAtrIX
519359a9eb fix: do not load annotations as patches 2023-06-27 04:09:03 +02:00
semantic-release-bot
b615ed6aab chore(release): 11.0.2-dev.3 [skip ci]
## [11.0.2-dev.3](https://github.com/revanced/revanced-patcher/compare/v11.0.2-dev.2...v11.0.2-dev.3) (2023-06-27)

### Performance Improvements

* resolve fingerprints using method maps ([#185](https://github.com/revanced/revanced-patcher/issues/185)) ([d718134](d718134ab2))
2023-06-27 02:08:29 +00:00
LisoUseInAIKyrios
d718134ab2 perf: resolve fingerprints using method maps (#185)
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>
2023-06-27 04:06:51 +02:00
134 changed files with 4639 additions and 2229 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

@@ -36,7 +36,7 @@ jobs:
- name: Build with Gradle
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: ./gradlew clean --no-daemon
run: ./gradlew build clean --no-daemon
- name: Setup semantic-release
run: npm install
- name: Release

View File

@@ -7,7 +7,13 @@
}
],
"plugins": [
"@semantic-release/commit-analyzer",
[
"@semantic-release/commit-analyzer", {
"releaseRules": [
{ "type": "build", "scope": "Needs bump", "release": "patch" }
]
}
],
"@semantic-release/release-notes-generator",
"@semantic-release/changelog",
"gradle-semantic-release-plugin",

File diff suppressed because it is too large Load Diff

View File

@@ -1,71 +1,10 @@
plugins {
kotlin("jvm") version "1.8.10"
`maven-publish`
kotlin("jvm") version "1.9.0" apply false
alias(libs.plugins.binary.compatibility.validator)
}
group = "app.revanced"
allprojects {
apply(plugin = "maven-publish")
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()
maven {
url = uri("https://maven.pkg.github.com/revanced/multidexlib2")
credentials {
username = githubUsername
password = githubPassword
}
}
}
dependencies {
implementation("xpp3:xpp3:1.1.4c")
implementation("app.revanced:smali:2.5.3-a3836654")
implementation("app.revanced:multidexlib2:2.5.3-a3836654")
implementation("app.revanced:apktool-lib:2.7.0")
implementation("org.jetbrains.kotlin:kotlin-reflect:1.8.20-RC")
testImplementation("org.jetbrains.kotlin:kotlin-test:1.8.20-RC")
}
tasks {
test {
useJUnitPlatform()
testLogging {
events("PASSED", "SKIPPED", "FAILED")
}
}
processResources {
expand("projectVersion" to project.version)
}
}
java {
withSourcesJar()
}
kotlin {
jvmToolchain(11)
}
publishing {
repositories {
if (System.getenv("GITHUB_ACTOR") != null)
maven {
name = "GitHubPackages"
url = uri("https://maven.pkg.github.com/revanced/revanced-patcher")
credentials {
username = System.getenv("GITHUB_ACTOR")
password = System.getenv("GITHUB_TOKEN")
}
}
else
mavenLocal()
}
publications {
register<MavenPublication>("gpr") {
from(components["java"])
}
}
}
group = "app.revanced"
}

View File

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

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

@@ -0,0 +1,31 @@
[versions]
android = "4.1.1.4"
kotlin-reflect = "1.9.0"
apktool-lib = "2.8.2-6"
kotlin-test = "1.8.20-RC"
kotlinx-coroutines-core = "1.7.1"
multidexlib2 = "3.0.3.r2"
smali = "3.0.3"
symbol-processing-api = "1.9.0-1.0.11"
xpp3 = "1.1.4c"
binary-compatibility-validator = "0.13.2"
kotlin-compile-testing-ksp = "1.5.0"
kotlinpoet-ksp = "1.14.2"
ksp = "1.9.0-1.0.11"
[libraries]
android = { module = "com.google.android:android", version.ref = "android" }
kotlin-reflect = { module = "org.jetbrains.kotlin:kotlin-reflect", version.ref = "kotlin-reflect" }
apktool-lib = { module = "app.revanced:apktool-lib", version.ref = "apktool-lib" }
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" }
multidexlib2 = { module = "app.revanced:multidexlib2", version.ref = "multidexlib2" }
smali = { module = "com.android.tools.smali:smali", version.ref = "smali" }
symbol-processing-api = { module = "com.google.devtools.ksp:symbol-processing-api", version.ref = "symbol-processing-api" }
xpp3 = { module = "xpp3:xpp3", version.ref = "xpp3" }
kotlin-compile-testing = { module = "com.github.tschuchortdev:kotlin-compile-testing-ksp", version.ref = "kotlin-compile-testing-ksp" }
kotlinpoet-ksp = { module = "com.squareup:kotlinpoet-ksp", version.ref = "kotlinpoet-ksp" }
[plugins]
binary-compatibility-validator = { id = "org.jetbrains.kotlinx.binary-compatibility-validator", version.ref = "binary-compatibility-validator" }
ksp = { id = "com.google.devtools.ksp", version.ref = "ksp" }

Binary file not shown.

View File

@@ -1,5 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.1.1-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

40
gradlew vendored
View File

@@ -1,7 +1,7 @@
#!/bin/sh
#
# Copyright © 2015-2021 the original 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.
@@ -32,10 +32,10 @@
# 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».
# * 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:
#
@@ -55,7 +55,7 @@
# Darwin, MinGW, and NonStop.
#
# (3) This script is generated from the Groovy template
# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
# 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/.
@@ -80,13 +80,10 @@ do
esac
done
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
APP_NAME="Gradle"
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${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"'
APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
@@ -133,22 +130,29 @@ 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.
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" && ! "$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
@@ -193,6 +197,10 @@ if "$cygwin" || "$msys" ; then
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
@@ -205,6 +213,12 @@ set -- \
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.

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

View File

@@ -0,0 +1,25 @@
public abstract interface annotation class app/revanced/patcher/patch/annotations/CompatiblePackage : java/lang/annotation/Annotation {
public abstract fun name ()Ljava/lang/String;
public abstract fun versions ()[Ljava/lang/String;
}
public abstract interface annotation class app/revanced/patcher/patch/annotations/Patch : java/lang/annotation/Annotation {
public abstract fun compatiblePackages ()[Lapp/revanced/patcher/patch/annotations/CompatiblePackage;
public abstract fun dependencies ()[Ljava/lang/Class;
public abstract fun description ()Ljava/lang/String;
public abstract fun name ()Ljava/lang/String;
public abstract fun requiresIntegrations ()Z
public abstract fun use ()Z
}
public final class app/revanced/patcher/patch/annotations/processor/PatchProcessor : com/google/devtools/ksp/processing/SymbolProcessor {
public fun <init> (Lcom/google/devtools/ksp/processing/CodeGenerator;Lcom/google/devtools/ksp/processing/KSPLogger;)V
public fun process (Lcom/google/devtools/ksp/processing/Resolver;)Ljava/util/List;
}
public final class app/revanced/patcher/patch/annotations/processor/PatchProcessorProvider : com/google/devtools/ksp/processing/SymbolProcessorProvider {
public fun <init> ()V
public fun create (Lcom/google/devtools/ksp/processing/SymbolProcessorEnvironment;)Lapp/revanced/patcher/patch/annotations/processor/PatchProcessor;
public synthetic fun create (Lcom/google/devtools/ksp/processing/SymbolProcessorEnvironment;)Lcom/google/devtools/ksp/processing/SymbolProcessor;
}

View File

@@ -0,0 +1,74 @@
plugins {
kotlin("jvm") version "1.9.0"
alias(libs.plugins.ksp)
}
dependencies {
implementation(libs.symbol.processing.api)
implementation(libs.kotlinpoet.ksp)
implementation(project(":revanced-patcher"))
testImplementation(libs.kotlin.test)
testImplementation(libs.kotlin.compile.testing)
}
tasks {
test {
useJUnitPlatform()
testLogging {
events("PASSED", "SKIPPED", "FAILED")
}
}
}
kotlin { jvmToolchain(11) }
java {
withSourcesJar()
}
publishing {
repositories {
mavenLocal()
maven {
name = "GitHubPackages"
url = uri("https://maven.pkg.github.com/revanced/revanced-patcher")
credentials {
username = System.getenv("GITHUB_ACTOR")
password = System.getenv("GITHUB_TOKEN")
}
}
}
publications {
create<MavenPublication>("gpr") {
from(components["java"])
version = project.version.toString()
pom {
name = "ReVanced Patch annotations processor"
description = "Annotation processor for patches."
url = "https://revanced.app"
licenses {
license {
name = "GNU General Public License v3.0"
url = "https://www.gnu.org/licenses/gpl-3.0.en.html"
}
}
developers {
developer {
id = "ReVanced"
name = "ReVanced"
email = "contact@revanced.app"
}
}
scm {
connection = "scm:git:git://github.com/revanced/revanced-patcher.git"
developerConnection = "scm:git:git@github.com:revanced/revanced-patcher.git"
url = "https://github.com/revanced/revanced-patcher"
}
}
}
}
}

View File

@@ -0,0 +1,2 @@
rootProject.name = "revanced-patch-annotations-processor"

View File

@@ -0,0 +1,38 @@
package app.revanced.patcher.patch.annotations
import java.lang.annotation.Inherited
import kotlin.reflect.KClass
/**
* Annotation for [app.revanced.patcher.patch.Patch] classes.
*
* @param name The name of the patch. If empty, the patch will be unnamed.
* @param description The description of the patch. If empty, no description will be used.
* @param dependencies The patches this patch depends on.
* @param compatiblePackages The packages this patch is compatible with.
* @param use Whether this patch should be used.
* @param requiresIntegrations Whether this patch requires integrations.
*/
@Retention(AnnotationRetention.SOURCE)
@Target(AnnotationTarget.CLASS)
@Inherited
annotation class Patch(
val name: String = "",
val description: String = "",
val dependencies: Array<KClass<out app.revanced.patcher.patch.Patch<*>>> = [],
val compatiblePackages: Array<CompatiblePackage> = [],
val use: Boolean = true,
// TODO: Remove this property, once integrations are coupled with patches.
val requiresIntegrations: Boolean = false,
)
/**
* A package that a [app.revanced.patcher.patch.Patch] is compatible with.
*
* @param name The name of the package.
* @param versions The versions of the package.
*/
annotation class CompatiblePackage(
val name: String,
val versions: Array<String> = [],
)

View File

@@ -0,0 +1,205 @@
package app.revanced.patcher.patch.annotations.processor
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.ResourcePatch
import app.revanced.patcher.patch.annotations.Patch
import com.google.devtools.ksp.processing.*
import com.google.devtools.ksp.symbol.KSAnnotated
import com.google.devtools.ksp.symbol.KSAnnotation
import com.google.devtools.ksp.symbol.KSClassDeclaration
import com.google.devtools.ksp.symbol.KSType
import com.google.devtools.ksp.validate
import com.squareup.kotlinpoet.*
import com.squareup.kotlinpoet.ksp.toClassName
import com.squareup.kotlinpoet.ksp.writeTo
import kotlin.reflect.KClass
class PatchProcessor(
private val codeGenerator: CodeGenerator,
private val logger: KSPLogger
) : SymbolProcessor {
private fun KSAnnotated.isSubclassOf(cls: KClass<*>): Boolean {
if (this !is KSClassDeclaration) return false
if (qualifiedName?.asString() == cls.qualifiedName) return true
return superTypes.any { it.resolve().declaration.isSubclassOf(cls) }
}
@Suppress("UNCHECKED_CAST")
override fun process(resolver: Resolver): List<KSAnnotated> {
val executablePatches = buildMap {
resolver.getSymbolsWithAnnotation(Patch::class.qualifiedName!!).filter {
// Do not check here if Patch is super of the class, because it is expensive.
// Check it later when processing.
it.validate() && it.isSubclassOf(app.revanced.patcher.patch.Patch::class)
}.map {
it as KSClassDeclaration
}.forEach { patchDeclaration ->
patchDeclaration.annotations.find {
it.annotationType.resolve().declaration.qualifiedName!!.asString() == Patch::class.qualifiedName!!
}?.let { annotation ->
fun KSAnnotation.property(name: String) =
arguments.find { it.name!!.asString() == name }?.value!!
val name =
annotation.property("name").toString().ifEmpty { null }
val description =
annotation.property("description").toString().ifEmpty { null }
val dependencies =
(annotation.property("dependencies") as List<KSType>).ifEmpty { null }
val compatiblePackages =
(annotation.property("compatiblePackages") as List<KSAnnotation>).ifEmpty { null }
val use =
annotation.property("use") as Boolean
val requiresIntegrations =
annotation.property("requiresIntegrations") as Boolean
// Data class for KotlinPoet
data class PatchData(
val name: String?,
val description: String?,
val dependencies: List<ClassName>?,
val compatiblePackages: List<CodeBlock>?,
val use: Boolean,
val requiresIntegrations: Boolean
)
this[patchDeclaration] = PatchData(
name,
description,
dependencies?.map { dependency -> dependency.toClassName() },
compatiblePackages?.map {
val packageName = it.property("name")
val packageVersions = (it.property("versions") as List<String>)
.joinToString(", ") { version -> "\"$version\"" }
CodeBlock.of(
"%T(%S, setOf(%L))",
app.revanced.patcher.patch.Patch.CompatiblePackage::class,
packageName,
packageVersions
)
},
use,
requiresIntegrations
)
}
}
}
// If a patch depends on another, that is annotated, the dependency should be replaced with the generated patch,
// because the generated patch has all the necessary properties to invoke the super constructor,
// unlike the annotated patch.
val dependencyResolutionMap = buildMap {
executablePatches.values.filter { it.dependencies != null }.flatMap {
it.dependencies!!
}.distinct().forEach { dependency ->
executablePatches.keys.find { it.qualifiedName?.asString() == dependency.toString() }
?.let { patch ->
this[dependency] = ClassName(
patch.packageName.asString(),
patch.simpleName.asString() + "Generated"
)
}
}
}
executablePatches.forEach { (patchDeclaration, patchAnnotation) ->
val isBytecodePatch = patchDeclaration.isSubclassOf(BytecodePatch::class)
val superClass = if (isBytecodePatch) {
BytecodePatch::class
} else {
ResourcePatch::class
}
val contextClass = if (isBytecodePatch) {
BytecodeContext::class
} else {
ResourceContext::class
}
val generatedPatchClassName = ClassName(
patchDeclaration.packageName.asString(),
patchDeclaration.simpleName.asString() + "Generated"
)
FileSpec.builder(generatedPatchClassName)
.addType(
TypeSpec.objectBuilder(generatedPatchClassName)
.superclass(superClass).apply {
patchAnnotation.name?.let { name ->
addSuperclassConstructorParameter("name = %S", name)
}
patchAnnotation.description?.let { description ->
addSuperclassConstructorParameter("description = %S", description)
}
patchAnnotation.compatiblePackages?.let { compatiblePackages ->
addSuperclassConstructorParameter(
"compatiblePackages = setOf(%L)",
compatiblePackages.joinToString(", ")
)
}
patchAnnotation.dependencies?.let { dependencies ->
addSuperclassConstructorParameter(
"dependencies = setOf(%L)",
buildList {
addAll(dependencies)
// Also add the source class of the generated class so that it is also executed.
add(patchDeclaration.toClassName())
}.joinToString(", ") { dependency ->
"${(dependencyResolutionMap[dependency] ?: dependency)}::class"
}
)
}
addSuperclassConstructorParameter(
"use = %L", patchAnnotation.use
)
addSuperclassConstructorParameter(
"requiresIntegrations = %L",
patchAnnotation.requiresIntegrations
)
}
.addFunction(
FunSpec.builder("execute")
.addModifiers(KModifier.OVERRIDE)
.addParameter("context", contextClass)
.build()
)
.addInitializerBlock(
CodeBlock.builder()
.add(
"%T.options.forEach { (key, option) ->",
patchDeclaration.toClassName()
)
.addStatement(
"options.register(option)"
)
.add(
"}"
)
.build()
)
.build()
).build().writeTo(
codeGenerator,
Dependencies(false, patchDeclaration.containingFile!!)
)
}
return emptyList()
}
}

View File

@@ -0,0 +1,9 @@
package app.revanced.patcher.patch.annotations.processor
import com.google.devtools.ksp.processing.SymbolProcessorEnvironment
import com.google.devtools.ksp.processing.SymbolProcessorProvider
class PatchProcessorProvider : SymbolProcessorProvider {
override fun create(environment: SymbolProcessorEnvironment) =
PatchProcessor(environment.codeGenerator, environment.logger)
}

View File

@@ -0,0 +1 @@
app.revanced.patcher.patch.annotations.processor.PatchProcessorProvider

View File

@@ -0,0 +1,130 @@
package app.revanced.patcher.patch.annotations.processor
import app.revanced.patcher.patch.Patch
import com.tschuchort.compiletesting.KotlinCompilation
import com.tschuchort.compiletesting.SourceFile
import com.tschuchort.compiletesting.kspWithCompilation
import com.tschuchort.compiletesting.symbolProcessorProviders
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertNull
class TestPatchAnnotationProcessor {
// region Processing
@Test
fun testProcessing() = assertEquals(
"Processable patch", compile(
getSourceFile(
"processing", "ProcessablePatch"
)
).loadPatch("$SAMPLE_PACKAGE.processing.ProcessablePatchGenerated").name
)
// endregion
// region Dependencies
@Test
fun testDependencies() {
compile(
getSourceFile(
"dependencies", "DependentPatch"
), getSourceFile(
"dependencies", "DependencyPatch"
)
).let { result ->
result.loadPatch("$SAMPLE_PACKAGE.dependencies.DependentPatchGenerated").let {
// Dependency as well as the source class of the generated class.
assertEquals(
2,
it.dependencies!!.size
)
// The last dependency is always the source class of the generated class to respect
// order of dependencies.
assertEquals(
result.loadPatch("$SAMPLE_PACKAGE.dependencies.DependentPatch")::class,
it.dependencies!!.last()
)
}
}
}
// endregion
// region Options
@Test
fun testOptions() {
val patch = compile(
getSourceFile(
"options", "OptionsPatch"
)
).loadPatch("$SAMPLE_PACKAGE.options.OptionsPatchGenerated")
assert(patch.options.isNotEmpty())
assertEquals(patch.options["print"].title, "Print message")
}
// endregion
// region Limitations
@Test
fun failingManualDependency() = assertNull(
compile(
getSourceFile(
"limitations/manualdependency", "DependentPatch"
), getSourceFile(
"limitations/manualdependency", "DependencyPatch"
)
).loadPatch("$SAMPLE_PACKAGE.limitations.manualdependency.DependentPatchGenerated").dependencies
)
// endregion
private companion object Utils {
const val SAMPLE_PACKAGE = "app.revanced.patcher.patch.annotations.processor.samples"
/**
* Get a source file from the given sample and class name.
*
* @param sample The sample to get the source file from.
* @param className The name of the class to get the source file from.
* @return The source file.
*/
fun getSourceFile(sample: String, className: String) = SourceFile.kotlin(
"$className.kt", TestPatchAnnotationProcessor::class.java.classLoader.getResourceAsStream(
"app/revanced/patcher/patch/annotations/processor/samples/$sample/$className.kt"
)?.readAllBytes()?.toString(Charsets.UTF_8) ?: error("Could not find resource $className")
)
/**
* Compile the given source files and return the result.
*
* @param sourceFiles The source files to compile.
* @return The result of the compilation.
*/
fun compile(vararg sourceFiles: SourceFile) = KotlinCompilation().apply {
sources = sourceFiles.asList()
symbolProcessorProviders = listOf(PatchProcessorProvider())
// Required until https://github.com/tschuchortdev/kotlin-compile-testing/issues/312 closed.
kspWithCompilation = true
inheritClassPath = true
messageOutputStream = System.out
}.compile().also { result ->
assertEquals(KotlinCompilation.ExitCode.OK, result.exitCode)
}
// region Class loading
fun KotlinCompilation.Result.loadPatch(name: String) = classLoader.loadClass(name).loadPatch()
fun Class<*>.loadPatch() = this.getField("INSTANCE").get(null) as Patch<*>
// endregion
}
}

View File

@@ -0,0 +1,10 @@
package app.revanced.patcher.patch.annotations.processor.samples.dependencies
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.ResourcePatch
import app.revanced.patcher.patch.annotations.Patch
@Patch(name = "Dependency patch")
object DependencyPatch : ResourcePatch() {
override fun execute(context: ResourceContext) {}
}

View File

@@ -0,0 +1,12 @@
package app.revanced.patcher.patch.annotations.processor.samples.dependencies
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotations.Patch
@Patch(
name = "Dependent patch",
dependencies = [DependencyPatch::class],
)
object DependentPatch : BytecodePatch() {
override fun execute(context: BytecodeContext) {}
}

View File

@@ -0,0 +1,10 @@
package app.revanced.patcher.patch.annotations.processor.samples.limitations.manualdependency
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.ResourcePatch
import app.revanced.patcher.patch.annotations.Patch
@Patch(name = "Dependency patch")
object DependencyPatch : ResourcePatch() {
override fun execute(context: ResourceContext) { }
}

View File

@@ -0,0 +1,17 @@
package app.revanced.patcher.patch.annotations.processor.samples.limitations.manualdependency
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotations.Patch
@Patch(name = "Dependent patch")
object DependentPatch : BytecodePatch(
// Dependency will not be executed correctly if it is manually specified.
// The reason for this is that the dependency patch is annotated too,
// so the processor will generate a new patch class for it embedding the annotated information.
// Because the dependency is manually specified,
// the processor will not be able to change this dependency to the generated class,
// which means that the dependency will lose the annotated information.
dependencies = setOf(DependencyPatch::class)
) {
override fun execute(context: BytecodeContext) {}
}

View File

@@ -0,0 +1,19 @@
package app.revanced.patcher.patch.annotations.processor.samples.options
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.ResourcePatch
import app.revanced.patcher.patch.annotations.Patch
import app.revanced.patcher.patch.options.types.StringPatchOption.Companion.stringPatchOption
@Patch(name = "Options patch")
object OptionsPatch : ResourcePatch() {
override fun execute(context: ResourceContext) {}
@Suppress("unused")
private val printOption by stringPatchOption(
"print",
null,
"Print message",
"The message to print."
)
}

View File

@@ -0,0 +1,10 @@
package app.revanced.patcher.patch.annotations.processor.samples.processing
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotations.Patch
@Patch("Processable patch")
object ProcessablePatch : BytecodePatch() {
override fun execute(context: BytecodeContext) {}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,82 @@
plugins {
kotlin("jvm") version "1.9.0"
}
dependencies {
implementation(libs.kotlinx.coroutines.core)
implementation(libs.xpp3)
implementation(libs.smali)
implementation(libs.multidexlib2)
implementation(libs.apktool.lib)
implementation(libs.kotlin.reflect)
compileOnly(libs.android)
testImplementation(project(":revanced-patch-annotations-processor"))
testImplementation(libs.kotlin.test)
}
tasks {
test {
useJUnitPlatform()
testLogging {
events("PASSED", "SKIPPED", "FAILED")
}
}
processResources {
expand("projectVersion" to project.version)
}
}
kotlin { jvmToolchain(11) }
java {
withSourcesJar()
}
publishing {
repositories {
mavenLocal()
maven {
name = "GitHubPackages"
url = uri("https://maven.pkg.github.com/revanced/revanced-patcher")
credentials {
username = System.getenv("GITHUB_ACTOR")
password = System.getenv("GITHUB_TOKEN")
}
}
}
publications {
create<MavenPublication>("gpr") {
from(components["java"])
version = project.version.toString()
pom {
name = "ReVanced Patcher"
description = "Patcher used by ReVanced."
url = "https://revanced.app"
licenses {
license {
name = "GNU General Public License v3.0"
url = "https://www.gnu.org/licenses/gpl-3.0.en.html"
}
}
developers {
developer {
id = "ReVanced"
name = "ReVanced"
email = "contact@revanced.app"
}
}
scm {
connection = "scm:git:git://github.com/revanced/revanced-patcher.git"
developerConnection = "scm:git:git@github.com:revanced/revanced-patcher.git"
url = "https://github.com/revanced/revanced-patcher"
}
}
}
}
}

View File

@@ -0,0 +1 @@
rootProject.name = "revanced-patcher"

View File

@@ -0,0 +1,8 @@
package app.revanced.patcher
import java.io.File
@FunctionalInterface
interface IntegrationsConsumer {
fun acceptIntegrations(integrations: List<File>)
}

View File

@@ -0,0 +1,14 @@
package app.revanced.patcher
import brut.androlib.apk.ApkInfo
/**
* Metadata about a package.
*/
class PackageMetadata internal constructor(internal val apkInfo: ApkInfo) {
lateinit var packageName: String
internal set
lateinit var packageVersion: String
internal set
}

View File

@@ -0,0 +1,124 @@
@file:Suppress("unused")
package app.revanced.patcher
import app.revanced.patcher.patch.Patch
import dalvik.system.DexClassLoader
import lanchon.multidexlib2.BasicDexFileNamer
import lanchon.multidexlib2.MultiDexIO
import java.io.File
import java.net.URLClassLoader
import java.util.jar.JarFile
import java.util.logging.Logger
import kotlin.reflect.KClass
/**
* [Patch]es mapped by their name.
*/
typealias PatchMap = Map<String, Patch<*>>
/**
* A [Patch] class.
*/
typealias PatchClass = KClass<out Patch<*>>
/**
* A loader of [Patch]es from patch bundles.
* This will load all [Patch]es from the given patch bundles that have a name.
*
* @param getBinaryClassNames A function that returns the binary names of all classes in a patch bundle.
* @param classLoader The [ClassLoader] to use for loading the classes.
*/
sealed class PatchBundleLoader private constructor(
classLoader: ClassLoader,
patchBundles: Array<out File>,
getBinaryClassNames: (patchBundle: File) -> List<String>,
) : PatchMap by mutableMapOf() {
private val logger = Logger.getLogger(PatchBundleLoader::class.java.name)
init {
patchBundles.flatMap(getBinaryClassNames).asSequence().map {
classLoader.loadClass(it)
}.filter {
it.isInstance(Patch::class.java)
}.mapNotNull { patchClass ->
patchClass.getInstance(logger)
}.filter {
it.name != null
}.associateBy {
it.name!!
}.let { patches ->
@Suppress("UNCHECKED_CAST")
(this as MutableMap<String, Patch<*>>).putAll(patches)
}
}
internal companion object Utils {
/**
* Instantiates a [Patch]. If the class is a singleton, the INSTANCE field will be used.
*
* @param logger The [Logger] to use for logging.
* @return The instantiated [Patch] or `null` if the [Patch] could not be instantiated.
*/
internal fun Class<*>.getInstance(logger: Logger): Patch<*>? {
return try {
getField("INSTANCE").get(null)
} catch (exception: NoSuchFileException) {
logger.fine(
"Patch class '${name}' has no INSTANCE field, therefor not a singleton. " +
"Will try to instantiate it."
)
try {
getDeclaredConstructor().newInstance()
} catch (exception: Exception) {
logger.severe(
"Patch class '${name}' is not singleton and has no suitable constructor, " +
"therefor cannot be instantiated and will be ignored."
)
return null
}
} as Patch<*>
}
}
/**
* A [PatchBundleLoader] for JAR files.
*
* @param patchBundles The path to patch bundles of JAR format.
*/
class Jar(vararg patchBundles: File) : PatchBundleLoader(
URLClassLoader(patchBundles.map { it.toURI().toURL() }.toTypedArray()),
patchBundles,
{ patchBundle ->
JarFile(patchBundle).entries().toList().filter { it.name.endsWith(".class") }
.map { it.name.replace('/', '.').replace(".class", "") }
}
)
/**
* A [PatchBundleLoader] for [Dex] files.
*
* @param patchBundles The path to patch bundles of DEX format.
* @param optimizedDexDirectory The directory to store optimized DEX files in.
* This parameter is deprecated and has no effect since API level 26.
*/
class Dex(vararg patchBundles: File, optimizedDexDirectory: File? = null) : PatchBundleLoader(
DexClassLoader(
patchBundles.joinToString(File.pathSeparator) { it.absolutePath }, optimizedDexDirectory?.absolutePath,
null,
PatchBundleLoader::class.java.classLoader
),
patchBundles,
{ patchBundle ->
MultiDexIO.readDexFile(true, patchBundle, BasicDexFileNamer(), null, null).classes
.map { classDef ->
classDef.type.substring(1, classDef.length - 1)
}
}
) {
@Deprecated("This constructor is deprecated. Use the constructor with the second parameter instead.")
constructor(vararg patchBundles: File) : this(*patchBundles, optimizedDexDirectory = null)
}
}

View File

@@ -0,0 +1,8 @@
package app.revanced.patcher
import app.revanced.patcher.patch.PatchResult
import kotlinx.coroutines.flow.Flow
import java.util.function.Function
@FunctionalInterface
interface PatchExecutorFunction : Function<Boolean, Flow<PatchResult>>

Some files were not shown because too many files have changed in this diff Show More