You've already forked revanced-patcher
mirror of
https://github.com/revanced/revanced-patcher
synced 2025-09-06 16:38:50 +02:00
Compare commits
258 Commits
v2.0.2
...
v7.1.0-dev
Author | SHA1 | Date | |
---|---|---|---|
![]() |
2432fde6bf | ||
![]() |
49c173dc14 | ||
![]() |
d83e9372bb | ||
![]() |
7e8cd3bede | ||
![]() |
d67436271d | ||
![]() |
aa07f35f06 | ||
![]() |
77e0536838 | ||
![]() |
a49e78234b | ||
![]() |
a3ae825e48 | ||
![]() |
146c8504ed | ||
![]() |
2eb125ad69 | ||
![]() |
6e24a85eab | ||
![]() |
e4c3e9ffc5 | ||
![]() |
4c1778a62f | ||
![]() |
d99261cdbb | ||
![]() |
ac1c0f2773 | ||
![]() |
eddd4ec7ac | ||
![]() |
07a2829c65 | ||
![]() |
3d77e299d9 | ||
![]() |
f1336f89e4 | ||
![]() |
0502f84c20 | ||
![]() |
058d292ad5 | ||
![]() |
1029d56a52 | ||
![]() |
709b5a0fec | ||
![]() |
e1accc5041 | ||
![]() |
6dbbf2e03e | ||
![]() |
16557eeab0 | ||
![]() |
6bca3e2bb5 | ||
![]() |
a263fdfd41 | ||
![]() |
e4b4bacae8 | ||
![]() |
cbc97af155 | ||
![]() |
d5533788e2 | ||
![]() |
5a4ea5cd7d | ||
![]() |
70f3c8b38c | ||
![]() |
6b410a0eea | ||
![]() |
73a013d75b | ||
![]() |
7159f3db4c | ||
![]() |
7d5ecf095c | ||
![]() |
fa015a424d | ||
![]() |
dd7dd38357 | ||
![]() |
22356f2d26 | ||
![]() |
66701f6076 | ||
![]() |
6a6ded084e | ||
![]() |
5887c69bde | ||
![]() |
4102f43b8a | ||
![]() |
5c09ef7837 | ||
![]() |
3e0bf8c863 | ||
![]() |
8f3ecc318c | ||
![]() |
365da96e2b | ||
![]() |
cd68ec4803 | ||
![]() |
35265e029c | ||
![]() |
9f0a09a756 | ||
![]() |
e802141df5 | ||
![]() |
abebc0862c | ||
![]() |
96ef150e89 | ||
![]() |
c5de9e2988 | ||
![]() |
c391ca648b | ||
![]() |
7cf79e68e0 | ||
![]() |
f07db3c214 | ||
![]() |
88bb3a8845 | ||
![]() |
b9e6bd6775 | ||
![]() |
cd1b72e078 | ||
![]() |
6b889557ab | ||
![]() |
4b1be8c647 | ||
![]() |
73c893c6e7 | ||
![]() |
75b36823b8 | ||
![]() |
d2d93cd075 | ||
![]() |
26b8621ac8 | ||
![]() |
f365a41741 | ||
![]() |
9ec720e983 | ||
![]() |
0f432b3fdd | ||
![]() |
96cd5618dd | ||
![]() |
c2a5a55e67 | ||
![]() |
6c5de8b414 | ||
![]() |
ea773cfa56 | ||
![]() |
a306561b55 | ||
![]() |
b6dcd88495 | ||
![]() |
a925650044 | ||
![]() |
77bbf6be1f | ||
![]() |
bd053b7e99 | ||
![]() |
fd742eba63 | ||
![]() |
ba9d998681 | ||
![]() |
75df245ec3 | ||
![]() |
4164cb0dea | ||
![]() |
18fe35ae73 | ||
![]() |
f9bc95f220 | ||
![]() |
d2f91a8545 | ||
![]() |
4016bdc37f | ||
![]() |
538b2a8599 | ||
![]() |
4aa14bbb85 | ||
![]() |
d37452997b | ||
![]() |
db21d5e953 | ||
![]() |
4d581811db | ||
![]() |
8c502448be | ||
![]() |
fec16d9442 | ||
![]() |
5583904994 | ||
![]() |
797286b758 | ||
![]() |
4ae9ad09d6 | ||
![]() |
447e1ad30e | ||
![]() |
843e62ad29 | ||
![]() |
9c07ffcc7a | ||
![]() |
438321330e | ||
![]() |
3ba4be240b | ||
![]() |
98ce0abfa9 | ||
![]() |
db4348c4fa | ||
![]() |
4839f87519 | ||
![]() |
809862c997 | ||
![]() |
fd5c878cee | ||
![]() |
124332f0e9 | ||
![]() |
d4cf0cea52 | ||
![]() |
76676fb567 | ||
![]() |
d802ef844e | ||
![]() |
90fc547673 | ||
![]() |
3813e28ac2 | ||
![]() |
a2bb4004c7 | ||
![]() |
a0cb449c60 | ||
![]() |
e0271790b8 | ||
![]() |
4bfd7ebff8 | ||
![]() |
2f7e62ef65 | ||
![]() |
4485af8036 | ||
![]() |
085a3a479d | ||
![]() |
f75c9a78b8 | ||
![]() |
172655bde0 | ||
![]() |
456db7289a | ||
![]() |
e722e3f4f9 | ||
![]() |
c348c1f0a0 | ||
![]() |
ed1851013e | ||
![]() |
e31ac1f132 | ||
![]() |
8f78f85e4a | ||
![]() |
0be2677519 | ||
![]() |
b873228ef0 | ||
![]() |
639ff1c0ba | ||
![]() |
f30671ddd1 | ||
![]() |
76c45dd7c1 | ||
![]() |
1bafb77355 | ||
![]() |
25f74dc5e9 | ||
![]() |
6e73631d4d | ||
![]() |
7761d5b85e | ||
![]() |
62aa295e73 | ||
![]() |
596ede1b12 | ||
![]() |
7debe62738 | ||
![]() |
002f84da1a | ||
![]() |
aff4968e6f | ||
![]() |
1d989abd55 | ||
![]() |
f1775f83d0 | ||
![]() |
4055939c08 | ||
![]() |
85120374d6 | ||
![]() |
8b4819faa1 | ||
![]() |
d219276298 | ||
![]() |
79f91e0e5a | ||
![]() |
fadf62f594 | ||
![]() |
ad3d332e27 | ||
![]() |
8f66df7666 | ||
![]() |
80c2e80925 | ||
![]() |
c3db23d3c7 | ||
![]() |
c28584736e | ||
![]() |
6b909c1ee6 | ||
![]() |
0e8446516e | ||
![]() |
aa46b953db | ||
![]() |
a562e476c0 | ||
![]() |
75d2be8803 | ||
![]() |
d6308e126c | ||
![]() |
bb97af4d86 | ||
![]() |
392164862c | ||
![]() |
53e807dec1 | ||
![]() |
288d50a8b4 | ||
![]() |
131dedd4b0 | ||
![]() |
5a92d5c29d | ||
![]() |
4b81318710 | ||
![]() |
44f6a3ebc5 | ||
![]() |
7882a8d928 | ||
![]() |
cc3d32748b | ||
![]() |
f9da2ad531 | ||
![]() |
b19e1131e8 | ||
![]() |
123ad54c15 | ||
![]() |
09f6ab4155 | ||
![]() |
01cf3fb50f | ||
![]() |
6c5f9d4198 | ||
![]() |
7b2d058144 | ||
![]() |
db2804270e | ||
![]() |
2572cd04b5 | ||
![]() |
5eb8b428b9 | ||
![]() |
3a118d9b9d | ||
![]() |
14a73bfcaf | ||
![]() |
567bf52e16 | ||
![]() |
35c6489dba | ||
![]() |
371f0c4d0b | ||
![]() |
1b42f65d95 | ||
![]() |
2aee0cbd0f | ||
![]() |
19256b5437 | ||
![]() |
67a5237541 | ||
![]() |
4e2e772389 | ||
![]() |
799bc9e163 | ||
![]() |
2431785d0e | ||
![]() |
fb3c0e87d4 | ||
![]() |
5f7ef2dbff | ||
![]() |
ec1d8a8fba | ||
![]() |
814ce0b9ae | ||
![]() |
8d95b14f35 | ||
![]() |
711b8a25a7 | ||
![]() |
fbb09f38dc | ||
![]() |
9a4d30e152 | ||
![]() |
368c61c1bf | ||
![]() |
bbd40bf2f6 | ||
![]() |
3de999a2d3 | ||
![]() |
83cbb2f110 | ||
![]() |
fcc7fa75d0 | ||
![]() |
495ebface8 | ||
![]() |
8c12f8d488 | ||
![]() |
523f67b238 | ||
![]() |
4813a8b48e | ||
![]() |
d5c66022c9 | ||
![]() |
1d4034b36c | ||
![]() |
dd2d696d00 | ||
![]() |
6326321b65 | ||
![]() |
f291a4ae3e | ||
![]() |
817b8db019 | ||
![]() |
a321b8971b | ||
![]() |
783b2de9db | ||
![]() |
77604d4078 | ||
![]() |
21b5404180 | ||
![]() |
9ac6d5c7da | ||
![]() |
1b39278b24 | ||
![]() |
0ebab8bf59 | ||
![]() |
112bc998f4 | ||
![]() |
12c96bf818 | ||
![]() |
91298a8790 | ||
![]() |
f2a7cff41c | ||
![]() |
dd941233ca | ||
![]() |
fc06dd1c29 | ||
![]() |
482af78f2b | ||
![]() |
89a27dfbe6 | ||
![]() |
4ea030d0a0 | ||
![]() |
4cc2fa17f5 | ||
![]() |
48068cb3d7 | ||
![]() |
d107c7245c | ||
![]() |
4b2e3230ec | ||
![]() |
fb5b82da4e | ||
![]() |
5970e32aa5 | ||
![]() |
0f00d33f4e | ||
![]() |
83187c9edd | ||
![]() |
79d70cff4b | ||
![]() |
6f72c4c4c0 | ||
![]() |
c8eedac4d9 | ||
![]() |
60a8278ae8 | ||
![]() |
ada5a033de | ||
![]() |
109b8a296d | ||
![]() |
e2faf4ca9b | ||
![]() |
2134182a0e | ||
![]() |
d8b5b8bb7c | ||
![]() |
49970b5926 | ||
![]() |
c1fbd8cf8c | ||
![]() |
a467fbb704 | ||
![]() |
5a4bd7a76e | ||
![]() |
e5ca86fac6 | ||
![]() |
68d9e9f02c | ||
![]() |
494a9a09ac | ||
![]() |
6bfe5716c3 |
72
.github/ISSUE_TEMPLATE/bug-issue.yml
vendored
Normal file
72
.github/ISSUE_TEMPLATE/bug-issue.yml
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
name: 🐞 Bug report
|
||||
description: Report a very clearly broken issue.
|
||||
title: 'bug: <title>'
|
||||
labels: [bug]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
# ReVanced bug report
|
||||
|
||||
Important to note that your issue may have already been reported before. Please check for existing issues [here](https://github.com/revanced/revanced-patcher/labels/bug).
|
||||
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: Type
|
||||
options:
|
||||
- Crash
|
||||
- Cosmetic
|
||||
- Other
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Bug description
|
||||
description: How did you find the bug? Any additional details that might help?
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Steps to reproduce
|
||||
description: Add the steps to reproduce this bug including your environment.
|
||||
placeholder: Step 1. Download some files. Step 2. ...
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Relevant log output
|
||||
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks.
|
||||
render: shell
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Screenshots or videos
|
||||
description: Add screenshots or videos that show the bug here.
|
||||
placeholder: Drag and drop the screenshots/videos into this box.
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Solution
|
||||
description: If applicable, add a possible solution.
|
||||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Additional context
|
||||
description: Add additional context here.
|
||||
validations:
|
||||
required: false
|
||||
- type: checkboxes
|
||||
id: acknowledgements
|
||||
attributes:
|
||||
label: Acknowledgements
|
||||
description: Your issue will be closed if you haven't done these steps.
|
||||
options:
|
||||
- label: I have searched the existing issues and this is a new and no duplicate or related to another open issue.
|
||||
required: true
|
||||
- label: I have written a short but informative title.
|
||||
required: true
|
||||
- label: I filled out all of the requested information in this issue properly.
|
||||
required: true
|
8
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
8
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
blank_issues_enabled: false
|
||||
contact_links:
|
||||
- name: 📃 Documentation
|
||||
url: https://github.com/revanced/revanced-documentation/
|
||||
about: Don't know how or where to start? Check out our documentation!
|
||||
- name: 🗨 Discussions
|
||||
url: https://github.com/revanced/revanced-suggestions/discussions
|
||||
about: Got something you think should change or be added? Search for or start a new discussion!
|
58
.github/ISSUE_TEMPLATE/feature-issue.yml
vendored
Normal file
58
.github/ISSUE_TEMPLATE/feature-issue.yml
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
name: ⭐ Feature request
|
||||
description: Create a detailed feature request.
|
||||
title: 'feat: <title>'
|
||||
labels: [feature-request]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
# ReVanced feature request
|
||||
|
||||
Do not submit requests for patches here. Please submit them [here](https://github.com/orgs/revanced/discussions/categories/patches) instead.
|
||||
Important to note that your feature request may have already been made before. Please check for existing feature requests [here](https://github.com/revanced/revanced-patcher/labels/feature-request).
|
||||
|
||||
- type: dropdown
|
||||
attributes:
|
||||
label: Type
|
||||
options:
|
||||
- Functionality
|
||||
- Cosmetic
|
||||
- Other
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Issue
|
||||
description: What is the current problem. Why does it require a feature request?
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Feature
|
||||
description: Describe your feature in detail. How does it solve the issue?
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Motivation
|
||||
description: Why should your feature should be considered?
|
||||
validations:
|
||||
required: true
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: Additional context
|
||||
description: Add additional context here.
|
||||
validations:
|
||||
required: false
|
||||
- type: checkboxes
|
||||
id: acknowledgements
|
||||
attributes:
|
||||
label: Acknowledgements
|
||||
description: Your issue will be closed if you haven't done these steps.
|
||||
options:
|
||||
- label: I have searched the existing issues and this is a new and no duplicate or related to another open issue.
|
||||
required: true
|
||||
- label: I have written a short but informative title.
|
||||
required: true
|
||||
- label: I filled out all of the requested information in this issue properly.
|
||||
required: true
|
2
.github/config.yml
vendored
Normal file
2
.github/config.yml
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
firstPRMergeComment: >
|
||||
Thank you for contributing to ReVanced. Join us on [Discord](https://revanced.app/discord) if you want to receive a contributor role.
|
25
.github/workflows/pull_request.yml
vendored
Normal file
25
.github/workflows/pull_request.yml
vendored
Normal file
@@ -0,0 +1,25 @@
|
||||
name: PR to main
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- dev
|
||||
workflow_dispatch:
|
||||
|
||||
env:
|
||||
MESSAGE: merge branch `${{ github.head_ref || github.ref_name }}` to `main`
|
||||
|
||||
jobs:
|
||||
pull-request:
|
||||
name: Open pull request
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: Open pull request
|
||||
uses: repo-sync/pull-request@v2
|
||||
with:
|
||||
destination_branch: 'main'
|
||||
pr_title: 'chore: ${{ env.MESSAGE }}'
|
||||
pr_body: 'This pull request will ${{ env.MESSAGE }}.'
|
||||
pr_draft: true
|
26
.github/workflows/release.yml
vendored
26
.github/workflows/release.yml
vendored
@@ -1,4 +1,5 @@
|
||||
name: Release
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
@@ -9,32 +10,33 @@ on:
|
||||
branches:
|
||||
- main
|
||||
- dev
|
||||
|
||||
jobs:
|
||||
release:
|
||||
name: Release
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
# Make sure the release step uses its own credentials:
|
||||
# https://github.com/cycjimmy/semantic-release-action#private-packages
|
||||
persist-credentials: false
|
||||
fetch-depth: 0
|
||||
- name: Setup JDK
|
||||
uses: actions/setup-java@v2
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: '17'
|
||||
distribution: 'adopt'
|
||||
distribution: 'zulu'
|
||||
cache: gradle
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v2
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: "lts/*"
|
||||
- name: Build with Gradle
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: ./gradlew build
|
||||
node-version: "18"
|
||||
cache: 'npm'
|
||||
- name: Setup semantic-release
|
||||
run: npm install -g semantic-release @semantic-release/git @semantic-release/changelog gradle-semantic-release-plugin -D
|
||||
run: npm install
|
||||
- name: Release
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: npx semantic-release
|
||||
GITHUB_TOKEN: ${{ secrets.REPOSITORY_PUSH_ACCESS }}
|
||||
run: npm exec semantic-release
|
||||
|
7
.gitignore
vendored
7
.gitignore
vendored
@@ -74,6 +74,7 @@ cmake-build-*/
|
||||
|
||||
# IntelliJ
|
||||
out/
|
||||
.idea/
|
||||
|
||||
# mpeltonen/sbt-idea plugin
|
||||
.idea_modules/
|
||||
@@ -115,3 +116,9 @@ gradle-app.setting
|
||||
|
||||
# Avoid ignoring test resources
|
||||
!src/test/resources/*
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
|
||||
# Gradle props, to avoid sharing the gpr key
|
||||
gradle.properties
|
||||
|
8
.idea/.gitignore
generated
vendored
8
.idea/.gitignore
generated
vendored
@@ -1,8 +0,0 @@
|
||||
# Default ignored files
|
||||
/shelf/
|
||||
/workspace.xml
|
||||
# Editor-based HTTP Client requests
|
||||
/httpRequests/
|
||||
# Datasource local storage ignored files
|
||||
/dataSources/
|
||||
/dataSources.local.xml
|
10
.idea/codeStyles/Project.xml
generated
10
.idea/codeStyles/Project.xml
generated
@@ -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>
|
5
.idea/codeStyles/codeStyleConfig.xml
generated
5
.idea/codeStyles/codeStyleConfig.xml
generated
@@ -1,5 +0,0 @@
|
||||
<component name="ProjectCodeStyleConfiguration">
|
||||
<state>
|
||||
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
|
||||
</state>
|
||||
</component>
|
7
.idea/discord.xml
generated
7
.idea/discord.xml
generated
@@ -1,7 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="DiscordProjectSettings">
|
||||
<option name="show" value="PROJECT_FILES" />
|
||||
<option name="description" value="" />
|
||||
</component>
|
||||
</project>
|
15
.idea/git_toolbox_prj.xml
generated
15
.idea/git_toolbox_prj.xml
generated
@@ -1,15 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="GitToolBoxProjectSettings">
|
||||
<option name="commitMessageIssueKeyValidationOverride">
|
||||
<BoolValueOverride>
|
||||
<option name="enabled" value="true" />
|
||||
</BoolValueOverride>
|
||||
</option>
|
||||
<option name="commitMessageValidationEnabledOverride">
|
||||
<BoolValueOverride>
|
||||
<option name="enabled" value="true" />
|
||||
</BoolValueOverride>
|
||||
</option>
|
||||
</component>
|
||||
</project>
|
6
.idea/inspectionProfiles/Project_Default.xml
generated
6
.idea/inspectionProfiles/Project_Default.xml
generated
@@ -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
10
.idea/misc.xml
generated
@@ -1,10 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ExternalStorageConfigurationManager" enabled="true" />
|
||||
<component name="FrameworkDetectionExcludesConfiguration">
|
||||
<file type="web" url="file://$PROJECT_DIR$" />
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_17" default="true" project-jdk-name="azul-17" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
12
.idea/vcs.xml
generated
12
.idea/vcs.xml
generated
@@ -1,12 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="CommitMessageInspectionProfile">
|
||||
<profile version="1.0">
|
||||
<inspection_tool class="CommitFormat" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
<inspection_tool class="CommitNamingConvention" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||
</profile>
|
||||
</component>
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
20
.releaserc
20
.releaserc
@@ -7,11 +7,7 @@
|
||||
}
|
||||
],
|
||||
"plugins": [
|
||||
["@semantic-release/commit-analyzer", {
|
||||
"releaseRules": [
|
||||
{"type": "build", "release": "patch"}
|
||||
]
|
||||
}],
|
||||
"@semantic-release/commit-analyzer",
|
||||
"@semantic-release/release-notes-generator",
|
||||
"@semantic-release/changelog",
|
||||
"gradle-semantic-release-plugin",
|
||||
@@ -24,6 +20,18 @@
|
||||
]
|
||||
}
|
||||
],
|
||||
"@semantic-release/github"
|
||||
[
|
||||
"@saithodev/semantic-release-backmerge",
|
||||
{
|
||||
backmergeBranches: [{"from": "main", "to": "dev"}],
|
||||
clearWorkspace: true
|
||||
}
|
||||
],
|
||||
[
|
||||
"@semantic-release/github",
|
||||
{
|
||||
successComment: false
|
||||
}
|
||||
]
|
||||
]
|
||||
}
|
||||
|
638
CHANGELOG.md
638
CHANGELOG.md
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,5 @@
|
||||
plugins {
|
||||
kotlin("jvm") version "1.7.0"
|
||||
java
|
||||
kotlin("jvm") version "1.8.10"
|
||||
`maven-publish`
|
||||
}
|
||||
|
||||
@@ -22,11 +21,12 @@ repositories {
|
||||
|
||||
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.6.6-SNAPSHOT")
|
||||
implementation("app.revanced:smali:2.5.3-a3836654")
|
||||
implementation("app.revanced:multidexlib2:2.5.3-a3836654")
|
||||
implementation("app.revanced:apktool-lib:2.7.0")
|
||||
|
||||
testImplementation(kotlin("test"))
|
||||
implementation("org.jetbrains.kotlin:kotlin-reflect:1.8.20-RC")
|
||||
testImplementation("org.jetbrains.kotlin:kotlin-test:1.8.20-RC")
|
||||
}
|
||||
|
||||
tasks {
|
||||
@@ -36,6 +36,9 @@ tasks {
|
||||
events("PASSED", "SKIPPED", "FAILED")
|
||||
}
|
||||
}
|
||||
processResources {
|
||||
expand("projectVersion" to project.version)
|
||||
}
|
||||
}
|
||||
|
||||
java {
|
||||
|
@@ -1,2 +1,2 @@
|
||||
kotlin.code.style = official
|
||||
version = 2.0.2
|
||||
version = 7.1.0-dev.2
|
||||
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,5 +1,5 @@
|
||||
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.1.1-all.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
6580
package-lock.json
generated
Normal file
6580
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
9
package.json
Normal file
9
package.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"devDependencies": {
|
||||
"@saithodev/semantic-release-backmerge": "^3.1.0",
|
||||
"@semantic-release/changelog": "^6.0.2",
|
||||
"@semantic-release/git": "^10.0.1",
|
||||
"gradle-semantic-release-plugin": "^1.7.6",
|
||||
"semantic-release": "^20.1.0"
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
64
src/main/kotlin/app/revanced/patcher/PatcherContext.kt
Normal file
64
src/main/kotlin/app/revanced/patcher/PatcherContext.kt
Normal file
@@ -0,0 +1,64 @@
|
||||
package app.revanced.patcher
|
||||
|
||||
import app.revanced.patcher.data.*
|
||||
import app.revanced.patcher.logging.Logger
|
||||
import app.revanced.patcher.patch.Patch
|
||||
import app.revanced.patcher.util.ClassMerger.merge
|
||||
import org.jf.dexlib2.iface.ClassDef
|
||||
import java.io.File
|
||||
|
||||
data class PatcherContext(
|
||||
val classes: MutableList<ClassDef>,
|
||||
val resourceCacheDirectory: File,
|
||||
) {
|
||||
val packageMetadata = PackageMetadata()
|
||||
internal val patches = mutableListOf<Class<out Patch<Context>>>()
|
||||
internal val integrations = Integrations(this)
|
||||
internal val bytecodeContext = BytecodeContext(classes)
|
||||
internal val resourceContext = ResourceContext(resourceCacheDirectory)
|
||||
|
||||
internal class Integrations(val context: PatcherContext) {
|
||||
var callback: ((File) -> Unit)? = null
|
||||
private val integrations: MutableList<File> = mutableListOf()
|
||||
|
||||
fun add(integrations: List<File>) = this@Integrations.integrations.addAll(integrations)
|
||||
|
||||
/**
|
||||
* Merge integrations.
|
||||
* @param logger A logger.
|
||||
*/
|
||||
fun merge(logger: Logger) {
|
||||
with(context.bytecodeContext.classes) {
|
||||
for (integrations in integrations) {
|
||||
callback?.let { it(integrations) }
|
||||
|
||||
for (classDef in lanchon.multidexlib2.MultiDexIO.readDexFile(
|
||||
true,
|
||||
integrations,
|
||||
NAMER,
|
||||
null,
|
||||
null
|
||||
).classes) {
|
||||
val type = classDef.type
|
||||
|
||||
val result = classes.findIndexed { it.type == type }
|
||||
if (result == null) {
|
||||
logger.trace("Merging type $type")
|
||||
classes.add(classDef)
|
||||
continue
|
||||
}
|
||||
|
||||
val (existingClass, existingClassIndex) = result
|
||||
|
||||
logger.trace("Type $type exists. Adding missing methods and fields.")
|
||||
|
||||
existingClass.merge(classDef, context, logger).let { mergedClass ->
|
||||
if (mergedClass !== existingClass) // referential equality check
|
||||
classes[existingClassIndex] = mergedClass
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,19 +0,0 @@
|
||||
package app.revanced.patcher
|
||||
|
||||
import app.revanced.patcher.data.Data
|
||||
import app.revanced.patcher.data.PackageMetadata
|
||||
import app.revanced.patcher.data.impl.BytecodeData
|
||||
import app.revanced.patcher.data.impl.ResourceData
|
||||
import app.revanced.patcher.patch.Patch
|
||||
import org.jf.dexlib2.iface.ClassDef
|
||||
import java.io.File
|
||||
|
||||
data class PatcherData(
|
||||
internal val internalClasses: MutableList<ClassDef>,
|
||||
internal val resourceCacheDirectory: String,
|
||||
val packageMetadata: PackageMetadata
|
||||
) {
|
||||
internal val patches = mutableListOf<Class<out Patch<Data>>>()
|
||||
internal val bytecodeData = BytecodeData(internalClasses)
|
||||
internal val resourceData = ResourceData(File(resourceCacheDirectory))
|
||||
}
|
@@ -8,7 +8,6 @@ import java.io.File
|
||||
* Options for the [Patcher].
|
||||
* @param inputFile The input file (usually an apk file).
|
||||
* @param resourceCacheDirectory Directory to cache resources.
|
||||
* @param patchResources Weather to use the resource patcher. Resources will still need to be decoded.
|
||||
* @param aaptPath Optional path to a custom aapt binary.
|
||||
* @param frameworkFolderLocation Optional path to a custom framework folder.
|
||||
* @param logger Custom logger implementation for the [Patcher].
|
||||
@@ -16,8 +15,7 @@ import java.io.File
|
||||
data class PatcherOptions(
|
||||
internal val inputFile: File,
|
||||
internal val resourceCacheDirectory: String,
|
||||
internal val patchResources: Boolean = false,
|
||||
internal val aaptPath: String = "",
|
||||
internal val aaptPath: String? = null,
|
||||
internal val frameworkFolderLocation: String? = null,
|
||||
internal val logger: Logger = NopLogger
|
||||
)
|
||||
|
@@ -1,15 +1,12 @@
|
||||
package app.revanced.patcher.annotation
|
||||
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import app.revanced.patcher.patch.Patch
|
||||
|
||||
/**
|
||||
* Annotation to constrain a [Patch] or [MethodFingerprint] to compatible packages.
|
||||
* @param compatiblePackages A list of packages a [Patch] or [MethodFingerprint] is compatible with.
|
||||
* Annotation to constrain a [Patch] to compatible packages.
|
||||
* @param compatiblePackages A list of packages a [Patch] is compatible with.
|
||||
*/
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
@MustBeDocumented
|
||||
annotation class Compatibility(
|
||||
val compatiblePackages: Array<Package>,
|
||||
)
|
||||
@@ -17,12 +14,10 @@ annotation class Compatibility(
|
||||
/**
|
||||
* Annotation to represent packages a patch can be compatible with.
|
||||
* @param name The package identifier name.
|
||||
* @param versions The versions of the package the [Patch] or [MethodFingerprint]is compatible with.
|
||||
* @param versions The versions of the package the [Patch] is compatible with.
|
||||
*/
|
||||
@Target()
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
@MustBeDocumented
|
||||
annotation class Package(
|
||||
val name: String,
|
||||
val versions: Array<String>
|
||||
)
|
||||
val versions: Array<String> = [],
|
||||
)
|
||||
|
@@ -1,38 +1,31 @@
|
||||
package app.revanced.patcher.annotation
|
||||
|
||||
import app.revanced.patcher.fingerprint.method.impl.MethodFingerprint
|
||||
import app.revanced.patcher.patch.Patch
|
||||
|
||||
/**
|
||||
* Annotation to name a [Patch] or [MethodFingerprint].
|
||||
* @param name A suggestive name for the [Patch] or [MethodFingerprint].
|
||||
* Annotation to name a [Patch].
|
||||
* @param name A suggestive name for the [Patch].
|
||||
*/
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
@MustBeDocumented
|
||||
annotation class Name(
|
||||
val name: String,
|
||||
)
|
||||
|
||||
/**
|
||||
* Annotation to describe a [Patch] or [MethodFingerprint].
|
||||
* @param description A description for the [Patch] or [MethodFingerprint].
|
||||
* Annotation to describe a [Patch].
|
||||
* @param description A description for the [Patch].
|
||||
*/
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
@MustBeDocumented
|
||||
annotation class Description(
|
||||
val description: String,
|
||||
)
|
||||
|
||||
|
||||
/**
|
||||
* Annotation to version a [Patch] or [MethodFingerprint].
|
||||
* @param version The version of a [Patch] or [MethodFingerprint].
|
||||
* Annotation to version a [Patch].
|
||||
* @param version The version of a [Patch].
|
||||
*/
|
||||
@Target(AnnotationTarget.CLASS)
|
||||
@Retention(AnnotationRetention.RUNTIME)
|
||||
@MustBeDocumented
|
||||
annotation class Version(
|
||||
val version: String,
|
||||
)
|
||||
|
181
src/main/kotlin/app/revanced/patcher/data/Context.kt
Normal file
181
src/main/kotlin/app/revanced/patcher/data/Context.kt
Normal file
@@ -0,0 +1,181 @@
|
||||
package app.revanced.patcher.data
|
||||
|
||||
import app.revanced.patcher.util.ProxyBackedClassList
|
||||
import app.revanced.patcher.util.method.MethodWalker
|
||||
import org.jf.dexlib2.iface.ClassDef
|
||||
import org.jf.dexlib2.iface.Method
|
||||
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
|
||||
|
||||
/**
|
||||
* A common interface to constrain [Context] to [BytecodeContext] and [ResourceContext].
|
||||
*/
|
||||
|
||||
sealed interface Context
|
||||
|
||||
class BytecodeContext internal constructor(classes: MutableList<ClassDef>) : Context {
|
||||
/**
|
||||
* The list of classes.
|
||||
*/
|
||||
val classes = ProxyBackedClassList(classes)
|
||||
|
||||
/**
|
||||
* 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) }
|
||||
|
||||
fun proxy(classDef: ClassDef): app.revanced.patcher.util.proxy.ClassProxy {
|
||||
var proxy = this.classes.proxies.find { it.immutableClass.type == classDef.type }
|
||||
if (proxy == null) {
|
||||
proxy = app.revanced.patcher.util.proxy.ClassProxy(classDef)
|
||||
this.classes.add(proxy)
|
||||
}
|
||||
return proxy
|
||||
}
|
||||
|
||||
private companion object {
|
||||
inline fun <reified T> Iterable<T>.find(predicate: (T) -> Boolean): T? {
|
||||
for (element in this) {
|
||||
if (predicate(element)) {
|
||||
return element
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a [MethodWalker] instance for the current [BytecodeContext].
|
||||
*
|
||||
* @param startMethod The method to start at.
|
||||
* @return A [MethodWalker] instance.
|
||||
*/
|
||||
fun BytecodeContext.toMethodWalker(startMethod: Method): MethodWalker {
|
||||
return MethodWalker(this, startMethod)
|
||||
}
|
||||
|
||||
internal inline fun <T> Iterable<T>.findIndexed(predicate: (T) -> Boolean): Pair<T, Int>? {
|
||||
for ((index, element) in this.withIndex()) {
|
||||
if (predicate(element)) {
|
||||
return element to index
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
class ResourceContext internal constructor(private val resourceCacheDirectory: File) : Context, Iterable<File> {
|
||||
val xmlEditor = XmlFileHolder()
|
||||
|
||||
operator fun get(path: String) = resourceCacheDirectory.resolve(path)
|
||||
|
||||
override fun iterator() = resourceCacheDirectory.walkTopDown().iterator()
|
||||
|
||||
inner class XmlFileHolder {
|
||||
operator fun get(inputStream: InputStream) =
|
||||
DomFileEditor(inputStream)
|
||||
|
||||
operator fun get(path: String): DomFileEditor {
|
||||
return DomFileEditor(this@ResourceContext[path])
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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>()
|
||||
}
|
||||
}
|
@@ -1,9 +0,0 @@
|
||||
package app.revanced.patcher.data
|
||||
|
||||
import app.revanced.patcher.data.impl.BytecodeData
|
||||
import app.revanced.patcher.data.impl.ResourceData
|
||||
|
||||
/**
|
||||
* Constraint interface for [BytecodeData] and [ResourceData]
|
||||
*/
|
||||
interface Data
|
@@ -1,69 +0,0 @@
|
||||
package app.revanced.patcher.data.impl
|
||||
|
||||
import app.revanced.patcher.data.Data
|
||||
import app.revanced.patcher.util.ProxyBackedClassList
|
||||
import app.revanced.patcher.util.method.MethodWalker
|
||||
import org.jf.dexlib2.iface.ClassDef
|
||||
import org.jf.dexlib2.iface.Method
|
||||
|
||||
class BytecodeData(
|
||||
internalClasses: MutableList<ClassDef>
|
||||
) : Data {
|
||||
val classes = ProxyBackedClassList(internalClasses)
|
||||
|
||||
/**
|
||||
* 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) }
|
||||
|
||||
fun proxy(classDef: ClassDef): app.revanced.patcher.util.proxy.ClassProxy {
|
||||
var proxy = this.classes.proxies.find { it.immutableClass.type == classDef.type }
|
||||
if (proxy == null) {
|
||||
proxy = app.revanced.patcher.util.proxy.ClassProxy(classDef)
|
||||
this.classes.add(proxy)
|
||||
}
|
||||
return proxy
|
||||
}
|
||||
}
|
||||
|
||||
internal class MethodNotFoundException(s: String) : Exception(s)
|
||||
|
||||
internal inline fun <reified T> Iterable<T>.find(predicate: (T) -> Boolean): T? {
|
||||
for (element in this) {
|
||||
if (predicate(element)) {
|
||||
return element
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a [MethodWalker] instance for the current [BytecodeData].
|
||||
* @param startMethod The method to start at.
|
||||
* @return A [MethodWalker] instance.
|
||||
*/
|
||||
fun BytecodeData.toMethodWalker(startMethod: Method): MethodWalker {
|
||||
return MethodWalker(this, startMethod)
|
||||
}
|
||||
|
||||
internal inline fun <T> Iterable<T>.findIndexed(predicate: (T) -> Boolean): Pair<T, Int>? {
|
||||
for ((index, element) in this.withIndex()) {
|
||||
if (predicate(element)) {
|
||||
return element to index
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user