1
mirror of https://github.com/revanced/revanced-patcher synced 2025-09-10 05:30:49 +02:00

Compare commits

...

58 Commits

Author SHA1 Message Date
semantic-release-bot
38ef2f470a chore(release): 16.0.2 [skip ci]
## [16.0.2](https://github.com/ReVanced/revanced-patcher/compare/v16.0.1...v16.0.2) (2023-10-06)

### Performance Improvements

* Use a map to merge integrations classes ([6059d3c](6059d3ca26))
2023-10-06 23:59:10 +00:00
oSumAtrIX
129d84e108 chore: Merge branch dev to main (#250) 2023-10-07 01:55:48 +02:00
semantic-release-bot
affeba76b8 chore(release): 16.0.2-dev.1 [skip ci]
## [16.0.2-dev.1](https://github.com/ReVanced/revanced-patcher/compare/v16.0.1...v16.0.2-dev.1) (2023-10-06)

### Performance Improvements

* Use a map to merge integrations classes ([6059d3c](6059d3ca26))
2023-10-06 23:55:11 +00:00
oSumAtrIX
6059d3ca26 perf: Use a map to merge integrations classes 2023-10-07 01:52:21 +02:00
semantic-release-bot
444dee5a16 chore(release): 16.0.1 [skip ci]
## [16.0.1](https://github.com/ReVanced/revanced-patcher/compare/v16.0.0...v16.0.1) (2023-10-05)

### Bug Fixes

* Merge integrations when required ([06c2b76](06c2b76f11))
2023-10-05 15:31:28 +00:00
oSumAtrIX
d314466ce2 chore: Merge branch dev to main (#249) 2023-10-05 17:28:45 +02:00
semantic-release-bot
fdaf9c21c8 chore(release): 16.0.1-dev.1 [skip ci]
## [16.0.1-dev.1](https://github.com/ReVanced/revanced-patcher/compare/v16.0.0...v16.0.1-dev.1) (2023-10-05)

### Bug Fixes

* Merge integrations when required ([06c2b76](06c2b76f11))
2023-10-05 15:27:34 +00:00
oSumAtrIX
06c2b76f11 fix: Merge integrations when required
Previous to this commit integrations were merged when not required.
2023-10-05 17:24:28 +02:00
semantic-release-bot
3896b30738 chore(release): 16.0.0 [skip ci]
# [16.0.0](https://github.com/ReVanced/revanced-patcher/compare/v15.0.3...v16.0.0) (2023-10-04)

### Bug Fixes

* Use correct super class type ([f590436](f590436399))

### BREAKING CHANGES

* This changes the super classes of some `PatchOptionException` classes
2023-10-04 02:18:27 +00:00
oSumAtrIX
2c4b88e1a0 chore: Merge branch dev to main (#248) 2023-10-04 04:15:04 +02:00
semantic-release-bot
dfc7e1596b chore(release): 16.0.0-dev.1 [skip ci]
# [16.0.0-dev.1](https://github.com/ReVanced/revanced-patcher/compare/v15.0.3...v16.0.0-dev.1) (2023-10-04)

### Bug Fixes

* Use correct super class type ([f590436](f590436399))

### BREAKING CHANGES

* This changes the super classes of some `PatchOptionException` classes
2023-10-04 02:06:03 +00:00
oSumAtrIX
f590436399 fix: Use correct super class type
BREAKING CHANGE: This changes the super classes of some `PatchOptionException` classes
2023-10-04 04:02:10 +02:00
semantic-release-bot
cbfb9ba02f chore(release): 15.0.3 [skip ci]
## [15.0.3](https://github.com/ReVanced/revanced-patcher/compare/v15.0.2...v15.0.3) (2023-10-01)

### Bug Fixes

* Fix SMALI compilation on devices with RTL language ([#242](https://github.com/ReVanced/revanced-patcher/issues/242)) ([356f1f1](356f1f1553))
2023-10-01 16:58:40 +00:00
oSumAtrIX
b4cfe80ad5 chore: Merge branch dev to main (#243) 2023-10-01 18:56:02 +02:00
semantic-release-bot
b37906fa35 chore(release): 15.0.3-dev.1 [skip ci]
## [15.0.3-dev.1](https://github.com/ReVanced/revanced-patcher/compare/v15.0.2...v15.0.3-dev.1) (2023-09-29)

### Bug Fixes

* Fix SMALI compilation on devices with RTL language ([#242](https://github.com/ReVanced/revanced-patcher/issues/242)) ([356f1f1](356f1f1553))
2023-09-29 13:18:47 +00:00
LisoUseInAIKyrios
356f1f1553 fix: Fix SMALI compilation on devices with RTL language (#242) 2023-09-29 15:15:14 +02:00
semantic-release-bot
e882af74ee chore(release): 15.0.2 [skip ci]
## [15.0.2](https://github.com/ReVanced/revanced-patcher/compare/v15.0.1...v15.0.2) (2023-09-27)

### Performance Improvements

* Do not unnecessary resolve fingeprints twice ([#241](https://github.com/ReVanced/revanced-patcher/issues/241)) ([4d6e08a](4d6e08a650))
2023-09-27 21:27:32 +00:00
oSumAtrIX
46875fb28e chore: Merge branch dev to main (#238) 2023-09-27 23:23:46 +02:00
oSumAtrIX
417c3e4234 ci: Bump checkout action 2023-09-27 18:02:50 +02:00
semantic-release-bot
6d2c28807b chore(release): 15.0.2-dev.1 [skip ci]
## [15.0.2-dev.1](https://github.com/ReVanced/revanced-patcher/compare/v15.0.1...v15.0.2-dev.1) (2023-09-26)

### Performance Improvements

* Do not unnecessary resolve fingeprints twice ([#241](https://github.com/ReVanced/revanced-patcher/issues/241)) ([4d6e08a](4d6e08a650))
2023-09-26 12:25:00 +00:00
LisoUseInAIKyrios
4d6e08a650 perf: Do not unnecessary resolve fingeprints twice (#241) 2023-09-26 14:21:43 +02:00
oSumAtrIX
5cebc1fd30 ci: Use better workflow name and PR message 2023-09-23 18:17:47 +02:00
semantic-release-bot
ac61731dc6 chore(release): 15.0.1 [skip ci]
## [15.0.1](https://github.com/ReVanced/revanced-patcher/compare/v15.0.0...v15.0.1) (2023-09-20)

### Bug Fixes

* Remove log management ([d51bc32](d51bc32e37))
2023-09-20 03:19:14 +00:00
oSumAtrIX
9e4ffabd5c chore: merge branch dev to main (#235) 2023-09-20 05:16:25 +02:00
semantic-release-bot
3f410bd39f chore(release): 15.0.1-dev.1 [skip ci]
## [15.0.1-dev.1](https://github.com/ReVanced/revanced-patcher/compare/v15.0.0...v15.0.1-dev.1) (2023-09-20)

### Bug Fixes

* Remove log management ([d51bc32](d51bc32e37))
2023-09-20 03:16:04 +00:00
oSumAtrIX
d51bc32e37 fix: Remove log management
Changing the logging behaviour caused unintended behaviour outside of the library.
2023-09-19 05:09:19 +02:00
oSumAtrIX
b7f6aa94cc chore: Fix inline docs reference 2023-09-19 05:08:37 +02:00
semantic-release-bot
ff965e6953 chore(release): 15.0.0 [skip ci]
# [15.0.0](https://github.com/ReVanced/revanced-patcher/compare/v14.2.2...v15.0.0) (2023-09-18)

### Bug Fixes

* Account for source patch dependency for tests ([6918418](69184187d9))
* Always make the generated patch depend on the source patch ([8de3063](8de30633ae))
* Catch correct exception ([637d487](637d48746f))
* Delegate `PatchBundleLoader` by mutable set of patches ([9a109c1](9a109c129b))
* Do not resolve the proxied patch to the proxy in the dependency list ([e112837](e11283744a))
* Do not set `CompatiblePackage.versions` if `@CompatiblePackage.versions` is empty ([6b1e0a1](6b1e0a1656))
* Filter for patches correctly ([4bc4b0d](4bc4b0dc01))
* Find dependency in `context.allPatches` ([670f015](670f0153de))
* Log the correct patch names ([9fdb8f0](9fdb8f087f))
* Make `CompatiblePackage.versions` a property ([67b7dff](67b7dff67a))
* Print patch name instead of class name ([4e7811e](4e7811ea07))
* Print stack trace of exception ([aa71146](aa71146b1b))
* Run code-block if `executablePatches` does not yet contain `patch` ([1d7aeca](1d7aeca696))
* Suppress logger when loading patches in `PatchBundleLoader` ([72c9eb2](72c9eb2129))
* Use correct module name ([080fbe9](080fbe9feb))

### Code Refactoring

* Internalize processor constructor ([a802d0d](a802d0df46))

* feat Use `Set` as super type for `PatchBundleLoader` ([4b76d19](4b76d19596))
* 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

* This gets rid of the public constructor.
* `PatchBundleLoader` is not a map anymore
* This renames packages and the Maven package.
* 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-18 15:44:01 +00:00
oSumAtrIX
468d5d7421 chore: merge branch dev to main (#232) 2023-09-18 17:40:24 +02:00
semantic-release-bot
fc95b28c49 chore(release): 15.0.0-dev.4 [skip ci]
# [15.0.0-dev.4](https://github.com/ReVanced/revanced-patcher/compare/v15.0.0-dev.3...v15.0.0-dev.4) (2023-09-13)

### Bug Fixes

* Account for source patch dependency for tests ([6918418](69184187d9))
* Always make the generated patch depend on the source patch ([8de3063](8de30633ae))
* Catch correct exception ([637d487](637d48746f))
* Delegate `PatchBundleLoader` by mutable set of patches ([9a109c1](9a109c129b))
* Do not resolve the proxied patch to the proxy in the dependency list ([e112837](e11283744a))
* Do not set `CompatiblePackage.versions` if `@CompatiblePackage.versions` is empty ([6b1e0a1](6b1e0a1656))
* Filter for patches correctly ([4bc4b0d](4bc4b0dc01))
* Find dependency in `context.allPatches` ([670f015](670f0153de))
* Log the correct patch names ([9fdb8f0](9fdb8f087f))
* Print patch name instead of class name ([4e7811e](4e7811ea07))
* Print stack trace of exception ([aa71146](aa71146b1b))
* Run code-block if `executablePatches` does not yet contain `patch` ([1d7aeca](1d7aeca696))
* Suppress logger when loading patches in `PatchBundleLoader` ([72c9eb2](72c9eb2129))

### Code Refactoring

* Internalize processor constructor ([a802d0d](a802d0df46))

### BREAKING CHANGES

* This gets rid of the public constructor.
2023-09-13 03:44:27 +00:00
oSumAtrIX
69184187d9 fix: Account for source patch dependency for tests 2023-09-13 05:40:59 +02:00
oSumAtrIX
a802d0df46 refactor: Internalize processor constructor
BREAKING CHANGE: This gets rid of the public constructor.
2023-09-13 05:32:40 +02:00
oSumAtrIX
8de30633ae fix: Always make the generated patch depend on the source patch 2023-09-13 05:18:28 +02:00
oSumAtrIX
a1fbb7990f refactor: Simplify fingerprint resolution 2023-09-13 04:13:38 +02:00
oSumAtrIX
aa71146b1b fix: Print stack trace of exception
Otherwise the log will not include what originally raised the exception.
2023-09-13 03:58:46 +02:00
oSumAtrIX
9fdb8f087f fix: Log the correct patch names 2023-09-13 03:35:39 +02:00
oSumAtrIX
670f0153de fix: Find dependency in context.allPatches 2023-09-13 03:06:40 +02:00
oSumAtrIX
1d7aeca696 fix: Run code-block if executablePatches does not yet contain patch 2023-09-13 03:06:19 +02:00
oSumAtrIX
4e7811ea07 fix: Print patch name instead of class name 2023-09-13 03:05:37 +02:00
oSumAtrIX
e11283744a fix: Do not resolve the proxied patch to the proxy in the dependency list
If a patch is used as a dependency, it would be present in `dependencyResolutionMap`. If that patch would also be annotated, then the generated patch would depend on itself.
2023-09-13 03:05:06 +02:00
oSumAtrIX
91cdfd53ef refactor: Simplify accessing the patches from PatcherContext.executablePatches 2023-09-13 02:22:31 +02:00
oSumAtrIX
bc7d6b9941 refactor: Rename unused destructed parameter to _ 2023-09-13 02:17:54 +02:00
oSumAtrIX
6b1e0a1656 fix: Do not set CompatiblePackage.versions if @CompatiblePackage.versions is empty 2023-09-13 02:17:24 +02:00
oSumAtrIX
72c9eb2129 fix: Suppress logger when loading patches in PatchBundleLoader 2023-09-13 02:11:51 +02:00
oSumAtrIX
4bc4b0dc01 fix: Filter for patches correctly 2023-09-13 01:52:15 +02:00
oSumAtrIX
637d48746f fix: Catch correct exception 2023-09-13 01:51:46 +02:00
oSumAtrIX
9a109c129b fix: Delegate PatchBundleLoader by mutable set of patches 2023-09-13 01:36:53 +02:00
oSumAtrIX
d49e4ee5ea refactor: Remove unused logger 2023-09-13 00:08:52 +02:00
semantic-release-bot
30f0ea29a3 chore(release): 15.0.0-dev.3 [skip ci]
# [15.0.0-dev.3](https://github.com/ReVanced/revanced-patcher/compare/v15.0.0-dev.2...v15.0.0-dev.3) (2023-09-06)

### Bug Fixes

* Make `CompatiblePackage.versions` a property ([67b7dff](67b7dff67a))
* Use correct module name ([080fbe9](080fbe9feb))

* feat Use `Set` as super type for `PatchBundleLoader` ([4b76d19](4b76d19596))

### BREAKING CHANGES

* `PatchBundleLoader` is not a map anymore
* This renames packages and the Maven package.
2023-09-06 12:32:05 +00:00
oSumAtrIX
49930f6565 chore: Use correct resource names for tests 2023-09-06 14:27:51 +02:00
oSumAtrIX
909d89fa8d chore: Print correct error message 2023-09-06 14:23:26 +02:00
oSumAtrIX
81d1d7f544 refactor: Do not reify generic type 2023-09-06 06:34:38 +02:00
oSumAtrIX
67b7dff67a fix: Make CompatiblePackage.versions a property 2023-09-06 06:12:44 +02:00
oSumAtrIX
4b76d19596 feat Use Set as super type for PatchBundleLoader
BREAKING CHANGE: `PatchBundleLoader` is not a map anymore
2023-09-06 06:12:22 +02:00
oSumAtrIX
080fbe9feb fix: Use correct module name
BREAKING CHANGE: This renames packages and the Maven package.
2023-09-06 06:11:15 +02:00
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
58 changed files with 1514 additions and 936 deletions

View File

@@ -1,4 +1,4 @@
name: PR to main name: Open a PR to main
on: on:
push: push:
@@ -7,7 +7,7 @@ on:
workflow_dispatch: workflow_dispatch:
env: env:
MESSAGE: merge branch `${{ github.head_ref || github.ref_name }}` to `main` MESSAGE: Merge branch `${{ github.head_ref || github.ref_name }}` to `main`
jobs: jobs:
pull-request: pull-request:
@@ -15,7 +15,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v4
- name: Open pull request - name: Open pull request
uses: repo-sync/pull-request@v2 uses: repo-sync/pull-request@v2
with: with:

View File

@@ -17,7 +17,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v3 uses: actions/checkout@v4
with: with:
# Make sure the release step uses its own credentials: # Make sure the release step uses its own credentials:
# https://github.com/cycjimmy/semantic-release-action#private-packages # https://github.com/cycjimmy/semantic-release-action#private-packages

View File

@@ -1,3 +1,190 @@
## [16.0.2](https://github.com/ReVanced/revanced-patcher/compare/v16.0.1...v16.0.2) (2023-10-06)
### Performance Improvements
* Use a map to merge integrations classes ([6059d3c](https://github.com/ReVanced/revanced-patcher/commit/6059d3ca2685cb659023b171b95d4b9d279c6e53))
## [16.0.2-dev.1](https://github.com/ReVanced/revanced-patcher/compare/v16.0.1...v16.0.2-dev.1) (2023-10-06)
### Performance Improvements
* Use a map to merge integrations classes ([6059d3c](https://github.com/ReVanced/revanced-patcher/commit/6059d3ca2685cb659023b171b95d4b9d279c6e53))
## [16.0.1](https://github.com/ReVanced/revanced-patcher/compare/v16.0.0...v16.0.1) (2023-10-05)
### Bug Fixes
* Merge integrations when required ([06c2b76](https://github.com/ReVanced/revanced-patcher/commit/06c2b76f11ac1bfe43d51d54d425e7577ecefdf6))
## [16.0.1-dev.1](https://github.com/ReVanced/revanced-patcher/compare/v16.0.0...v16.0.1-dev.1) (2023-10-05)
### Bug Fixes
* Merge integrations when required ([06c2b76](https://github.com/ReVanced/revanced-patcher/commit/06c2b76f11ac1bfe43d51d54d425e7577ecefdf6))
# [16.0.0](https://github.com/ReVanced/revanced-patcher/compare/v15.0.3...v16.0.0) (2023-10-04)
### Bug Fixes
* Use correct super class type ([f590436](https://github.com/ReVanced/revanced-patcher/commit/f590436399f6385c51cea54618251b5d823c31f9))
### BREAKING CHANGES
* This changes the super classes of some `PatchOptionException` classes
# [16.0.0-dev.1](https://github.com/ReVanced/revanced-patcher/compare/v15.0.3...v16.0.0-dev.1) (2023-10-04)
### Bug Fixes
* Use correct super class type ([f590436](https://github.com/ReVanced/revanced-patcher/commit/f590436399f6385c51cea54618251b5d823c31f9))
### BREAKING CHANGES
* This changes the super classes of some `PatchOptionException` classes
## [15.0.3](https://github.com/ReVanced/revanced-patcher/compare/v15.0.2...v15.0.3) (2023-10-01)
### Bug Fixes
* Fix SMALI compilation on devices with RTL language ([#242](https://github.com/ReVanced/revanced-patcher/issues/242)) ([356f1f1](https://github.com/ReVanced/revanced-patcher/commit/356f1f155348347a8f318a2e024716ebf4fec99b))
## [15.0.3-dev.1](https://github.com/ReVanced/revanced-patcher/compare/v15.0.2...v15.0.3-dev.1) (2023-09-29)
### Bug Fixes
* Fix SMALI compilation on devices with RTL language ([#242](https://github.com/ReVanced/revanced-patcher/issues/242)) ([356f1f1](https://github.com/ReVanced/revanced-patcher/commit/356f1f155348347a8f318a2e024716ebf4fec99b))
## [15.0.2](https://github.com/ReVanced/revanced-patcher/compare/v15.0.1...v15.0.2) (2023-09-27)
### Performance Improvements
* Do not unnecessary resolve fingeprints twice ([#241](https://github.com/ReVanced/revanced-patcher/issues/241)) ([4d6e08a](https://github.com/ReVanced/revanced-patcher/commit/4d6e08a650dde6ec2e18611c5db1ab92b9a61dd1))
## [15.0.2-dev.1](https://github.com/ReVanced/revanced-patcher/compare/v15.0.1...v15.0.2-dev.1) (2023-09-26)
### Performance Improvements
* Do not unnecessary resolve fingeprints twice ([#241](https://github.com/ReVanced/revanced-patcher/issues/241)) ([4d6e08a](https://github.com/ReVanced/revanced-patcher/commit/4d6e08a650dde6ec2e18611c5db1ab92b9a61dd1))
## [15.0.1](https://github.com/ReVanced/revanced-patcher/compare/v15.0.0...v15.0.1) (2023-09-20)
### Bug Fixes
* Remove log management ([d51bc32](https://github.com/ReVanced/revanced-patcher/commit/d51bc32e37a865194c3825471085b3ccf8c78421))
## [15.0.1-dev.1](https://github.com/ReVanced/revanced-patcher/compare/v15.0.0...v15.0.1-dev.1) (2023-09-20)
### Bug Fixes
* Remove log management ([d51bc32](https://github.com/ReVanced/revanced-patcher/commit/d51bc32e37a865194c3825471085b3ccf8c78421))
# [15.0.0](https://github.com/ReVanced/revanced-patcher/compare/v14.2.2...v15.0.0) (2023-09-18)
### Bug Fixes
* Account for source patch dependency for tests ([6918418](https://github.com/ReVanced/revanced-patcher/commit/69184187d90f126478d2f49415c1e3381217557f))
* Always make the generated patch depend on the source patch ([8de3063](https://github.com/ReVanced/revanced-patcher/commit/8de30633ae6eb7acf7f0a351e26d4a6c2fdbdfec))
* Catch correct exception ([637d487](https://github.com/ReVanced/revanced-patcher/commit/637d48746ff8694e01c5aead1c75a9a1efeb5ac8))
* Delegate `PatchBundleLoader` by mutable set of patches ([9a109c1](https://github.com/ReVanced/revanced-patcher/commit/9a109c129b135a634be1aad4130a06d9e8e96ecd))
* Do not resolve the proxied patch to the proxy in the dependency list ([e112837](https://github.com/ReVanced/revanced-patcher/commit/e11283744a21fe2d09435e99d6924462b6aac3b8))
* Do not set `CompatiblePackage.versions` if `@CompatiblePackage.versions` is empty ([6b1e0a1](https://github.com/ReVanced/revanced-patcher/commit/6b1e0a16568124e9f82fb5740353360fa8ec614a))
* Filter for patches correctly ([4bc4b0d](https://github.com/ReVanced/revanced-patcher/commit/4bc4b0dc0104073b62528d02a88383cecd7a50e7))
* Find dependency in `context.allPatches` ([670f015](https://github.com/ReVanced/revanced-patcher/commit/670f0153de10c6f0db25b08df1c01a2905037f84))
* Log the correct patch names ([9fdb8f0](https://github.com/ReVanced/revanced-patcher/commit/9fdb8f087f62babf6081879db65c80db639aa0a7))
* Make `CompatiblePackage.versions` a property ([67b7dff](https://github.com/ReVanced/revanced-patcher/commit/67b7dff67a212b4fc30eb4f0cbe58f0ba09fb09a))
* Print patch name instead of class name ([4e7811e](https://github.com/ReVanced/revanced-patcher/commit/4e7811ea07762667a1f22526dc176022038f60eb))
* Print stack trace of exception ([aa71146](https://github.com/ReVanced/revanced-patcher/commit/aa71146b1bf4ffebcc81a1663e15abae89e97ff0))
* Run code-block if `executablePatches` does not yet contain `patch` ([1d7aeca](https://github.com/ReVanced/revanced-patcher/commit/1d7aeca696be873dfaf88eaa6d312949a3b8572b))
* Suppress logger when loading patches in `PatchBundleLoader` ([72c9eb2](https://github.com/ReVanced/revanced-patcher/commit/72c9eb212985f99f3390cf1faa10ab547d2dbe7e))
* Use correct module name ([080fbe9](https://github.com/ReVanced/revanced-patcher/commit/080fbe9feb9d4ea9ec4e599ecef296eacd803b05))
### Code Refactoring
* Internalize processor constructor ([a802d0d](https://github.com/ReVanced/revanced-patcher/commit/a802d0df463695976e85d8391762942eb977920b))
* feat Use `Set` as super type for `PatchBundleLoader` ([4b76d19](https://github.com/ReVanced/revanced-patcher/commit/4b76d1959691babf8c99d3d5235df4a4388956f0))
* feat!: Add patch annotation processor ([3fc6a13](https://github.com/ReVanced/revanced-patcher/commit/3fc6a139eef67237c116fb4e3e29bf9542d3a981))
* feat!: Remove patch annotations ([3b4db3d](https://github.com/ReVanced/revanced-patcher/commit/3b4db3ddb72cdcee8af2f787eadf58eeb37543de))
### Features
* Add patch annotation processor ([#231](https://github.com/ReVanced/revanced-patcher/issues/231)) ([a29931f](https://github.com/ReVanced/revanced-patcher/commit/a29931f2ec0a666dba209b54855425d9dc2f4462))
### BREAKING CHANGES
* This gets rid of the public constructor.
* `PatchBundleLoader` is not a map anymore
* This renames packages and the Maven package.
* 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.
# [15.0.0-dev.4](https://github.com/ReVanced/revanced-patcher/compare/v15.0.0-dev.3...v15.0.0-dev.4) (2023-09-13)
### Bug Fixes
* Account for source patch dependency for tests ([6918418](https://github.com/ReVanced/revanced-patcher/commit/69184187d90f126478d2f49415c1e3381217557f))
* Always make the generated patch depend on the source patch ([8de3063](https://github.com/ReVanced/revanced-patcher/commit/8de30633ae6eb7acf7f0a351e26d4a6c2fdbdfec))
* Catch correct exception ([637d487](https://github.com/ReVanced/revanced-patcher/commit/637d48746ff8694e01c5aead1c75a9a1efeb5ac8))
* Delegate `PatchBundleLoader` by mutable set of patches ([9a109c1](https://github.com/ReVanced/revanced-patcher/commit/9a109c129b135a634be1aad4130a06d9e8e96ecd))
* Do not resolve the proxied patch to the proxy in the dependency list ([e112837](https://github.com/ReVanced/revanced-patcher/commit/e11283744a21fe2d09435e99d6924462b6aac3b8))
* Do not set `CompatiblePackage.versions` if `@CompatiblePackage.versions` is empty ([6b1e0a1](https://github.com/ReVanced/revanced-patcher/commit/6b1e0a16568124e9f82fb5740353360fa8ec614a))
* Filter for patches correctly ([4bc4b0d](https://github.com/ReVanced/revanced-patcher/commit/4bc4b0dc0104073b62528d02a88383cecd7a50e7))
* Find dependency in `context.allPatches` ([670f015](https://github.com/ReVanced/revanced-patcher/commit/670f0153de10c6f0db25b08df1c01a2905037f84))
* Log the correct patch names ([9fdb8f0](https://github.com/ReVanced/revanced-patcher/commit/9fdb8f087f62babf6081879db65c80db639aa0a7))
* Print patch name instead of class name ([4e7811e](https://github.com/ReVanced/revanced-patcher/commit/4e7811ea07762667a1f22526dc176022038f60eb))
* Print stack trace of exception ([aa71146](https://github.com/ReVanced/revanced-patcher/commit/aa71146b1bf4ffebcc81a1663e15abae89e97ff0))
* Run code-block if `executablePatches` does not yet contain `patch` ([1d7aeca](https://github.com/ReVanced/revanced-patcher/commit/1d7aeca696be873dfaf88eaa6d312949a3b8572b))
* Suppress logger when loading patches in `PatchBundleLoader` ([72c9eb2](https://github.com/ReVanced/revanced-patcher/commit/72c9eb212985f99f3390cf1faa10ab547d2dbe7e))
### Code Refactoring
* Internalize processor constructor ([a802d0d](https://github.com/ReVanced/revanced-patcher/commit/a802d0df463695976e85d8391762942eb977920b))
### BREAKING CHANGES
* This gets rid of the public constructor.
# [15.0.0-dev.3](https://github.com/ReVanced/revanced-patcher/compare/v15.0.0-dev.2...v15.0.0-dev.3) (2023-09-06)
### Bug Fixes
* Make `CompatiblePackage.versions` a property ([67b7dff](https://github.com/ReVanced/revanced-patcher/commit/67b7dff67a212b4fc30eb4f0cbe58f0ba09fb09a))
* Use correct module name ([080fbe9](https://github.com/ReVanced/revanced-patcher/commit/080fbe9feb9d4ea9ec4e599ecef296eacd803b05))
* feat Use `Set` as super type for `PatchBundleLoader` ([4b76d19](https://github.com/ReVanced/revanced-patcher/commit/4b76d1959691babf8c99d3d5235df4a4388956f0))
### BREAKING CHANGES
* `PatchBundleLoader` is not a map anymore
* This renames packages and the Maven package.
# [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)
# [15.0.0-dev.1](https://github.com/ReVanced/revanced-patcher/compare/v14.2.2...v15.0.0-dev.1) (2023-09-04) # [15.0.0-dev.1](https://github.com/ReVanced/revanced-patcher/compare/v14.2.2...v15.0.0-dev.1) (2023-09-04)

View File

@@ -2,3 +2,9 @@ plugins {
kotlin("jvm") version "1.9.0" apply false kotlin("jvm") version "1.9.0" apply false
alias(libs.plugins.binary.compatibility.validator) alias(libs.plugins.binary.compatibility.validator)
} }
allprojects {
apply(plugin = "maven-publish")
group = "app.revanced"
}

View File

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

View File

@@ -1,10 +1,10 @@
public abstract interface annotation class app/revanced/patcher/patch/annotations/CompatiblePackage : java/lang/annotation/Annotation { public abstract interface annotation class app/revanced/patcher/patch/annotation/CompatiblePackage : java/lang/annotation/Annotation {
public abstract fun name ()Ljava/lang/String; public abstract fun name ()Ljava/lang/String;
public abstract fun versions ()[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 interface annotation class app/revanced/patcher/patch/annotation/Patch : java/lang/annotation/Annotation {
public abstract fun compatiblePackages ()[Lapp/revanced/patcher/patch/annotations/CompatiblePackage; public abstract fun compatiblePackages ()[Lapp/revanced/patcher/patch/annotation/CompatiblePackage;
public abstract fun dependencies ()[Ljava/lang/Class; public abstract fun dependencies ()[Ljava/lang/Class;
public abstract fun description ()Ljava/lang/String; public abstract fun description ()Ljava/lang/String;
public abstract fun name ()Ljava/lang/String; public abstract fun name ()Ljava/lang/String;
@@ -12,14 +12,13 @@ public abstract interface annotation class app/revanced/patcher/patch/annotation
public abstract fun use ()Z public abstract fun use ()Z
} }
public final class app/revanced/patcher/patch/annotations/processor/PatchProcessor : com/google/devtools/ksp/processing/SymbolProcessor { public final class app/revanced/patcher/patch/annotation/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 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 final class app/revanced/patcher/patch/annotation/processor/PatchProcessorProvider : com/google/devtools/ksp/processing/SymbolProcessorProvider {
public fun <init> ()V public fun <init> ()V
public fun create (Lcom/google/devtools/ksp/processing/SymbolProcessorEnvironment;)Lapp/revanced/patcher/patch/annotations/processor/PatchProcessor; public fun create (Lcom/google/devtools/ksp/processing/SymbolProcessorEnvironment;)Lapp/revanced/patcher/patch/annotation/processor/PatchProcessor;
public synthetic fun create (Lcom/google/devtools/ksp/processing/SymbolProcessorEnvironment;)Lcom/google/devtools/ksp/processing/SymbolProcessor; 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 annotation 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-annotation-processor"

View File

@@ -1,4 +1,4 @@
package app.revanced.patcher.patch.annotations package app.revanced.patcher.patch.annotation
import java.lang.annotation.Inherited import java.lang.annotation.Inherited
import kotlin.reflect.KClass import kotlin.reflect.KClass

View File

@@ -1,12 +1,14 @@
package app.revanced.patcher.patch.annotations.processor package app.revanced.patcher.patch.annotation.processor
import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.data.ResourceContext import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.PatchOptions
import app.revanced.patcher.patch.ResourcePatch import app.revanced.patcher.patch.ResourcePatch
import app.revanced.patcher.patch.annotations.Patch import app.revanced.patcher.patch.annotation.Patch
import com.google.devtools.ksp.processing.* import com.google.devtools.ksp.processing.CodeGenerator
import com.google.devtools.ksp.processing.Dependencies
import com.google.devtools.ksp.processing.Resolver
import com.google.devtools.ksp.processing.SymbolProcessor
import com.google.devtools.ksp.symbol.KSAnnotated import com.google.devtools.ksp.symbol.KSAnnotated
import com.google.devtools.ksp.symbol.KSAnnotation import com.google.devtools.ksp.symbol.KSAnnotation
import com.google.devtools.ksp.symbol.KSClassDeclaration import com.google.devtools.ksp.symbol.KSClassDeclaration
@@ -17,9 +19,8 @@ import com.squareup.kotlinpoet.ksp.toClassName
import com.squareup.kotlinpoet.ksp.writeTo import com.squareup.kotlinpoet.ksp.writeTo
import kotlin.reflect.KClass import kotlin.reflect.KClass
class PatchProcessor( class PatchProcessor internal constructor(
private val codeGenerator: CodeGenerator, private val codeGenerator: CodeGenerator,
private val logger: KSPLogger
) : SymbolProcessor { ) : SymbolProcessor {
private fun KSAnnotated.isSubclassOf(cls: KClass<*>): Boolean { private fun KSAnnotated.isSubclassOf(cls: KClass<*>): Boolean {
@@ -32,7 +33,7 @@ class PatchProcessor(
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
override fun process(resolver: Resolver): List<KSAnnotated> { override fun process(resolver: Resolver): List<KSAnnotated> {
val executablePatches = buildMap { val patches = buildMap {
resolver.getSymbolsWithAnnotation(Patch::class.qualifiedName!!).filter { resolver.getSymbolsWithAnnotation(Patch::class.qualifiedName!!).filter {
// Do not check here if Patch is super of the class, because it is expensive. // Do not check here if Patch is super of the class, because it is expensive.
// Check it later when processing. // Check it later when processing.
@@ -80,14 +81,14 @@ class PatchProcessor(
dependencies?.map { dependency -> dependency.toClassName() }, dependencies?.map { dependency -> dependency.toClassName() },
compatiblePackages?.map { compatiblePackages?.map {
val packageName = it.property("name") val packageName = it.property("name")
val packageVersions = (it.property("versions") as List<String>) val packageVersions = (it.property("versions") as List<String>).ifEmpty { null }
.joinToString(", ") { version -> "\"$version\"" } ?.joinToString(", ") { version -> "\"$version\"" }
CodeBlock.of( CodeBlock.of(
"%T(%S, setOf(%L))", "%T(%S, %L)",
app.revanced.patcher.patch.Patch.CompatiblePackage::class, app.revanced.patcher.patch.Patch.CompatiblePackage::class,
packageName, packageName,
packageVersions packageVersions?.let { "setOf($packageVersions)" },
) )
}, },
use, use,
@@ -98,13 +99,13 @@ class PatchProcessor(
} }
// If a patch depends on another, that is annotated, the dependency should be replaced with the generated patch, // 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, // because the generated patch has all the necessary properties to invoke the super constructor with,
// unlike the annotated patch. // unlike the annotated patch.
val dependencyResolutionMap = buildMap { val dependencyResolutionMap = buildMap {
executablePatches.values.filter { it.dependencies != null }.flatMap { patches.values.filter { it.dependencies != null }.flatMap {
it.dependencies!! it.dependencies!!
}.distinct().forEach { dependency -> }.distinct().forEach { dependency ->
executablePatches.keys.find { it.qualifiedName?.asString() == dependency.toString() } patches.keys.find { it.qualifiedName?.asString() == dependency.toString() }
?.let { patch -> ?.let { patch ->
this[dependency] = ClassName( this[dependency] = ClassName(
patch.packageName.asString(), patch.packageName.asString(),
@@ -114,8 +115,7 @@ class PatchProcessor(
} }
} }
// kotlin poet generate a class for each patch patches.forEach { (patchDeclaration, patchAnnotation) ->
executablePatches.forEach { (patchDeclaration, patchAnnotation) ->
val isBytecodePatch = patchDeclaration.isSubclassOf(BytecodePatch::class) val isBytecodePatch = patchDeclaration.isSubclassOf(BytecodePatch::class)
val superClass = if (isBytecodePatch) { val superClass = if (isBytecodePatch) {
@@ -154,18 +154,18 @@ class PatchProcessor(
) )
} }
patchAnnotation.dependencies?.let { dependencies -> // The generated patch always depends on the source patch.
addSuperclassConstructorParameter( addSuperclassConstructorParameter(
"dependencies = setOf(%L)", "dependencies = setOf(%L)",
buildList { buildList {
addAll(dependencies) patchAnnotation.dependencies?.forEach { dependency ->
// Also add the source class of the generated class so that it is also executed add("${(dependencyResolutionMap[dependency] ?: dependency)}::class")
add(patchDeclaration.toClassName())
}.joinToString(", ") { dependency ->
"${(dependencyResolutionMap[dependency] ?: dependency)}::class"
} }
)
} add("${patchDeclaration.toClassName()}::class")
}.joinToString(", "),
)
addSuperclassConstructorParameter( addSuperclassConstructorParameter(
"use = %L", patchAnnotation.use "use = %L", patchAnnotation.use
) )
@@ -181,9 +181,18 @@ class PatchProcessor(
.addParameter("context", contextClass) .addParameter("context", contextClass)
.build() .build()
) )
.addProperty( .addInitializerBlock(
PropertySpec.builder("options", PatchOptions::class, KModifier.OVERRIDE) CodeBlock.builder()
.initializer("%T.options", patchDeclaration.toClassName()) .add(
"%T.options.forEach { (_, option) ->",
patchDeclaration.toClassName()
)
.addStatement(
"options.register(option)"
)
.add(
"}"
)
.build() .build()
) )
.build() .build()

View File

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

View File

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

View File

@@ -1,4 +1,4 @@
package app.revanced.patcher.patch.annotations.processor package app.revanced.patcher.patch.annotation.processor
import app.revanced.patcher.patch.Patch import app.revanced.patcher.patch.Patch
import com.tschuchort.compiletesting.KotlinCompilation import com.tschuchort.compiletesting.KotlinCompilation
@@ -7,7 +7,6 @@ import com.tschuchort.compiletesting.kspWithCompilation
import com.tschuchort.compiletesting.symbolProcessorProviders import com.tschuchort.compiletesting.symbolProcessorProviders
import kotlin.test.Test import kotlin.test.Test
import kotlin.test.assertEquals import kotlin.test.assertEquals
import kotlin.test.assertNotNull
import kotlin.test.assertNull import kotlin.test.assertNull
class TestPatchAnnotationProcessor { class TestPatchAnnotationProcessor {
@@ -22,6 +21,16 @@ class TestPatchAnnotationProcessor {
).loadPatch("$SAMPLE_PACKAGE.processing.ProcessablePatchGenerated").name ).loadPatch("$SAMPLE_PACKAGE.processing.ProcessablePatchGenerated").name
) )
@Test
fun generateNullProperties() = compile(
getSourceFile(
"null", "NullPropertiesPatch"
)
).loadPatch("$SAMPLE_PACKAGE.null.NullPropertiesPatchGenerated").let {
assertNull(it.description) // Because no description was provided.
assertNull(it.compatiblePackages!!.first().versions) // Because no versions were provided.
}
// endregion // endregion
// region Dependencies // region Dependencies
@@ -64,28 +73,30 @@ class TestPatchAnnotationProcessor {
) )
).loadPatch("$SAMPLE_PACKAGE.options.OptionsPatchGenerated") ).loadPatch("$SAMPLE_PACKAGE.options.OptionsPatchGenerated")
assertNotNull(patch.options) assert(patch.options.isNotEmpty())
assertEquals(patch.options["print"].title, "Print message") assertEquals(patch.options["print"].title, "Print message")
} }
// endregion // endregion
// region Limitations // region Limitations
@Test @Test
fun failingManualDependency() = assertNull( fun failingManualDependency() = assertEquals(
1, // Generated patch is always dependent on source class.
compile( compile(
getSourceFile( getSourceFile(
"limitations/manualdependency", "DependentPatch" "limitations/manualdependency", "DependentPatch"
), getSourceFile( ), getSourceFile(
"limitations/manualdependency", "DependencyPatch" "limitations/manualdependency", "DependencyPatch"
) )
).loadPatch("$SAMPLE_PACKAGE.limitations.manualdependency.DependentPatchGenerated").dependencies ).loadPatch("$SAMPLE_PACKAGE.limitations.manualdependency.DependentPatchGenerated").dependencies!!.size
) )
// endregion // endregion
private companion object Utils { private companion object Utils {
const val SAMPLE_PACKAGE = "app.revanced.patcher.patch.annotations.processor.samples" const val SAMPLE_PACKAGE = "app.revanced.patcher.patch.annotation.processor.samples"
/** /**
* Get a source file from the given sample and class name. * Get a source file from the given sample and class name.
@@ -94,11 +105,16 @@ class TestPatchAnnotationProcessor {
* @param className The name of the class to get the source file from. * @param className The name of the class to get the source file from.
* @return The source file. * @return The source file.
*/ */
fun getSourceFile(sample: String, className: String) = SourceFile.kotlin( fun getSourceFile(sample: String, className: String): SourceFile {
"$className.kt", TestPatchAnnotationProcessor::class.java.classLoader.getResourceAsStream( val resourceName = "app/revanced/patcher/patch/annotation/processor/samples/$sample/$className.kt"
"app/revanced/patcher/patch/annotations/processor/samples/$sample/$className.kt" return SourceFile.kotlin(
)?.readAllBytes()?.toString(Charsets.UTF_8) ?: error("Could not find resource $className") "$className.kt",
) TestPatchAnnotationProcessor::class.java.classLoader.getResourceAsStream(resourceName)
?.readAllBytes()
?.toString(Charsets.UTF_8)
?: error("Could not find resource $resourceName")
)
}
/** /**
* Compile the given source files and return the result. * Compile the given source files and return the result.

View File

@@ -1,8 +1,8 @@
package app.revanced.patcher.patch.annotations.processor.samples.dependencies package app.revanced.patcher.patch.annotation.processor.samples.dependencies
import app.revanced.patcher.data.ResourceContext import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.ResourcePatch import app.revanced.patcher.patch.ResourcePatch
import app.revanced.patcher.patch.annotations.Patch import app.revanced.patcher.patch.annotation.Patch
@Patch(name = "Dependency patch") @Patch(name = "Dependency patch")
object DependencyPatch : ResourcePatch() { object DependencyPatch : ResourcePatch() {

View File

@@ -1,7 +1,7 @@
package app.revanced.patcher.patch.annotations.processor.samples.dependencies package app.revanced.patcher.patch.annotation.processor.samples.dependencies
import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotations.Patch import app.revanced.patcher.patch.annotation.Patch
@Patch( @Patch(
name = "Dependent patch", name = "Dependent patch",

View File

@@ -1,8 +1,8 @@
package app.revanced.patcher.patch.annotations.processor.samples.limitations.manualdependency package app.revanced.patcher.patch.annotation.processor.samples.limitations.manualdependency
import app.revanced.patcher.data.ResourceContext import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.ResourcePatch import app.revanced.patcher.patch.ResourcePatch
import app.revanced.patcher.patch.annotations.Patch import app.revanced.patcher.patch.annotation.Patch
@Patch(name = "Dependency patch") @Patch(name = "Dependency patch")
object DependencyPatch : ResourcePatch() { object DependencyPatch : ResourcePatch() {

View File

@@ -1,7 +1,7 @@
package app.revanced.patcher.patch.annotations.processor.samples.limitations.manualdependency package app.revanced.patcher.patch.annotation.processor.samples.limitations.manualdependency
import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotations.Patch import app.revanced.patcher.patch.annotation.Patch
@Patch(name = "Dependent patch") @Patch(name = "Dependent patch")
object DependentPatch : BytecodePatch( object DependentPatch : BytecodePatch(

View File

@@ -0,0 +1,14 @@
package app.revanced.patcher.patch.annotation.processor.samples.`null`
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.CompatiblePackage
import app.revanced.patcher.patch.annotation.Patch
@Patch(
"Patch with null properties",
compatiblePackages = [CompatiblePackage("com.google.android.youtube")],
)
object NullPropertiesPatch : BytecodePatch() {
override fun execute(context: BytecodeContext) {}
}

View File

@@ -0,0 +1,19 @@
package app.revanced.patcher.patch.annotation.processor.samples.options
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.ResourcePatch
import app.revanced.patcher.patch.annotation.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

@@ -1,8 +1,8 @@
package app.revanced.patcher.patch.annotations.processor.samples.processing package app.revanced.patcher.patch.annotation.processor.samples.processing
import app.revanced.patcher.data.BytecodeContext import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.patch.BytecodePatch import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotations.Patch import app.revanced.patcher.patch.annotation.Patch
@Patch("Processable patch") @Patch("Processable patch")
object ProcessablePatch : BytecodePatch() { object ProcessablePatch : BytecodePatch() {

View File

@@ -1,50 +0,0 @@
plugins {
kotlin("jvm") version "1.9.0"
`maven-publish`
alias(libs.plugins.ksp)
}
group = "app.revanced"
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-patch-annotations-processor")
credentials {
username = System.getenv("GITHUB_ACTOR")
password = System.getenv("GITHUB_TOKEN")
}
}
}
publications {
create<MavenPublication>("gpr") {
from(components["java"])
}
}
}

View File

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

View File

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

View File

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

File diff suppressed because it is too large Load Diff

View File

@@ -1,10 +1,7 @@
plugins { plugins {
kotlin("jvm") version "1.9.0" kotlin("jvm") version "1.9.0"
`maven-publish`
} }
group = "app.revanced"
dependencies { dependencies {
implementation(libs.kotlinx.coroutines.core) implementation(libs.kotlinx.coroutines.core)
implementation(libs.xpp3) implementation(libs.xpp3)
@@ -15,7 +12,7 @@ dependencies {
compileOnly(libs.android) compileOnly(libs.android)
testImplementation(project(":revanced-patch-annotations-processor")) testImplementation(project(":revanced-patch-annotation-processor"))
testImplementation(libs.kotlin.test) testImplementation(libs.kotlin.test)
} }
@@ -53,6 +50,33 @@ publishing {
publications { publications {
create<MavenPublication>("gpr") { create<MavenPublication>("gpr") {
from(components["java"]) 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

@@ -13,9 +13,9 @@ import java.util.logging.Logger
import kotlin.reflect.KClass import kotlin.reflect.KClass
/** /**
* [Patch]es mapped by their name. * A set of [Patch]es.
*/ */
typealias PatchMap = Map<String, Patch<*>> typealias PatchSet = Set<Patch<*>>
/** /**
* A [Patch] class. * A [Patch] class.
@@ -28,28 +28,30 @@ typealias PatchClass = KClass<out Patch<*>>
* *
* @param getBinaryClassNames A function that returns the binary names of all classes in a patch bundle. * @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. * @param classLoader The [ClassLoader] to use for loading the classes.
* @param patchBundles A set of patches to initialize this instance with.
*/ */
sealed class PatchBundleLoader private constructor( sealed class PatchBundleLoader private constructor(
classLoader: ClassLoader, classLoader: ClassLoader,
patchBundles: Array<out File>, patchBundles: Array<out File>,
getBinaryClassNames: (patchBundle: File) -> List<String>, getBinaryClassNames: (patchBundle: File) -> List<String>,
) : PatchMap by mutableMapOf() { // This constructor parameter is unfortunately necessary,
// so that a reference to the mutable set is present in the constructor to be able to add patches to it.
// because the instance itself is a PatchSet, which is immutable, that is delegated by the parameter.
private val patchSet: MutableSet<Patch<*>> = mutableSetOf()
) : PatchSet by patchSet {
private val logger = Logger.getLogger(PatchBundleLoader::class.java.name) private val logger = Logger.getLogger(PatchBundleLoader::class.java.name)
init { init {
patchBundles.flatMap(getBinaryClassNames).asSequence().map { patchBundles.flatMap(getBinaryClassNames).asSequence().map {
classLoader.loadClass(it) classLoader.loadClass(it)
}.filter { }.filter {
it.isInstance(Patch::class.java) Patch::class.java.isAssignableFrom(it)
}.mapNotNull { patchClass -> }.mapNotNull { patchClass ->
patchClass.getInstance(logger) patchClass.getInstance(logger, silent = true)
}.filter { }.filter {
it.name != null it.name != null
}.associateBy {
it.name!!
}.let { patches -> }.let { patches ->
@Suppress("UNCHECKED_CAST") patchSet.addAll(patches)
(this as MutableMap<String, Patch<*>>).putAll(patches)
} }
} }
@@ -58,13 +60,14 @@ sealed class PatchBundleLoader private constructor(
* Instantiates a [Patch]. If the class is a singleton, the INSTANCE field will be used. * Instantiates a [Patch]. If the class is a singleton, the INSTANCE field will be used.
* *
* @param logger The [Logger] to use for logging. * @param logger The [Logger] to use for logging.
* @param silent Whether to suppress logging.
* @return The instantiated [Patch] or `null` if the [Patch] could not be instantiated. * @return The instantiated [Patch] or `null` if the [Patch] could not be instantiated.
*/ */
internal fun Class<*>.getInstance(logger: Logger): Patch<*>? { internal fun Class<*>.getInstance(logger: Logger, silent: Boolean = false): Patch<*>? {
return try { return try {
getField("INSTANCE").get(null) getField("INSTANCE").get(null)
} catch (exception: NoSuchFileException) { } catch (exception: NoSuchFieldException) {
logger.fine( if (!silent) logger.fine(
"Patch class '${name}' has no INSTANCE field, therefor not a singleton. " + "Patch class '${name}' has no INSTANCE field, therefor not a singleton. " +
"Will try to instantiate it." "Will try to instantiate it."
) )
@@ -72,7 +75,7 @@ sealed class PatchBundleLoader private constructor(
try { try {
getDeclaredConstructor().newInstance() getDeclaredConstructor().newInstance()
} catch (exception: Exception) { } catch (exception: Exception) {
logger.severe( if (!silent) logger.severe(
"Patch class '${name}' is not singleton and has no suitable constructor, " + "Patch class '${name}' is not singleton and has no suitable constructor, " +
"therefor cannot be instantiated and will be ignored." "therefor cannot be instantiated and will be ignored."
) )

View File

@@ -9,8 +9,6 @@ import kotlinx.coroutines.flow.flow
import java.io.Closeable import java.io.Closeable
import java.io.File import java.io.File
import java.util.function.Supplier import java.util.function.Supplier
import java.util.logging.Level
import java.util.logging.LogManager
import java.util.logging.Logger import java.util.logging.Logger
/** /**
@@ -30,18 +28,6 @@ class Patcher(
val context = PatcherContext(options) val context = PatcherContext(options)
init { init {
LogManager.getLogManager().let { manager ->
// Disable root logger.
manager.getLogger("").level = Level.OFF
// Enable ReVanced logging only.
manager.loggerNames
.toList()
.filter { it.startsWith("app.revanced") }
.map { manager.getLogger(it) }
.forEach { it.level = Level.INFO }
}
context.resourceContext.decodeResources(ResourceContext.ResourceDecodingMode.MANIFEST_ONLY) context.resourceContext.decodeResources(ResourceContext.ResourceDecodingMode.MANIFEST_ONLY)
} }
@@ -74,7 +60,7 @@ class Patcher(
} }
// Add all patches and their dependencies to the context. // Add all patches and their dependencies to the context.
for (patch in patches) context.executablePatches.putIfAbsent(patch::class, patch) ?: { for (patch in patches) context.executablePatches.putIfAbsent(patch::class, patch) ?: run {
context.allPatches[patch::class] = patch context.allPatches[patch::class] = patch
patch.dependencies?.forEach { it.putDependenciesRecursively() } patch.dependencies?.forEach { it.putDependenciesRecursively() }
@@ -118,7 +104,7 @@ class Patcher(
// Determine, if merging integrations is required. // Determine, if merging integrations is required.
for (patch in patches) for (patch in patches)
if (!patch.anyRecursively { it.requiresIntegrations }) { if (patch.anyRecursively { it.requiresIntegrations }) {
context.bytecodeContext.integrations.merge = true context.bytecodeContext.integrations.merge = true
break break
} }
@@ -153,7 +139,7 @@ class Patcher(
patch: Patch<*>, patch: Patch<*>,
executedPatches: LinkedHashMap<Patch<*>, PatchResult> executedPatches: LinkedHashMap<Patch<*>, PatchResult>
): PatchResult { ): PatchResult {
val patchName = patch.name val patchName = patch.name ?: patch.toString()
executedPatches[patch]?.let { patchResult -> executedPatches[patch]?.let { patchResult ->
patchResult.exception ?: return patchResult patchResult.exception ?: return patchResult
@@ -164,14 +150,17 @@ class Patcher(
} }
// Recursively execute all dependency patches. // Recursively execute all dependency patches.
patch.dependencies?.forEach { dependencyName -> patch.dependencies?.forEach { dependencyClass ->
val dependency = context.executablePatches[dependencyName]!! val dependency = context.allPatches[dependencyClass]!!
val result = executePatch(dependency, executedPatches) val result = executePatch(dependency, executedPatches)
result.exception?.let { result.exception?.let {
return PatchResult( return PatchResult(
patch, patch,
PatchException("'$patchName' depends on '${dependency}' that raised an exception: $it") PatchException(
"'$patchName' depends on '${dependency.name ?: dependency}' " +
"that raised an exception:\n${it.stackTraceToString()}"
)
) )
} }
} }
@@ -180,7 +169,7 @@ class Patcher(
// TODO: Implement this in a more polymorphic way. // TODO: Implement this in a more polymorphic way.
when (patch) { when (patch) {
is BytecodePatch -> { is BytecodePatch -> {
patch.fingerprints.toList().resolveUsingLookupMap(context.bytecodeContext) patch.fingerprints.resolveUsingLookupMap(context.bytecodeContext)
patch.execute(context.bytecodeContext) patch.execute(context.bytecodeContext)
} }
is ResourcePatch -> { is ResourcePatch -> {
@@ -208,7 +197,7 @@ class Patcher(
val executedPatches = LinkedHashMap<Patch<*>, PatchResult>() // Key is name. val executedPatches = LinkedHashMap<Patch<*>, PatchResult>() // Key is name.
context.executablePatches.map { it.value }.sortedBy { it.name }.forEach { patch -> context.executablePatches.values.sortedBy { it.name }.forEach { patch ->
val patchResult = executePatch(patch, executedPatches) val patchResult = executePatch(patch, executedPatches)
// If the patch failed, emit the result, even if it is closeable. // If the patch failed, emit the result, even if it is closeable.
@@ -245,7 +234,7 @@ class Patcher(
PatchResult( PatchResult(
patch, patch,
PatchException( PatchException(
"'${patch.name}' raised an exception while being closed: $it", "'${patch.name}' raised an exception while being closed: ${it.stackTraceToString()}",
result.exception result.exception
) )
) )

View File

@@ -96,7 +96,7 @@ class BytecodeContext internal constructor(private val options: PatcherOptions)
internal inner class Integrations : MutableList<File> by mutableListOf(), Flushable { internal inner class Integrations : MutableList<File> by mutableListOf(), Flushable {
/** /**
* Whether to merge integrations. * Whether to merge integrations.
* True when any supplied [Patch] is annotated with [RequiresIntegrations]. * Set to true, if the field requiresIntegrations of any supplied [Patch] is true.
*/ */
var merge = false var merge = false
@@ -108,7 +108,8 @@ class BytecodeContext internal constructor(private val options: PatcherOptions)
logger.info("Merging integrations") logger.info("Merging integrations")
// TODO: Multi-thread this. val classMap = classes.associateBy { it.type }
this@Integrations.forEach { integrations -> this@Integrations.forEach { integrations ->
MultiDexIO.readDexFile( MultiDexIO.readDexFile(
true, true,
@@ -116,8 +117,8 @@ class BytecodeContext internal constructor(private val options: PatcherOptions)
null, null,
null null
).classes.forEach classDef@{ classDef -> ).classes.forEach classDef@{ classDef ->
val existingClass = classes.find { it.type == classDef.type } ?: run { val existingClass = classMap[classDef.type] ?: run {
logger.fine("Merging $classDef") logger.fine("Adding $classDef")
classes.add(classDef) classes.add(classDef)
return@classDef return@classDef
} }
@@ -131,7 +132,6 @@ class BytecodeContext internal constructor(private val options: PatcherOptions)
} }
} }
} }
clear() clear()
} }
} }

View File

@@ -159,10 +159,10 @@ abstract class MethodFingerprint(
* - Faster: Specify [accessFlags], [returnType] and [parameters]. * - Faster: Specify [accessFlags], [returnType] and [parameters].
* - Fastest: Specify [strings], with at least one string being an exact (non-partial) match. * - Fastest: Specify [strings], with at least one string being an exact (non-partial) match.
*/ */
internal fun List<MethodFingerprint>.resolveUsingLookupMap(context: BytecodeContext) { internal fun Set<MethodFingerprint>.resolveUsingLookupMap(context: BytecodeContext) {
if (methods.isEmpty()) throw PatchException("lookup map not initialized") if (methods.isEmpty()) throw PatchException("lookup map not initialized")
for (fingerprint in this) { forEach { fingerprint ->
fingerprint.resolveUsingLookupMap(context) fingerprint.resolveUsingLookupMap(context)
} }
} }

View File

@@ -0,0 +1,27 @@
package app.revanced.patcher.patch
import app.revanced.patcher.PatchClass
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
/**
* A ReVanced [Patch] that works on [BytecodeContext].
*
* @param fingerprints A list of [MethodFingerprint]s which will be resolved before the patch is executed.
* @param name The name of the patch.
* @param description The description of the patch.
* @param compatiblePackages The packages the patch is compatible with.
* @param dependencies The names of patches this patch depends on.
* @param use Weather or not the patch should be used.
* @param requiresIntegrations Weather or not the patch requires integrations.
*/
abstract class BytecodePatch(
internal val fingerprints: Set<MethodFingerprint> = emptySet(),
name: String? = null,
description: String? = null,
compatiblePackages: Set<CompatiblePackage>? = null,
dependencies: Set<PatchClass>? = null,
use: Boolean = true,
// TODO: Remove this property, once integrations are coupled with patches.
requiresIntegrations: Boolean = false,
) : Patch<BytecodeContext>(name, description, compatiblePackages, dependencies, use, requiresIntegrations)

View File

@@ -1,23 +0,0 @@
package app.revanced.patcher.patch
/**
* A container for patch options.
*/
abstract class OptionsContainer {
/**
* A list of [PatchOption]s.
* @see PatchOptions
*/
@Suppress("MemberVisibilityCanBePrivate")
open val options = PatchOptions()
/**
* Registers a [PatchOption].
* @param opt The [PatchOption] to register.
* @return The registered [PatchOption].
*/
protected fun <T> option(opt: PatchOption<T>): PatchOption<T> {
options.register(opt)
return opt
}
}

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