Compare commits

...

254 Commits

Author SHA1 Message Date
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
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
semantic-release-bot
5e681ed381 chore(release): 11.0.2-dev.2 [skip ci]
## [11.0.2-dev.2](https://github.com/revanced/revanced-patcher/compare/v11.0.2-dev.1...v11.0.2-dev.2) (2023-06-18)

### Bug Fixes

* use `versionCode` if `versionName` is unavailable ([6e1b647](6e1b6479b6))
2023-06-18 14:41:34 +00:00
oSumAtrIX
6e1b6479b6 fix: use versionCode if versionName is unavailable 2023-06-18 16:39:49 +02:00
semantic-release-bot
f3c9e28a62 chore(release): 11.0.2-dev.1 [skip ci]
## [11.0.2-dev.1](https://github.com/revanced/revanced-patcher/compare/v11.0.1...v11.0.2-dev.1) (2023-06-14)

### Bug Fixes

* catch exceptions from closing patches ([d5d6f85](d5d6f85084))
* only close succeeded patches ([b8151eb](b8151ebccb))
2023-06-14 00:16:26 +00:00
oSumAtrIX
d5d6f85084 fix: catch exceptions from closing patches 2023-06-14 02:14:37 +02:00
oSumAtrIX
b8151ebccb fix: only close succeeded patches 2023-06-14 01:43:19 +02:00
semantic-release-bot
5650e34432 chore(release): 11.0.1 [skip ci]
## [11.0.1](https://github.com/revanced/revanced-patcher/compare/v11.0.0...v11.0.1) (2023-06-12)

### Bug Fixes

* revert using `OutputStream.nullOutputStream` ([f02a426](f02a42610b))
2023-06-12 03:36:10 +00:00
oSumAtrIX
c893d16d52 chore: merge branch dev to main (#190) 2023-06-12 05:34:23 +02:00
semantic-release-bot
34f08bf206 chore(release): 11.0.1-dev.1 [skip ci]
## [11.0.1-dev.1](https://github.com/revanced/revanced-patcher/compare/v11.0.0...v11.0.1-dev.1) (2023-06-12)

### Bug Fixes

* revert using `OutputStream.nullOutputStream` ([f02a426](f02a42610b))
2023-06-12 03:33:53 +00:00
oSumAtrIX
f02a42610b fix: revert using OutputStream.nullOutputStream
Older Android versions don't support this API
2023-06-12 05:32:13 +02:00
oSumAtrIX
c95e6fa92f ci: add cache step 2023-06-12 02:55:09 +02:00
oSumAtrIX
fd738e723b ci: build before running semantic-release 2023-06-12 01:52:52 +02:00
oSumAtrIX
b1d1956323 ci: remove unnecessary steps 2023-06-12 01:47:26 +02:00
semantic-release-bot
725a8012ac chore(release): 11.0.0 [skip ci]
# [11.0.0](https://github.com/revanced/revanced-patcher/compare/v10.0.0...v11.0.0) (2023-06-10)

### Bug Fixes

* add imports to fix failing tests ([43d6868](43d6868d1f))

* refactor!: move extension functions to their corresponding classes ([a12fe7d](a12fe7dd9e))
* refactor!: use proper extension function names ([efdd01a](efdd01a988))
* fix!: implement extension functions consistently ([aacf900](aacf900764))

### BREAKING CHANGES

* This changes the import paths for extension functions.
* This changes the names of extension functions
* This changes the name of functions
2023-06-10 23:11:52 +00:00
oSumAtrIX
bb9a73e53b chore: merge branch dev to main (#187) 2023-06-11 01:10:59 +02:00
semantic-release-bot
ef2de35a74 chore(release): 11.0.0-dev.2 [skip ci]
# [11.0.0-dev.2](https://github.com/revanced/revanced-patcher/compare/v11.0.0-dev.1...v11.0.0-dev.2) (2023-06-09)

### Bug Fixes

* add imports to fix failing tests ([43d6868](43d6868d1f))
2023-06-09 23:56:16 +00:00
oSumAtrIX
2a453d51a8 refactor: rename helper methods for tests 2023-06-10 01:55:05 +02:00
oSumAtrIX
43d6868d1f fix: add imports to fix failing tests 2023-06-10 01:43:09 +02:00
semantic-release-bot
cea9379b32 chore(release): 11.0.0-dev.1 [skip ci]
# [11.0.0-dev.1](https://github.com/revanced/revanced-patcher/compare/v10.0.0...v11.0.0-dev.1) (2023-06-07)

* refactor!: move extension functions to their corresponding classes ([a12fe7d](a12fe7dd9e))
* refactor!: use proper extension function names ([efdd01a](efdd01a988))
* fix!: implement extension functions consistently ([aacf900](aacf900764))

### BREAKING CHANGES

* This changes the import paths for extension functions.
* This changes the names of extension functions
* This changes the name of functions
2023-06-07 01:45:31 +00:00
oSumAtrIX
a12fe7dd9e refactor!: move extension functions to their corresponding classes
BREAKING CHANGE: This changes the import paths for extension functions.
2023-06-07 03:43:17 +02:00
oSumAtrIX
efdd01a988 refactor!: use proper extension function names
BREAKING CHANGE: This changes the names of extension functions
2023-06-07 03:43:13 +02:00
oSumAtrIX
eafe1c631f refactor: use existing null output stream 2023-06-07 03:32:19 +02:00
oSumAtrIX
aacf900764 fix!: implement extension functions consistently
BREAKING CHANGE: This changes the name of functions
2023-06-07 03:32:19 +02:00
semantic-release-bot
f82494e9bb chore(release): 10.0.0 [skip ci]
# [10.0.0](https://github.com/revanced/revanced-patcher/compare/v9.0.0...v10.0.0) (2023-06-07)

* fix!: check for two methods parameters orders (#183) ([b6d6a75](b6d6a7591b)), closes [#183](https://github.com/revanced/revanced-patcher/issues/183)

### BREAKING CHANGES

* This requires changes to `MethodFingerprint`
2023-06-07 00:59:13 +00:00
oSumAtrIX
1e0ffa176e chore: merge branch dev to main 2023-06-07 02:58:23 +02:00
semantic-release-bot
b7eb2d2249 chore(release): 10.0.0-dev.1 [skip ci]
# [10.0.0-dev.1](https://github.com/revanced/revanced-patcher/compare/v9.0.0...v10.0.0-dev.1) (2023-06-07)

* fix!: check for two methods parameters orders (#183) ([b6d6a75](b6d6a7591b)), closes [#183](https://github.com/revanced/revanced-patcher/issues/183)

### BREAKING CHANGES

* This requires changes to `MethodFingerprint`
2023-06-07 00:52:08 +00:00
LisoUseInAIKyrios
b6d6a7591b fix!: check for two methods parameters orders (#183)
BREAKING CHANGE: This requires changes to `MethodFingerprint`
2023-06-07 02:50:38 +02:00
semantic-release-bot
8f1c835299 chore(release): 9.0.0 [skip ci]
# [9.0.0](https://github.com/revanced/revanced-patcher/compare/v8.0.0...v9.0.0) (2023-05-23)

* refactor!: rename parameter ([526a3d7](526a3d7c35))

### BREAKING CHANGES

* This changes named parameters.
2023-05-23 23:58:07 +00:00
oSumAtrIX
a188c16a99 chore: merge branch dev to main (#177) 2023-05-24 01:56:40 +02:00
semantic-release-bot
3e6804f06c chore(release): 9.0.0-dev.1 [skip ci]
# [9.0.0-dev.1](https://github.com/revanced/revanced-patcher/compare/v8.0.0...v9.0.0-dev.1) (2023-05-23)

* refactor!: rename parameter ([526a3d7](526a3d7c35))

### BREAKING CHANGES

* This changes named parameters.
2023-05-23 23:50:12 +00:00
oSumAtrIX
526a3d7c35 refactor!: rename parameter
BREAKING CHANGE: This changes named parameters.
2023-05-24 01:49:07 +02:00
oSumAtrIX
28fc6a2ddd refactor: apply Kotlin idioms 2023-05-24 01:45:46 +02:00
semantic-release-bot
d4f08d7bff chore(release): 8.0.0 [skip ci]
# [8.0.0](https://github.com/revanced/revanced-patcher/compare/v7.1.1...v8.0.0) (2023-05-13)

* feat!: add `classDef` parameter to `MethodFingerprint` (#175) ([a205220](a2052202b2)), closes [#175](https://github.com/revanced/revanced-patcher/issues/175)

### BREAKING CHANGES

* This changes the signature of the `customFingerprint` function.
2023-05-13 23:58:31 +00:00
oSumAtrIX
ca9fe322eb chore: merge branch dev to main (#174) 2023-05-14 01:57:34 +02:00
Jim Man
239ea0bcaa refactor: simplify loading patches (#172) 2023-05-14 01:55:26 +02:00
semantic-release-bot
7f02b8df48 chore(release): 8.0.0-dev.1 [skip ci]
# [8.0.0-dev.1](https://github.com/revanced/revanced-patcher/compare/v7.1.1...v8.0.0-dev.1) (2023-05-10)

* feat!: add `classDef` parameter to `MethodFingerprint` (#175) ([a205220](a2052202b2)), closes [#175](https://github.com/revanced/revanced-patcher/issues/175)

### BREAKING CHANGES

* This changes the signature of the `customFingerprint` function.
2023-05-10 23:38:38 +00:00
badawoll
a2052202b2 feat!: add classDef parameter to MethodFingerprint (#175)
BREAKING CHANGE: This changes the signature of the `customFingerprint` function.
2023-05-11 01:37:17 +02:00
oSumAtrIX
223cea7021 build: use Java SDK 17 for building 2023-05-09 08:16:15 +02:00
semantic-release-bot
ac9337f694 chore(release): 7.1.1 [skip ci]
## [7.1.1](https://github.com/revanced/revanced-patcher/compare/v7.1.0...v7.1.1) (2023-05-07)

### Bug Fixes

* remove `count` instead of `count + 1` instructions with `removeInstructions` ([#167](https://github.com/revanced/revanced-patcher/issues/167)) ([98f8eed](98f8eedecd))
2023-05-07 23:06:19 +00:00
oSumAtrIX
549651d04a chore: merge branch dev to main (#171) 2023-05-08 01:05:17 +02:00
semantic-release-bot
966bbd902e chore(release): 7.1.1-dev.1 [skip ci]
## [7.1.1-dev.1](https://github.com/revanced/revanced-patcher/compare/v7.1.0...v7.1.1-dev.1) (2023-05-07)

### Bug Fixes

* remove `count` instead of `count + 1` instructions with `removeInstructions` ([#167](https://github.com/revanced/revanced-patcher/issues/167)) ([98f8eed](98f8eedecd))
2023-05-07 23:04:09 +00:00
oSumAtrIX
81e6f8784e docs: fix heading 2023-05-08 01:03:11 +02:00
oSumAtrIX
9c53877888 build: downgrade to JDK version 11
This is to properly support Android
2023-05-08 01:03:11 +02:00
rstular
98f8eedecd fix: remove count instead of count + 1 instructions with removeInstructions (#167)
Co-authored-by: oSumAtrIX <johan.melkonyan1@web.de>

BREAKING-CHANGE: This alters the behaviour of the function. Instead of removing `count + 1` instructions, this now removes `count` instructions.
2023-05-08 01:03:09 +02:00
semantic-release-bot
4ed429d25c chore(release): 7.1.0 [skip ci]
# [7.1.0](https://github.com/revanced/revanced-patcher/compare/v7.0.0...v7.1.0) (2023-05-05)

### Features

* add appreciation message for new contributors ([d674362](d67436271d))
* add overload to get instruction as type ([49c173d](49c173dc14))
2023-05-05 23:06:29 +00:00
oSumAtrIX
119d05f469 chore: merge branch dev to main (#161) 2023-05-06 01:05:01 +02:00
semantic-release-bot
2432fde6bf chore(release): 7.1.0-dev.2 [skip ci]
# [7.1.0-dev.2](https://github.com/revanced/revanced-patcher/compare/v7.1.0-dev.1...v7.1.0-dev.2) (2023-05-05)

### Features

* add overload to get instruction as type ([49c173d](49c173dc14))
2023-05-05 21:38:29 +00:00
oSumAtrIX
49c173dc14 feat: add overload to get instruction as type 2023-05-05 23:36:30 +02:00
oSumAtrIX
d83e9372bb chore: update gradle and dependencies 2023-04-30 05:27:22 +02:00
semantic-release-bot
7e8cd3bede chore(release): 7.1.0-dev.1 [skip ci]
# [7.1.0-dev.1](https://github.com/revanced/revanced-patcher/compare/v7.0.0...v7.1.0-dev.1) (2023-04-30)

### Features

* add appreciation message for new contributors ([d674362](d67436271d))
2023-04-30 01:16:45 +00:00
oSumAtrIX
d67436271d feat: add appreciation message for new contributors 2023-04-30 03:15:12 +02:00
oSumAtrIX
aa07f35f06 chore: bump dependencies 2023-04-03 03:04:05 +02:00
oSumAtrIX
77e0536838 build: update Kotlin to 1.8.10 2023-03-31 17:19:40 +02:00
oSumAtrIX
a49e78234b chore: remove project files
Signed-off-by: oSumAtrIX <johan.melkonyan1@web.de>
2023-03-02 19:23:41 +01:00
semantic-release-bot
a3ae825e48 chore(release): 7.0.0 [skip ci]
# [7.0.0](https://github.com/revanced/revanced-patcher/compare/v6.4.3...v7.0.0) (2023-02-26)

* feat!: merge integrations only when necessary ([6e24a85](6e24a85eab))

### BREAKING CHANGES

* `Patcher.addFiles` is now renamed to `Patcher.addIntegrations`

Signed-off-by: oSumAtrIX <johan.melkonyan1@web.de>
2023-02-26 23:42:48 +00:00
oSumAtrIX
146c8504ed chore: merge branch dev to main (#159) 2023-02-27 00:41:27 +01:00
semantic-release-bot
2eb125ad69 chore(release): 7.0.0-dev.1 [skip ci]
# [7.0.0-dev.1](https://github.com/revanced/revanced-patcher/compare/v6.4.3...v7.0.0-dev.1) (2023-02-26)

* feat!: merge integrations only when necessary ([6e24a85](6e24a85eab))

### BREAKING CHANGES

* `Patcher.addFiles` is now renamed to `Patcher.addIntegrations`

Signed-off-by: oSumAtrIX <johan.melkonyan1@web.de>
2023-02-26 23:24:38 +00:00
oSumAtrIX
6e24a85eab feat!: merge integrations only when necessary
BREAKING CHANGE: `Patcher.addFiles` is now renamed to `Patcher.addIntegrations`

Signed-off-by: oSumAtrIX <johan.melkonyan1@web.de>
2023-02-27 00:23:27 +01:00
oSumAtrIX
e4c3e9ffc5 refactor: remove unnecessary annotations
Signed-off-by: oSumAtrIX <johan.melkonyan1@web.de>
2023-02-26 23:18:35 +01:00
Javier Flores
4c1778a62f chore: update gradle wrapper to 8.0.1 (#160) 2023-02-26 03:46:33 +01:00
oSumAtrIX
d99261cdbb ci: fix backmerge direction
Signed-off-by: oSumAtrIX <johan.melkonyan1@web.de>
2023-02-22 16:39:50 +01:00
oSumAtrIX
ac1c0f2773 ci: add backmerge target branch
Signed-off-by: oSumAtrIX <johan.melkonyan1@web.de>
2023-02-22 06:45:16 +01:00
oSumAtrIX
eddd4ec7ac ci: use new semantic-release-backmerge option
Signed-off-by: oSumAtrIX <johan.melkonyan1@web.de>
2023-02-18 21:55:40 +01:00
Palm
07a2829c65 ci: update actions (#158) 2023-02-13 22:29:20 +01:00
semantic-release-bot
3d77e299d9 chore(release): 6.4.3 [skip ci]
## [6.4.3](https://github.com/revanced/revanced-patcher/compare/v6.4.2...v6.4.3) (2023-02-10)

### Bug Fixes

* check `CONST_STRING_JUMP` instructions for matching string ([058d292](058d292ad5))
2023-02-10 04:28:15 +00:00
oSumAtrIX
f1336f89e4 chore: merge branch dev to main (#156) 2023-02-10 05:26:43 +01:00
semantic-release-bot
0502f84c20 chore(release): 6.4.3-dev.1 [skip ci]
## [6.4.3-dev.1](https://github.com/revanced/revanced-patcher/compare/v6.4.2...v6.4.3-dev.1) (2023-02-10)

### Bug Fixes

* check `CONST_STRING_JUMP` instructions for matching string ([058d292](058d292ad5))
2023-02-10 04:20:46 +00:00
oSumAtrIX
058d292ad5 fix: check CONST_STRING_JUMP instructions for matching string
Signed-off-by: oSumAtrIX <johan.melkonyan1@web.de>
2023-02-10 05:18:38 +01:00
oSumAtrIX
1029d56a52 refactor: remove dead code
Signed-off-by: oSumAtrIX <johan.melkonyan1@web.de>
2023-02-10 05:17:36 +01:00
oSumAtrIX
709b5a0fec chore: fix typo
Signed-off-by: oSumAtrIX <johan.melkonyan1@web.de>
2023-02-10 05:16:00 +01:00
semantic-release-bot
e1accc5041 chore(release): 6.4.2 [skip ci]
## [6.4.2](https://github.com/revanced/revanced-patcher/compare/v6.4.1...v6.4.2) (2023-01-17)

### Bug Fixes

* resolve failing builds ([a263fdf](a263fdfd41))
2023-01-17 23:29:34 +00:00
oSumAtrIX
6dbbf2e03e chore: merge branch dev to main (#153) 2023-01-18 00:14:38 +01:00
semantic-release-bot
16557eeab0 chore(release): 6.4.2-dev.1 [skip ci]
## [6.4.2-dev.1](https://github.com/revanced/revanced-patcher/compare/v6.4.1...v6.4.2-dev.1) (2023-01-17)

### Bug Fixes

* resolve failing builds ([a263fdf](a263fdfd41))
2023-01-17 23:09:26 +00:00
oSumAtrIX
6bca3e2bb5 build: update dependencies 2023-01-17 23:57:19 +01:00
oSumAtrIX
a263fdfd41 fix: resolve failing builds
This updates dependencies, because the previous ones were missing or outdated.
2023-01-17 01:32:11 +01:00
semantic-release-bot
e4b4bacae8 chore(release): 6.4.1 [skip ci]
## [6.4.1](https://github.com/revanced/revanced-patcher/compare/v6.4.0...v6.4.1) (2023-01-15)

### Bug Fixes

* update dependency `app.revanced:multidexlib2` ([#150](https://github.com/revanced/revanced-patcher/issues/150)) ([dd7dd38](dd7dd38357))
2023-01-15 05:13:48 +00:00
semantic-release-bot
cbc97af155 chore(release): 6.4.1 [skip ci]
## [6.4.1](https://github.com/revanced/revanced-patcher/compare/v6.4.0...v6.4.1) (2023-01-15)

### Bug Fixes

* update dependency `app.revanced:multidexlib2` ([#150](https://github.com/revanced/revanced-patcher/issues/150)) ([dd7dd38](dd7dd38357))
2023-01-15 04:32:33 +00:00
oSumAtrIX
d5533788e2 chore: merge branch dev to main (#152) 2023-01-15 05:31:12 +01:00
oSumAtrIX
5a4ea5cd7d ci: add missing PAT in step Release 2023-01-15 05:29:50 +01:00
oSumAtrIX
70f3c8b38c chore: merge branch dev to main (#151) 2023-01-15 05:24:25 +01:00
semantic-release-bot
6b410a0eea chore(release): 6.4.1-dev.1 [skip ci]
## [6.4.1-dev.1](https://github.com/revanced/revanced-patcher/compare/v6.4.0...v6.4.1-dev.1) (2023-01-15)

### Bug Fixes

* update dependency `app.revanced:multidexlib2` ([#150](https://github.com/revanced/revanced-patcher/issues/150)) ([dd7dd38](dd7dd38357))
2023-01-15 03:07:43 +00:00
oSumAtrIX
73a013d75b ci: use PAT in step Release 2023-01-15 04:06:45 +01:00
oSumAtrIX
7159f3db4c ci: downgrade semantic release and plugins to v19 2023-01-15 04:06:45 +01:00
oSumAtrIX
7d5ecf095c ci: give jobs names 2023-01-15 04:06:44 +01:00
oSumAtrIX
fa015a424d refactor: fix formatting 2023-01-15 04:06:44 +01:00
oSumAtrIX
dd7dd38357 fix: update dependency app.revanced:multidexlib2 (#150)
This commit addresses https://github.com/revanced/multidexlib2/issues/2.
2023-01-15 04:06:43 +01:00
semantic-release-bot
22356f2d26 chore(release): 6.4.0 [skip ci]
# [6.4.0](https://github.com/revanced/revanced-patcher/compare/v6.3.2...v6.4.0) (2023-01-02)

### Features

* add missing setter to `MutableMethod` ([8f3ecc3](8f3ecc318c))
* do not fix methods or methods in class merger ([4102f43](4102f43b8a))
* fix method and field access when merging classes ([5c09ef7](5c09ef7837))
* make `aaptPath` nullable ([#146](https://github.com/revanced/revanced-patcher/issues/146)) ([9f0a09a](9f0a09a756))
2023-01-02 08:07:08 +00:00
oSumAtrIX
66701f6076 chore: merge branch dev to main (#147) 2023-01-02 09:05:19 +01:00
semantic-release-bot
6a6ded084e chore(release): 6.4.0-dev.2 [skip ci]
# [6.4.0-dev.2](https://github.com/revanced/revanced-patcher/compare/v6.4.0-dev.1...v6.4.0-dev.2) (2023-01-02)

### Features

* add missing setter to `MutableMethod` ([8f3ecc3](8f3ecc318c))
* do not fix methods or methods in class merger ([4102f43](4102f43b8a))
* fix method and field access when merging classes ([5c09ef7](5c09ef7837))
2023-01-02 07:58:55 +00:00
oSumAtrIX
5887c69bde refactor: move merging classes code to own class (#149) 2023-01-02 08:58:05 +01:00
oSumAtrIX
4102f43b8a feat: do not fix methods or methods in class merger 2023-01-02 08:50:08 +01:00
oSumAtrIX
5c09ef7837 feat: fix method and field access when merging classes 2023-01-02 07:57:50 +01:00
oSumAtrIX
3e0bf8c863 refactor: move merging classes code to own class 2023-01-02 07:57:48 +01:00
oSumAtrIX
8f3ecc318c feat: add missing setter to MutableMethod 2023-01-02 07:09:58 +01:00
oSumAtrIX
365da96e2b build: do not comment on successful releases 2022-12-31 21:12:03 +01:00
oSumAtrIX
cd68ec4803 ci: do not escape in environment variable MESSAGE 2022-12-29 19:07:31 +01:00
152 changed files with 6644 additions and 2806 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

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

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

View File

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

View File

@@ -1,4 +1,5 @@
name: Release
on:
workflow_dispatch:
push:
@@ -9,29 +10,36 @@ on:
branches:
- main
- dev
jobs:
release:
name: Release
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
with:
# Make sure the release step uses its own credentials:
# https://github.com/cycjimmy/semantic-release-action#private-packages
persist-credentials: false
fetch-depth: 0
- name: Setup JDK
uses: actions/setup-java@v3
- name: Cache
uses: actions/cache@v3
with:
java-version: '17'
distribution: 'zulu'
cache: gradle
- name: Setup Node.js
uses: actions/setup-node@v3
with:
node-version: "latest"
cache: 'npm'
- name: Setup semantic-release
run: npm install semantic-release @saithodev/semantic-release-backmerge @semantic-release/git @semantic-release/changelog gradle-semantic-release-plugin -D
- name: Release
path: |
${{ runner.home }}/.gradle/caches
${{ runner.home }}/.gradle/wrapper
.gradle
build
node_modules
key: ${{ runner.os }}-gradle-npm-${{ hashFiles('**/*.gradle*', '**/gradle-wrapper.properties', 'package-lock.json') }}
- name: Build with Gradle
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: npx semantic-release
run: ./gradlew build clean --no-daemon
- name: Setup semantic-release
run: npm install
- name: Release
env:
GITHUB_TOKEN: ${{ secrets.REPOSITORY_PUSH_ACCESS }}
run: npm exec semantic-release

6
.gitignore vendored
View File

@@ -74,6 +74,7 @@ cmake-build-*/
# IntelliJ
out/
.idea/
# mpeltonen/sbt-idea plugin
.idea_modules/
@@ -117,4 +118,7 @@ gradle-app.setting
!src/test/resources/*
# Dependency directories
node_modules/
node_modules/
# Gradle props, to avoid sharing the gpr key
gradle.properties

9
.idea/.gitignore generated vendored
View File

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

View File

@@ -1,10 +0,0 @@
<component name="ProjectCodeStyleConfiguration">
<code_scheme name="Project" version="173">
<JetCodeStyleSettings>
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
</JetCodeStyleSettings>
<codeStyleSettings language="kotlin">
<option name="CODE_STYLE_DEFAULTS" value="KOTLIN_OFFICIAL" />
</codeStyleSettings>
</code_scheme>
</component>

View File

@@ -1,5 +0,0 @@
<component name="ProjectCodeStyleConfiguration">
<state>
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
</state>
</component>

7
.idea/discord.xml generated
View File

@@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DiscordProjectSettings">
<option name="show" value="PROJECT_FILES" />
<option name="description" value="" />
</component>
</project>

View File

@@ -1,15 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GitToolBoxProjectSettings">
<option name="commitMessageIssueKeyValidationOverride">
<BoolValueOverride>
<option name="enabled" value="true" />
</BoolValueOverride>
</option>
<option name="commitMessageValidationEnabledOverride">
<BoolValueOverride>
<option name="enabled" value="true" />
</BoolValueOverride>
</option>
</component>
</project>

View File

@@ -1,6 +0,0 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="UnusedSymbol" enabled="false" level="WARNING" enabled_by_default="false" />
</profile>
</component>

10
.idea/misc.xml generated
View File

@@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="FrameworkDetectionExcludesConfiguration">
<file type="web" url="file://$PROJECT_DIR$" />
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="azul-17" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

12
.idea/vcs.xml generated
View File

@@ -1,12 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CommitMessageInspectionProfile">
<profile version="1.0">
<inspection_tool class="CommitFormat" enabled="true" level="WARNING" enabled_by_default="true" />
<inspection_tool class="CommitNamingConvention" enabled="true" level="WARNING" enabled_by_default="true" />
</profile>
</component>
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

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",
@@ -23,10 +29,15 @@
[
"@saithodev/semantic-release-backmerge",
{
branches: [{from: "main", to: "dev"}],
backmergeBranches: [{"from": "main", "to": "dev"}],
clearWorkspace: true
}
],
"@semantic-release/github"
[
"@semantic-release/github",
{
successComment: false
}
]
]
}

View File

@@ -1,3 +1,786 @@
## [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)
* 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
* 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.
## [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](https://github.com/ReVanced/revanced-patcher/commit/11a337865947a6ac74a63ebb3f3f9bc2610f7771))
## [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](https://github.com/ReVanced/revanced-patcher/commit/11a337865947a6ac74a63ebb3f3f9bc2610f7771))
## [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](https://github.com/ReVanced/revanced-patcher/commit/b832812767a06ec6ec232291e6d14c8c2f14118c))
## [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](https://github.com/ReVanced/revanced-patcher/commit/b832812767a06ec6ec232291e6d14c8c2f14118c))
# [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](https://github.com/ReVanced/revanced-patcher/commit/e8f2087a6ffa6077fb3a6a69e29f3aec72e2fc1b))
* log when merging integrations ([983563e](https://github.com/ReVanced/revanced-patcher/commit/983563efb6d7c8d289464b8bf71a016b8a735630))
### Performance Improvements
* compare types of classes ([55d6945](https://github.com/ReVanced/revanced-patcher/commit/55d694579ac2718b9e2c61ca5f38419c3775ef87))
# [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](https://github.com/ReVanced/revanced-patcher/commit/55d694579ac2718b9e2c61ca5f38419c3775ef87))
# [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](https://github.com/ReVanced/revanced-patcher/commit/983563efb6d7c8d289464b8bf71a016b8a735630))
# [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](https://github.com/ReVanced/revanced-patcher/commit/e8f2087a6ffa6077fb3a6a69e29f3aec72e2fc1b))
# [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](https://github.com/ReVanced/revanced-patcher/commit/e985676c2d8e5d6cb907d371de30428caaa6da43))
### Features
* properly make use of logging facade ([ba56a6a](https://github.com/ReVanced/revanced-patcher/commit/ba56a6a2eef503c0d6cdd846ddce2e1474d8ed1a))
# [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](https://github.com/ReVanced/revanced-patcher/commit/ba56a6a2eef503c0d6cdd846ddce2e1474d8ed1a))
## [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](https://github.com/ReVanced/revanced-patcher/commit/e985676c2d8e5d6cb907d371de30428caaa6da43))
# [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](https://github.com/ReVanced/revanced-patcher/commit/db62a1607b4a9d6256b5f5153decb088d9680553))
* only emit closed patches that did not throw an exception with the `@Patch` annotation ([5938f6b](https://github.com/ReVanced/revanced-patcher/commit/5938f6b7ea25103a0a1b56ceebe49139bc80c6f5))
* supply the parent classloader to `DexClassLoader` ([0f15077](https://github.com/ReVanced/revanced-patcher/commit/0f15077225600b65200022c1a318e504deb472b9))
### Code Refactoring
* improve structure and public API ([6b8977f](https://github.com/ReVanced/revanced-patcher/commit/6b8977f17854ef0344d868e6391cb18134eceadc))
### Features
* do not log instantiation of ReVanced Patcher ([273dd8d](https://github.com/ReVanced/revanced-patcher/commit/273dd8d388f8e9b7436c6d6145a94c12c1fabe55))
### 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.
# [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](https://github.com/ReVanced/revanced-patcher/commit/5938f6b7ea25103a0a1b56ceebe49139bc80c6f5))
# [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](https://github.com/ReVanced/revanced-patcher/commit/0f15077225600b65200022c1a318e504deb472b9))
### Features
* do not log instantiation of ReVanced Patcher ([273dd8d](https://github.com/ReVanced/revanced-patcher/commit/273dd8d388f8e9b7436c6d6145a94c12c1fabe55))
# [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)
# [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](https://github.com/ReVanced/revanced-patcher/commit/db62a1607b4a9d6256b5f5153decb088d9680553))
### Code Refactoring
* improve structure and public API ([6b8977f](https://github.com/ReVanced/revanced-patcher/commit/6b8977f17854ef0344d868e6391cb18134eceadc))
### 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.
# [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](https://github.com/ReVanced/revanced-patcher/commit/8fb2f2dc1d3b9b1e9fd13b39485985d2886d52ae))
* disable correct loggers ([c2d89c6](https://github.com/ReVanced/revanced-patcher/commit/c2d89c622e06e58e5042e1a00ef67cee8a246e53))
* get framework ids to compile resources ([f2cb7ee](https://github.com/ReVanced/revanced-patcher/commit/f2cb7ee7dffa573c31df497cf235a3f5d120f91f))
* only enable logging for ReVanced ([783ccf8](https://github.com/ReVanced/revanced-patcher/commit/783ccf8529f5d16aa463982da6977328306232bb))
* set package metadata correctly ([02d6ff1](https://github.com/ReVanced/revanced-patcher/commit/02d6ff15fe87c2352de29749610e9d72db8ba418))
* build(Needs bump)!: Bump dependencies ([d5f89a9](https://github.com/ReVanced/revanced-patcher/commit/d5f89a903f019c199bdb27a50287124fc4b4978e))
### BREAKING CHANGES
* This bump updates smali, a crucial dependency
# [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](https://github.com/ReVanced/revanced-patcher/commit/8fb2f2dc1d3b9b1e9fd13b39485985d2886d52ae))
* only enable logging for ReVanced ([783ccf8](https://github.com/ReVanced/revanced-patcher/commit/783ccf8529f5d16aa463982da6977328306232bb))
# [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](https://github.com/ReVanced/revanced-patcher/commit/c2d89c622e06e58e5042e1a00ef67cee8a246e53))
* get framework ids to compile resources ([f2cb7ee](https://github.com/ReVanced/revanced-patcher/commit/f2cb7ee7dffa573c31df497cf235a3f5d120f91f))
* set package metadata correctly ([02d6ff1](https://github.com/ReVanced/revanced-patcher/commit/02d6ff15fe87c2352de29749610e9d72db8ba418))
# [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](https://github.com/ReVanced/revanced-patcher/commit/d5f89a903f019c199bdb27a50287124fc4b4978e))
### BREAKING CHANGES
* This bump updates smali, a crucial dependency
## [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](https://github.com/ReVanced/revanced-patcher/commit/746544f9d51d1013bb160075709cd26bffd425b3))
## [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)
## [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](https://github.com/ReVanced/revanced-patcher/commit/746544f9d51d1013bb160075709cd26bffd425b3))
# [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](https://github.com/ReVanced/revanced-patcher/commit/fae4029cfccfad7aa3dd8f7fbef1c63ee26b85b3))
# [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)
# [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](https://github.com/ReVanced/revanced-patcher/commit/fae4029cfccfad7aa3dd8f7fbef1c63ee26b85b3))
# [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](https://github.com/ReVanced/revanced-patcher/commit/416d69142f50dab49c9ea3f027e9d53e4777f257))
* set resource table via resource decoder ([e0f8e1b](https://github.com/ReVanced/revanced-patcher/commit/e0f8e1b71a295948b610029c89a48f52762396b6))
### Features
* Deprecate `Version` annotation ([c9bbcf2](https://github.com/ReVanced/revanced-patcher/commit/c9bbcf2bf2b0f50ab9100380a3a66c6346ad42ac))
* remove `Path` option ([#202](https://github.com/ReVanced/revanced-patcher/issues/202)) ([69e4a49](https://github.com/ReVanced/revanced-patcher/commit/69e4a490659ebc4fb4bf46148634f4b064ef1713))
### BREAKING CHANGES
* This removes the previously available `Path` option
# [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](https://github.com/ReVanced/revanced-patcher/commit/400442f70ee56cafd4493b2ce64a294db9836509))
# [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](https://github.com/ReVanced/revanced-patcher/commit/416d69142f50dab49c9ea3f027e9d53e4777f257))
* set resource table via resource decoder ([e0f8e1b](https://github.com/ReVanced/revanced-patcher/commit/e0f8e1b71a295948b610029c89a48f52762396b6))
### Features
* remove `Path` option ([#202](https://github.com/ReVanced/revanced-patcher/issues/202)) ([69e4a49](https://github.com/ReVanced/revanced-patcher/commit/69e4a490659ebc4fb4bf46148634f4b064ef1713))
### BREAKING CHANGES
* This removes the previously available `Path` option
## [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](https://github.com/revanced/revanced-patcher/commit/9d81baf4b4ca7514f8a1009e72218638609a7c7f))
## [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](https://github.com/revanced/revanced-patcher/commit/9d81baf4b4ca7514f8a1009e72218638609a7c7f))
## [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](https://github.com/revanced/revanced-patcher/commit/fcef4342e8bde73945e8315aef6337cc8a8d8572))
## [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](https://github.com/revanced/revanced-patcher/commit/fcef4342e8bde73945e8315aef6337cc8a8d8572))
## [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](https://github.com/revanced/revanced-patcher/commit/d5d6f85084c03ed9c776632823ca12394a716167))
* do not load annotations as patches ([519359a](https://github.com/revanced/revanced-patcher/commit/519359a9eb0e9dfa390c5016e9fe4a7490b8ab18))
* only close succeeded patches ([b8151eb](https://github.com/revanced/revanced-patcher/commit/b8151ebccb5b27dd9e06fa63235cf9baeef1c0ee))
* use `versionCode` if `versionName` is unavailable ([6e1b647](https://github.com/revanced/revanced-patcher/commit/6e1b6479b677657c226693e9cc6b63f4ef2ee060))
### Performance Improvements
* resolve fingerprints using method maps ([#185](https://github.com/revanced/revanced-patcher/issues/185)) ([d718134](https://github.com/revanced/revanced-patcher/commit/d718134ab26423e02708e01eba711737f9260ba0))
## [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](https://github.com/revanced/revanced-patcher/commit/519359a9eb0e9dfa390c5016e9fe4a7490b8ab18))
## [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](https://github.com/revanced/revanced-patcher/commit/d718134ab26423e02708e01eba711737f9260ba0))
## [11.0.2-dev.2](https://github.com/revanced/revanced-patcher/compare/v11.0.2-dev.1...v11.0.2-dev.2) (2023-06-18)
### Bug Fixes
* use `versionCode` if `versionName` is unavailable ([6e1b647](https://github.com/revanced/revanced-patcher/commit/6e1b6479b677657c226693e9cc6b63f4ef2ee060))
## [11.0.2-dev.1](https://github.com/revanced/revanced-patcher/compare/v11.0.1...v11.0.2-dev.1) (2023-06-14)
### Bug Fixes
* catch exceptions from closing patches ([d5d6f85](https://github.com/revanced/revanced-patcher/commit/d5d6f85084c03ed9c776632823ca12394a716167))
* only close succeeded patches ([b8151eb](https://github.com/revanced/revanced-patcher/commit/b8151ebccb5b27dd9e06fa63235cf9baeef1c0ee))
## [11.0.1](https://github.com/revanced/revanced-patcher/compare/v11.0.0...v11.0.1) (2023-06-12)
### Bug Fixes
* revert using `OutputStream.nullOutputStream` ([f02a426](https://github.com/revanced/revanced-patcher/commit/f02a42610b7698fc8cc6bc5183c9ccba2ed96cda))
## [11.0.1-dev.1](https://github.com/revanced/revanced-patcher/compare/v11.0.0...v11.0.1-dev.1) (2023-06-12)
### Bug Fixes
* revert using `OutputStream.nullOutputStream` ([f02a426](https://github.com/revanced/revanced-patcher/commit/f02a42610b7698fc8cc6bc5183c9ccba2ed96cda))
# [11.0.0](https://github.com/revanced/revanced-patcher/compare/v10.0.0...v11.0.0) (2023-06-10)
### Bug Fixes
* add imports to fix failing tests ([43d6868](https://github.com/revanced/revanced-patcher/commit/43d6868d1f59922f9812f3e4a2a890f3b331def6))
* refactor!: move extension functions to their corresponding classes ([a12fe7d](https://github.com/revanced/revanced-patcher/commit/a12fe7dd9e976c38a0a82fe35e6650f58f815de4))
* refactor!: use proper extension function names ([efdd01a](https://github.com/revanced/revanced-patcher/commit/efdd01a9886b6f06af213731824621964367b2a3))
* fix!: implement extension functions consistently ([aacf900](https://github.com/revanced/revanced-patcher/commit/aacf9007647b1cc11bc40053625802573efda6ef))
### BREAKING CHANGES
* This changes the import paths for extension functions.
* This changes the names of extension functions
* This changes the name of functions
# [11.0.0-dev.2](https://github.com/revanced/revanced-patcher/compare/v11.0.0-dev.1...v11.0.0-dev.2) (2023-06-09)
### Bug Fixes
* add imports to fix failing tests ([43d6868](https://github.com/revanced/revanced-patcher/commit/43d6868d1f59922f9812f3e4a2a890f3b331def6))
# [11.0.0-dev.1](https://github.com/revanced/revanced-patcher/compare/v10.0.0...v11.0.0-dev.1) (2023-06-07)
* refactor!: move extension functions to their corresponding classes ([a12fe7d](https://github.com/revanced/revanced-patcher/commit/a12fe7dd9e976c38a0a82fe35e6650f58f815de4))
* refactor!: use proper extension function names ([efdd01a](https://github.com/revanced/revanced-patcher/commit/efdd01a9886b6f06af213731824621964367b2a3))
* fix!: implement extension functions consistently ([aacf900](https://github.com/revanced/revanced-patcher/commit/aacf9007647b1cc11bc40053625802573efda6ef))
### BREAKING CHANGES
* This changes the import paths for extension functions.
* This changes the names of extension functions
* This changes the name of functions
# [10.0.0](https://github.com/revanced/revanced-patcher/compare/v9.0.0...v10.0.0) (2023-06-07)
* fix!: check for two methods parameters orders (#183) ([b6d6a75](https://github.com/revanced/revanced-patcher/commit/b6d6a7591ba1c0b48ffdef52352709564da8d9be)), closes [#183](https://github.com/revanced/revanced-patcher/issues/183)
### BREAKING CHANGES
* This requires changes to `MethodFingerprint`
# [10.0.0-dev.1](https://github.com/revanced/revanced-patcher/compare/v9.0.0...v10.0.0-dev.1) (2023-06-07)
* fix!: check for two methods parameters orders (#183) ([b6d6a75](https://github.com/revanced/revanced-patcher/commit/b6d6a7591ba1c0b48ffdef52352709564da8d9be)), closes [#183](https://github.com/revanced/revanced-patcher/issues/183)
### BREAKING CHANGES
* This requires changes to `MethodFingerprint`
# [9.0.0](https://github.com/revanced/revanced-patcher/compare/v8.0.0...v9.0.0) (2023-05-23)
* refactor!: rename parameter ([526a3d7](https://github.com/revanced/revanced-patcher/commit/526a3d7c359e2d95d26756da0f88d5ce975f5d9b))
### BREAKING CHANGES
* This changes named parameters.
# [9.0.0-dev.1](https://github.com/revanced/revanced-patcher/compare/v8.0.0...v9.0.0-dev.1) (2023-05-23)
* refactor!: rename parameter ([526a3d7](https://github.com/revanced/revanced-patcher/commit/526a3d7c359e2d95d26756da0f88d5ce975f5d9b))
### BREAKING CHANGES
* This changes named parameters.
# [8.0.0](https://github.com/revanced/revanced-patcher/compare/v7.1.1...v8.0.0) (2023-05-13)
* feat!: add `classDef` parameter to `MethodFingerprint` (#175) ([a205220](https://github.com/revanced/revanced-patcher/commit/a2052202b23037150df6aadc47f6e91efcd481cf)), closes [#175](https://github.com/revanced/revanced-patcher/issues/175)
### BREAKING CHANGES
* This changes the signature of the `customFingerprint` function.
# [8.0.0-dev.1](https://github.com/revanced/revanced-patcher/compare/v7.1.1...v8.0.0-dev.1) (2023-05-10)
* feat!: add `classDef` parameter to `MethodFingerprint` (#175) ([a205220](https://github.com/revanced/revanced-patcher/commit/a2052202b23037150df6aadc47f6e91efcd481cf)), closes [#175](https://github.com/revanced/revanced-patcher/issues/175)
### BREAKING CHANGES
* This changes the signature of the `customFingerprint` function.
## [7.1.1](https://github.com/revanced/revanced-patcher/compare/v7.1.0...v7.1.1) (2023-05-07)
### Bug Fixes
* remove `count` instead of `count + 1` instructions with `removeInstructions` ([#167](https://github.com/revanced/revanced-patcher/issues/167)) ([98f8eed](https://github.com/revanced/revanced-patcher/commit/98f8eedecd72b0afe6a0f099a3641a1cc6be2698))
## [7.1.1-dev.1](https://github.com/revanced/revanced-patcher/compare/v7.1.0...v7.1.1-dev.1) (2023-05-07)
### Bug Fixes
* remove `count` instead of `count + 1` instructions with `removeInstructions` ([#167](https://github.com/revanced/revanced-patcher/issues/167)) ([98f8eed](https://github.com/revanced/revanced-patcher/commit/98f8eedecd72b0afe6a0f099a3641a1cc6be2698))
# [7.1.0](https://github.com/revanced/revanced-patcher/compare/v7.0.0...v7.1.0) (2023-05-05)
### Features
* add appreciation message for new contributors ([d674362](https://github.com/revanced/revanced-patcher/commit/d67436271ddca9ccfe008272c1ca82c6123ae7ee))
* add overload to get instruction as type ([49c173d](https://github.com/revanced/revanced-patcher/commit/49c173dc14137ddd198a611e9882dc71300831ee))
# [7.1.0-dev.2](https://github.com/revanced/revanced-patcher/compare/v7.1.0-dev.1...v7.1.0-dev.2) (2023-05-05)
### Features
* add overload to get instruction as type ([49c173d](https://github.com/revanced/revanced-patcher/commit/49c173dc14137ddd198a611e9882dc71300831ee))
# [7.1.0-dev.1](https://github.com/revanced/revanced-patcher/compare/v7.0.0...v7.1.0-dev.1) (2023-04-30)
### Features
* add appreciation message for new contributors ([d674362](https://github.com/revanced/revanced-patcher/commit/d67436271ddca9ccfe008272c1ca82c6123ae7ee))
# [7.0.0](https://github.com/revanced/revanced-patcher/compare/v6.4.3...v7.0.0) (2023-02-26)
* feat!: merge integrations only when necessary ([6e24a85](https://github.com/revanced/revanced-patcher/commit/6e24a85eabd1e7a1484fad229d5ba55c3ba1f1b4))
### BREAKING CHANGES
* `Patcher.addFiles` is now renamed to `Patcher.addIntegrations`
Signed-off-by: oSumAtrIX <johan.melkonyan1@web.de>
# [7.0.0-dev.1](https://github.com/revanced/revanced-patcher/compare/v6.4.3...v7.0.0-dev.1) (2023-02-26)
* feat!: merge integrations only when necessary ([6e24a85](https://github.com/revanced/revanced-patcher/commit/6e24a85eabd1e7a1484fad229d5ba55c3ba1f1b4))
### BREAKING CHANGES
* `Patcher.addFiles` is now renamed to `Patcher.addIntegrations`
Signed-off-by: oSumAtrIX <johan.melkonyan1@web.de>
## [6.4.3](https://github.com/revanced/revanced-patcher/compare/v6.4.2...v6.4.3) (2023-02-10)
### Bug Fixes
* check `CONST_STRING_JUMP` instructions for matching string ([058d292](https://github.com/revanced/revanced-patcher/commit/058d292ad5e297f4c652ff543c13e77a39f7fb1b))
## [6.4.3-dev.1](https://github.com/revanced/revanced-patcher/compare/v6.4.2...v6.4.3-dev.1) (2023-02-10)
### Bug Fixes
* check `CONST_STRING_JUMP` instructions for matching string ([058d292](https://github.com/revanced/revanced-patcher/commit/058d292ad5e297f4c652ff543c13e77a39f7fb1b))
## [6.4.2](https://github.com/revanced/revanced-patcher/compare/v6.4.1...v6.4.2) (2023-01-17)
### Bug Fixes
* resolve failing builds ([a263fdf](https://github.com/revanced/revanced-patcher/commit/a263fdfd413fc05098e28d4800e36ce7d313085b))
## [6.4.2-dev.1](https://github.com/revanced/revanced-patcher/compare/v6.4.1...v6.4.2-dev.1) (2023-01-17)
### Bug Fixes
* resolve failing builds ([a263fdf](https://github.com/revanced/revanced-patcher/commit/a263fdfd413fc05098e28d4800e36ce7d313085b))
## [6.4.1](https://github.com/revanced/revanced-patcher/compare/v6.4.0...v6.4.1) (2023-01-15)
### Bug Fixes
* update dependency `app.revanced:multidexlib2` ([#150](https://github.com/revanced/revanced-patcher/issues/150)) ([dd7dd38](https://github.com/revanced/revanced-patcher/commit/dd7dd383577dcfc95e97f77b446a89b41b589dc0))
## [6.4.1](https://github.com/revanced/revanced-patcher/compare/v6.4.0...v6.4.1) (2023-01-15)
### Bug Fixes
* update dependency `app.revanced:multidexlib2` ([#150](https://github.com/revanced/revanced-patcher/issues/150)) ([dd7dd38](https://github.com/revanced/revanced-patcher/commit/dd7dd383577dcfc95e97f77b446a89b41b589dc0))
## [6.4.1-dev.1](https://github.com/revanced/revanced-patcher/compare/v6.4.0...v6.4.1-dev.1) (2023-01-15)
### Bug Fixes
* update dependency `app.revanced:multidexlib2` ([#150](https://github.com/revanced/revanced-patcher/issues/150)) ([dd7dd38](https://github.com/revanced/revanced-patcher/commit/dd7dd383577dcfc95e97f77b446a89b41b589dc0))
# [6.4.0](https://github.com/revanced/revanced-patcher/compare/v6.3.2...v6.4.0) (2023-01-02)
### Features
* add missing setter to `MutableMethod` ([8f3ecc3](https://github.com/revanced/revanced-patcher/commit/8f3ecc318c39f0270aff53efdee7a1c8d82af421))
* do not fix methods or methods in class merger ([4102f43](https://github.com/revanced/revanced-patcher/commit/4102f43b8a9473fd0ee96c5d4fb8f6e9b4e30e70))
* fix method and field access when merging classes ([5c09ef7](https://github.com/revanced/revanced-patcher/commit/5c09ef7837f9b731e137b66c19da77f63c007595))
* make `aaptPath` nullable ([#146](https://github.com/revanced/revanced-patcher/issues/146)) ([9f0a09a](https://github.com/revanced/revanced-patcher/commit/9f0a09a7569fd5dd78afa27cb66a73d1662edc69))
# [6.4.0-dev.2](https://github.com/revanced/revanced-patcher/compare/v6.4.0-dev.1...v6.4.0-dev.2) (2023-01-02)
### Features
* add missing setter to `MutableMethod` ([8f3ecc3](https://github.com/revanced/revanced-patcher/commit/8f3ecc318c39f0270aff53efdee7a1c8d82af421))
* do not fix methods or methods in class merger ([4102f43](https://github.com/revanced/revanced-patcher/commit/4102f43b8a9473fd0ee96c5d4fb8f6e9b4e30e70))
* fix method and field access when merging classes ([5c09ef7](https://github.com/revanced/revanced-patcher/commit/5c09ef7837f9b731e137b66c19da77f63c007595))
# [6.4.0-dev.1](https://github.com/revanced/revanced-patcher/compare/v6.3.2...v6.4.0-dev.1) (2022-12-20)

View File

@@ -1,2 +1,3 @@
# Patcher
Patcher framework used in the ReVanced project.
# 💉 ReVanced Patcher
ReVanced Patcher used to patch Android applications.

View File

@@ -1,68 +1,10 @@
plugins {
kotlin("jvm") version "1.7.0"
java
`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("org.smali:smali:2.5.2")
implementation("app.revanced:multidexlib2:2.5.2.r2")
implementation("org.apktool:apktool-lib:2.9.0-SNAPSHOT")
implementation(kotlin("reflect"))
testImplementation(kotlin("test"))
}
tasks {
test {
useJUnitPlatform()
testLogging {
events("PASSED", "SKIPPED", "FAILED")
}
}
processResources {
expand("projectVersion" to project.version)
}
}
java {
withSourcesJar()
}
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 = 6.4.0-dev.1
version = 16.0.2-dev.1

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-7.4.2-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip
networkTimeout=10000
validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

40
gradlew vendored
View File

@@ -1,7 +1,7 @@
#!/bin/sh
#
# Copyright <EFBFBD> 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 <EFBFBD>$var<EFBFBD>, <EFBFBD>${var}<EFBFBD>, <EFBFBD>${var:-default}<EFBFBD>, <EFBFBD>${var+SET}<EFBFBD>,
# <EFBFBD>${var#prefix}<EFBFBD>, <EFBFBD>${var%suffix}<EFBFBD>, and <EFBFBD>$( cmd )<EFBFBD>;
# * compound commands having a testable exit status, especially <EFBFBD>case<EFBFBD>;
# * various built-in commands including <EFBFBD>command<EFBFBD>, <EFBFBD>set<EFBFBD>, and <EFBFBD>ulimit<EFBFBD>.
# * 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

727
package-lock.json generated
View File

@@ -5,10 +5,11 @@
"packages": {
"": {
"devDependencies": {
"@saithodev/semantic-release-backmerge": "^3.1.0",
"@semantic-release/changelog": "^6.0.2",
"@semantic-release/git": "^10.0.1",
"gradle-semantic-release-plugin": "^1.7.4",
"semantic-release": "^19.0.5"
"gradle-semantic-release-plugin": "^1.7.6",
"semantic-release": "^20.1.0"
}
},
"node_modules/@babel/code-frame": {
@@ -312,6 +313,20 @@
"@octokit/openapi-types": "^14.0.0"
}
},
"node_modules/@saithodev/semantic-release-backmerge": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/@saithodev/semantic-release-backmerge/-/semantic-release-backmerge-3.1.0.tgz",
"integrity": "sha512-92AN5eI8svpxeUD6cw2JjCrHHZVlWIxQ67SiSSwoI1UP4N5QohCOf9O/W3OUApxKg3C8Y0RpGt7TUpGEwGhXhw==",
"dev": true,
"dependencies": {
"@semantic-release/error": "^3.0.0",
"aggregate-error": "^3.1.0",
"debug": "^4.3.4",
"execa": "^5.1.1",
"lodash": "^4.17.21",
"semantic-release": ">=20.0.0"
}
},
"node_modules/@semantic-release/changelog": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/@semantic-release/changelog/-/changelog-6.0.2.tgz",
@@ -498,12 +513,6 @@
"integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==",
"dev": true
},
"node_modules/@types/parse-json": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz",
"integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==",
"dev": true
},
"node_modules/@types/retry": {
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz",
@@ -580,6 +589,12 @@
"integrity": "sha512-QXu7BPrP29VllRxH8GwB7x5iX5qWKAAMLqKQGWTeLWVlNHNOpVMJ91dsxQAIWXpjuW5wqvxu3Jd/nRjrJ+0pqg==",
"dev": true
},
"node_modules/argparse": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
"dev": true
},
"node_modules/argv-formatter": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/argv-formatter/-/argv-formatter-1.0.0.tgz",
@@ -735,14 +750,17 @@
}
},
"node_modules/cliui": {
"version": "7.0.4",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
"integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
"version": "8.0.1",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
"integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
"dev": true,
"dependencies": {
"string-width": "^4.2.0",
"strip-ansi": "^6.0.0",
"strip-ansi": "^6.0.1",
"wrap-ansi": "^7.0.0"
},
"engines": {
"node": ">=12"
}
},
"node_modules/color-convert": {
@@ -887,19 +905,18 @@
"dev": true
},
"node_modules/cosmiconfig": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz",
"integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==",
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.0.0.tgz",
"integrity": "sha512-da1EafcpH6b/TD8vDRaWV7xFINlHlF6zKsGwS1TsuVJTZRkquaS5HTMq7uq6h31619QjbsYl21gVDOm32KM1vQ==",
"dev": true,
"dependencies": {
"@types/parse-json": "^4.0.0",
"import-fresh": "^3.2.1",
"js-yaml": "^4.1.0",
"parse-json": "^5.0.0",
"path-type": "^4.0.0",
"yaml": "^1.10.0"
"path-type": "^4.0.0"
},
"engines": {
"node": ">=10"
"node": ">=14"
}
},
"node_modules/cross-spawn": {
@@ -1077,17 +1094,126 @@
"dev": true
},
"node_modules/env-ci": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/env-ci/-/env-ci-5.5.0.tgz",
"integrity": "sha512-o0JdWIbOLP+WJKIUt36hz1ImQQFuN92nhsfTkHHap+J8CiI8WgGpH/a9jEGHh4/TU5BUUGjlnKXNoDb57+ne+A==",
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/env-ci/-/env-ci-8.0.0.tgz",
"integrity": "sha512-W+3BqGZozFua9MPeXpmTm5eYEBtGgL76jGu/pwMVp/L8PdECSCEWaIp7d4Mw7kuUrbUldK0oV0bNd6ZZjLiMiA==",
"dev": true,
"dependencies": {
"execa": "^5.0.0",
"fromentries": "^1.3.2",
"java-properties": "^1.0.0"
"execa": "^6.1.0",
"java-properties": "^1.0.2"
},
"engines": {
"node": ">=10.17"
"node": "^16.10 || >=18"
}
},
"node_modules/env-ci/node_modules/execa": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/execa/-/execa-6.1.0.tgz",
"integrity": "sha512-QVWlX2e50heYJcCPG0iWtf8r0xjEYfz/OYLGDYH+IyjWezzPNxz63qNFOu0l4YftGWuizFVZHHs8PrLU5p2IDA==",
"dev": true,
"dependencies": {
"cross-spawn": "^7.0.3",
"get-stream": "^6.0.1",
"human-signals": "^3.0.1",
"is-stream": "^3.0.0",
"merge-stream": "^2.0.0",
"npm-run-path": "^5.1.0",
"onetime": "^6.0.0",
"signal-exit": "^3.0.7",
"strip-final-newline": "^3.0.0"
},
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"funding": {
"url": "https://github.com/sindresorhus/execa?sponsor=1"
}
},
"node_modules/env-ci/node_modules/human-signals": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/human-signals/-/human-signals-3.0.1.tgz",
"integrity": "sha512-rQLskxnM/5OCldHo+wNXbpVgDn5A17CUoKX+7Sokwaknlq7CdSnphy0W39GU8dw59XiCXmFXDg4fRuckQRKewQ==",
"dev": true,
"engines": {
"node": ">=12.20.0"
}
},
"node_modules/env-ci/node_modules/is-stream": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz",
"integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==",
"dev": true,
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/env-ci/node_modules/mimic-fn": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz",
"integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==",
"dev": true,
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/env-ci/node_modules/npm-run-path": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz",
"integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==",
"dev": true,
"dependencies": {
"path-key": "^4.0.0"
},
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/env-ci/node_modules/onetime": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz",
"integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==",
"dev": true,
"dependencies": {
"mimic-fn": "^4.0.0"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/env-ci/node_modules/path-key": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz",
"integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==",
"dev": true,
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/env-ci/node_modules/strip-final-newline": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz",
"integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==",
"dev": true,
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/error-ex": {
@@ -1179,15 +1305,28 @@
}
},
"node_modules/figures": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz",
"integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==",
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/figures/-/figures-5.0.0.tgz",
"integrity": "sha512-ej8ksPF4x6e5wvK9yevct0UCXh8TTFlWGVLlgjZuoBH1HwjIfKE/IdL5mq89sFA7zELi1VhKpmtDnrs7zWyeyg==",
"dev": true,
"dependencies": {
"escape-string-regexp": "^1.0.5"
"escape-string-regexp": "^5.0.0",
"is-unicode-supported": "^1.2.0"
},
"engines": {
"node": ">=8"
"node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/figures/node_modules/escape-string-regexp": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz",
"integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==",
"dev": true,
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
@@ -1219,15 +1358,15 @@
}
},
"node_modules/find-versions": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/find-versions/-/find-versions-4.0.0.tgz",
"integrity": "sha512-wgpWy002tA+wgmO27buH/9KzyEOQnKsG/R0yrcjPT9BOFm0zRBVQbZ95nRGXWMywS8YR5knRbpohio0bcJABxQ==",
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/find-versions/-/find-versions-5.1.0.tgz",
"integrity": "sha512-+iwzCJ7C5v5KgcBuueqVoNiHVoQpwiUK5XFLjf0affFTep+Wcw93tPvmb8tqujDNmzhBDPddnWV/qgWSXgq+Hg==",
"dev": true,
"dependencies": {
"semver-regex": "^3.1.2"
"semver-regex": "^4.0.5"
},
"engines": {
"node": ">=10"
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
@@ -1243,26 +1382,6 @@
"readable-stream": "^2.0.0"
}
},
"node_modules/fromentries": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.3.2.tgz",
"integrity": "sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
]
},
"node_modules/fs-extra": {
"version": "11.1.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.1.0.tgz",
@@ -1402,9 +1521,9 @@
"dev": true
},
"node_modules/gradle-semantic-release-plugin": {
"version": "1.7.4",
"resolved": "https://registry.npmjs.org/gradle-semantic-release-plugin/-/gradle-semantic-release-plugin-1.7.4.tgz",
"integrity": "sha512-Mm2JnmodHxQlCmn0GtSi5j8z4PS2+2VBY993b9GuNGGM+JaIrr8T3tF9uTLR2nGH/oJba6a9jx1ZqVEJdOXDPw==",
"version": "1.7.6",
"resolved": "https://registry.npmjs.org/gradle-semantic-release-plugin/-/gradle-semantic-release-plugin-1.7.6.tgz",
"integrity": "sha512-FNoZAm9jntxOXLee5uJLlCb9hsFsJ1d4jUnvz08NF6p72OwSmaSBeFN7Wnl6RjW8mPrAuOSwkuinuWWjVeO2aw==",
"dev": true,
"funding": [
{
@@ -1413,14 +1532,14 @@
}
],
"dependencies": {
"promisified-properties": "^2.0.3",
"promisified-properties": "^2.0.27",
"split2": "^4.1.0"
},
"engines": {
"node": ">=16 || ^14.17"
"node": ">=18"
},
"peerDependencies": {
"semantic-release": "^19.0.2"
"semantic-release": "^20.0.0"
}
},
"node_modules/handlebars": {
@@ -1475,12 +1594,15 @@
}
},
"node_modules/hook-std": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/hook-std/-/hook-std-2.0.0.tgz",
"integrity": "sha512-zZ6T5WcuBMIUVh49iPQS9t977t7C0l7OtHrpeMb5uk48JdflRX0NSFvCekfYNmGQETnLq9W/isMyHl69kxGi8g==",
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/hook-std/-/hook-std-3.0.0.tgz",
"integrity": "sha512-jHRQzjSDzMtFy34AGj1DN+vq54WVuhSvKgrHf0OMiFQTwDD4L/qqofVEWjLOBMTn5+lCD3fPg32W9yOfnEJTTw==",
"dev": true,
"engines": {
"node": ">=8"
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/hosted-git-info": {
@@ -1750,6 +1872,18 @@
"node": ">=0.10.0"
}
},
"node_modules/is-unicode-supported": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-1.3.0.tgz",
"integrity": "sha512-43r2mRvz+8JRIKnWJ+3j8JtjRKZ6GmjzfaE/qiBJnikNnYv/6bagRJ1kUhNk8R5EX/GkobD+r+sfxCPJsiKBLQ==",
"dev": true,
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
@@ -1793,6 +1927,18 @@
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
"dev": true
},
"node_modules/js-yaml": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
"dev": true,
"dependencies": {
"argparse": "^2.0.1"
},
"bin": {
"js-yaml": "bin/js-yaml.js"
}
},
"node_modules/json-parse-better-errors": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
@@ -1909,6 +2055,12 @@
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
"dev": true
},
"node_modules/lodash-es": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz",
"integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==",
"dev": true
},
"node_modules/lodash.capitalize": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/lodash.capitalize/-/lodash.capitalize-4.2.1.tgz",
@@ -4817,12 +4969,12 @@
}
},
"node_modules/p-each-series": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-2.2.0.tgz",
"integrity": "sha512-ycIL2+1V32th+8scbpTvyHNaHe02z0sjgh91XXjAk+ZeXoPN4Z46DVUnzdso0aX4KckKw0FNNFHdjZ2UsZvxiA==",
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/p-each-series/-/p-each-series-3.0.0.tgz",
"integrity": "sha512-lastgtAdoH9YaLyDa5i5z64q+kzOcQHsQ5SsZJD3q0VEyI8mq872S3geuNbRUQLVAE9siMfgKrpj7MloKFHruw==",
"dev": true,
"engines": {
"node": ">=8"
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
@@ -5102,9 +5254,9 @@
"dev": true
},
"node_modules/promisified-properties": {
"version": "2.0.25",
"resolved": "https://registry.npmjs.org/promisified-properties/-/promisified-properties-2.0.25.tgz",
"integrity": "sha512-FtyMDSNf3IwVBjVq4uj5JD4lG+YmOMzt/Huuc+VwPHVqbzim3/U04iMBnVH3lYgOc9s5Jj9sC4G0OVGoo2KbWA==",
"version": "2.0.27",
"resolved": "https://registry.npmjs.org/promisified-properties/-/promisified-properties-2.0.27.tgz",
"integrity": "sha512-fmx256M3b0QcHnqOj+Ok127LoYpmnYRf7g2OyLl7qD7Z0fzNbIZhHHIPKyvegbA29iAPP5BVWv7BJ/y2cMHHjA==",
"dev": true,
"dependencies": {
"parsimmon": "^1.13.0"
@@ -5393,9 +5545,9 @@
"dev": true
},
"node_modules/semantic-release": {
"version": "19.0.5",
"resolved": "https://registry.npmjs.org/semantic-release/-/semantic-release-19.0.5.tgz",
"integrity": "sha512-NMPKdfpXTnPn49FDogMBi36SiBfXkSOJqCkk0E4iWOY1tusvvgBwqUmxTX1kmlT6kIYed9YwNKD1sfPpqa5yaA==",
"version": "20.1.0",
"resolved": "https://registry.npmjs.org/semantic-release/-/semantic-release-20.1.0.tgz",
"integrity": "sha512-+9+n6RIr0Fz0F53cXrjpawxWlUg3O7/qr1jF9lrE+/v6WqwBrSWnavVHTPaf2WLerET2EngoqI0M4pahkKl6XQ==",
"dev": true,
"dependencies": {
"@semantic-release/commit-analyzer": "^9.0.2",
@@ -5403,35 +5555,350 @@
"@semantic-release/github": "^8.0.0",
"@semantic-release/npm": "^9.0.0",
"@semantic-release/release-notes-generator": "^10.0.0",
"aggregate-error": "^3.0.0",
"cosmiconfig": "^7.0.0",
"aggregate-error": "^4.0.1",
"cosmiconfig": "^8.0.0",
"debug": "^4.0.0",
"env-ci": "^5.0.0",
"execa": "^5.0.0",
"figures": "^3.0.0",
"find-versions": "^4.0.0",
"env-ci": "^8.0.0",
"execa": "^6.1.0",
"figures": "^5.0.0",
"find-versions": "^5.1.0",
"get-stream": "^6.0.0",
"git-log-parser": "^1.2.0",
"hook-std": "^2.0.0",
"hosted-git-info": "^4.0.0",
"lodash": "^4.17.21",
"marked": "^4.0.10",
"marked-terminal": "^5.0.0",
"hook-std": "^3.0.0",
"hosted-git-info": "^6.0.0",
"lodash-es": "^4.17.21",
"marked": "^4.1.0",
"marked-terminal": "^5.1.1",
"micromatch": "^4.0.2",
"p-each-series": "^2.1.0",
"p-reduce": "^2.0.0",
"read-pkg-up": "^7.0.0",
"p-each-series": "^3.0.0",
"p-reduce": "^3.0.0",
"read-pkg-up": "^9.1.0",
"resolve-from": "^5.0.0",
"semver": "^7.3.2",
"semver-diff": "^3.1.1",
"semver-diff": "^4.0.0",
"signale": "^1.2.1",
"yargs": "^16.2.0"
"yargs": "^17.5.1"
},
"bin": {
"semantic-release": "bin/semantic-release.js"
},
"engines": {
"node": ">=16 || ^14.17"
"node": ">=18"
}
},
"node_modules/semantic-release/node_modules/aggregate-error": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-4.0.1.tgz",
"integrity": "sha512-0poP0T7el6Vq3rstR8Mn4V/IQrpBLO6POkUSrN7RhyY+GF/InCFShQzsQ39T25gkHhLgSLByyAz+Kjb+c2L98w==",
"dev": true,
"dependencies": {
"clean-stack": "^4.0.0",
"indent-string": "^5.0.0"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/semantic-release/node_modules/clean-stack": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-4.2.0.tgz",
"integrity": "sha512-LYv6XPxoyODi36Dp976riBtSY27VmFo+MKqEU9QCCWyTrdEPDog+RWA7xQWHi6Vbp61j5c4cdzzX1NidnwtUWg==",
"dev": true,
"dependencies": {
"escape-string-regexp": "5.0.0"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/semantic-release/node_modules/escape-string-regexp": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz",
"integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==",
"dev": true,
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/semantic-release/node_modules/execa": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/execa/-/execa-6.1.0.tgz",
"integrity": "sha512-QVWlX2e50heYJcCPG0iWtf8r0xjEYfz/OYLGDYH+IyjWezzPNxz63qNFOu0l4YftGWuizFVZHHs8PrLU5p2IDA==",
"dev": true,
"dependencies": {
"cross-spawn": "^7.0.3",
"get-stream": "^6.0.1",
"human-signals": "^3.0.1",
"is-stream": "^3.0.0",
"merge-stream": "^2.0.0",
"npm-run-path": "^5.1.0",
"onetime": "^6.0.0",
"signal-exit": "^3.0.7",
"strip-final-newline": "^3.0.0"
},
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"funding": {
"url": "https://github.com/sindresorhus/execa?sponsor=1"
}
},
"node_modules/semantic-release/node_modules/find-up": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz",
"integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==",
"dev": true,
"dependencies": {
"locate-path": "^7.1.0",
"path-exists": "^5.0.0"
},
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/semantic-release/node_modules/hosted-git-info": {
"version": "6.1.1",
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-6.1.1.tgz",
"integrity": "sha512-r0EI+HBMcXadMrugk0GCQ+6BQV39PiWAZVfq7oIckeGiN7sjRGyQxPdft3nQekFTCQbYxLBH+/axZMeH8UX6+w==",
"dev": true,
"dependencies": {
"lru-cache": "^7.5.1"
},
"engines": {
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
}
},
"node_modules/semantic-release/node_modules/human-signals": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/human-signals/-/human-signals-3.0.1.tgz",
"integrity": "sha512-rQLskxnM/5OCldHo+wNXbpVgDn5A17CUoKX+7Sokwaknlq7CdSnphy0W39GU8dw59XiCXmFXDg4fRuckQRKewQ==",
"dev": true,
"engines": {
"node": ">=12.20.0"
}
},
"node_modules/semantic-release/node_modules/indent-string": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz",
"integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==",
"dev": true,
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/semantic-release/node_modules/is-stream": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz",
"integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==",
"dev": true,
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/semantic-release/node_modules/locate-path": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz",
"integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==",
"dev": true,
"dependencies": {
"p-locate": "^6.0.0"
},
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/semantic-release/node_modules/lru-cache": {
"version": "7.14.1",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.14.1.tgz",
"integrity": "sha512-ysxwsnTKdAx96aTRdhDOCQfDgbHnt8SK0KY8SEjO0wHinhWOFTESbjVCMPbU1uGXg/ch4lifqx0wfjOawU2+WA==",
"dev": true,
"engines": {
"node": ">=12"
}
},
"node_modules/semantic-release/node_modules/mimic-fn": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz",
"integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==",
"dev": true,
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/semantic-release/node_modules/npm-run-path": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.1.0.tgz",
"integrity": "sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==",
"dev": true,
"dependencies": {
"path-key": "^4.0.0"
},
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/semantic-release/node_modules/onetime": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz",
"integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==",
"dev": true,
"dependencies": {
"mimic-fn": "^4.0.0"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/semantic-release/node_modules/p-limit": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz",
"integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==",
"dev": true,
"dependencies": {
"yocto-queue": "^1.0.0"
},
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/semantic-release/node_modules/p-locate": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz",
"integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==",
"dev": true,
"dependencies": {
"p-limit": "^4.0.0"
},
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/semantic-release/node_modules/p-reduce": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/p-reduce/-/p-reduce-3.0.0.tgz",
"integrity": "sha512-xsrIUgI0Kn6iyDYm9StOpOeK29XM1aboGji26+QEortiFST1hGZaUQOLhtEbqHErPpGW/aSz6allwK2qcptp0Q==",
"dev": true,
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/semantic-release/node_modules/path-exists": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz",
"integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==",
"dev": true,
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
}
},
"node_modules/semantic-release/node_modules/path-key": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz",
"integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==",
"dev": true,
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/semantic-release/node_modules/read-pkg": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-7.1.0.tgz",
"integrity": "sha512-5iOehe+WF75IccPc30bWTbpdDQLOCc3Uu8bi3Dte3Eueij81yx1Mrufk8qBx/YAbR4uL1FdUr+7BKXDwEtisXg==",
"dev": true,
"dependencies": {
"@types/normalize-package-data": "^2.4.1",
"normalize-package-data": "^3.0.2",
"parse-json": "^5.2.0",
"type-fest": "^2.0.0"
},
"engines": {
"node": ">=12.20"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/semantic-release/node_modules/read-pkg-up": {
"version": "9.1.0",
"resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-9.1.0.tgz",
"integrity": "sha512-vaMRR1AC1nrd5CQM0PhlRsO5oc2AAigqr7cCrZ/MW/Rsaflz4RlgzkpL4qoU/z1F6wrbd85iFv1OQj/y5RdGvg==",
"dev": true,
"dependencies": {
"find-up": "^6.3.0",
"read-pkg": "^7.1.0",
"type-fest": "^2.5.0"
},
"engines": {
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/semantic-release/node_modules/strip-final-newline": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz",
"integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==",
"dev": true,
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/semantic-release/node_modules/type-fest": {
"version": "2.19.0",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-2.19.0.tgz",
"integrity": "sha512-RAH822pAdBgcNMAfWnCBU3CFZcfZ/i1eZjwFU/dsLKumyuuP3niueg2UAukXYF0E2AAoc82ZSSf9J0WQBinzHA==",
"dev": true,
"engines": {
"node": ">=12.20"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/semver": {
@@ -5450,33 +5917,27 @@
}
},
"node_modules/semver-diff": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-3.1.1.tgz",
"integrity": "sha512-GX0Ix/CJcHyB8c4ykpHGIAvLyOwOobtM/8d+TQkAd81/bEjgPHrfba41Vpesr7jX/t8Uh+R3EX9eAS5be+jQYg==",
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/semver-diff/-/semver-diff-4.0.0.tgz",
"integrity": "sha512-0Ju4+6A8iOnpL/Thra7dZsSlOHYAHIeMxfhWQRI1/VLcT3WDBZKKtQt/QkBOsiIN9ZpuvHE6cGZ0x4glCMmfiA==",
"dev": true,
"dependencies": {
"semver": "^6.3.0"
"semver": "^7.3.5"
},
"engines": {
"node": ">=8"
}
},
"node_modules/semver-diff/node_modules/semver": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
"dev": true,
"bin": {
"semver": "bin/semver.js"
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/semver-regex": {
"version": "3.1.4",
"resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-3.1.4.tgz",
"integrity": "sha512-6IiqeZNgq01qGf0TId0t3NvKzSvUsjcpdEO3AQNeIjR6A2+ckTnQlDpl4qu1bjRv0RzN3FP9hzFmws3lKqRWkA==",
"version": "4.0.5",
"resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-4.0.5.tgz",
"integrity": "sha512-hunMQrEy1T6Jr2uEVjrAIqjwWcQTgOAcIM52C8MY1EZSD3DDNft04XzvYKPqjED65bNVVko0YI38nYeEHCX3yw==",
"dev": true,
"engines": {
"node": ">=8"
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
@@ -6067,31 +6528,22 @@
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
"dev": true
},
"node_modules/yaml": {
"version": "1.10.2",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz",
"integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==",
"dev": true,
"engines": {
"node": ">= 6"
}
},
"node_modules/yargs": {
"version": "16.2.0",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
"integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==",
"version": "17.6.2",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.6.2.tgz",
"integrity": "sha512-1/9UrdHjDZc0eOU0HxOHoS78C69UD3JRMvzlJ7S79S2nTaWRA/whGCTV8o9e/N/1Va9YIV7Q4sOxD8VV4pCWOw==",
"dev": true,
"dependencies": {
"cliui": "^7.0.2",
"cliui": "^8.0.1",
"escalade": "^3.1.1",
"get-caller-file": "^2.0.5",
"require-directory": "^2.1.1",
"string-width": "^4.2.0",
"string-width": "^4.2.3",
"y18n": "^5.0.5",
"yargs-parser": "^20.2.2"
"yargs-parser": "^21.1.1"
},
"engines": {
"node": ">=10"
"node": ">=12"
}
},
"node_modules/yargs-parser": {
@@ -6102,6 +6554,27 @@
"engines": {
"node": ">=10"
}
},
"node_modules/yargs/node_modules/yargs-parser": {
"version": "21.1.1",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
"integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
"dev": true,
"engines": {
"node": ">=12"
}
},
"node_modules/yocto-queue": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.0.0.tgz",
"integrity": "sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==",
"dev": true,
"engines": {
"node": ">=12.20"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
}
}
}

View File

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

View File

@@ -0,0 +1,24 @@
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 versions ()[Ljava/lang/String;
}
public abstract interface annotation class app/revanced/patcher/patch/annotation/Patch : java/lang/annotation/Annotation {
public abstract fun compatiblePackages ()[Lapp/revanced/patcher/patch/annotation/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/annotation/processor/PatchProcessor : com/google/devtools/ksp/processing/SymbolProcessor {
public fun process (Lcom/google/devtools/ksp/processing/Resolver;)Ljava/util/List;
}
public final class app/revanced/patcher/patch/annotation/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/annotation/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 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

@@ -0,0 +1,38 @@
package app.revanced.patcher.patch.annotation
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,207 @@
package app.revanced.patcher.patch.annotation.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.annotation.Patch
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.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 internal constructor(
private val codeGenerator: CodeGenerator,
) : 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 patches = 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>).ifEmpty { null }
?.joinToString(", ") { version -> "\"$version\"" }
CodeBlock.of(
"%T(%S, %L)",
app.revanced.patcher.patch.Patch.CompatiblePackage::class,
packageName,
packageVersions?.let { "setOf($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 with,
// unlike the annotated patch.
val dependencyResolutionMap = buildMap {
patches.values.filter { it.dependencies != null }.flatMap {
it.dependencies!!
}.distinct().forEach { dependency ->
patches.keys.find { it.qualifiedName?.asString() == dependency.toString() }
?.let { patch ->
this[dependency] = ClassName(
patch.packageName.asString(),
patch.simpleName.asString() + "Generated"
)
}
}
}
patches.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(", ")
)
}
// The generated patch always depends on the source patch.
addSuperclassConstructorParameter(
"dependencies = setOf(%L)",
buildList {
patchAnnotation.dependencies?.forEach { dependency ->
add("${(dependencyResolutionMap[dependency] ?: dependency)}::class")
}
add("${patchDeclaration.toClassName()}::class")
}.joinToString(", "),
)
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 { (_, 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.annotation.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)
}

View File

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

View File

@@ -0,0 +1,147 @@
package app.revanced.patcher.patch.annotation.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
)
@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
// 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() = assertEquals(
1, // Generated patch is always dependent on source class.
compile(
getSourceFile(
"limitations/manualdependency", "DependentPatch"
), getSourceFile(
"limitations/manualdependency", "DependencyPatch"
)
).loadPatch("$SAMPLE_PACKAGE.limitations.manualdependency.DependentPatchGenerated").dependencies!!.size
)
// endregion
private companion object Utils {
const val SAMPLE_PACKAGE = "app.revanced.patcher.patch.annotation.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 {
val resourceName = "app/revanced/patcher/patch/annotation/processor/samples/$sample/$className.kt"
return SourceFile.kotlin(
"$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.
*
* @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.annotation.processor.samples.dependencies
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.ResourcePatch
import app.revanced.patcher.patch.annotation.Patch
@Patch(name = "Dependency patch")
object DependencyPatch : ResourcePatch() {
override fun execute(context: ResourceContext) {}
}

View File

@@ -0,0 +1,12 @@
package app.revanced.patcher.patch.annotation.processor.samples.dependencies
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.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.annotation.processor.samples.limitations.manualdependency
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.ResourcePatch
import app.revanced.patcher.patch.annotation.Patch
@Patch(name = "Dependency patch")
object DependencyPatch : ResourcePatch() {
override fun execute(context: ResourceContext) { }
}

View File

@@ -0,0 +1,17 @@
package app.revanced.patcher.patch.annotation.processor.samples.limitations.manualdependency
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.patch.BytecodePatch
import app.revanced.patcher.patch.annotation.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,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

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

View File

@@ -0,0 +1,904 @@
public abstract interface class app/revanced/patcher/IntegrationsConsumer {
public abstract fun acceptIntegrations (Ljava/util/List;)V
}
public final class app/revanced/patcher/PackageMetadata {
public final fun getPackageName ()Ljava/lang/String;
public final fun getPackageVersion ()Ljava/lang/String;
}
public abstract class app/revanced/patcher/PatchBundleLoader : java/util/Set, kotlin/jvm/internal/markers/KMappedMarker {
public synthetic fun <init> (Ljava/lang/ClassLoader;[Ljava/io/File;Lkotlin/jvm/functions/Function1;Ljava/util/Set;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun add (Lapp/revanced/patcher/patch/Patch;)Z
public synthetic fun add (Ljava/lang/Object;)Z
public fun addAll (Ljava/util/Collection;)Z
public fun clear ()V
public fun contains (Lapp/revanced/patcher/patch/Patch;)Z
public final fun contains (Ljava/lang/Object;)Z
public fun containsAll (Ljava/util/Collection;)Z
public fun getSize ()I
public fun isEmpty ()Z
public fun iterator ()Ljava/util/Iterator;
public fun remove (Ljava/lang/Object;)Z
public fun removeAll (Ljava/util/Collection;)Z
public fun retainAll (Ljava/util/Collection;)Z
public final fun size ()I
public fun toArray ()[Ljava/lang/Object;
public fun toArray ([Ljava/lang/Object;)[Ljava/lang/Object;
}
public final class app/revanced/patcher/PatchBundleLoader$Dex : app/revanced/patcher/PatchBundleLoader {
public fun <init> ([Ljava/io/File;)V
public fun <init> ([Ljava/io/File;Ljava/io/File;)V
public synthetic fun <init> ([Ljava/io/File;Ljava/io/File;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
}
public final class app/revanced/patcher/PatchBundleLoader$Jar : app/revanced/patcher/PatchBundleLoader {
public fun <init> ([Ljava/io/File;)V
}
public abstract interface class app/revanced/patcher/PatchExecutorFunction : java/util/function/Function {
}
public final class app/revanced/patcher/Patcher : app/revanced/patcher/IntegrationsConsumer, app/revanced/patcher/PatchExecutorFunction, app/revanced/patcher/PatchesConsumer, java/io/Closeable, java/util/function/Supplier {
public fun <init> (Lapp/revanced/patcher/PatcherOptions;)V
public fun acceptIntegrations (Ljava/util/List;)V
public fun acceptPatches (Ljava/util/List;)V
public synthetic fun apply (Ljava/lang/Object;)Ljava/lang/Object;
public fun apply (Z)Lkotlinx/coroutines/flow/Flow;
public fun close ()V
public fun get ()Lapp/revanced/patcher/PatcherResult;
public synthetic fun get ()Ljava/lang/Object;
public final fun getContext ()Lapp/revanced/patcher/PatcherContext;
}
public final class app/revanced/patcher/PatcherContext {
public final fun getPackageMetadata ()Lapp/revanced/patcher/PackageMetadata;
}
public abstract class app/revanced/patcher/PatcherException : java/lang/Exception {
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/Throwable;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
public synthetic fun <init> (Ljava/lang/String;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
}
public final class app/revanced/patcher/PatcherException$CircularDependencyException : app/revanced/patcher/PatcherException {
}
public final class app/revanced/patcher/PatcherOptions {
public fun <init> (Ljava/io/File;Ljava/io/File;Ljava/lang/String;Ljava/lang/String;)V
public synthetic fun <init> (Ljava/io/File;Ljava/io/File;Ljava/lang/String;Ljava/lang/String;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun <init> (Ljava/io/File;Ljava/io/File;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patcher/logging/Logger;)V
public synthetic fun <init> (Ljava/io/File;Ljava/io/File;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patcher/logging/Logger;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun copy (Ljava/io/File;Ljava/io/File;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patcher/logging/Logger;)Lapp/revanced/patcher/PatcherOptions;
public static synthetic fun copy$default (Lapp/revanced/patcher/PatcherOptions;Ljava/io/File;Ljava/io/File;Ljava/lang/String;Ljava/lang/String;Lapp/revanced/patcher/logging/Logger;ILjava/lang/Object;)Lapp/revanced/patcher/PatcherOptions;
public fun equals (Ljava/lang/Object;)Z
public fun hashCode ()I
public final fun recreateResourceCacheDirectory ()Ljava/io/File;
public fun toString ()Ljava/lang/String;
}
public final class app/revanced/patcher/PatcherResult {
public fun <init> (Ljava/util/List;Ljava/io/File;Ljava/util/List;)V
public synthetic fun <init> (Ljava/util/List;Ljava/io/File;Ljava/util/List;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun component1 ()Ljava/util/List;
public final fun component2 ()Ljava/io/File;
public final fun component3 ()Ljava/util/List;
public final fun copy (Ljava/util/List;Ljava/io/File;Ljava/util/List;)Lapp/revanced/patcher/PatcherResult;
public static synthetic fun copy$default (Lapp/revanced/patcher/PatcherResult;Ljava/util/List;Ljava/io/File;Ljava/util/List;ILjava/lang/Object;)Lapp/revanced/patcher/PatcherResult;
public fun equals (Ljava/lang/Object;)Z
public final fun getDexFiles ()Ljava/util/List;
public final fun getDoNotCompress ()Ljava/util/List;
public final fun getResourceFile ()Ljava/io/File;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
public final class app/revanced/patcher/PatcherResult$PatchedDexFile {
public fun <init> (Ljava/lang/String;Ljava/io/InputStream;)V
public final fun getName ()Ljava/lang/String;
public final fun getStream ()Ljava/io/InputStream;
}
public abstract interface class app/revanced/patcher/PatchesConsumer {
public abstract fun acceptPatches (Ljava/util/List;)V
}
public final class app/revanced/patcher/data/BytecodeContext : app/revanced/patcher/data/Context {
public final fun findClass (Ljava/lang/String;)Lapp/revanced/patcher/util/proxy/ClassProxy;
public final fun findClass (Lkotlin/jvm/functions/Function1;)Lapp/revanced/patcher/util/proxy/ClassProxy;
public synthetic fun get ()Ljava/lang/Object;
public fun get ()Ljava/util/List;
public final fun getClasses ()Lapp/revanced/patcher/util/ProxyClassList;
public final fun proxy (Lcom/android/tools/smali/dexlib2/iface/ClassDef;)Lapp/revanced/patcher/util/proxy/ClassProxy;
public final fun toMethodWalker (Lcom/android/tools/smali/dexlib2/iface/Method;)Lapp/revanced/patcher/util/method/MethodWalker;
}
public abstract interface class app/revanced/patcher/data/Context : java/util/function/Supplier {
}
public final class app/revanced/patcher/data/ResourceContext : app/revanced/patcher/data/Context, java/lang/Iterable, kotlin/jvm/internal/markers/KMappedMarker {
public fun get ()Ljava/io/File;
public synthetic fun get ()Ljava/lang/Object;
public final fun get (Ljava/lang/String;)Ljava/io/File;
public final fun getXmlEditor ()Lapp/revanced/patcher/data/ResourceContext$XmlFileHolder;
public fun iterator ()Ljava/util/Iterator;
}
public final class app/revanced/patcher/data/ResourceContext$XmlFileHolder {
public fun <init> (Lapp/revanced/patcher/data/ResourceContext;)V
public final fun get (Ljava/io/InputStream;)Lapp/revanced/patcher/util/DomFileEditor;
public final fun get (Ljava/lang/String;)Lapp/revanced/patcher/util/DomFileEditor;
}
public final class app/revanced/patcher/extensions/ExtensionsKt {
public static final fun newLabel (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;I)Lcom/android/tools/smali/dexlib2/builder/Label;
public static final fun or (ILcom/android/tools/smali/dexlib2/AccessFlags;)I
public static final fun or (Lcom/android/tools/smali/dexlib2/AccessFlags;I)I
public static final fun or (Lcom/android/tools/smali/dexlib2/AccessFlags;Lcom/android/tools/smali/dexlib2/AccessFlags;)I
}
public final class app/revanced/patcher/extensions/InstructionExtensions {
public static final field INSTANCE Lapp/revanced/patcher/extensions/InstructionExtensions;
public final fun addInstruction (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;ILcom/android/tools/smali/dexlib2/builder/BuilderInstruction;)V
public final fun addInstruction (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;ILjava/lang/String;)V
public final fun addInstruction (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;Lcom/android/tools/smali/dexlib2/builder/BuilderInstruction;)V
public final fun addInstruction (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;Ljava/lang/String;)V
public final fun addInstructions (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;ILjava/lang/String;)V
public final fun addInstructions (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;ILjava/util/List;)V
public final fun addInstructions (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;Ljava/lang/String;)V
public final fun addInstructions (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;Ljava/util/List;)V
public final fun addInstructions (Lcom/android/tools/smali/dexlib2/builder/MutableMethodImplementation;ILjava/util/List;)V
public final fun addInstructions (Lcom/android/tools/smali/dexlib2/builder/MutableMethodImplementation;Ljava/util/List;)V
public final fun addInstructionsWithLabels (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;ILjava/lang/String;[Lapp/revanced/patcher/util/smali/ExternalLabel;)V
public final fun getInstruction (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;I)Lcom/android/tools/smali/dexlib2/builder/BuilderInstruction;
public final fun getInstruction (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;I)Ljava/lang/Object;
public final fun getInstruction (Lcom/android/tools/smali/dexlib2/builder/MutableMethodImplementation;I)Lcom/android/tools/smali/dexlib2/builder/BuilderInstruction;
public final fun getInstruction (Lcom/android/tools/smali/dexlib2/builder/MutableMethodImplementation;I)Ljava/lang/Object;
public final fun getInstructions (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;)Ljava/util/List;
public final fun removeInstruction (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;I)V
public final fun removeInstructions (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;I)V
public final fun removeInstructions (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;II)V
public final fun removeInstructions (Lcom/android/tools/smali/dexlib2/builder/MutableMethodImplementation;I)V
public final fun removeInstructions (Lcom/android/tools/smali/dexlib2/builder/MutableMethodImplementation;II)V
public final fun replaceInstruction (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;ILcom/android/tools/smali/dexlib2/builder/BuilderInstruction;)V
public final fun replaceInstruction (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;ILjava/lang/String;)V
public final fun replaceInstructions (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;ILjava/lang/String;)V
public final fun replaceInstructions (Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;ILjava/util/List;)V
public final fun replaceInstructions (Lcom/android/tools/smali/dexlib2/builder/MutableMethodImplementation;ILjava/util/List;)V
}
public final class app/revanced/patcher/extensions/MethodFingerprintExtensions {
public static final field INSTANCE Lapp/revanced/patcher/extensions/MethodFingerprintExtensions;
public final fun getFuzzyPatternScanMethod (Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprint;)Lapp/revanced/patcher/fingerprint/method/annotation/FuzzyPatternScanMethod;
}
public abstract interface class app/revanced/patcher/fingerprint/Fingerprint {
}
public abstract interface annotation class app/revanced/patcher/fingerprint/method/annotation/FuzzyPatternScanMethod : java/lang/annotation/Annotation {
public abstract fun threshold ()I
}
public abstract class app/revanced/patcher/fingerprint/method/impl/MethodFingerprint : app/revanced/patcher/fingerprint/Fingerprint {
public static final field Companion Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprint$Companion;
public fun <init> ()V
public fun <init> (Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/Iterable;Ljava/lang/Iterable;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function2;)V
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/Iterable;Ljava/lang/Iterable;Ljava/lang/Iterable;Lkotlin/jvm/functions/Function2;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun getResult ()Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult;
public final fun setResult (Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult;)V
}
public final class app/revanced/patcher/fingerprint/method/impl/MethodFingerprint$Companion {
public final fun resolve (Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprint;Lapp/revanced/patcher/data/BytecodeContext;Lcom/android/tools/smali/dexlib2/iface/ClassDef;)Z
public final fun resolve (Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprint;Lapp/revanced/patcher/data/BytecodeContext;Lcom/android/tools/smali/dexlib2/iface/Method;Lcom/android/tools/smali/dexlib2/iface/ClassDef;)Z
public final fun resolve (Ljava/lang/Iterable;Lapp/revanced/patcher/data/BytecodeContext;Ljava/lang/Iterable;)V
}
public final class app/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult {
public fun <init> (Lcom/android/tools/smali/dexlib2/iface/Method;Lcom/android/tools/smali/dexlib2/iface/ClassDef;Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult;Lapp/revanced/patcher/data/BytecodeContext;)V
public final fun component1 ()Lcom/android/tools/smali/dexlib2/iface/Method;
public final fun component2 ()Lcom/android/tools/smali/dexlib2/iface/ClassDef;
public final fun component3 ()Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult;
public final fun copy (Lcom/android/tools/smali/dexlib2/iface/Method;Lcom/android/tools/smali/dexlib2/iface/ClassDef;Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult;Lapp/revanced/patcher/data/BytecodeContext;)Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult;
public static synthetic fun copy$default (Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult;Lcom/android/tools/smali/dexlib2/iface/Method;Lcom/android/tools/smali/dexlib2/iface/ClassDef;Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult;Lapp/revanced/patcher/data/BytecodeContext;ILjava/lang/Object;)Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult;
public fun equals (Ljava/lang/Object;)Z
public final fun getClassDef ()Lcom/android/tools/smali/dexlib2/iface/ClassDef;
public final fun getMethod ()Lcom/android/tools/smali/dexlib2/iface/Method;
public final fun getMutableClass ()Lapp/revanced/patcher/util/proxy/mutableTypes/MutableClass;
public final fun getMutableMethod ()Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;
public final fun getScanResult ()Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
public final class app/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult {
public fun <init> (Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult$PatternScanResult;Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult$StringsScanResult;)V
public final fun component1 ()Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult$PatternScanResult;
public final fun component2 ()Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult$StringsScanResult;
public final fun copy (Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult$PatternScanResult;Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult$StringsScanResult;)Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult;
public static synthetic fun copy$default (Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult;Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult$PatternScanResult;Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult$StringsScanResult;ILjava/lang/Object;)Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult;
public fun equals (Ljava/lang/Object;)Z
public final fun getPatternScanResult ()Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult$PatternScanResult;
public final fun getStringsScanResult ()Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult$StringsScanResult;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
public final class app/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult$PatternScanResult {
public fun <init> (IILjava/util/List;)V
public synthetic fun <init> (IILjava/util/List;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun component1 ()I
public final fun component2 ()I
public final fun component3 ()Ljava/util/List;
public final fun copy (IILjava/util/List;)Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult$PatternScanResult;
public static synthetic fun copy$default (Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult$PatternScanResult;IILjava/util/List;ILjava/lang/Object;)Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult$PatternScanResult;
public fun equals (Ljava/lang/Object;)Z
public final fun getEndIndex ()I
public final fun getStartIndex ()I
public final fun getWarnings ()Ljava/util/List;
public fun hashCode ()I
public final fun setWarnings (Ljava/util/List;)V
public fun toString ()Ljava/lang/String;
}
public final class app/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult$PatternScanResult$Warning {
public fun <init> (Lcom/android/tools/smali/dexlib2/Opcode;Lcom/android/tools/smali/dexlib2/Opcode;II)V
public final fun component1 ()Lcom/android/tools/smali/dexlib2/Opcode;
public final fun component2 ()Lcom/android/tools/smali/dexlib2/Opcode;
public final fun component3 ()I
public final fun component4 ()I
public final fun copy (Lcom/android/tools/smali/dexlib2/Opcode;Lcom/android/tools/smali/dexlib2/Opcode;II)Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult$PatternScanResult$Warning;
public static synthetic fun copy$default (Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult$PatternScanResult$Warning;Lcom/android/tools/smali/dexlib2/Opcode;Lcom/android/tools/smali/dexlib2/Opcode;IIILjava/lang/Object;)Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult$PatternScanResult$Warning;
public fun equals (Ljava/lang/Object;)Z
public final fun getCorrectOpcode ()Lcom/android/tools/smali/dexlib2/Opcode;
public final fun getInstructionIndex ()I
public final fun getPatternIndex ()I
public final fun getWrongOpcode ()Lcom/android/tools/smali/dexlib2/Opcode;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
public final class app/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult$StringsScanResult {
public fun <init> (Ljava/util/List;)V
public final fun component1 ()Ljava/util/List;
public final fun copy (Ljava/util/List;)Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult$StringsScanResult;
public static synthetic fun copy$default (Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult$StringsScanResult;Ljava/util/List;ILjava/lang/Object;)Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult$StringsScanResult;
public fun equals (Ljava/lang/Object;)Z
public final fun getMatches ()Ljava/util/List;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
public final class app/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult$StringsScanResult$StringMatch {
public fun <init> (Ljava/lang/String;I)V
public final fun component1 ()Ljava/lang/String;
public final fun component2 ()I
public final fun copy (Ljava/lang/String;I)Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult$StringsScanResult$StringMatch;
public static synthetic fun copy$default (Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult$StringsScanResult$StringMatch;Ljava/lang/String;IILjava/lang/Object;)Lapp/revanced/patcher/fingerprint/method/impl/MethodFingerprintResult$MethodFingerprintScanResult$StringsScanResult$StringMatch;
public fun equals (Ljava/lang/Object;)Z
public final fun getIndex ()I
public final fun getString ()Ljava/lang/String;
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
public abstract interface class app/revanced/patcher/logging/Logger {
public abstract fun error (Ljava/lang/String;)V
public abstract fun info (Ljava/lang/String;)V
public abstract fun trace (Ljava/lang/String;)V
public abstract fun warn (Ljava/lang/String;)V
}
public final class app/revanced/patcher/logging/Logger$DefaultImpls {
public static fun error (Lapp/revanced/patcher/logging/Logger;Ljava/lang/String;)V
public static fun info (Lapp/revanced/patcher/logging/Logger;Ljava/lang/String;)V
public static fun trace (Lapp/revanced/patcher/logging/Logger;Ljava/lang/String;)V
public static fun warn (Lapp/revanced/patcher/logging/Logger;Ljava/lang/String;)V
}
public final class app/revanced/patcher/logging/impl/NopLogger : app/revanced/patcher/logging/Logger {
public static final field INSTANCE Lapp/revanced/patcher/logging/impl/NopLogger;
public fun error (Ljava/lang/String;)V
public fun info (Ljava/lang/String;)V
public fun trace (Ljava/lang/String;)V
public fun warn (Ljava/lang/String;)V
}
public abstract class app/revanced/patcher/patch/BytecodePatch : app/revanced/patcher/patch/Patch {
public fun <init> ()V
public fun <init> (Ljava/util/Set;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;Ljava/util/Set;ZZ)V
public synthetic fun <init> (Ljava/util/Set;Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;Ljava/util/Set;ZZILkotlin/jvm/internal/DefaultConstructorMarker;)V
}
public abstract class app/revanced/patcher/patch/Patch {
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;Ljava/util/Set;ZZILkotlin/jvm/internal/DefaultConstructorMarker;)V
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;Ljava/util/Set;ZZLkotlin/jvm/internal/DefaultConstructorMarker;)V
public fun equals (Ljava/lang/Object;)Z
public abstract fun execute (Lapp/revanced/patcher/data/Context;)V
public final fun getCompatiblePackages ()Ljava/util/Set;
public final fun getDependencies ()Ljava/util/Set;
public final fun getDescription ()Ljava/lang/String;
public final fun getName ()Ljava/lang/String;
public final fun getOptions ()Lapp/revanced/patcher/patch/options/PatchOptions;
public final fun getRequiresIntegrations ()Z
public final fun getUse ()Z
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
public final class app/revanced/patcher/patch/Patch$CompatiblePackage {
public fun <init> (Ljava/lang/String;Ljava/util/Set;)V
public synthetic fun <init> (Ljava/lang/String;Ljava/util/Set;ILkotlin/jvm/internal/DefaultConstructorMarker;)V
public final fun getName ()Ljava/lang/String;
public final fun getVersions ()Ljava/util/Set;
}
public final class app/revanced/patcher/patch/PatchException : java/lang/Exception {
public fun <init> (Ljava/lang/String;)V
public fun <init> (Ljava/lang/String;Ljava/lang/Throwable;)V
public fun <init> (Ljava/lang/Throwable;)V
}
public final class app/revanced/patcher/patch/PatchResult {
public final fun getException ()Lapp/revanced/patcher/patch/PatchException;
public final fun getPatch ()Lapp/revanced/patcher/patch/Patch;
}
public abstract class app/revanced/patcher/patch/ResourcePatch : app/revanced/patcher/patch/Patch {
public fun <init> ()V
public fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;Ljava/util/Set;ZZ)V
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/util/Set;Ljava/util/Set;ZZILkotlin/jvm/internal/DefaultConstructorMarker;)V
}
public abstract class app/revanced/patcher/patch/options/PatchOption {
public fun <init> (Ljava/lang/String;Ljava/lang/Object;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;)V
public final fun getDescription ()Ljava/lang/String;
public final fun getKey ()Ljava/lang/String;
public final fun getRequired ()Z
public final fun getTitle ()Ljava/lang/String;
public final fun getValidate ()Lkotlin/jvm/functions/Function1;
public final fun getValue ()Ljava/lang/Object;
public final fun getValue (Ljava/lang/Object;Lkotlin/reflect/KProperty;)Ljava/lang/Object;
public final fun setValue (Ljava/lang/Object;)V
public final fun setValue (Ljava/lang/Object;Lkotlin/reflect/KProperty;Ljava/lang/Object;)V
}
public abstract class app/revanced/patcher/patch/options/PatchOptionException : java/lang/Exception {
public synthetic fun <init> (Ljava/lang/String;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
}
public final class app/revanced/patcher/patch/options/PatchOptionException$InvalidValueTypeException : app/revanced/patcher/patch/options/PatchOptionException {
public fun <init> (Ljava/lang/String;Ljava/lang/String;)V
}
public final class app/revanced/patcher/patch/options/PatchOptionException$PatchOptionNotFoundException : app/revanced/patcher/patch/options/PatchOptionException {
public fun <init> (Ljava/lang/String;)V
}
public final class app/revanced/patcher/patch/options/PatchOptionException$ValueRequiredException : app/revanced/patcher/patch/options/PatchOptionException {
public fun <init> (Lapp/revanced/patcher/patch/options/PatchOption;)V
}
public final class app/revanced/patcher/patch/options/PatchOptionException$ValueValidationException : app/revanced/patcher/patch/options/PatchOptionException {
public fun <init> (Ljava/lang/Object;Lapp/revanced/patcher/patch/options/PatchOption;)V
}
public final class app/revanced/patcher/patch/options/PatchOptions : java/util/Map, kotlin/jvm/internal/markers/KMutableMap {
public fun <init> ()V
public fun clear ()V
public final fun containsKey (Ljava/lang/Object;)Z
public fun containsKey (Ljava/lang/String;)Z
public fun containsValue (Lapp/revanced/patcher/patch/options/PatchOption;)Z
public final fun containsValue (Ljava/lang/Object;)Z
public final fun entrySet ()Ljava/util/Set;
public final fun get (Ljava/lang/Object;)Lapp/revanced/patcher/patch/options/PatchOption;
public final synthetic fun get (Ljava/lang/Object;)Ljava/lang/Object;
public fun get (Ljava/lang/String;)Lapp/revanced/patcher/patch/options/PatchOption;
public fun getEntries ()Ljava/util/Set;
public fun getKeys ()Ljava/util/Set;
public fun getSize ()I
public fun getValues ()Ljava/util/Collection;
public fun isEmpty ()Z
public final fun keySet ()Ljava/util/Set;
public synthetic fun put (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
public fun put (Ljava/lang/String;Lapp/revanced/patcher/patch/options/PatchOption;)Lapp/revanced/patcher/patch/options/PatchOption;
public fun putAll (Ljava/util/Map;)V
public final fun register (Lapp/revanced/patcher/patch/options/PatchOption;)V
public final fun remove (Ljava/lang/Object;)Lapp/revanced/patcher/patch/options/PatchOption;
public final synthetic fun remove (Ljava/lang/Object;)Ljava/lang/Object;
public fun remove (Ljava/lang/String;)Lapp/revanced/patcher/patch/options/PatchOption;
public final fun set (Ljava/lang/String;Ljava/lang/Object;)V
public final fun size ()I
public final fun values ()Ljava/util/Collection;
}
public final class app/revanced/patcher/patch/options/types/BooleanPatchOption : app/revanced/patcher/patch/options/PatchOption {
public static final field Companion Lapp/revanced/patcher/patch/options/types/BooleanPatchOption$Companion;
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/Boolean;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
}
public final class app/revanced/patcher/patch/options/types/BooleanPatchOption$Companion {
public final fun booleanPatchOption (Lapp/revanced/patcher/patch/Patch;Ljava/lang/String;Ljava/lang/Boolean;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;)Lapp/revanced/patcher/patch/options/types/BooleanPatchOption;
public static synthetic fun booleanPatchOption$default (Lapp/revanced/patcher/patch/options/types/BooleanPatchOption$Companion;Lapp/revanced/patcher/patch/Patch;Ljava/lang/String;Ljava/lang/Boolean;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lapp/revanced/patcher/patch/options/types/BooleanPatchOption;
}
public final class app/revanced/patcher/patch/options/types/FloatPatchOption : app/revanced/patcher/patch/options/PatchOption {
public static final field Companion Lapp/revanced/patcher/patch/options/types/FloatPatchOption$Companion;
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/Float;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
}
public final class app/revanced/patcher/patch/options/types/FloatPatchOption$Companion {
public final fun floatPatchOption (Lapp/revanced/patcher/patch/Patch;Ljava/lang/String;Ljava/lang/Float;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;)Lapp/revanced/patcher/patch/options/types/FloatPatchOption;
public static synthetic fun floatPatchOption$default (Lapp/revanced/patcher/patch/options/types/FloatPatchOption$Companion;Lapp/revanced/patcher/patch/Patch;Ljava/lang/String;Ljava/lang/Float;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lapp/revanced/patcher/patch/options/types/FloatPatchOption;
}
public final class app/revanced/patcher/patch/options/types/IntPatchOption : app/revanced/patcher/patch/options/PatchOption {
public static final field Companion Lapp/revanced/patcher/patch/options/types/IntPatchOption$Companion;
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
}
public final class app/revanced/patcher/patch/options/types/IntPatchOption$Companion {
public final fun intPatchOption (Lapp/revanced/patcher/patch/Patch;Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;)Lapp/revanced/patcher/patch/options/types/IntPatchOption;
public static synthetic fun intPatchOption$default (Lapp/revanced/patcher/patch/options/types/IntPatchOption$Companion;Lapp/revanced/patcher/patch/Patch;Ljava/lang/String;Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lapp/revanced/patcher/patch/options/types/IntPatchOption;
}
public final class app/revanced/patcher/patch/options/types/LongPatchOption : app/revanced/patcher/patch/options/PatchOption {
public static final field Companion Lapp/revanced/patcher/patch/options/types/LongPatchOption$Companion;
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/Long;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
}
public final class app/revanced/patcher/patch/options/types/LongPatchOption$Companion {
public final fun longPatchOption (Lapp/revanced/patcher/patch/Patch;Ljava/lang/String;Ljava/lang/Long;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;)Lapp/revanced/patcher/patch/options/types/LongPatchOption;
public static synthetic fun longPatchOption$default (Lapp/revanced/patcher/patch/options/types/LongPatchOption$Companion;Lapp/revanced/patcher/patch/Patch;Ljava/lang/String;Ljava/lang/Long;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lapp/revanced/patcher/patch/options/types/LongPatchOption;
}
public final class app/revanced/patcher/patch/options/types/StringPatchOption : app/revanced/patcher/patch/options/PatchOption {
public static final field Companion Lapp/revanced/patcher/patch/options/types/StringPatchOption$Companion;
public synthetic fun <init> (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
}
public final class app/revanced/patcher/patch/options/types/StringPatchOption$Companion {
public final fun stringPatchOption (Lapp/revanced/patcher/patch/Patch;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;)Lapp/revanced/patcher/patch/options/types/StringPatchOption;
public static synthetic fun stringPatchOption$default (Lapp/revanced/patcher/patch/options/types/StringPatchOption$Companion;Lapp/revanced/patcher/patch/Patch;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lapp/revanced/patcher/patch/options/types/StringPatchOption;
}
public final class app/revanced/patcher/patch/options/types/array/BooleanArrayPatchOption : app/revanced/patcher/patch/options/PatchOption {
public static final field Companion Lapp/revanced/patcher/patch/options/types/array/BooleanArrayPatchOption$Companion;
public synthetic fun <init> (Ljava/lang/String;[Ljava/lang/Boolean;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
}
public final class app/revanced/patcher/patch/options/types/array/BooleanArrayPatchOption$Companion {
public final fun booleanArrayPatchOption (Lapp/revanced/patcher/patch/Patch;Ljava/lang/String;[Ljava/lang/Boolean;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;)Lapp/revanced/patcher/patch/options/types/array/BooleanArrayPatchOption;
public static synthetic fun booleanArrayPatchOption$default (Lapp/revanced/patcher/patch/options/types/array/BooleanArrayPatchOption$Companion;Lapp/revanced/patcher/patch/Patch;Ljava/lang/String;[Ljava/lang/Boolean;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lapp/revanced/patcher/patch/options/types/array/BooleanArrayPatchOption;
}
public final class app/revanced/patcher/patch/options/types/array/FloatArrayPatchOption : app/revanced/patcher/patch/options/PatchOption {
public static final field Companion Lapp/revanced/patcher/patch/options/types/array/FloatArrayPatchOption$Companion;
public synthetic fun <init> (Ljava/lang/String;[Ljava/lang/Float;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
}
public final class app/revanced/patcher/patch/options/types/array/FloatArrayPatchOption$Companion {
public final fun floatArrayPatchOption (Lapp/revanced/patcher/patch/Patch;Ljava/lang/String;[Ljava/lang/Float;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;)Lapp/revanced/patcher/patch/options/types/array/FloatArrayPatchOption;
public static synthetic fun floatArrayPatchOption$default (Lapp/revanced/patcher/patch/options/types/array/FloatArrayPatchOption$Companion;Lapp/revanced/patcher/patch/Patch;Ljava/lang/String;[Ljava/lang/Float;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lapp/revanced/patcher/patch/options/types/array/FloatArrayPatchOption;
}
public final class app/revanced/patcher/patch/options/types/array/IntArrayPatchOption : app/revanced/patcher/patch/options/PatchOption {
public static final field Companion Lapp/revanced/patcher/patch/options/types/array/IntArrayPatchOption$Companion;
public synthetic fun <init> (Ljava/lang/String;[Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
}
public final class app/revanced/patcher/patch/options/types/array/IntArrayPatchOption$Companion {
public final fun intArrayPatchOption (Lapp/revanced/patcher/patch/Patch;Ljava/lang/String;[Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;)Lapp/revanced/patcher/patch/options/types/array/IntArrayPatchOption;
public static synthetic fun intArrayPatchOption$default (Lapp/revanced/patcher/patch/options/types/array/IntArrayPatchOption$Companion;Lapp/revanced/patcher/patch/Patch;Ljava/lang/String;[Ljava/lang/Integer;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lapp/revanced/patcher/patch/options/types/array/IntArrayPatchOption;
}
public final class app/revanced/patcher/patch/options/types/array/LongArrayPatchOption : app/revanced/patcher/patch/options/PatchOption {
public static final field Companion Lapp/revanced/patcher/patch/options/types/array/LongArrayPatchOption$Companion;
public synthetic fun <init> (Ljava/lang/String;[Ljava/lang/Long;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
}
public final class app/revanced/patcher/patch/options/types/array/LongArrayPatchOption$Companion {
public final fun longArrayPatchOption (Lapp/revanced/patcher/patch/Patch;Ljava/lang/String;[Ljava/lang/Long;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;)Lapp/revanced/patcher/patch/options/types/array/LongArrayPatchOption;
public static synthetic fun longArrayPatchOption$default (Lapp/revanced/patcher/patch/options/types/array/LongArrayPatchOption$Companion;Lapp/revanced/patcher/patch/Patch;Ljava/lang/String;[Ljava/lang/Long;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lapp/revanced/patcher/patch/options/types/array/LongArrayPatchOption;
}
public final class app/revanced/patcher/patch/options/types/array/StringArrayPatchOption : app/revanced/patcher/patch/options/PatchOption {
public static final field Companion Lapp/revanced/patcher/patch/options/types/array/StringArrayPatchOption$Companion;
public synthetic fun <init> (Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;Lkotlin/jvm/internal/DefaultConstructorMarker;)V
}
public final class app/revanced/patcher/patch/options/types/array/StringArrayPatchOption$Companion {
public final fun stringArrayPatchOption (Lapp/revanced/patcher/patch/Patch;Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;)Lapp/revanced/patcher/patch/options/types/array/StringArrayPatchOption;
public static synthetic fun stringArrayPatchOption$default (Lapp/revanced/patcher/patch/options/types/array/StringArrayPatchOption$Companion;Lapp/revanced/patcher/patch/Patch;Ljava/lang/String;[Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZLkotlin/jvm/functions/Function1;ILjava/lang/Object;)Lapp/revanced/patcher/patch/options/types/array/StringArrayPatchOption;
}
public final class app/revanced/patcher/util/DomFileEditor : java/io/Closeable {
public fun <init> (Ljava/io/File;)V
public fun close ()V
public final fun getFile ()Lorg/w3c/dom/Document;
}
public final class app/revanced/patcher/util/ProxyClassList : java/util/Set, kotlin/jvm/internal/markers/KMutableSet {
public final fun add (Lapp/revanced/patcher/util/proxy/ClassProxy;)Z
public fun add (Lcom/android/tools/smali/dexlib2/iface/ClassDef;)Z
public synthetic fun add (Ljava/lang/Object;)Z
public fun addAll (Ljava/util/Collection;)Z
public fun clear ()V
public fun contains (Lcom/android/tools/smali/dexlib2/iface/ClassDef;)Z
public final fun contains (Ljava/lang/Object;)Z
public fun containsAll (Ljava/util/Collection;)Z
public fun getSize ()I
public fun isEmpty ()Z
public fun iterator ()Ljava/util/Iterator;
public fun remove (Lcom/android/tools/smali/dexlib2/iface/ClassDef;)Z
public final fun remove (Ljava/lang/Object;)Z
public fun removeAll (Ljava/util/Collection;)Z
public fun retainAll (Ljava/util/Collection;)Z
public final fun size ()I
public fun toArray ()[Ljava/lang/Object;
public fun toArray ([Ljava/lang/Object;)[Ljava/lang/Object;
}
public final class app/revanced/patcher/util/method/MethodWalker {
public final fun getMethod ()Lcom/android/tools/smali/dexlib2/iface/Method;
public final fun nextMethod (IZ)Lapp/revanced/patcher/util/method/MethodWalker;
public static synthetic fun nextMethod$default (Lapp/revanced/patcher/util/method/MethodWalker;IZILjava/lang/Object;)Lapp/revanced/patcher/util/method/MethodWalker;
}
public final class app/revanced/patcher/util/proxy/ClassProxy {
public final fun getImmutableClass ()Lcom/android/tools/smali/dexlib2/iface/ClassDef;
public final fun getMutableClass ()Lapp/revanced/patcher/util/proxy/mutableTypes/MutableClass;
}
public final class app/revanced/patcher/util/proxy/mutableTypes/MutableAnnotation : com/android/tools/smali/dexlib2/base/BaseAnnotation {
public static final field Companion Lapp/revanced/patcher/util/proxy/mutableTypes/MutableAnnotation$Companion;
public fun <init> (Lcom/android/tools/smali/dexlib2/iface/Annotation;)V
public fun getElements ()Ljava/util/Set;
public fun getType ()Ljava/lang/String;
public fun getVisibility ()I
}
public final class app/revanced/patcher/util/proxy/mutableTypes/MutableAnnotation$Companion {
public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/Annotation;)Lapp/revanced/patcher/util/proxy/mutableTypes/MutableAnnotation;
}
public final class app/revanced/patcher/util/proxy/mutableTypes/MutableAnnotationElement : com/android/tools/smali/dexlib2/base/BaseAnnotationElement {
public static final field Companion Lapp/revanced/patcher/util/proxy/mutableTypes/MutableAnnotationElement$Companion;
public fun <init> (Lcom/android/tools/smali/dexlib2/iface/AnnotationElement;)V
public fun getName ()Ljava/lang/String;
public fun getValue ()Lcom/android/tools/smali/dexlib2/iface/value/EncodedValue;
public final fun setName (Ljava/lang/String;)V
public final fun setValue (Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableEncodedValue;)V
}
public final class app/revanced/patcher/util/proxy/mutableTypes/MutableAnnotationElement$Companion {
public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/AnnotationElement;)Lapp/revanced/patcher/util/proxy/mutableTypes/MutableAnnotationElement;
}
public final class app/revanced/patcher/util/proxy/mutableTypes/MutableClass : com/android/tools/smali/dexlib2/base/reference/BaseTypeReference, com/android/tools/smali/dexlib2/iface/ClassDef {
public static final field Companion Lapp/revanced/patcher/util/proxy/mutableTypes/MutableClass$Companion;
public fun <init> (Lcom/android/tools/smali/dexlib2/iface/ClassDef;)V
public final fun charAt (I)C
public fun get (I)C
public fun getAccessFlags ()I
public fun getAnnotations ()Ljava/util/Set;
public synthetic fun getDirectMethods ()Ljava/lang/Iterable;
public fun getDirectMethods ()Ljava/util/Set;
public synthetic fun getFields ()Ljava/lang/Iterable;
public fun getFields ()Ljava/util/Set;
public synthetic fun getInstanceFields ()Ljava/lang/Iterable;
public fun getInstanceFields ()Ljava/util/Set;
public fun getInterfaces ()Ljava/util/List;
public fun getLength ()I
public synthetic fun getMethods ()Ljava/lang/Iterable;
public fun getMethods ()Ljava/util/Set;
public fun getSourceFile ()Ljava/lang/String;
public synthetic fun getStaticFields ()Ljava/lang/Iterable;
public fun getStaticFields ()Ljava/util/Set;
public fun getSuperclass ()Ljava/lang/String;
public fun getType ()Ljava/lang/String;
public synthetic fun getVirtualMethods ()Ljava/lang/Iterable;
public fun getVirtualMethods ()Ljava/util/Set;
public final fun length ()I
public final fun setAccessFlags (I)V
public final fun setSourceFile (Ljava/lang/String;)V
public final fun setSuperClass (Ljava/lang/String;)V
public final fun setType (Ljava/lang/String;)V
}
public final class app/revanced/patcher/util/proxy/mutableTypes/MutableClass$Companion {
public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/ClassDef;)Lapp/revanced/patcher/util/proxy/mutableTypes/MutableClass;
}
public final class app/revanced/patcher/util/proxy/mutableTypes/MutableField : com/android/tools/smali/dexlib2/base/reference/BaseFieldReference, com/android/tools/smali/dexlib2/iface/Field {
public static final field Companion Lapp/revanced/patcher/util/proxy/mutableTypes/MutableField$Companion;
public fun <init> (Lcom/android/tools/smali/dexlib2/iface/Field;)V
public fun getAccessFlags ()I
public fun getAnnotations ()Ljava/util/Set;
public fun getDefiningClass ()Ljava/lang/String;
public fun getHiddenApiRestrictions ()Ljava/util/Set;
public fun getInitialValue ()Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableEncodedValue;
public synthetic fun getInitialValue ()Lcom/android/tools/smali/dexlib2/iface/value/EncodedValue;
public fun getName ()Ljava/lang/String;
public fun getType ()Ljava/lang/String;
public final fun setAccessFlags (I)V
public final fun setDefiningClass (Ljava/lang/String;)V
public final fun setInitialValue (Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableEncodedValue;)V
public final fun setName (Ljava/lang/String;)V
public final fun setType (Ljava/lang/String;)V
}
public final class app/revanced/patcher/util/proxy/mutableTypes/MutableField$Companion {
public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/Field;)Lapp/revanced/patcher/util/proxy/mutableTypes/MutableField;
}
public final class app/revanced/patcher/util/proxy/mutableTypes/MutableMethod : com/android/tools/smali/dexlib2/base/reference/BaseMethodReference, com/android/tools/smali/dexlib2/iface/Method {
public static final field Companion Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod$Companion;
public fun <init> (Lcom/android/tools/smali/dexlib2/iface/Method;)V
public fun getAccessFlags ()I
public fun getAnnotations ()Ljava/util/Set;
public fun getDefiningClass ()Ljava/lang/String;
public fun getHiddenApiRestrictions ()Ljava/util/Set;
public fun getImplementation ()Lcom/android/tools/smali/dexlib2/builder/MutableMethodImplementation;
public synthetic fun getImplementation ()Lcom/android/tools/smali/dexlib2/iface/MethodImplementation;
public fun getName ()Ljava/lang/String;
public fun getParameterTypes ()Ljava/util/List;
public fun getParameters ()Ljava/util/List;
public fun getReturnType ()Ljava/lang/String;
public final fun setAccessFlags (I)V
public final fun setDefiningClass (Ljava/lang/String;)V
public final fun setName (Ljava/lang/String;)V
public final fun setReturnType (Ljava/lang/String;)V
}
public final class app/revanced/patcher/util/proxy/mutableTypes/MutableMethod$Companion {
public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/Method;)Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;
}
public final class app/revanced/patcher/util/proxy/mutableTypes/MutableMethodParameter : com/android/tools/smali/dexlib2/base/BaseMethodParameter, com/android/tools/smali/dexlib2/iface/MethodParameter {
public static final field Companion Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethodParameter$Companion;
public fun <init> (Lcom/android/tools/smali/dexlib2/iface/MethodParameter;)V
public final fun charAt (I)C
public fun get (I)C
public fun getAnnotations ()Ljava/util/Set;
public fun getLength ()I
public fun getName ()Ljava/lang/String;
public fun getSignature ()Ljava/lang/String;
public fun getType ()Ljava/lang/String;
public final fun length ()I
}
public final class app/revanced/patcher/util/proxy/mutableTypes/MutableMethodParameter$Companion {
public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/MethodParameter;)Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethodParameter;
}
public final class app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableAnnotationEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseAnnotationEncodedValue, app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableEncodedValue {
public static final field Companion Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableAnnotationEncodedValue$Companion;
public fun <init> (Lcom/android/tools/smali/dexlib2/iface/value/AnnotationEncodedValue;)V
public fun getElements ()Ljava/util/Set;
public fun getType ()Ljava/lang/String;
public final fun setType (Ljava/lang/String;)V
}
public final class app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableAnnotationEncodedValue$Companion {
public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/AnnotationEncodedValue;)Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableAnnotationEncodedValue;
}
public final class app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableArrayEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseArrayEncodedValue, app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableEncodedValue {
public static final field Companion Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableArrayEncodedValue$Companion;
public fun <init> (Lcom/android/tools/smali/dexlib2/iface/value/ArrayEncodedValue;)V
public fun getValue ()Ljava/util/List;
}
public final class app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableArrayEncodedValue$Companion {
public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/ArrayEncodedValue;)Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableArrayEncodedValue;
}
public final class app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableBooleanEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseBooleanEncodedValue, app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableEncodedValue {
public static final field Companion Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableBooleanEncodedValue$Companion;
public fun <init> (Lcom/android/tools/smali/dexlib2/iface/value/BooleanEncodedValue;)V
public fun getValue ()Z
public final fun setValue (Z)V
}
public final class app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableBooleanEncodedValue$Companion {
public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/BooleanEncodedValue;)Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableBooleanEncodedValue;
}
public final class app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableByteEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseByteEncodedValue, app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableEncodedValue {
public static final field Companion Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableByteEncodedValue$Companion;
public fun <init> (Lcom/android/tools/smali/dexlib2/iface/value/ByteEncodedValue;)V
public fun getValue ()B
public final fun setValue (B)V
}
public final class app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableByteEncodedValue$Companion {
public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/ByteEncodedValue;)Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableByteEncodedValue;
}
public final class app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableCharEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseCharEncodedValue, app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableEncodedValue {
public static final field Companion Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableCharEncodedValue$Companion;
public fun <init> (Lcom/android/tools/smali/dexlib2/iface/value/CharEncodedValue;)V
public fun getValue ()C
public final fun setValue (C)V
}
public final class app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableCharEncodedValue$Companion {
public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/CharEncodedValue;)Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableCharEncodedValue;
}
public final class app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableDoubleEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseDoubleEncodedValue, app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableEncodedValue {
public static final field Companion Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableDoubleEncodedValue$Companion;
public fun <init> (Lcom/android/tools/smali/dexlib2/iface/value/DoubleEncodedValue;)V
public fun getValue ()D
public final fun setValue (D)V
}
public final class app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableDoubleEncodedValue$Companion {
public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/DoubleEncodedValue;)Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableDoubleEncodedValue;
}
public abstract interface class app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableEncodedValue : com/android/tools/smali/dexlib2/iface/value/EncodedValue {
public static final field Companion Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableEncodedValue$Companion;
}
public final class app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableEncodedValue$Companion {
public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/EncodedValue;)Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableEncodedValue;
}
public final class app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableEnumEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseEnumEncodedValue, app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableEncodedValue {
public static final field Companion Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableEnumEncodedValue$Companion;
public fun <init> (Lcom/android/tools/smali/dexlib2/iface/value/EnumEncodedValue;)V
public fun getValue ()Lcom/android/tools/smali/dexlib2/iface/reference/FieldReference;
public final fun setValue (Lcom/android/tools/smali/dexlib2/iface/reference/FieldReference;)V
}
public final class app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableEnumEncodedValue$Companion {
public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/EnumEncodedValue;)Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableEnumEncodedValue;
}
public final class app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableFieldEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseFieldEncodedValue, app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableEncodedValue {
public static final field Companion Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableFieldEncodedValue$Companion;
public fun <init> (Lcom/android/tools/smali/dexlib2/iface/value/FieldEncodedValue;)V
public fun getValue ()Lcom/android/tools/smali/dexlib2/iface/reference/FieldReference;
public fun getValueType ()I
public final fun setValue (Lcom/android/tools/smali/dexlib2/iface/reference/FieldReference;)V
}
public final class app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableFieldEncodedValue$Companion {
public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/FieldEncodedValue;)Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableFieldEncodedValue;
}
public final class app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableFloatEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseFloatEncodedValue, app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableEncodedValue {
public static final field Companion Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableFloatEncodedValue$Companion;
public fun <init> (Lcom/android/tools/smali/dexlib2/iface/value/FloatEncodedValue;)V
public fun getValue ()F
public final fun setValue (F)V
}
public final class app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableFloatEncodedValue$Companion {
public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/FloatEncodedValue;)Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableFloatEncodedValue;
}
public final class app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableIntEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseIntEncodedValue, app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableEncodedValue {
public static final field Companion Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableIntEncodedValue$Companion;
public fun <init> (Lcom/android/tools/smali/dexlib2/iface/value/IntEncodedValue;)V
public fun getValue ()I
public final fun setValue (I)V
}
public final class app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableIntEncodedValue$Companion {
public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/IntEncodedValue;)Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableIntEncodedValue;
}
public final class app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableLongEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseLongEncodedValue, app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableEncodedValue {
public static final field Companion Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableLongEncodedValue$Companion;
public fun <init> (Lcom/android/tools/smali/dexlib2/iface/value/LongEncodedValue;)V
public fun getValue ()J
public final fun setValue (J)V
}
public final class app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableLongEncodedValue$Companion {
public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/LongEncodedValue;)Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableLongEncodedValue;
}
public final class app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableMethodEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseMethodEncodedValue, app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableEncodedValue {
public static final field Companion Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableMethodEncodedValue$Companion;
public fun <init> (Lcom/android/tools/smali/dexlib2/iface/value/MethodEncodedValue;)V
public fun getValue ()Lcom/android/tools/smali/dexlib2/iface/reference/MethodReference;
public final fun setValue (Lcom/android/tools/smali/dexlib2/iface/reference/MethodReference;)V
}
public final class app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableMethodEncodedValue$Companion {
public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/MethodEncodedValue;)Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableMethodEncodedValue;
}
public final class app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableMethodHandleEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseMethodHandleEncodedValue, app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableEncodedValue {
public static final field Companion Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableMethodHandleEncodedValue$Companion;
public fun <init> (Lcom/android/tools/smali/dexlib2/iface/value/MethodHandleEncodedValue;)V
public fun getValue ()Lcom/android/tools/smali/dexlib2/iface/reference/MethodHandleReference;
public final fun setValue (Lcom/android/tools/smali/dexlib2/iface/reference/MethodHandleReference;)V
}
public final class app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableMethodHandleEncodedValue$Companion {
public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/MethodHandleEncodedValue;)Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableMethodHandleEncodedValue;
}
public final class app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableMethodTypeEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseMethodTypeEncodedValue, app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableEncodedValue {
public static final field Companion Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableMethodTypeEncodedValue$Companion;
public fun <init> (Lcom/android/tools/smali/dexlib2/iface/value/MethodTypeEncodedValue;)V
public fun getValue ()Lcom/android/tools/smali/dexlib2/iface/reference/MethodProtoReference;
public final fun setValue (Lcom/android/tools/smali/dexlib2/iface/reference/MethodProtoReference;)V
}
public final class app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableMethodTypeEncodedValue$Companion {
public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/MethodTypeEncodedValue;)Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableMethodTypeEncodedValue;
}
public final class app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableNullEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseNullEncodedValue, app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableEncodedValue {
public static final field Companion Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableNullEncodedValue$Companion;
public fun <init> ()V
}
public final class app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableNullEncodedValue$Companion {
public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/ByteEncodedValue;)Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableByteEncodedValue;
}
public final class app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableShortEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseShortEncodedValue, app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableEncodedValue {
public static final field Companion Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableShortEncodedValue$Companion;
public fun <init> (Lcom/android/tools/smali/dexlib2/iface/value/ShortEncodedValue;)V
public fun getValue ()S
public final fun setValue (S)V
}
public final class app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableShortEncodedValue$Companion {
public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/ShortEncodedValue;)Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableShortEncodedValue;
}
public final class app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableStringEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseStringEncodedValue, app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableEncodedValue {
public static final field Companion Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableStringEncodedValue$Companion;
public fun <init> (Lcom/android/tools/smali/dexlib2/iface/value/StringEncodedValue;)V
public fun getValue ()Ljava/lang/String;
public final fun setValue (Ljava/lang/String;)V
}
public final class app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableStringEncodedValue$Companion {
public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/ByteEncodedValue;)Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableByteEncodedValue;
}
public final class app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableTypeEncodedValue : com/android/tools/smali/dexlib2/base/value/BaseTypeEncodedValue, app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableEncodedValue {
public static final field Companion Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableTypeEncodedValue$Companion;
public fun <init> (Lcom/android/tools/smali/dexlib2/iface/value/TypeEncodedValue;)V
public fun getValue ()Ljava/lang/String;
public final fun setValue (Ljava/lang/String;)V
}
public final class app/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableTypeEncodedValue$Companion {
public final fun toMutable (Lcom/android/tools/smali/dexlib2/iface/value/TypeEncodedValue;)Lapp/revanced/patcher/util/proxy/mutableTypes/encodedValue/MutableTypeEncodedValue;
}
public final class app/revanced/patcher/util/smali/ExternalLabel {
public fun <init> (Ljava/lang/String;Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction;)V
public final fun copy (Ljava/lang/String;Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction;)Lapp/revanced/patcher/util/smali/ExternalLabel;
public static synthetic fun copy$default (Lapp/revanced/patcher/util/smali/ExternalLabel;Ljava/lang/String;Lcom/android/tools/smali/dexlib2/iface/instruction/Instruction;ILjava/lang/Object;)Lapp/revanced/patcher/util/smali/ExternalLabel;
public fun equals (Ljava/lang/Object;)Z
public fun hashCode ()I
public fun toString ()Ljava/lang/String;
}
public final class app/revanced/patcher/util/smali/InlineSmaliCompiler {
public static final field Companion Lapp/revanced/patcher/util/smali/InlineSmaliCompiler$Companion;
public fun <init> ()V
}
public final class app/revanced/patcher/util/smali/InlineSmaliCompiler$Companion {
public final fun compile (Ljava/lang/String;Ljava/lang/String;IZ)Ljava/util/List;
}
public final class app/revanced/patcher/util/smali/InlineSmaliCompilerKt {
public static final fun toInstruction (Ljava/lang/String;Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;)Lcom/android/tools/smali/dexlib2/builder/BuilderInstruction;
public static synthetic fun toInstruction$default (Ljava/lang/String;Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;ILjava/lang/Object;)Lcom/android/tools/smali/dexlib2/builder/BuilderInstruction;
public static final fun toInstructions (Ljava/lang/String;Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;)Ljava/util/List;
public static synthetic fun toInstructions$default (Ljava/lang/String;Lapp/revanced/patcher/util/proxy/mutableTypes/MutableMethod;ILjava/lang/Object;)Ljava/util/List;
}

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-annotation-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,127 @@
@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
/**
* A set of [Patch]es.
*/
typealias PatchSet = Set<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.
* @param patchBundles A set of patches to initialize this instance with.
*/
sealed class PatchBundleLoader private constructor(
classLoader: ClassLoader,
patchBundles: Array<out File>,
getBinaryClassNames: (patchBundle: File) -> List<String>,
// 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)
init {
patchBundles.flatMap(getBinaryClassNames).asSequence().map {
classLoader.loadClass(it)
}.filter {
Patch::class.java.isAssignableFrom(it)
}.mapNotNull { patchClass ->
patchClass.getInstance(logger, silent = true)
}.filter {
it.name != null
}.let { patches ->
patchSet.addAll(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.
* @param silent Whether to suppress logging.
* @return The instantiated [Patch] or `null` if the [Patch] could not be instantiated.
*/
internal fun Class<*>.getInstance(logger: Logger, silent: Boolean = false): Patch<*>? {
return try {
getField("INSTANCE").get(null)
} catch (exception: NoSuchFieldException) {
if (!silent) logger.fine(
"Patch class '${name}' has no INSTANCE field, therefor not a singleton. " +
"Will try to instantiate it."
)
try {
getDeclaredConstructor().newInstance()
} catch (exception: Exception) {
if (!silent) 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>>

View File

@@ -0,0 +1,265 @@
package app.revanced.patcher
import app.revanced.patcher.PatchBundleLoader.Utils.getInstance
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint.Companion.resolveUsingLookupMap
import app.revanced.patcher.patch.*
import kotlinx.coroutines.flow.flow
import java.io.Closeable
import java.io.File
import java.util.function.Supplier
import java.util.logging.Logger
/**
* ReVanced Patcher.
*
* @param options The options for the patcher.
*/
class Patcher(
private val options: PatcherOptions
) : PatchExecutorFunction, PatchesConsumer, IntegrationsConsumer, Supplier<PatcherResult>, Closeable {
private val logger = Logger.getLogger(Patcher::class.java.name)
/**
* The context of ReVanced [Patcher].
* This holds the current state of the patcher.
*/
val context = PatcherContext(options)
init {
context.resourceContext.decodeResources(ResourceContext.ResourceDecodingMode.MANIFEST_ONLY)
}
// TODO: Fix circular dependency detection.
// /**
// * Add [Patch]es to ReVanced [Patcher].
// * It is not guaranteed that all supplied [Patch]es will be accepted, if an exception is thrown.
// *
// * @param patches The [Patch]es to add.
// * @throws PatcherException.CircularDependencyException If a circular dependency is detected.
// */
/**
* Add [Patch]es to ReVanced [Patcher].
*
* @param patches The [Patch]es to add.
*/
@Suppress("NAME_SHADOWING")
override fun acceptPatches(patches: List<Patch<*>>) {
/**
* Add dependencies of a [Patch] recursively to [PatcherContext.allPatches].
* If a [Patch] is already in [PatcherContext.allPatches], it will not be added again.
*/
fun PatchClass.putDependenciesRecursively() {
if (context.allPatches.contains(this)) return
val dependency = this.java.getInstance(logger)!!
context.allPatches[this] = dependency
dependency.dependencies?.forEach { it.putDependenciesRecursively() }
}
// Add all patches and their dependencies to the context.
for (patch in patches) context.executablePatches.putIfAbsent(patch::class, patch) ?: run {
context.allPatches[patch::class] = patch
patch.dependencies?.forEach { it.putDependenciesRecursively() }
}
/* TODO: Fix circular dependency detection.
val graph = mutableMapOf<PatchClass, MutableList<PatchClass>>()
fun PatchClass.visit() {
if (this in graph) return
val group = graph.getOrPut(this) { mutableListOf(this) }
val dependencies = context.allPatches[this]!!.manifest.dependencies ?: return
dependencies.forEach { dependency ->
if (group == graph[dependency])
throw PatcherException.CircularDependencyException(context.allPatches[this]!!.manifest.name)
graph[dependency] = group.apply { add(dependency) }
dependency.visit()
}
}
*/
/**
* Returns true if at least one patch or its dependencies matches the given predicate.
*
* @param predicate The predicate to match.
*/
fun Patch<*>.anyRecursively(predicate: (Patch<*>) -> Boolean): Boolean =
predicate(this) || dependencies?.any { dependency ->
context.allPatches[dependency]!!.anyRecursively(predicate)
} ?: false
context.allPatches.values.let { patches ->
// Determine, if resource patching is required.
for (patch in patches)
if (patch.anyRecursively { patch is ResourcePatch }) {
options.resourceDecodingMode = ResourceContext.ResourceDecodingMode.FULL
break
}
// Determine, if merging integrations is required.
for (patch in patches)
if (patch.anyRecursively { it.requiresIntegrations }) {
context.bytecodeContext.integrations.merge = true
break
}
}
}
/**
* Add integrations to the [Patcher].
*
* @param integrations The integrations to add. Must be a DEX file or container of DEX files.
*/
override fun acceptIntegrations(integrations: List<File>) {
context.bytecodeContext.integrations.addAll(integrations)
}
/**
* Execute [Patch]es that were added to ReVanced [Patcher].
*
* @param returnOnError If true, ReVanced [Patcher] will return immediately if a [Patch] fails.
* @return A pair of the name of the [Patch] and its [PatchResult].
*/
override fun apply(returnOnError: Boolean) = flow {
/**
* Execute a [Patch] and its dependencies recursively.
*
* @param patch The [Patch] to execute.
* @param executedPatches A map to prevent [Patch]es from being executed twice due to dependencies.
* @return The result of executing the [Patch].
*/
fun executePatch(
patch: Patch<*>,
executedPatches: LinkedHashMap<Patch<*>, PatchResult>
): PatchResult {
val patchName = patch.name ?: patch.toString()
executedPatches[patch]?.let { patchResult ->
patchResult.exception ?: return patchResult
// Return a new result with an exception indicating that the patch was not executed previously,
// because it is a dependency of another patch that failed.
return PatchResult(patch, PatchException("'$patchName' did not succeed previously"))
}
// Recursively execute all dependency patches.
patch.dependencies?.forEach { dependencyClass ->
val dependency = context.allPatches[dependencyClass]!!
val result = executePatch(dependency, executedPatches)
result.exception?.let {
return PatchResult(
patch,
PatchException(
"'$patchName' depends on '${dependency.name ?: dependency}' " +
"that raised an exception:\n${it.stackTraceToString()}"
)
)
}
}
return try {
// TODO: Implement this in a more polymorphic way.
when (patch) {
is BytecodePatch -> {
patch.fingerprints.resolveUsingLookupMap(context.bytecodeContext)
patch.execute(context.bytecodeContext)
}
is ResourcePatch -> {
patch.execute(context.resourceContext)
}
}
PatchResult(patch)
} catch (exception: PatchException) {
PatchResult(patch, exception)
} catch (exception: Exception) {
PatchResult(patch, PatchException(exception))
}.also { executedPatches[patch] = it }
}
if (context.bytecodeContext.integrations.merge) context.bytecodeContext.integrations.flush()
MethodFingerprint.initializeFingerprintResolutionLookupMaps(context.bytecodeContext)
// Prevent from decoding the app manifest twice if it is not needed.
if (options.resourceDecodingMode == ResourceContext.ResourceDecodingMode.FULL)
context.resourceContext.decodeResources(ResourceContext.ResourceDecodingMode.FULL)
logger.info("Executing patches")
val executedPatches = LinkedHashMap<Patch<*>, PatchResult>() // Key is name.
context.executablePatches.values.sortedBy { it.name }.forEach { patch ->
val patchResult = executePatch(patch, executedPatches)
// If the patch failed, emit the result, even if it is closeable.
// Results of executed patches that are closeable will be emitted later.
patchResult.exception?.let {
// Propagate exception to caller instead of wrapping it in a new exception.
emit(patchResult)
if (returnOnError) return@flow
} ?: run {
if (patch is Closeable) return@run
emit(patchResult)
}
}
executedPatches.values
.filter { it.exception == null }
.filter { it.patch is Closeable }.asReversed().forEach { executedPatch ->
val patch = executedPatch.patch
val result = try {
(patch as Closeable).close()
executedPatch
} catch (exception: PatchException) {
PatchResult(patch, exception)
} catch (exception: Exception) {
PatchResult(patch, PatchException(exception))
}
result.exception?.let {
emit(
PatchResult(
patch,
PatchException(
"'${patch.name}' raised an exception while being closed: ${it.stackTraceToString()}",
result.exception
)
)
)
if (returnOnError) return@flow
} ?: run {
patch.name ?: return@run
emit(result)
}
}
}
override fun close() = MethodFingerprint.clearFingerprintResolutionLookupMaps()
/**
* Compile and save the patched APK file.
*
* @return The [PatcherResult] containing the patched input files.
*/
override fun get() = PatcherResult(
context.bytecodeContext.get(),
context.resourceContext.get(),
context.packageMetadata.apkInfo.doNotCompress?.toList()
)
}

View File

@@ -0,0 +1,40 @@
package app.revanced.patcher
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.patch.Patch
import brut.androlib.apk.ApkInfo
import brut.directory.ExtFile
/**
* A context for ReVanced [Patcher].
*
* @param options The [PatcherOptions] used to create this context.
*/
class PatcherContext internal constructor(options: PatcherOptions) {
/**
* [PackageMetadata] of the supplied [PatcherOptions.inputFile].
*/
val packageMetadata = PackageMetadata(ApkInfo(ExtFile(options.inputFile)))
/**
* The map of [Patch]es associated by their [PatchClass].
*/
internal val executablePatches = mutableMapOf<PatchClass, Patch<*>>()
/**
* The map of all [Patch]es and their dependencies associated by their [PatchClass].
*/
internal val allPatches = mutableMapOf<PatchClass, Patch<*>>()
/**
* The [ResourceContext] of this [PatcherContext].
* This holds the current state of the resources.
*/
internal val resourceContext = ResourceContext(this, options)
/**
* The [BytecodeContext] of this [PatcherContext].
* This holds the current state of the bytecode.
*/
internal val bytecodeContext = BytecodeContext(options) }

View File

@@ -0,0 +1,16 @@
package app.revanced.patcher
/**
* An exception thrown by ReVanced [Patcher].
*
* @param errorMessage The exception message.
* @param cause The corresponding [Throwable].
*/
sealed class PatcherException(errorMessage: String?, cause: Throwable?) : Exception(errorMessage, cause) {
constructor(errorMessage: String) : this(errorMessage, null)
class CircularDependencyException internal constructor(dependant: String) : PatcherException(
"Patch '$dependant' causes a circular dependency"
)
}

View File

@@ -0,0 +1,73 @@
package app.revanced.patcher
import app.revanced.patcher.data.ResourceContext
import app.revanced.patcher.logging.impl.NopLogger
import brut.androlib.Config
import java.io.File
import java.util.logging.Logger
/**
* Options for ReVanced [Patcher].
* @param inputFile The input file to patch.
* @param resourceCachePath The path to the directory to use for caching resources.
* @param aaptBinaryPath The path to a custom aapt binary.
* @param frameworkFileDirectory The path to the directory to cache the framework file in.
* @param unusedLogger The logger to use for logging.
*/
data class PatcherOptions
@Deprecated("Use the constructor without the logger parameter instead")
constructor(
internal val inputFile: File,
internal val resourceCachePath: File = File("revanced-resource-cache"),
internal val aaptBinaryPath: String? = null,
internal val frameworkFileDirectory: String? = null,
internal val unusedLogger: app.revanced.patcher.logging.Logger = NopLogger
) {
private val logger = Logger.getLogger(PatcherOptions::class.java.name)
/**
* The mode to use for resource decoding.
* @see ResourceContext.ResourceDecodingMode
*/
internal var resourceDecodingMode = ResourceContext.ResourceDecodingMode.MANIFEST_ONLY
/**
* The configuration to use for resource decoding and compiling.
*/
internal val resourceConfig = Config.getDefaultConfig().apply {
useAapt2 = true
aaptPath = aaptBinaryPath ?: ""
frameworkDirectory = frameworkFileDirectory
}
/**
* Options for ReVanced [Patcher].
* @param inputFile The input file to patch.
* @param resourceCachePath The path to the directory to use for caching resources.
* @param aaptBinaryPath The path to a custom aapt binary.
* @param frameworkFileDirectory The path to the directory to cache the framework file in.
*/
constructor(
inputFile: File,
resourceCachePath: File = File("revanced-resource-cache"),
aaptBinaryPath: String? = null,
frameworkFileDirectory: String? = null,
) : this(
inputFile,
resourceCachePath,
aaptBinaryPath,
frameworkFileDirectory,
NopLogger
)
fun recreateResourceCacheDirectory() = resourceCachePath.also {
if (it.exists()) {
logger.info("Deleting existing resource cache directory")
if (!it.deleteRecursively())
logger.severe("Failed to delete existing resource cache directory")
}
it.mkdirs()
}
}

View File

@@ -0,0 +1,23 @@
package app.revanced.patcher
import java.io.File
import java.io.InputStream
/**
* The result of a patcher.
* @param dexFiles The patched dex files.
* @param resourceFile File containing resources that need to be extracted into the APK.
* @param doNotCompress List of relative paths of files to exclude from compressing.
*/
data class PatcherResult(
val dexFiles: List<PatchedDexFile>,
val resourceFile: File?,
val doNotCompress: List<String>? = null
) {
/**
* Wrapper for dex files.
* @param name The original name of the dex file.
* @param stream The dex file as [InputStream].
*/
class PatchedDexFile(val name: String, val stream: InputStream)
}

View File

@@ -0,0 +1,8 @@
package app.revanced.patcher
import app.revanced.patcher.patch.Patch
@FunctionalInterface
interface PatchesConsumer {
fun acceptPatches(patches: List<Patch<*>>)
}

View File

@@ -0,0 +1,157 @@
package app.revanced.patcher.data
import app.revanced.patcher.PatcherContext
import app.revanced.patcher.PatcherOptions
import app.revanced.patcher.PatcherResult
import app.revanced.patcher.patch.Patch
import app.revanced.patcher.util.ClassMerger.merge
import app.revanced.patcher.util.ProxyClassList
import app.revanced.patcher.util.method.MethodWalker
import app.revanced.patcher.util.proxy.ClassProxy
import com.android.tools.smali.dexlib2.Opcodes
import com.android.tools.smali.dexlib2.iface.ClassDef
import com.android.tools.smali.dexlib2.iface.DexFile
import com.android.tools.smali.dexlib2.iface.Method
import com.android.tools.smali.dexlib2.writer.io.MemoryDataStore
import lanchon.multidexlib2.BasicDexFileNamer
import lanchon.multidexlib2.DexIO
import lanchon.multidexlib2.MultiDexIO
import java.io.File
import java.io.Flushable
import java.util.logging.Logger
/**
* A context for bytecode.
* This holds the current state of the bytecode.
*
* @param options The [PatcherOptions] used to create this context.
*/
class BytecodeContext internal constructor(private val options: PatcherOptions) :
Context<List<PatcherResult.PatchedDexFile>> {
private val logger = Logger.getLogger(BytecodeContext::class.java.name)
/**
* [Opcodes] of the supplied [PatcherOptions.inputFile].
*/
internal lateinit var opcodes: Opcodes
/**
* The list of classes.
*/
val classes by lazy {
ProxyClassList(
MultiDexIO.readDexFile(
true, options.inputFile, BasicDexFileNamer(), null, null
).also { opcodes = it.opcodes }.classes.toMutableSet()
)
}
/**
* The [Integrations] of this [PatcherContext].
*/
internal val integrations = Integrations()
/**
* Find a class by a given class name.
*
* @param className The name of the class.
* @return A proxy for the first class that matches the class name.
*/
fun findClass(className: String) = findClass { it.type.contains(className) }
/**
* Find a class by a given predicate.
*
* @param predicate A predicate to match the class.
* @return A proxy for the first class that matches the predicate.
*/
fun findClass(predicate: (ClassDef) -> Boolean) =
// if we already proxied the class matching the predicate...
classes.proxies.firstOrNull { predicate(it.immutableClass) } ?:
// else resolve the class to a proxy and return it, if the predicate is matching a class
classes.find(predicate)?.let { proxy(it) }
/**
* Proxy a class.
* This will allow the class to be modified.
*
* @param classDef The class to proxy.
* @return A proxy for the class.
*/
fun proxy(classDef: ClassDef) = this.classes.proxies.find { it.immutableClass.type == classDef.type } ?: let {
ClassProxy(classDef).also { this.classes.add(it) }
}
/**
* Create a [MethodWalker] instance for the current [BytecodeContext].
*
* @param startMethod The method to start at.
* @return A [MethodWalker] instance.
*/
fun toMethodWalker(startMethod: Method) = MethodWalker(this, startMethod)
/**
* The integrations of a [PatcherContext].
*/
internal inner class Integrations : MutableList<File> by mutableListOf(), Flushable {
/**
* Whether to merge integrations.
* Set to true, if the field requiresIntegrations of any supplied [Patch] is true.
*/
var merge = false
/**
* Merge integrations into the [BytecodeContext] and flush all [Integrations].
*/
override fun flush() {
if (!merge) return
logger.info("Merging integrations")
val classMap = classes.associateBy { it.type }
this@Integrations.forEach { integrations ->
MultiDexIO.readDexFile(
true,
integrations, BasicDexFileNamer(),
null,
null
).classes.forEach classDef@{ classDef ->
val existingClass = classMap[classDef.type] ?: run {
logger.fine("Adding $classDef")
classes.add(classDef)
return@classDef
}
logger.fine("$classDef exists. Adding missing methods and fields.")
existingClass.merge(classDef, this@BytecodeContext).let { mergedClass ->
// If the class was merged, replace the original class with the merged class.
if (mergedClass === existingClass) return@let
classes.apply { remove(existingClass); add(mergedClass) }
}
}
}
clear()
}
}
/**
* Compile bytecode from the [BytecodeContext].
*
* @return The compiled bytecode.
*/
override fun get(): List<PatcherResult.PatchedDexFile> {
logger.info("Compiling modified dex files")
return mutableMapOf<String, MemoryDataStore>().apply {
MultiDexIO.writeDexFile(
true, -1, // Defaults to amount of available cores.
this, BasicDexFileNamer(), object : DexFile {
override fun getClasses() = this@BytecodeContext.classes.also(ProxyClassList::replaceClasses)
override fun getOpcodes() = this@BytecodeContext.opcodes
}, DexIO.DEFAULT_MAX_DEX_POOL_SIZE, null
)
}.map { PatcherResult.PatchedDexFile(it.key, it.value.readAt(0)) }
}
}

View File

@@ -0,0 +1,9 @@
package app.revanced.patcher.data
import java.util.function.Supplier
/**
* A common interface for contexts such as [ResourceContext] and [BytecodeContext].
*/
sealed interface Context<T> : Supplier<T>

View File

@@ -0,0 +1,170 @@
package app.revanced.patcher.data
import app.revanced.patcher.PatcherContext
import app.revanced.patcher.PatcherOptions
import app.revanced.patcher.util.DomFileEditor
import brut.androlib.AaptInvoker
import brut.androlib.ApkDecoder
import brut.androlib.apk.UsesFramework
import brut.androlib.res.Framework
import brut.androlib.res.ResourcesDecoder
import brut.androlib.res.decoder.AndroidManifestResourceParser
import brut.androlib.res.decoder.XmlPullStreamDecoder
import brut.androlib.res.xml.ResXmlPatcher
import brut.directory.ExtFile
import java.io.File
import java.io.InputStream
import java.io.OutputStream
import java.nio.file.Files
import java.util.logging.Logger
/**
* A context for resources.
* This holds the current state of the resources.
*
* @param context The [PatcherContext] to create the context for.
*/
class ResourceContext internal constructor(
private val context: PatcherContext,
private val options: PatcherOptions
) : Context<File?>, Iterable<File> {
private val logger = Logger.getLogger(ResourceContext::class.java.name)
val xmlEditor = XmlFileHolder()
/**
* Decode resources for the patcher.
*
* @param mode The [ResourceDecodingMode] to use when decoding.
*/
internal fun decodeResources(mode: ResourceDecodingMode) = with(context.packageMetadata.apkInfo) {
// Needed to decode resources.
val resourcesDecoder = ResourcesDecoder(options.resourceConfig, this)
when (mode) {
ResourceDecodingMode.FULL -> {
val outDir = options.recreateResourceCacheDirectory()
logger.info("Decoding resources")
resourcesDecoder.decodeResources(outDir)
resourcesDecoder.decodeManifest(outDir)
// Needed to record uncompressed files.
val apkDecoder = ApkDecoder(options.resourceConfig, this)
apkDecoder.recordUncompressedFiles(resourcesDecoder.resFileMapping)
usesFramework = UsesFramework().apply {
ids = resourcesDecoder.resTable.listFramePackages().map { it.id }
}
}
ResourceDecodingMode.MANIFEST_ONLY -> {
logger.info("Decoding app manifest")
// Decode manually instead of using resourceDecoder.decodeManifest
// because it does not support decoding to an OutputStream.
XmlPullStreamDecoder(
AndroidManifestResourceParser(resourcesDecoder.resTable),
resourcesDecoder.resXmlSerializer
).decodeManifest(
apkFile.directory.getFileInput("AndroidManifest.xml"),
// Older Android versions do not support OutputStream.nullOutputStream()
object : OutputStream() {
override fun write(b: Int) { /* do nothing */
}
}
)
// Get the package name and version from the manifest using the XmlPullStreamDecoder.
// XmlPullStreamDecoder.decodeManifest() sets metadata.apkInfo.
context.packageMetadata.let { metadata ->
metadata.packageName = resourcesDecoder.resTable.packageRenamed
versionInfo.let {
metadata.packageVersion = it.versionName ?: it.versionCode
}
/*
The ResTable if flagged as sparse if the main package is not loaded, which is the case here,
because ResourcesDecoder.decodeResources loads the main package
and not XmlPullStreamDecoder.decodeManifest.
See ARSCDecoder.readTableType for more info.
Set this to false again to prevent the ResTable from being flagged as sparse falsely.
*/
metadata.apkInfo.sparseResources = false
}
}
}
}
operator fun get(path: String) = options.resourceCachePath.resolve(path)
override fun iterator() = options.resourceCachePath.walkTopDown().iterator()
/**
* Compile resources from the [ResourceContext].
*
* @return The compiled resources.
*/
override fun get(): File? {
var resourceFile: File? = null
if (options.resourceDecodingMode == ResourceDecodingMode.FULL) {
logger.info("Compiling modified resources")
val cacheDirectory = ExtFile(options.resourceCachePath)
val aaptFile = cacheDirectory.resolve("aapt_temp_file").also {
Files.deleteIfExists(it.toPath())
}.also { resourceFile = it }
try {
AaptInvoker(
options.resourceConfig, context.packageMetadata.apkInfo
).invokeAapt(aaptFile,
cacheDirectory.resolve("AndroidManifest.xml").also {
ResXmlPatcher.fixingPublicAttrsInProviderAttributes(it)
},
cacheDirectory.resolve("res"),
null,
null,
context.packageMetadata.apkInfo.usesFramework.let { usesFramework ->
usesFramework.ids.map { id ->
Framework(options.resourceConfig).getFrameworkApk(id, usesFramework.tag)
}.toTypedArray()
})
} finally {
cacheDirectory.close()
}
}
return resourceFile
}
/**
* The type of decoding the resources.
*/
internal enum class ResourceDecodingMode {
/**
* Decode all resources.
*/
FULL,
/**
* Decode the manifest file only.
*/
MANIFEST_ONLY,
}
inner class XmlFileHolder {
operator fun get(inputStream: InputStream) =
DomFileEditor(inputStream)
operator fun get(path: String): DomFileEditor {
return DomFileEditor(this@ResourceContext[path])
}
}
}

View File

@@ -0,0 +1,33 @@
package app.revanced.patcher.extensions
import kotlin.reflect.KClass
internal object AnnotationExtensions {
/**
* Recursively find a given annotation on a class.
*
* @param targetAnnotation The annotation to find.
* @return The annotation.
*/
fun <T : Annotation> Class<*>.findAnnotationRecursively(targetAnnotation: KClass<T>): T? {
fun <T : Annotation> Class<*>.findAnnotationRecursively(
targetAnnotation: Class<T>, traversed: MutableSet<Annotation>
): T? {
val found = this.annotations.firstOrNull { it.annotationClass.java.name == targetAnnotation.name }
@Suppress("UNCHECKED_CAST") if (found != null) return found as T
for (annotation in this.annotations) {
if (traversed.contains(annotation)) continue
traversed.add(annotation)
return (annotation.annotationClass.java.findAnnotationRecursively(targetAnnotation, traversed))
?: continue
}
return null
}
return this.findAnnotationRecursively(targetAnnotation.java, mutableSetOf())
}
}

View File

@@ -0,0 +1,33 @@
package app.revanced.patcher.extensions
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import com.android.tools.smali.dexlib2.AccessFlags
/**
* Create a label for the instruction at given index.
*
* @param index The index to create the label for the instruction at.
* @return The label.
*/
fun MutableMethod.newLabel(index: Int) = implementation!!.newLabelForIndex(index)
/**
* Perform a bitwise OR operation between two [AccessFlags].
*
* @param other The other [AccessFlags] to perform the operation with.
*/
infix fun AccessFlags.or(other: AccessFlags) = value or other.value
/**
* Perform a bitwise OR operation between an [AccessFlags] and an [Int].
*
* @param other The [Int] to perform the operation with.
*/
infix fun Int.or(other: AccessFlags) = this or other.value
/**
* Perform a bitwise OR operation between an [Int] and an [AccessFlags].
*
* @param other The [AccessFlags] to perform the operation with.
*/
infix fun AccessFlags.or(other: Int) = value or other

View File

@@ -0,0 +1,330 @@
package app.revanced.patcher.extensions
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patcher.util.smali.ExternalLabel
import app.revanced.patcher.util.smali.toInstruction
import app.revanced.patcher.util.smali.toInstructions
import com.android.tools.smali.dexlib2.builder.BuilderInstruction
import com.android.tools.smali.dexlib2.builder.BuilderOffsetInstruction
import com.android.tools.smali.dexlib2.builder.Label
import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation
import com.android.tools.smali.dexlib2.builder.instruction.*
import com.android.tools.smali.dexlib2.iface.instruction.Instruction
object InstructionExtensions {
/**
* Add instructions to a method at the given index.
*
* @param index The index to add the instructions at.
* @param instructions The instructions to add.
*/
fun MutableMethodImplementation.addInstructions(
index: Int,
instructions: List<BuilderInstruction>
) = instructions.asReversed().forEach { addInstruction(index, it) }
/**
* Add instructions to a method.
* The instructions will be added at the end of the method.
*
* @param instructions The instructions to add.
*/
fun MutableMethodImplementation.addInstructions(instructions: List<BuilderInstruction>) =
instructions.forEach { this.addInstruction(it) }
/**
* Remove instructions from a method at the given index.
*
* @param index The index to remove the instructions at.
* @param count The amount of instructions to remove.
*/
fun MutableMethodImplementation.removeInstructions(index: Int, count: Int) = repeat(count) {
removeInstruction(index)
}
/**
* Remove the first instructions from a method.
*
* @param count The amount of instructions to remove.
*/
fun MutableMethodImplementation.removeInstructions(count: Int) = removeInstructions(0, count)
/**
* Replace instructions at the given index with the given instructions.
* The amount of instructions to replace is the amount of instructions in the given list.
*
* @param index The index to replace the instructions at.
* @param instructions The instructions to replace the instructions with.
*/
fun MutableMethodImplementation.replaceInstructions(index: Int, instructions: List<BuilderInstruction>) {
// Remove the instructions at the given index.
removeInstructions(index, instructions.size)
// Add the instructions at the given index.
addInstructions(index, instructions)
}
/**
* Add an instruction to a method at the given index.
*
* @param index The index to add the instruction at.
* @param instruction The instruction to add.
*/
fun MutableMethod.addInstruction(index: Int, instruction: BuilderInstruction) =
implementation!!.addInstruction(index, instruction)
/**
* Add an instruction to a method.
*
* @param instruction The instructions to add.
*/
fun MutableMethod.addInstruction(instruction: BuilderInstruction) =
implementation!!.addInstruction(instruction)
/**
* Add an instruction to a method at the given index.
*
* @param index The index to add the instruction at.
* @param smaliInstructions The instruction to add.
*/
fun MutableMethod.addInstruction(index: Int, smaliInstructions: String) =
implementation!!.addInstruction(index, smaliInstructions.toInstruction(this))
/**
* Add an instruction to a method.
*
* @param smaliInstructions The instruction to add.
*/
fun MutableMethod.addInstruction(smaliInstructions: String) =
implementation!!.addInstruction(smaliInstructions.toInstruction(this))
/**
* Add instructions to a method at the given index.
*
* @param index The index to add the instructions at.
* @param instructions The instructions to add.
*/
fun MutableMethod.addInstructions(index: Int, instructions: List<BuilderInstruction>) =
implementation!!.addInstructions(index, instructions)
/**
* Add instructions to a method.
*
* @param instructions The instructions to add.
*/
fun MutableMethod.addInstructions(instructions: List<BuilderInstruction>) =
implementation!!.addInstructions(instructions)
/**
* Add instructions to a method.
*
* @param smaliInstructions The instructions to add.
*/
fun MutableMethod.addInstructions(index: Int, smaliInstructions: String) =
implementation!!.addInstructions(index, smaliInstructions.toInstructions(this))
/**
* Add instructions to a method.
*
* @param smaliInstructions The instructions to add.
*/
fun MutableMethod.addInstructions(smaliInstructions: String) =
implementation!!.addInstructions(smaliInstructions.toInstructions(this))
/**
* Add instructions to a method at the given index.
*
* @param index The index to add the instructions at.
* @param smaliInstructions The instructions to add.
* @param externalLabels A list of [ExternalLabel] for instructions outside of [smaliInstructions].
*/
// Special function for adding instructions with external labels.
fun MutableMethod.addInstructionsWithLabels(
index: Int,
smaliInstructions: String,
vararg externalLabels: ExternalLabel
) {
// Create reference dummy instructions for the instructions.
val nopSmali = StringBuilder(smaliInstructions).also { builder ->
externalLabels.forEach { (name, _) ->
builder.append("\n:$name\nnop")
}
}.toString()
// Compile the instructions with the dummy labels
val compiledInstructions = nopSmali.toInstructions(this)
// Add the compiled list of instructions to the method.
addInstructions(
index,
compiledInstructions.subList(0, compiledInstructions.size - externalLabels.size)
)
implementation!!.apply {
this@apply.instructions.subList(index, index + compiledInstructions.size - externalLabels.size)
.forEachIndexed { compiledInstructionIndex, compiledInstruction ->
// If the compiled instruction is not an offset instruction, skip it.
if (compiledInstruction !is BuilderOffsetInstruction) return@forEachIndexed
/**
* Creates a new label for the instruction
* and replaces it with the label of the [compiledInstruction] at [compiledInstructionIndex].
*/
fun Instruction.makeNewLabel() {
fun replaceOffset(
i: BuilderOffsetInstruction, label: Label
): BuilderOffsetInstruction {
return when (i) {
is BuilderInstruction10t -> BuilderInstruction10t(i.opcode, label)
is BuilderInstruction20t -> BuilderInstruction20t(i.opcode, label)
is BuilderInstruction21t -> BuilderInstruction21t(i.opcode, i.registerA, label)
is BuilderInstruction22t -> BuilderInstruction22t(
i.opcode,
i.registerA,
i.registerB,
label
)
is BuilderInstruction30t -> BuilderInstruction30t(i.opcode, label)
is BuilderInstruction31t -> BuilderInstruction31t(i.opcode, i.registerA, label)
else -> throw IllegalStateException(
"A non-offset instruction was given, this should never happen!"
)
}
}
// Create the final label.
val label = newLabelForIndex(this@apply.instructions.indexOf(this))
// Create the final instruction with the new label.
val newInstruction = replaceOffset(
compiledInstruction, label
)
// Replace the instruction pointing to the dummy label
// with the new instruction pointing to the real instruction.
replaceInstruction(index + compiledInstructionIndex, newInstruction)
}
// If the compiled instruction targets its own instruction,
// which means it points to some of its own, simply an offset has to be applied.
val labelIndex = compiledInstruction.target.location.index
if (labelIndex < compiledInstructions.size - externalLabels.size) {
// Get the targets index (insertion index + the index of the dummy instruction).
this.instructions[index + labelIndex].makeNewLabel()
return@forEachIndexed
}
// Since the compiled instruction points to a dummy instruction,
// we can find the real instruction which it was created for by calculation.
// Get the index of the instruction in the externalLabels list
// which the dummy instruction was created for.
// This works because we created the dummy instructions in the same order as the externalLabels list.
val (_, instruction) = externalLabels[(compiledInstructions.size - 1) - labelIndex]
instruction.makeNewLabel()
}
}
}
/**
* Remove an instruction at the given index.
*
* @param index The index to remove the instruction at.
*/
fun MutableMethod.removeInstruction(index: Int) =
implementation!!.removeInstruction(index)
/**
* Remove instructions at the given index.
*
* @param index The index to remove the instructions at.
* @param count The amount of instructions to remove.
*/
fun MutableMethod.removeInstructions(index: Int, count: Int) =
implementation!!.removeInstructions(index, count)
/**
* Remove instructions at the given index.
*
* @param count The amount of instructions to remove.
*/
fun MutableMethod.removeInstructions(count: Int) =
implementation!!.removeInstructions(count)
/**
* Replace an instruction at the given index.
*
* @param index The index to replace the instruction at.
* @param instruction The instruction to replace the instruction with.
*/
fun MutableMethod.replaceInstruction(index: Int, instruction: BuilderInstruction) =
implementation!!.replaceInstruction(index, instruction)
/**
* Replace an instruction at the given index.
*
* @param index The index to replace the instruction at.
* @param smaliInstruction The smali instruction to replace the instruction with.
*/
fun MutableMethod.replaceInstruction(index: Int, smaliInstruction: String) =
implementation!!.replaceInstruction(index, smaliInstruction.toInstruction(this))
/**
* Replace instructions at the given index.
*
* @param index The index to replace the instructions at.
* @param instructions The instructions to replace the instructions with.
*/
fun MutableMethod.replaceInstructions(index: Int, instructions: List<BuilderInstruction>) =
implementation!!.replaceInstructions(index, instructions)
/**
* Replace instructions at the given index.
*
* @param index The index to replace the instructions at.
* @param smaliInstructions The smali instructions to replace the instructions with.
*/
fun MutableMethod.replaceInstructions(index: Int, smaliInstructions: String) =
implementation!!.replaceInstructions(index, smaliInstructions.toInstructions(this))
/**
* Get an instruction at the given index.
*
* @param index The index to get the instruction at.
* @return The instruction.
*/
fun MutableMethodImplementation.getInstruction(index: Int): BuilderInstruction = instructions[index]
/**
* Get an instruction at the given index.
*
* @param index The index to get the instruction at.
* @param T The type of instruction to return.
* @return The instruction.
*/
@Suppress("UNCHECKED_CAST")
fun <T> MutableMethodImplementation.getInstruction(index: Int): T = getInstruction(index) as T
/**
* Get an instruction at the given index.
* @param index The index to get the instruction at.
* @return The instruction.
*/
fun MutableMethod.getInstruction(index: Int): BuilderInstruction = implementation!!.getInstruction(index)
/**
* Get an instruction at the given index.
* @param index The index to get the instruction at.
* @param T The type of instruction to return.
* @return The instruction.
*/
fun <T> MutableMethod.getInstruction(index: Int): T = implementation!!.getInstruction<T>(index)
/**
* Get the instructions of a method.
* @return The instructions.
*/
fun MutableMethod.getInstructions(): MutableList<BuilderInstruction> = implementation!!.instructions
}

View File

@@ -0,0 +1,14 @@
package app.revanced.patcher.extensions
import app.revanced.patcher.extensions.AnnotationExtensions.findAnnotationRecursively
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
object MethodFingerprintExtensions {
// TODO: Make this a property.
/**
* The [FuzzyPatternScanMethod] annotation of a [MethodFingerprint].
*/
val MethodFingerprint.fuzzyPatternScanMethod
get() = javaClass.findAnnotationRecursively(FuzzyPatternScanMethod::class)
}

View File

@@ -7,7 +7,6 @@ import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
* @param threshold if [threshold] or more of the opcodes do not match, skip.
*/
@Target(AnnotationTarget.CLASS)
@Retention(AnnotationRetention.RUNTIME)
annotation class FuzzyPatternScanMethod(
val threshold: Int = 1
)

View File

@@ -0,0 +1,513 @@
package app.revanced.patcher.fingerprint.method.impl
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.MethodFingerprintExtensions.fuzzyPatternScanMethod
import app.revanced.patcher.fingerprint.Fingerprint
import app.revanced.patcher.fingerprint.method.annotation.FuzzyPatternScanMethod
import app.revanced.patcher.patch.PatchException
import app.revanced.patcher.util.proxy.ClassProxy
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.Opcode
import com.android.tools.smali.dexlib2.iface.ClassDef
import com.android.tools.smali.dexlib2.iface.Method
import com.android.tools.smali.dexlib2.iface.instruction.Instruction
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
import com.android.tools.smali.dexlib2.iface.reference.StringReference
import com.android.tools.smali.dexlib2.util.MethodUtil
import java.util.*
private typealias StringMatch = MethodFingerprintResult.MethodFingerprintScanResult.StringsScanResult.StringMatch
private typealias StringsScanResult = MethodFingerprintResult.MethodFingerprintScanResult.StringsScanResult
private typealias MethodClassPair = Pair<Method, ClassDef>
/**
* A fingerprint to resolve methods.
*
* @param returnType The method's return type compared using [String.startsWith].
* @param accessFlags The method's exact access flags using values of [AccessFlags].
* @param parameters The parameters of the method. Partial matches allowed and follow the same rules as [returnType].
* @param opcodes An opcode pattern of the method's instructions. Wildcard or unknown opcodes can be specified by `null`.
* @param strings A list of the method's strings compared each using [String.contains].
* @param customFingerprint A custom condition for this fingerprint.
*/
abstract class MethodFingerprint(
internal val returnType: String? = null,
internal val accessFlags: Int? = null,
internal val parameters: Iterable<String>? = null,
internal val opcodes: Iterable<Opcode?>? = null,
internal val strings: Iterable<String>? = null,
internal val customFingerprint: ((methodDef: Method, classDef: ClassDef) -> Boolean)? = null
) : Fingerprint {
/**
* The result of the [MethodFingerprint].
*/
var result: MethodFingerprintResult? = null
companion object {
/**
* A list of methods and the class they were found in.
*/
private val methods = mutableListOf<MethodClassPair>()
/**
* Lookup map for methods keyed to the methods access flags, return type and parameter.
*/
private val methodSignatureLookupMap = mutableMapOf<String, MutableList<MethodClassPair>>()
/**
* Lookup map for methods keyed to the strings contained in the method.
*/
private val methodStringsLookupMap = mutableMapOf<String, MutableList<MethodClassPair>>()
/**
* Appends a string based on the parameter reference types of this method.
*/
private fun StringBuilder.appendParameters(parameters: Iterable<CharSequence>) {
// Maximum parameters to use in the signature key.
// Some apps have methods with an incredible number of parameters (over 100 parameters have been seen).
// To keep the signature map from becoming needlessly bloated,
// group together in the same map entry all methods with the same access/return and 5 or more parameters.
// The value of 5 was chosen based on local performance testing and is not set in stone.
val maxSignatureParameters = 5
// Must append a unique value before the parameters to distinguish this key includes the parameters.
// If this is not appended, then methods with no parameters
// will collide with different keys that specify access/return but omit the parameters.
append("p:")
parameters.forEachIndexed { index, parameter ->
if (index >= maxSignatureParameters) return
append(parameter.first())
}
}
/**
* Initializes lookup maps for [MethodFingerprint] resolution
* using attributes of methods such as the method signature or strings.
*
* @param context The [BytecodeContext] containing the classes to initialize the lookup maps with.
*/
internal fun initializeFingerprintResolutionLookupMaps(context: BytecodeContext) {
fun MutableMap<String, MutableList<MethodClassPair>>.add(
key: String,
methodClassPair: MethodClassPair
) {
var methodClassPairs = this[key]
methodClassPairs ?: run {
methodClassPairs = LinkedList<MethodClassPair>().also { this[key] = it }
}
methodClassPairs!!.add(methodClassPair)
}
if (methods.isNotEmpty()) clearFingerprintResolutionLookupMaps()
context.classes.forEach { classDef ->
classDef.methods.forEach { method ->
val methodClassPair = method to classDef
// For fingerprints with no access or return type specified.
methods += methodClassPair
val accessFlagsReturnKey = method.accessFlags.toString() + method.returnType.first()
// Add <access><returnType> as the key.
methodSignatureLookupMap.add(accessFlagsReturnKey, methodClassPair)
// Add <access><returnType>[parameters] as the key.
methodSignatureLookupMap.add(
buildString {
append(accessFlagsReturnKey)
appendParameters(method.parameterTypes)
},
methodClassPair
)
// Add strings contained in the method as the key.
method.implementation?.instructions?.forEach instructions@{ instruction ->
if (instruction.opcode != Opcode.CONST_STRING && instruction.opcode != Opcode.CONST_STRING_JUMBO)
return@instructions
val string = ((instruction as ReferenceInstruction).reference as StringReference).string
methodStringsLookupMap.add(string, methodClassPair)
}
// In the future, the class type could be added to the lookup map.
// This would require MethodFingerprint to be changed to include the class type.
}
}
}
/**
* Clears the internal lookup maps created in [initializeFingerprintResolutionLookupMaps]
*/
internal fun clearFingerprintResolutionLookupMaps() {
methods.clear()
methodSignatureLookupMap.clear()
methodStringsLookupMap.clear()
}
/**
* Resolve a list of [MethodFingerprint] using the lookup map built by [initializeFingerprintResolutionLookupMaps].
*
* [MethodFingerprint] resolution is fast, but if many are present they can consume a noticeable
* amount of time because they are resolved in sequence.
*
* For apps with many fingerprints, resolving performance can be improved by:
* - Slowest: Specify [opcodes] and nothing else.
* - Fast: Specify [accessFlags], [returnType].
* - Faster: Specify [accessFlags], [returnType] and [parameters].
* - Fastest: Specify [strings], with at least one string being an exact (non-partial) match.
*/
internal fun Set<MethodFingerprint>.resolveUsingLookupMap(context: BytecodeContext) {
if (methods.isEmpty()) throw PatchException("lookup map not initialized")
forEach { fingerprint ->
fingerprint.resolveUsingLookupMap(context)
}
}
/**
* Resolve a [MethodFingerprint] using the lookup map built by [initializeFingerprintResolutionLookupMaps].
*
* [MethodFingerprint] resolution is fast, but if many are present they can consume a noticeable
* amount of time because they are resolved in sequence.
*
* For apps with many fingerprints, resolving performance can be improved by:
* - Slowest: Specify [opcodes] and nothing else.
* - Fast: Specify [accessFlags], [returnType].
* - Faster: Specify [accessFlags], [returnType] and [parameters].
* - Fastest: Specify [strings], with at least one string being an exact (non-partial) match.
*/
internal fun MethodFingerprint.resolveUsingLookupMap(context: BytecodeContext): Boolean {
/**
* Lookup [MethodClassPair]s that match the methods strings present in a [MethodFingerprint].
*
* @return A list of [MethodClassPair]s that match the methods strings present in a [MethodFingerprint].
*/
fun MethodFingerprint.methodStringsLookup(): List<MethodClassPair>? {
strings?.forEach {
val methods = methodStringsLookupMap[it]
if (methods != null) return methods
}
return null
}
/**
* Lookup [MethodClassPair]s that match the method signature present in a [MethodFingerprint].
*
* @return A list of [MethodClassPair]s that match the method signature present in a [MethodFingerprint].
*/
fun MethodFingerprint.methodSignatureLookup(): List<MethodClassPair> {
if (accessFlags == null) return methods
var returnTypeValue = returnType
if (returnTypeValue == null) {
if (AccessFlags.CONSTRUCTOR.isSet(accessFlags)) {
// Constructors always have void return type
returnTypeValue = "V"
} else {
return methods
}
}
val key = buildString {
append(accessFlags)
append(returnTypeValue.first())
if (parameters != null) appendParameters(parameters)
}
return methodSignatureLookupMap[key] ?: return emptyList()
}
/**
* Resolve a [MethodFingerprint] using a list of [MethodClassPair].
*
* @return True if the resolution was successful, false otherwise.
*/
fun MethodFingerprint.resolveUsingMethodClassPair(classMethods: Iterable<MethodClassPair>): Boolean {
classMethods.forEach { classAndMethod ->
if (resolve(context, classAndMethod.first, classAndMethod.second)) return true
}
return false
}
val methodsWithSameStrings = methodStringsLookup()
if (methodsWithSameStrings != null) if (resolveUsingMethodClassPair(methodsWithSameStrings)) return true
// No strings declared or none matched (partial matches are allowed).
// Use signature matching.
return resolveUsingMethodClassPair(methodSignatureLookup())
}
/**
* Resolve a list of [MethodFingerprint] against a list of [ClassDef].
*
* @param classes The classes on which to resolve the [MethodFingerprint] in.
* @param context The [BytecodeContext] to host proxies.
* @return True if the resolution was successful, false otherwise.
*/
fun Iterable<MethodFingerprint>.resolve(context: BytecodeContext, classes: Iterable<ClassDef>) {
for (fingerprint in this) // For each fingerprint...
classes@ for (classDef in classes) // ...search through all classes for the MethodFingerprint
if (fingerprint.resolve(context, classDef))
break@classes // ...if the resolution succeeded, continue with the next MethodFingerprint.
}
/**
* Resolve a [MethodFingerprint] against a [ClassDef].
*
* @param forClass The class on which to resolve the [MethodFingerprint] in.
* @param context The [BytecodeContext] to host proxies.
* @return True if the resolution was successful, false otherwise.
*/
fun MethodFingerprint.resolve(context: BytecodeContext, forClass: ClassDef): Boolean {
for (method in forClass.methods)
if (this.resolve(context, method, forClass))
return true
return false
}
/**
* Resolve a [MethodFingerprint] against a [Method].
*
* @param method The class on which to resolve the [MethodFingerprint] in.
* @param forClass The class on which to resolve the [MethodFingerprint].
* @param context The [BytecodeContext] to host proxies.
* @return True if the resolution was successful or if the fingerprint is already resolved, false otherwise.
*/
fun MethodFingerprint.resolve(context: BytecodeContext, method: Method, forClass: ClassDef): Boolean {
val methodFingerprint = this
if (methodFingerprint.result != null) return true
if (methodFingerprint.returnType != null && !method.returnType.startsWith(methodFingerprint.returnType))
return false
if (methodFingerprint.accessFlags != null && methodFingerprint.accessFlags != method.accessFlags)
return false
fun parametersEqual(
parameters1: Iterable<CharSequence>, parameters2: Iterable<CharSequence>
): Boolean {
if (parameters1.count() != parameters2.count()) return false
val iterator1 = parameters1.iterator()
parameters2.forEach {
if (!it.startsWith(iterator1.next())) return false
}
return true
}
if (methodFingerprint.parameters != null && !parametersEqual(
methodFingerprint.parameters, // TODO: parseParameters()
method.parameterTypes
)
) return false
@Suppress("UNNECESSARY_NOT_NULL_ASSERTION")
if (methodFingerprint.customFingerprint != null && !methodFingerprint.customFingerprint!!(method, forClass))
return false
val stringsScanResult: StringsScanResult? =
if (methodFingerprint.strings != null) {
StringsScanResult(
buildList {
val implementation = method.implementation ?: return false
val stringsList = methodFingerprint.strings.toMutableList()
implementation.instructions.forEachIndexed { instructionIndex, instruction ->
if (
instruction.opcode != Opcode.CONST_STRING &&
instruction.opcode != Opcode.CONST_STRING_JUMBO
) return@forEachIndexed
val string = ((instruction as ReferenceInstruction).reference as StringReference).string
val index = stringsList.indexOfFirst(string::contains)
if (index == -1) return@forEachIndexed
add(
StringMatch(
string,
instructionIndex
)
)
stringsList.removeAt(index)
}
if (stringsList.isNotEmpty()) return false
}
)
} else null
val patternScanResult = if (methodFingerprint.opcodes != null) {
method.implementation?.instructions ?: return false
fun Method.patternScan(
fingerprint: MethodFingerprint
): MethodFingerprintResult.MethodFingerprintScanResult.PatternScanResult? {
val instructions = this.implementation!!.instructions
val fingerprintFuzzyPatternScanThreshold = fingerprint.fuzzyPatternScanMethod?.threshold ?: 0
val pattern = fingerprint.opcodes!!
val instructionLength = instructions.count()
val patternLength = pattern.count()
for (index in 0 until instructionLength) {
var patternIndex = 0
var threshold = fingerprintFuzzyPatternScanThreshold
while (index + patternIndex < instructionLength) {
val originalOpcode = instructions.elementAt(index + patternIndex).opcode
val patternOpcode = pattern.elementAt(patternIndex)
if (patternOpcode != null && patternOpcode.ordinal != originalOpcode.ordinal) {
// reaching maximum threshold (0) means,
// the pattern does not match to the current instructions
if (threshold-- == 0) break
}
if (patternIndex < patternLength - 1) {
// if the entire pattern has not been scanned yet
// continue the scan
patternIndex++
continue
}
// the pattern is valid, generate warnings if fuzzyPatternScanMethod is FuzzyPatternScanMethod
val result =
MethodFingerprintResult.MethodFingerprintScanResult.PatternScanResult(
index,
index + patternIndex
)
if (fingerprint.fuzzyPatternScanMethod !is FuzzyPatternScanMethod) return result
result.warnings = result.createWarnings(pattern, instructions)
return result
}
}
return null
}
method.patternScan(methodFingerprint) ?: return false
} else null
methodFingerprint.result = MethodFingerprintResult(
method,
forClass,
MethodFingerprintResult.MethodFingerprintScanResult(
patternScanResult,
stringsScanResult
),
context
)
return true
}
private fun MethodFingerprintResult.MethodFingerprintScanResult.PatternScanResult.createWarnings(
pattern: Iterable<Opcode?>, instructions: Iterable<Instruction>
) = buildList {
for ((patternIndex, instructionIndex) in (this@createWarnings.startIndex until this@createWarnings.endIndex).withIndex()) {
val originalOpcode = instructions.elementAt(instructionIndex).opcode
val patternOpcode = pattern.elementAt(patternIndex)
if (patternOpcode == null || patternOpcode.ordinal == originalOpcode.ordinal) continue
this.add(
MethodFingerprintResult.MethodFingerprintScanResult.PatternScanResult.Warning(
originalOpcode,
patternOpcode,
instructionIndex,
patternIndex
)
)
}
}
}
}
/**
* Represents the result of a [MethodFingerprintResult].
*
* @param method The matching method.
* @param classDef The [ClassDef] that contains the matching [method].
* @param scanResult The result of scanning for the [MethodFingerprint].
* @param context The [BytecodeContext] this [MethodFingerprintResult] is attached to, to create proxies.
*/
data class MethodFingerprintResult(
val method: Method,
val classDef: ClassDef,
val scanResult: MethodFingerprintScanResult,
internal val context: BytecodeContext
) {
/**
* Returns a mutable clone of [classDef]
*
* Please note, this method allocates a [ClassProxy].
* Use [classDef] where possible.
*/
@Suppress("MemberVisibilityCanBePrivate")
val mutableClass by lazy { context.proxy(classDef).mutableClass }
/**
* Returns a mutable clone of [method]
*
* Please note, this method allocates a [ClassProxy].
* Use [method] where possible.
*/
val mutableMethod by lazy {
mutableClass.methods.first {
MethodUtil.methodSignaturesMatch(it, this.method)
}
}
/**
* The result of scanning on the [MethodFingerprint].
* @param patternScanResult The result of the pattern scan.
* @param stringsScanResult The result of the string scan.
*/
data class MethodFingerprintScanResult(
val patternScanResult: PatternScanResult?,
val stringsScanResult: StringsScanResult?
) {
/**
* The result of scanning strings on the [MethodFingerprint].
* @param matches The list of strings that were matched.
*/
data class StringsScanResult(val matches: List<StringMatch>) {
/**
* Represents a match for a string at an index.
* @param string The string that was matched.
* @param index The index of the string.
*/
data class StringMatch(val string: String, val index: Int)
}
/**
* The result of a pattern scan.
* @param startIndex The start index of the instructions where to which this pattern matches.
* @param endIndex The end index of the instructions where to which this pattern matches.
* @param warnings A list of warnings considering this [PatternScanResult].
*/
data class PatternScanResult(
val startIndex: Int,
val endIndex: Int,
var warnings: List<Warning>? = null
) {
/**
* Represents warnings of the pattern scan.
* @param correctOpcode The opcode the instruction list has.
* @param wrongOpcode The opcode the pattern list of the signature currently has.
* @param instructionIndex The index of the opcode relative to the instruction list.
* @param patternIndex The index of the opcode relative to the pattern list from the signature.
*/
data class Warning(
val correctOpcode: Opcode,
val wrongOpcode: Opcode,
val instructionIndex: Int,
val patternIndex: Int,
)
}
}
}

View File

@@ -1,5 +1,6 @@
package app.revanced.patcher.logging
@Deprecated("This will be removed in a future release")
interface Logger {
fun error(msg: String) {}
fun warn(msg: String) {}

View File

@@ -2,4 +2,5 @@ package app.revanced.patcher.logging.impl
import app.revanced.patcher.logging.Logger
@Deprecated("This will be removed in a future release")
object NopLogger : Logger

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

@@ -0,0 +1,71 @@
@file:Suppress("MemberVisibilityCanBePrivate")
package app.revanced.patcher.patch
import app.revanced.patcher.PatchClass
import app.revanced.patcher.Patcher
import app.revanced.patcher.data.Context
import app.revanced.patcher.patch.options.PatchOptions
import java.io.Closeable
/**
* A ReVanced patch.
*
* If an implementation of [Patch] also implements [Closeable]
* it will be closed in reverse execution order of patches executed by ReVanced [Patcher].
*
* @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.
* @param T The [Context] type this patch will work on.
*/
sealed class Patch<out T : Context<*>>(
val name: String? = null,
val description: String? = null,
val compatiblePackages: Set<CompatiblePackage>? = null,
val dependencies: Set<PatchClass>? = null,
val use: Boolean = true,
// TODO: Remove this property, once integrations are coupled with patches.
val requiresIntegrations: Boolean = false,
) {
/**
* The options of the patch associated by the options key.
*/
val options = PatchOptions()
/**
* The execution function of the patch.
*
* @param context The [Context] the patch will work on.
* @return The result of executing the patch.
*/
abstract fun execute(context: @UnsafeVariance T)
override fun hashCode() = name.hashCode()
override fun toString() = name ?: this::class.simpleName ?: "Unnamed patch"
override fun equals(other: Any?): Boolean {
if (this === other) return true
if (javaClass != other?.javaClass) return false
other as Patch<*>
return name == other.name
}
/**
* A package a [Patch] is compatible with.
*
* @param name The name of the package.
* @param versions The versions of the package.
*/
class CompatiblePackage(
val name: String,
val versions: Set<String>? = null,
)
}

View File

@@ -0,0 +1,12 @@
package app.revanced.patcher.patch
/**
* An exception thrown when patching.
*
* @param errorMessage The exception message.
* @param cause The corresponding [Throwable].
*/
class PatchException(errorMessage: String?, cause: Throwable?) : Exception(errorMessage, cause) {
constructor(errorMessage: String) : this(errorMessage, null)
constructor(cause: Throwable) : this(cause.message, cause)
}

View File

@@ -0,0 +1,9 @@
package app.revanced.patcher.patch
/**
* A result of executing a [Patch].
*
* @param patch The [Patch] that was executed.
* @param exception The [PatchException] thrown, if any.
*/
class PatchResult internal constructor(val patch: Patch<*>, val exception: PatchException? = null)

View File

@@ -0,0 +1,24 @@
package app.revanced.patcher.patch
import app.revanced.patcher.PatchClass
import app.revanced.patcher.data.ResourceContext
/**
* A ReVanced [Patch] that works on [ResourceContext].
*
* @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 ResourcePatch(
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<ResourceContext>(name, description, compatiblePackages, dependencies, use, requiresIntegrations)

View File

@@ -0,0 +1,40 @@
package app.revanced.patcher.patch.options
import app.revanced.patcher.patch.Patch
import kotlin.reflect.KProperty
/**
* A [Patch] option.
* @param key The identifier.
* @param default The default value.
* @param title The title.
* @param description A description.
* @param required Whether the option is required.
* @param validate The function to validate values of the option.
* @param T The value type of the option.
*/
abstract class PatchOption<T>(
val key: String,
default: T?,
val title: String?,
val description: String?,
val required: Boolean,
val validate: (T?) -> Boolean
) {
/**
* The value of the [PatchOption].
*/
var value: T? = default
set(value) {
if (required && value == null) throw PatchOptionException.ValueRequiredException(this)
if (!validate(value)) throw PatchOptionException.ValueValidationException(value, this)
field = value
}
operator fun getValue(thisRef: Any?, property: KProperty<*>) = value
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T?) {
this.value = value
}
}

View File

@@ -0,0 +1,41 @@
package app.revanced.patcher.patch.options
/**
* An exception thrown when using [PatchOption]s.
*
* @param errorMessage The exception message.
*/
sealed class PatchOptionException(errorMessage: String) : Exception(errorMessage, null) {
/**
* An exception thrown when a [PatchOption] is set to an invalid value.
*
* @param invalidType The type of the value that was passed.
* @param expectedType The type of the value that was expected.
*/
class InvalidValueTypeException(invalidType: String, expectedType: String) :
PatchOptionException("Type $expectedType was expected but received type $invalidType")
/**
* An exception thrown when a value did not satisfy the value conditions specified by the [PatchOption].
*
* @param value The value that failed validation.
*/
class ValueValidationException(value: Any?, option: PatchOption<*>) :
PatchOptionException("The option value \"$value\" failed validation for ${option.key}")
/**
* An exception thrown when a value is required but null was passed.
*
* @param option The [PatchOption] that requires a value.
*/
class ValueRequiredException(option: PatchOption<*>) :
PatchOptionException("The option ${option.key} requires a value, but null was passed")
/**
* An exception thrown when a [PatchOption] is not found.
*
* @param key The key of the [PatchOption].
*/
class PatchOptionNotFoundException(key: String)
: PatchOptionException("No option with key $key")
}

View File

@@ -0,0 +1,45 @@
package app.revanced.patcher.patch.options
/**
* A map of [PatchOption]s associated by their keys.
*
* @param options The [PatchOption]s to initialize with.
*/
class PatchOptions internal constructor(
private val options: MutableMap<String, PatchOption<*>> = mutableMapOf()
) : MutableMap<String, PatchOption<*>> by options {
/**
* Register a [PatchOption]. Acts like [MutableMap.put].
* @param value The [PatchOption] to register.
*/
fun register(value: PatchOption<*>) {
options[value.key] = value
}
/**
* Set an option's value.
* @param key The identifier.
* @param value The value.
* @throws PatchOptionException.PatchOptionNotFoundException If the option does not exist.
*/
operator fun <T : Any> set(key: String, value: T?) {
val option = this[key]
try {
@Suppress("UNCHECKED_CAST")
(option as PatchOption<T>).value = value
} catch (e: ClassCastException) {
throw PatchOptionException.InvalidValueTypeException(
value?.let { it::class.java.name } ?: "null",
option.value?.let { it::class.java.name } ?: "null",
)
}
}
/**
* Get an option.
*/
override operator fun get(key: String) =
options[key] ?: throw PatchOptionException.PatchOptionNotFoundException(key)
}

View File

@@ -0,0 +1,48 @@
package app.revanced.patcher.patch.options.types
import app.revanced.patcher.patch.Patch
import app.revanced.patcher.patch.options.PatchOption
/**
* A [PatchOption] representing a [Boolean].
*
* @param key The identifier.
* @param default The default value.
* @param title The title.
* @param description A description.
* @param required Whether the option is required.
*
* @see PatchOption
*/
class BooleanPatchOption private constructor(
key: String,
default: Boolean?,
title: String?,
description: String?,
required: Boolean,
validator: (Boolean?) -> Boolean
) : PatchOption<Boolean>(key, default, title, description, required, validator) {
companion object {
/**
* Create a new [BooleanPatchOption] and add it to the current [Patch].
*
* @param key The identifier.
* @param default The default value.
* @param title The title.
* @param description A description.
* @param required Whether the option is required.
* @return The created [BooleanPatchOption].
*
* @see BooleanPatchOption
* @see PatchOption
*/
fun <T : Patch<*>> T.booleanPatchOption(
key: String,
default: Boolean? = null,
title: String? = null,
description: String? = null,
required: Boolean = false,
validator: (Boolean?) -> Boolean = { true }
) = BooleanPatchOption(key, default, title, description, required, validator).also { options.register(it) }
}
}

View File

@@ -0,0 +1,48 @@
package app.revanced.patcher.patch.options.types
import app.revanced.patcher.patch.Patch
import app.revanced.patcher.patch.options.PatchOption
/**
* A [PatchOption] representing a [Float].
*
* @param key The identifier.
* @param default The default value.
* @param title The title.
* @param description A description.
* @param required Whether the option is required.
*
* @see PatchOption
*/
class FloatPatchOption private constructor(
key: String,
default: Float?,
title: String?,
description: String?,
required: Boolean,
validator: (Float?) -> Boolean
) : PatchOption<Float>(key, default, title, description, required, validator) {
companion object {
/**
* Create a new [FloatPatchOption] and add it to the current [Patch].
*
* @param key The identifier.
* @param default The default value.
* @param title The title.
* @param description A description.
* @param required Whether the option is required.
* @return The created [FloatPatchOption].
*
* @see FloatPatchOption
* @see PatchOption
*/
fun <T : Patch<*>> T.floatPatchOption(
key: String,
default: Float? = null,
title: String? = null,
description: String? = null,
required: Boolean = false,
validator: (Float?) -> Boolean = { true }
) = FloatPatchOption(key, default, title, description, required, validator).also { options.register(it) }
}
}

View File

@@ -0,0 +1,48 @@
package app.revanced.patcher.patch.options.types
import app.revanced.patcher.patch.Patch
import app.revanced.patcher.patch.options.PatchOption
/**
* A [PatchOption] representing an [Integer].
*
* @param key The identifier.
* @param default The default value.
* @param title The title.
* @param description A description.
* @param required Whether the option is required.
*
* @see PatchOption
*/
class IntPatchOption private constructor(
key: String,
default: Int?,
title: String?,
description: String?,
required: Boolean,
validator: (Int?) -> Boolean
) : PatchOption<Int>(key, default, title, description, required, validator) {
companion object {
/**
* Create a new [IntPatchOption] and add it to the current [Patch].
*
* @param key The identifier.
* @param default The default value.
* @param title The title.
* @param description A description.
* @param required Whether the option is required.
* @return The created [IntPatchOption].
*
* @see IntPatchOption
* @see PatchOption
*/
fun <T : Patch<*>> T.intPatchOption(
key: String,
default: Int? = null,
title: String? = null,
description: String? = null,
required: Boolean = false,
validator: (Int?) -> Boolean = { true }
) = IntPatchOption(key, default, title, description, required, validator).also { options.register(it) }
}
}

View File

@@ -0,0 +1,48 @@
package app.revanced.patcher.patch.options.types
import app.revanced.patcher.patch.Patch
import app.revanced.patcher.patch.options.PatchOption
/**
* A [PatchOption] representing a [Long].
*
* @param key The identifier.
* @param default The default value.
* @param title The title.
* @param description A description.
* @param required Whether the option is required.
*
* @see PatchOption
*/
class LongPatchOption private constructor(
key: String,
default: Long?,
title: String?,
description: String?,
required: Boolean,
validator: (Long?) -> Boolean
) : PatchOption<Long>(key, default, title, description, required, validator) {
companion object {
/**
* Create a new [LongPatchOption] and add it to the current [Patch].
*
* @param key The identifier.
* @param default The default value.
* @param title The title.
* @param description A description.
* @param required Whether the option is required.
* @return The created [LongPatchOption].
*
* @see LongPatchOption
* @see PatchOption
*/
fun <T : Patch<*>> T.longPatchOption(
key: String,
default: Long? = null,
title: String? = null,
description: String? = null,
required: Boolean = false,
validator: (Long?) -> Boolean = { true }
) = LongPatchOption(key, default, title, description, required, validator).also { options.register(it) }
}
}

View File

@@ -0,0 +1,48 @@
package app.revanced.patcher.patch.options.types
import app.revanced.patcher.patch.Patch
import app.revanced.patcher.patch.options.PatchOption
/**
* A [PatchOption] representing a [String].
*
* @param key The identifier.
* @param default The default value.
* @param title The title.
* @param description A description.
* @param required Whether the option is required.
*
* @see PatchOption
*/
class StringPatchOption private constructor(
key: String,
default: String?,
title: String?,
description: String?,
required: Boolean,
validator: (String?) -> Boolean
) : PatchOption<String>(key, default, title, description, required, validator) {
companion object {
/**
* Create a new [StringPatchOption] and add it to the current [Patch].
*
* @param key The identifier.
* @param default The default value.
* @param title The title.
* @param description A description.
* @param required Whether the option is required.
* @return The created [StringPatchOption].
*
* @see StringPatchOption
* @see PatchOption
*/
fun <T : Patch<*>> T.stringPatchOption(
key: String,
default: String? = null,
title: String? = null,
description: String? = null,
required: Boolean = false,
validator: (String?) -> Boolean = { true }
) = StringPatchOption(key, default, title, description, required, validator).also { options.register(it) }
}
}

View File

@@ -0,0 +1,48 @@
package app.revanced.patcher.patch.options.types.array
import app.revanced.patcher.patch.Patch
import app.revanced.patcher.patch.options.PatchOption
/**
* A [PatchOption] representing a [Boolean] array.
*
* @param key The identifier.
* @param default The default value.
* @param title The title.
* @param description A description.
* @param required Whether the option is required.
*
* @see PatchOption
*/
class BooleanArrayPatchOption private constructor(
key: String,
default: Array<Boolean>?,
title: String?,
description: String?,
required: Boolean,
validator: (Array<Boolean>?) -> Boolean
) : PatchOption<Array<Boolean>>(key, default, title, description, required, validator) {
companion object {
/**
* Create a new [BooleanArrayPatchOption] and add it to the current [Patch].
*
* @param key The identifier.
* @param default The default value.
* @param title The title.
* @param description A description.
* @param required Whether the option is required.
* @return The created [BooleanArrayPatchOption].
*
* @see BooleanArrayPatchOption
* @see PatchOption
*/
fun <T : Patch<*>> T.booleanArrayPatchOption(
key: String,
default: Array<Boolean>? = null,
title: String? = null,
description: String? = null,
required: Boolean = false,
validator: (Array<Boolean>?) -> Boolean = { true }
) = BooleanArrayPatchOption(key, default, title, description, required, validator).also { options.register(it) }
}
}

View File

@@ -0,0 +1,48 @@
package app.revanced.patcher.patch.options.types.array
import app.revanced.patcher.patch.Patch
import app.revanced.patcher.patch.options.PatchOption
/**
* A [PatchOption] representing a [Float] array.
*
* @param key The identifier.
* @param default The default value.
* @param title The title.
* @param description A description.
* @param required Whether the option is required.
*
* @see PatchOption
*/
class FloatArrayPatchOption private constructor(
key: String,
default: Array<Float>?,
title: String?,
description: String?,
required: Boolean,
validator: (Array<Float>?) -> Boolean
) : PatchOption<Array<Float>>(key, default, title, description, required, validator) {
companion object {
/**
* Create a new [FloatArrayPatchOption] and add it to the current [Patch].
*
* @param key The identifier.
* @param default The default value.
* @param title The title.
* @param description A description.
* @param required Whether the option is required.
* @return The created [FloatArrayPatchOption].
*
* @see FloatArrayPatchOption
* @see PatchOption
*/
fun <T : Patch<*>> T.floatArrayPatchOption(
key: String,
default: Array<Float>? = null,
title: String? = null,
description: String? = null,
required: Boolean = false,
validator: (Array<Float>?) -> Boolean = { true }
) = FloatArrayPatchOption(key, default, title, description, required, validator).also { options.register(it) }
}
}

View File

@@ -0,0 +1,48 @@
package app.revanced.patcher.patch.options.types.array
import app.revanced.patcher.patch.Patch
import app.revanced.patcher.patch.options.PatchOption
/**
* A [PatchOption] representing an [Integer] array.
*
* @param key The identifier.
* @param default The default value.
* @param title The title.
* @param description A description.
* @param required Whether the option is required.
*
* @see PatchOption
*/
class IntArrayPatchOption private constructor(
key: String,
default: Array<Int>?,
title: String?,
description: String?,
required: Boolean,
validator: (Array<Int>?) -> Boolean
) : PatchOption<Array<Int>>(key, default, title, description, required, validator) {
companion object {
/**
* Create a new [IntArrayPatchOption] and add it to the current [Patch].
*
* @param key The identifier.
* @param default The default value.
* @param title The title.
* @param description A description.
* @param required Whether the option is required.
* @return The created [IntArrayPatchOption].
*
* @see IntArrayPatchOption
* @see PatchOption
*/
fun <T : Patch<*>> T.intArrayPatchOption(
key: String,
default: Array<Int>? = null,
title: String? = null,
description: String? = null,
required: Boolean = false,
validator: (Array<Int>?) -> Boolean = { true }
) = IntArrayPatchOption(key, default, title, description, required, validator).also { options.register(it) }
}
}

View File

@@ -0,0 +1,48 @@
package app.revanced.patcher.patch.options.types.array
import app.revanced.patcher.patch.Patch
import app.revanced.patcher.patch.options.PatchOption
/**
* A [PatchOption] representing a [Long] array.
*
* @param key The identifier.
* @param default The default value.
* @param title The title.
* @param description A description.
* @param required Whether the option is required.
*
* @see PatchOption
*/
class LongArrayPatchOption private constructor(
key: String,
default: Array<Long>?,
title: String?,
description: String?,
required: Boolean,
validator: (Array<Long>?) -> Boolean
) : PatchOption<Array<Long>>(key, default, title, description, required, validator) {
companion object {
/**
* Create a new [LongArrayPatchOption] and add it to the current [Patch].
*
* @param key The identifier.
* @param default The default value.
* @param title The title.
* @param description A description.
* @param required Whether the option is required.
* @return The created [LongArrayPatchOption].
*
* @see LongArrayPatchOption
* @see PatchOption
*/
fun <T : Patch<*>> T.longArrayPatchOption(
key: String,
default: Array<Long>? = null,
title: String? = null,
description: String? = null,
required: Boolean = false,
validator: (Array<Long>?) -> Boolean = { true }
) = LongArrayPatchOption(key, default, title, description, required, validator).also { options.register(it) }
}
}

View File

@@ -0,0 +1,48 @@
package app.revanced.patcher.patch.options.types.array
import app.revanced.patcher.patch.Patch
import app.revanced.patcher.patch.options.PatchOption
/**
* A [PatchOption] representing a [String] array.
*
* @param key The identifier.
* @param default The default value.
* @param title The title.
* @param description A description.
* @param required Whether the option is required.
*
* @see PatchOption
*/
class StringArrayPatchOption private constructor(
key: String,
default: Array<String>?,
title: String?,
description: String?,
required: Boolean,
validator: (Array<String>?) -> Boolean
) : PatchOption<Array<String>>(key, default, title, description, required, validator) {
companion object {
/**
* Create a new [StringArrayPatchOption] and add it to the current [Patch].
*
* @param key The identifier.
* @param default The default value.
* @param title The title.
* @param description A description.
* @param required Whether the option is required.
* @return The created [StringArrayPatchOption].
*
* @see StringArrayPatchOption
* @see PatchOption
*/
fun <T : Patch<*>> T.stringArrayPatchOption(
key: String,
default: Array<String>? = null,
title: String? = null,
description: String? = null,
required: Boolean = false,
validator: (Array<String>?) -> Boolean = { true }
) = StringArrayPatchOption(key, default, title, description, required, validator).also { options.register(it) }
}
}

View File

@@ -0,0 +1,222 @@
package app.revanced.patcher.util
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.extensions.or
import app.revanced.patcher.util.ClassMerger.Utils.asMutableClass
import app.revanced.patcher.util.ClassMerger.Utils.filterAny
import app.revanced.patcher.util.ClassMerger.Utils.filterNotAny
import app.revanced.patcher.util.ClassMerger.Utils.isPublic
import app.revanced.patcher.util.ClassMerger.Utils.toPublic
import app.revanced.patcher.util.ClassMerger.Utils.traverseClassHierarchy
import app.revanced.patcher.util.proxy.mutableTypes.MutableClass
import app.revanced.patcher.util.proxy.mutableTypes.MutableClass.Companion.toMutable
import app.revanced.patcher.util.proxy.mutableTypes.MutableField
import app.revanced.patcher.util.proxy.mutableTypes.MutableField.Companion.toMutable
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
import com.android.tools.smali.dexlib2.AccessFlags
import com.android.tools.smali.dexlib2.iface.ClassDef
import com.android.tools.smali.dexlib2.util.MethodUtil
import java.util.logging.Logger
import kotlin.reflect.KFunction2
/**
* Experimental class to merge a [ClassDef] with another.
* Note: This will not consider method implementations or if the class is missing a superclass or interfaces.
*/
internal object ClassMerger {
private val logger = Logger.getLogger(ClassMerger::class.java.name)
/**
* Merge a class with [otherClass].
*
* @param otherClass The class to merge with
* @param context The context to traverse the class hierarchy in.
* @return The merged class or the original class if no merge was needed.
*/
fun ClassDef.merge(otherClass: ClassDef, context: BytecodeContext) = this
//.fixFieldAccess(otherClass)
//.fixMethodAccess(otherClass)
.addMissingFields(otherClass)
.addMissingMethods(otherClass)
.publicize(otherClass, context)
/**
* Add methods which are missing but existing in [fromClass].
*
* @param fromClass The class to add missing methods from.
*/
private fun ClassDef.addMissingMethods(fromClass: ClassDef): ClassDef {
val missingMethods = fromClass.methods.let { fromMethods ->
methods.filterNot { method ->
fromMethods.any { fromMethod ->
MethodUtil.methodSignaturesMatch(fromMethod, method)
}
}
}
if (missingMethods.isEmpty()) return this
logger.fine("Found ${missingMethods.size} missing methods")
return asMutableClass().apply {
methods.addAll(missingMethods.map { it.toMutable() })
}
}
/**
* Add fields which are missing but existing in [fromClass].
*
* @param fromClass The class to add missing fields from.
*/
private fun ClassDef.addMissingFields(fromClass: ClassDef): ClassDef {
val missingFields = fields.filterNotAny(fromClass.fields) { field, fromField ->
fromField.name == field.name
}
if (missingFields.isEmpty()) return this
logger.fine("Found ${missingFields.size} missing fields")
return asMutableClass().apply {
fields.addAll(missingFields.map { it.toMutable() })
}
}
/**
* Make a class and its super class public recursively.
* @param reference The class to check the [AccessFlags] of.
* @param context The context to traverse the class hierarchy in.
*/
private fun ClassDef.publicize(reference: ClassDef, context: BytecodeContext) =
if (reference.accessFlags.isPublic() && !accessFlags.isPublic())
this.asMutableClass().apply {
context.traverseClassHierarchy(this) {
if (accessFlags.isPublic()) return@traverseClassHierarchy
logger.fine("Publicizing ${this.type}")
accessFlags = accessFlags.toPublic()
}
}
else this
/**
* Publicize fields if they are public in [reference].
*
* @param reference The class to check the [AccessFlags] of the fields in.
*/
private fun ClassDef.fixFieldAccess(reference: ClassDef): ClassDef {
val brokenFields = fields.filterAny(reference.fields) { field, referenceField ->
if (field.name != referenceField.name) return@filterAny false
referenceField.accessFlags.isPublic() && !field.accessFlags.isPublic()
}
if (brokenFields.isEmpty()) return this
logger.fine("Found ${brokenFields.size} broken fields")
/**
* Make a field public.
*/
fun MutableField.publicize() {
accessFlags = accessFlags.toPublic()
}
return asMutableClass().apply {
fields.filter { brokenFields.contains(it) }.forEach(MutableField::publicize)
}
}
/**
* Publicize methods if they are public in [reference].
*
* @param reference The class to check the [AccessFlags] of the methods in.
*/
private fun ClassDef.fixMethodAccess(reference: ClassDef): ClassDef {
val brokenMethods = methods.filterAny(reference.methods) { method, referenceMethod ->
if (!MethodUtil.methodSignaturesMatch(method, referenceMethod)) return@filterAny false
referenceMethod.accessFlags.isPublic() && !method.accessFlags.isPublic()
}
if (brokenMethods.isEmpty()) return this
logger.fine("Found ${brokenMethods.size} methods")
/**
* Make a method public.
*/
fun MutableMethod.publicize() {
accessFlags = accessFlags.toPublic()
}
return asMutableClass().apply {
methods.filter { brokenMethods.contains(it) }.forEach(MutableMethod::publicize)
}
}
private object Utils {
/**
* traverse the class hierarchy starting from the given root class
*
* @param targetClass the class to start traversing the class hierarchy from
* @param callback function that is called for every class in the hierarchy
*/
fun BytecodeContext.traverseClassHierarchy(targetClass: MutableClass, callback: MutableClass.() -> Unit) {
callback(targetClass)
this.findClass(targetClass.superclass ?: return)?.mutableClass?.let {
traverseClassHierarchy(it, callback)
}
}
fun ClassDef.asMutableClass() = if (this is MutableClass) this else this.toMutable()
/**
* Check if the [AccessFlags.PUBLIC] flag is set.
*
* @return True, if the flag is set.
*/
fun Int.isPublic() = AccessFlags.PUBLIC.isSet(this)
/**
* Make [AccessFlags] public.
*
* @return The new [AccessFlags].
*/
fun Int.toPublic() = this.or(AccessFlags.PUBLIC).and(AccessFlags.PRIVATE.value.inv())
/**
* Filter [this] on [needles] matching the given [predicate].
*
* @param needles The needles to filter [this] with.
* @param predicate The filter.
* @return The [this] filtered on [needles] matching the given [predicate].
*/
fun <HayType, NeedleType> Iterable<HayType>.filterAny(
needles: Iterable<NeedleType>, predicate: (HayType, NeedleType) -> Boolean
) = Iterable<HayType>::filter.any(this, needles, predicate)
/**
* Filter [this] on [needles] not matching the given [predicate].
*
* @param needles The needles to filter [this] with.
* @param predicate The filter.
* @return The [this] filtered on [needles] not matching the given [predicate].
*/
fun <HayType, NeedleType> Iterable<HayType>.filterNotAny(
needles: Iterable<NeedleType>, predicate: (HayType, NeedleType) -> Boolean
) = Iterable<HayType>::filterNot.any(this, needles, predicate)
fun <HayType, NeedleType> KFunction2<Iterable<HayType>, (HayType) -> Boolean, List<HayType>>.any(
haystack: Iterable<HayType>,
needles: Iterable<NeedleType>,
predicate: (HayType, NeedleType) -> Boolean
) = this(haystack) { hay ->
needles.any { needle ->
predicate(hay, needle)
}
}
}
}

View File

@@ -0,0 +1,87 @@
package app.revanced.patcher.util
import org.w3c.dom.Document
import java.io.Closeable
import java.io.File
import java.io.InputStream
import java.io.OutputStream
import javax.xml.parsers.DocumentBuilderFactory
import javax.xml.transform.TransformerFactory
import javax.xml.transform.dom.DOMSource
import javax.xml.transform.stream.StreamResult
/**
* Wrapper for a file that can be edited as a dom document.
*
* This constructor does not check for locks to the file when writing.
* Use the secondary constructor.
*
* @param inputStream the input stream to read the xml file from.
* @param outputStream the output stream to write the xml file to. If null, the file will be read only.
*
*/
class DomFileEditor internal constructor(
private val inputStream: InputStream,
private val outputStream: Lazy<OutputStream>? = null,
) : Closeable {
// path to the xml file to unlock the resource when closing the editor
private var filePath: String? = null
private var closed: Boolean = false
/**
* The document of the xml file
*/
val file: Document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(inputStream)
.also(Document::normalize)
// lazily open an output stream
// this is required because when constructing a DomFileEditor the output stream is created along with the input stream, which is not allowed
// the workaround is to lazily create the output stream. This way it would be used after the input stream is closed, which happens in the constructor
constructor(file: File) : this(file.inputStream(), lazy { file.outputStream() }) {
// increase the lock
locks.merge(file.path, 1, Integer::sum)
filePath = file.path
}
/**
* Closes the editor. Write backs and decreases the lock count.
*
* Will not write back to the file if the file is still locked.
*/
override fun close() {
if (closed) return
inputStream.close()
// if the output stream is not null, do not close it
outputStream?.let {
// prevent writing to same file, if it is being locked
// isLocked will be false if the editor was created through a stream
val isLocked = filePath?.let { path ->
val isLocked = locks[path]!! > 1
// decrease the lock count if the editor was opened for a file
locks.merge(path, -1, Integer::sum)
isLocked
} ?: false
// if unlocked, write back to the file
if (!isLocked) {
it.value.use { stream ->
val result = StreamResult(stream)
TransformerFactory.newInstance().newTransformer().transform(DOMSource(file), result)
}
it.value.close()
return
}
}
closed = true
}
private companion object {
// map of concurrent open files
val locks = mutableMapOf<String, Int>()
}
}

View File

@@ -0,0 +1,33 @@
package app.revanced.patcher.util
import app.revanced.patcher.util.proxy.ClassProxy
import com.android.tools.smali.dexlib2.iface.ClassDef
/**
* A class that represents a set of classes and proxies.
*
* @param classes The classes to be backed by proxies.
*/
class ProxyClassList internal constructor(classes: MutableSet<ClassDef>) : MutableSet<ClassDef> by classes {
internal val proxies = mutableListOf<ClassProxy>()
/**
* Add a [ClassProxy].
*/
fun add(classProxy: ClassProxy) = proxies.add(classProxy)
/**
* Replace all classes with their mutated versions.
*/
internal fun replaceClasses() = proxies.removeIf { proxy ->
// If the proxy is unused, return false to keep it in the proxies list.
if (!proxy.resolved) return@removeIf false
// If it has been used, replace the original class with the mutable class.
remove(proxy.immutableClass)
add(proxy.mutableClass)
// Return true to remove the proxy from the proxies list.
return@removeIf true
}
}

View File

@@ -2,10 +2,10 @@ package app.revanced.patcher.util.method
import app.revanced.patcher.data.BytecodeContext
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod
import org.jf.dexlib2.iface.Method
import org.jf.dexlib2.iface.instruction.ReferenceInstruction
import org.jf.dexlib2.iface.reference.MethodReference
import org.jf.dexlib2.util.MethodUtil
import com.android.tools.smali.dexlib2.iface.Method
import com.android.tools.smali.dexlib2.iface.instruction.ReferenceInstruction
import com.android.tools.smali.dexlib2.iface.reference.MethodReference
import com.android.tools.smali.dexlib2.util.MethodUtil
/**
* Find a method from another method via instruction offsets.

View File

@@ -1,7 +1,7 @@
package app.revanced.patcher.util.proxy
import app.revanced.patcher.util.proxy.mutableTypes.MutableClass
import org.jf.dexlib2.iface.ClassDef
import com.android.tools.smali.dexlib2.iface.ClassDef
/**
* A proxy class for a [ClassDef].

View File

@@ -1,8 +1,8 @@
package app.revanced.patcher.util.proxy.mutableTypes
import app.revanced.patcher.util.proxy.mutableTypes.MutableAnnotationElement.Companion.toMutable
import org.jf.dexlib2.base.BaseAnnotation
import org.jf.dexlib2.iface.Annotation
import com.android.tools.smali.dexlib2.base.BaseAnnotation
import com.android.tools.smali.dexlib2.iface.Annotation
class MutableAnnotation(annotation: Annotation) : BaseAnnotation() {
private val visibility = annotation.visibility

View File

@@ -2,9 +2,9 @@ package app.revanced.patcher.util.proxy.mutableTypes
import app.revanced.patcher.util.proxy.mutableTypes.encodedValue.MutableEncodedValue
import app.revanced.patcher.util.proxy.mutableTypes.encodedValue.MutableEncodedValue.Companion.toMutable
import org.jf.dexlib2.base.BaseAnnotationElement
import org.jf.dexlib2.iface.AnnotationElement
import org.jf.dexlib2.iface.value.EncodedValue
import com.android.tools.smali.dexlib2.base.BaseAnnotationElement
import com.android.tools.smali.dexlib2.iface.AnnotationElement
import com.android.tools.smali.dexlib2.iface.value.EncodedValue
class MutableAnnotationElement(annotationElement: AnnotationElement) : BaseAnnotationElement() {
private var name = annotationElement.name

View File

@@ -4,10 +4,10 @@ import app.revanced.patcher.util.proxy.mutableTypes.MutableAnnotation.Companion.
import app.revanced.patcher.util.proxy.mutableTypes.MutableField.Companion.toMutable
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethod.Companion.toMutable
import com.google.common.collect.Iterables
import org.jf.dexlib2.base.reference.BaseTypeReference
import org.jf.dexlib2.iface.ClassDef
import org.jf.dexlib2.util.FieldUtil
import org.jf.dexlib2.util.MethodUtil
import com.android.tools.smali.dexlib2.base.reference.BaseTypeReference
import com.android.tools.smali.dexlib2.iface.ClassDef
import com.android.tools.smali.dexlib2.util.FieldUtil
import com.android.tools.smali.dexlib2.util.MethodUtil
class MutableClass(classDef: ClassDef) : ClassDef, BaseTypeReference() {
// Class

View File

@@ -3,9 +3,9 @@ package app.revanced.patcher.util.proxy.mutableTypes
import app.revanced.patcher.util.proxy.mutableTypes.MutableAnnotation.Companion.toMutable
import app.revanced.patcher.util.proxy.mutableTypes.encodedValue.MutableEncodedValue
import app.revanced.patcher.util.proxy.mutableTypes.encodedValue.MutableEncodedValue.Companion.toMutable
import org.jf.dexlib2.HiddenApiRestriction
import org.jf.dexlib2.base.reference.BaseFieldReference
import org.jf.dexlib2.iface.Field
import com.android.tools.smali.dexlib2.HiddenApiRestriction
import com.android.tools.smali.dexlib2.base.reference.BaseFieldReference
import com.android.tools.smali.dexlib2.iface.Field
class MutableField(field: Field) : Field, BaseFieldReference() {
private var definingClass = field.definingClass

View File

@@ -2,10 +2,10 @@ package app.revanced.patcher.util.proxy.mutableTypes
import app.revanced.patcher.util.proxy.mutableTypes.MutableAnnotation.Companion.toMutable
import app.revanced.patcher.util.proxy.mutableTypes.MutableMethodParameter.Companion.toMutable
import org.jf.dexlib2.HiddenApiRestriction
import org.jf.dexlib2.base.reference.BaseMethodReference
import org.jf.dexlib2.builder.MutableMethodImplementation
import org.jf.dexlib2.iface.Method
import com.android.tools.smali.dexlib2.HiddenApiRestriction
import com.android.tools.smali.dexlib2.base.reference.BaseMethodReference
import com.android.tools.smali.dexlib2.builder.MutableMethodImplementation
import com.android.tools.smali.dexlib2.iface.Method
class MutableMethod(method: Method) : Method, BaseMethodReference() {
private var definingClass = method.definingClass
@@ -20,6 +20,22 @@ class MutableMethod(method: Method) : Method, BaseMethodReference() {
private val _parameterTypes by lazy { method.parameterTypes.toMutableList() }
private val _hiddenApiRestrictions by lazy { method.hiddenApiRestrictions }
fun setDefiningClass(definingClass: String) {
this.definingClass = definingClass
}
fun setName(name: String) {
this.name = name
}
fun setAccessFlags(accessFlags: Int) {
this.accessFlags = accessFlags
}
fun setReturnType(returnType: String) {
this.returnType = returnType
}
override fun getDefiningClass(): String {
return definingClass
}

View File

@@ -1,8 +1,8 @@
package app.revanced.patcher.util.proxy.mutableTypes
import app.revanced.patcher.util.proxy.mutableTypes.MutableAnnotation.Companion.toMutable
import org.jf.dexlib2.base.BaseMethodParameter
import org.jf.dexlib2.iface.MethodParameter
import com.android.tools.smali.dexlib2.base.BaseMethodParameter
import com.android.tools.smali.dexlib2.iface.MethodParameter
// TODO: finish overriding all members if necessary
class MutableMethodParameter(parameter: MethodParameter) : MethodParameter, BaseMethodParameter() {

View File

@@ -1,9 +1,9 @@
package app.revanced.patcher.util.proxy.mutableTypes.encodedValue
import app.revanced.patcher.util.proxy.mutableTypes.MutableAnnotationElement.Companion.toMutable
import org.jf.dexlib2.base.value.BaseAnnotationEncodedValue
import org.jf.dexlib2.iface.AnnotationElement
import org.jf.dexlib2.iface.value.AnnotationEncodedValue
import com.android.tools.smali.dexlib2.base.value.BaseAnnotationEncodedValue
import com.android.tools.smali.dexlib2.iface.AnnotationElement
import com.android.tools.smali.dexlib2.iface.value.AnnotationEncodedValue
class MutableAnnotationEncodedValue(annotationEncodedValue: AnnotationEncodedValue) : BaseAnnotationEncodedValue(),
MutableEncodedValue {

View File

@@ -1,9 +1,9 @@
package app.revanced.patcher.util.proxy.mutableTypes.encodedValue
import app.revanced.patcher.util.proxy.mutableTypes.encodedValue.MutableEncodedValue.Companion.toMutable
import org.jf.dexlib2.base.value.BaseArrayEncodedValue
import org.jf.dexlib2.iface.value.ArrayEncodedValue
import org.jf.dexlib2.iface.value.EncodedValue
import com.android.tools.smali.dexlib2.base.value.BaseArrayEncodedValue
import com.android.tools.smali.dexlib2.iface.value.ArrayEncodedValue
import com.android.tools.smali.dexlib2.iface.value.EncodedValue
class MutableArrayEncodedValue(arrayEncodedValue: ArrayEncodedValue) : BaseArrayEncodedValue(), MutableEncodedValue {
private val _value by lazy {

View File

@@ -1,7 +1,7 @@
package app.revanced.patcher.util.proxy.mutableTypes.encodedValue
import org.jf.dexlib2.base.value.BaseBooleanEncodedValue
import org.jf.dexlib2.iface.value.BooleanEncodedValue
import com.android.tools.smali.dexlib2.base.value.BaseBooleanEncodedValue
import com.android.tools.smali.dexlib2.iface.value.BooleanEncodedValue
class MutableBooleanEncodedValue(booleanEncodedValue: BooleanEncodedValue) : BaseBooleanEncodedValue(),
MutableEncodedValue {

View File

@@ -1,7 +1,7 @@
package app.revanced.patcher.util.proxy.mutableTypes.encodedValue
import org.jf.dexlib2.base.value.BaseByteEncodedValue
import org.jf.dexlib2.iface.value.ByteEncodedValue
import com.android.tools.smali.dexlib2.base.value.BaseByteEncodedValue
import com.android.tools.smali.dexlib2.iface.value.ByteEncodedValue
class MutableByteEncodedValue(byteEncodedValue: ByteEncodedValue) : BaseByteEncodedValue(), MutableEncodedValue {
private var value = byteEncodedValue.value

View File

@@ -1,7 +1,7 @@
package app.revanced.patcher.util.proxy.mutableTypes.encodedValue
import org.jf.dexlib2.base.value.BaseCharEncodedValue
import org.jf.dexlib2.iface.value.CharEncodedValue
import com.android.tools.smali.dexlib2.base.value.BaseCharEncodedValue
import com.android.tools.smali.dexlib2.iface.value.CharEncodedValue
class MutableCharEncodedValue(charEncodedValue: CharEncodedValue) : BaseCharEncodedValue(), MutableEncodedValue {
private var value = charEncodedValue.value

View File

@@ -1,7 +1,7 @@
package app.revanced.patcher.util.proxy.mutableTypes.encodedValue
import org.jf.dexlib2.base.value.BaseDoubleEncodedValue
import org.jf.dexlib2.iface.value.DoubleEncodedValue
import com.android.tools.smali.dexlib2.base.value.BaseDoubleEncodedValue
import com.android.tools.smali.dexlib2.iface.value.DoubleEncodedValue
class MutableDoubleEncodedValue(doubleEncodedValue: DoubleEncodedValue) : BaseDoubleEncodedValue(),
MutableEncodedValue {

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