Skip to content

Commit e7c3d64

Browse files
committed
feat: Allow selecting first Adb device, if none supplied automatically by updating dependencies
1 parent 3765957 commit e7c3d64

File tree

5 files changed

+113
-90
lines changed

5 files changed

+113
-90
lines changed

docs/1_usage.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ ReVanced CLI is divided into the following fundamental commands:
116116
```bash
117117
java -jar revanced-cli.jar utility uninstall \
118118
--package-name <package-name> \
119-
<device-serial>
119+
[<device-serial>]
120120
```
121121
122122
> [!NOTE]
@@ -128,7 +128,7 @@ ReVanced CLI is divided into the following fundamental commands:
128128
```bash
129129
java -jar revanced-cli.jar utility install \
130130
-a input.apk \
131-
<device-serial>
131+
[<device-serial>]
132132
```
133133
134134
> [!NOTE]

gradle/libs.versions.toml

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
[versions]
22
shadow = "8.1.1"
3-
kotlin-test = "1.9.10"
3+
kotlin-test = "1.9.20"
44
kotlinx-coroutines-core = "1.7.3"
55
picocli = "4.7.3"
66
revanced-patcher = "19.0.0"
7-
revanced-library = "1.2.0"
7+
revanced-library = "1.3.0"
88

99
[libraries]
1010
kotlin-test = { module = "org.jetbrains.kotlin:kotlin-test", version.ref = "kotlin-test" }

src/main/kotlin/app/revanced/cli/command/PatchCommand.kt

+92-72
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,9 @@ import java.io.PrintWriter
1818
import java.io.StringWriter
1919
import java.util.logging.Logger
2020

21-
2221
@CommandLine.Command(
2322
name = "patch",
24-
description = ["Patch an APK file."]
23+
description = ["Patch an APK file."],
2524
)
2625
internal object PatchCommand : Runnable {
2726
private val logger = Logger.getLogger(PatchCommand::class.java.name)
@@ -37,25 +36,25 @@ internal object PatchCommand : Runnable {
3736

3837
@CommandLine.Option(
3938
names = ["-i", "--include"],
40-
description = ["List of patches to include."]
39+
description = ["List of patches to include."],
4140
)
4241
private var includedPatches = hashSetOf<String>()
4342

4443
@CommandLine.Option(
4544
names = ["--ii"],
46-
description = ["List of patches to include by their index in relation to the supplied patch bundles."]
45+
description = ["List of patches to include by their index in relation to the supplied patch bundles."],
4746
)
4847
private var includedPatchesByIndex = arrayOf<Int>()
4948

5049
@CommandLine.Option(
5150
names = ["-e", "--exclude"],
52-
description = ["List of patches to exclude."]
51+
description = ["List of patches to exclude."],
5352
)
5453
private var excludedPatches = hashSetOf<String>()
5554

5655
@CommandLine.Option(
5756
names = ["--ei"],
58-
description = ["List of patches to exclude by their index in relation to the supplied patch bundles."]
57+
description = ["List of patches to exclude by their index in relation to the supplied patch bundles."],
5958
)
6059
private var excludedPatchesByIndex = arrayOf<Int>()
6160

@@ -68,14 +67,14 @@ internal object PatchCommand : Runnable {
6867
@CommandLine.Option(
6968
names = ["--exclusive"],
7069
description = ["Only include patches that are explicitly specified to be included."],
71-
showDefaultValue = ALWAYS
70+
showDefaultValue = ALWAYS,
7271
)
7372
private var exclusive = false
7473

7574
@CommandLine.Option(
76-
names = ["-f","--force"],
75+
names = ["-f", "--force"],
7776
description = ["Bypass compatibility checks for the supplied APK's version."],
78-
showDefaultValue = ALWAYS
77+
showDefaultValue = ALWAYS,
7978
)
8079
private var force: Boolean = false
8180

@@ -91,48 +90,52 @@ internal object PatchCommand : Runnable {
9190

9291
@CommandLine.Option(
9392
names = ["-d", "--device-serial"],
94-
description = ["ADB device serial to install to."],
93+
description = ["ADB device serial to install to. If not supplied, the first connected device will be used."],
94+
fallbackValue = "", // Empty string to indicate that the first connected device should be used.
95+
arity = "0..1",
9596
)
9697
private var deviceSerial: String? = null
9798

9899
@CommandLine.Option(
99100
names = ["--mount"],
100101
description = ["Install by mounting the patched APK file."],
101-
showDefaultValue = ALWAYS
102+
showDefaultValue = ALWAYS,
102103
)
103104
private var mount: Boolean = false
104105

105106
@CommandLine.Option(
106107
names = ["--keystore"],
107-
description = ["Path to the keystore to sign the patched APK file with. " +
108-
"Defaults to the same directory as the supplied APK file."],
108+
description = [
109+
"Path to the keystore to sign the patched APK file with. " +
110+
"Defaults to the same directory as the supplied APK file.",
111+
],
109112
)
110113
private var keystoreFilePath: File? = null
111114

112115
// key store password
113116
@CommandLine.Option(
114117
names = ["--keystore-password"],
115-
description = ["The password of the keystore to sign the patched APK file with. Empty password by default."]
118+
description = ["The password of the keystore to sign the patched APK file with. Empty password by default."],
116119
)
117120
private var keyStorePassword: String? = null // Empty password by default
118121

119122
@CommandLine.Option(
120123
names = ["--alias"],
121124
description = ["The alias of the key from the keystore to sign the patched APK file with."],
122-
showDefaultValue = ALWAYS
125+
showDefaultValue = ALWAYS,
123126
)
124127
private var alias = "ReVanced Key"
125128

126129
@CommandLine.Option(
127130
names = ["--keystore-entry-password"],
128-
description = ["The password of the entry from the keystore for the key to sign the patched APK file with."]
131+
description = ["The password of the entry from the keystore for the key to sign the patched APK file with."],
129132
)
130133
private var password = "" // Empty password by default
131134

132135
@CommandLine.Option(
133136
names = ["--signer"],
134137
description = ["The name of the signer to sign the patched APK file with."],
135-
showDefaultValue = ALWAYS
138+
showDefaultValue = ALWAYS,
136139
)
137140
private var signer = "ReVanced"
138141

@@ -147,33 +150,35 @@ internal object PatchCommand : Runnable {
147150
@CommandLine.Option(
148151
names = ["-p", "--purge"],
149152
description = ["Purge the temporary resource cache directory after patching."],
150-
showDefaultValue = ALWAYS
153+
showDefaultValue = ALWAYS,
151154
)
152155
private var purge: Boolean = false
153156

154157
@CommandLine.Option(
155158
names = ["-w", "--warn"],
156159
description = ["Warn if a patch can not be found in the supplied patch bundles."],
157-
showDefaultValue = ALWAYS
160+
showDefaultValue = ALWAYS,
158161
)
159162
private var warn: Boolean = false
160163

161164
@CommandLine.Parameters(
162165
description = ["APK file to be patched."],
163-
arity = "1..1"
166+
arity = "1..1",
164167
)
165168
@Suppress("unused")
166169
private fun setApk(apk: File) {
167-
if (!apk.exists()) throw CommandLine.ParameterException(
168-
spec.commandLine(),
169-
"APK file ${apk.name} does not exist"
170-
)
170+
if (!apk.exists()) {
171+
throw CommandLine.ParameterException(
172+
spec.commandLine(),
173+
"APK file ${apk.name} does not exist",
174+
)
175+
}
171176
this.apk = apk
172177
}
173178

174179
@CommandLine.Option(
175180
names = ["-m", "--merge"],
176-
description = ["One or more DEX files or containers to merge into the APK."]
181+
description = ["One or more DEX files or containers to merge into the APK."],
177182
)
178183
@Suppress("unused")
179184
private fun setIntegrations(integrations: Array<File>) {
@@ -186,7 +191,7 @@ internal object PatchCommand : Runnable {
186191
@CommandLine.Option(
187192
names = ["-b", "--patch-bundle"],
188193
description = ["One or more bundles of patches."],
189-
required = true
194+
required = true,
190195
)
191196
@Suppress("unused")
192197
private fun setPatchBundles(patchBundles: Array<File>) {
@@ -198,37 +203,37 @@ internal object PatchCommand : Runnable {
198203

199204
@CommandLine.Option(
200205
names = ["--custom-aapt2-binary"],
201-
description = ["Path to a custom AAPT binary to compile resources with."]
206+
description = ["Path to a custom AAPT binary to compile resources with."],
202207
)
203208
@Suppress("unused")
204209
private fun setAaptBinaryPath(aaptBinaryPath: File) {
205-
if (!aaptBinaryPath.exists()) throw CommandLine.ParameterException(
206-
spec.commandLine(),
207-
"AAPT binary ${aaptBinaryPath.name} does not exist"
208-
)
210+
if (!aaptBinaryPath.exists()) {
211+
throw CommandLine.ParameterException(
212+
spec.commandLine(),
213+
"AAPT binary ${aaptBinaryPath.name} does not exist",
214+
)
215+
}
209216
this.aaptBinaryPath = aaptBinaryPath
210217
}
211218

212219
override fun run() {
213220
// region Setup
214221

215222
val outputFilePath = outputFilePath ?: File("").absoluteFile.resolve(
216-
"${apk.nameWithoutExtension}-patched.${apk.extension}"
223+
"${apk.nameWithoutExtension}-patched.${apk.extension}",
217224
)
218225

219226
val resourceCachePath = resourceCachePath ?: outputFilePath.parentFile.resolve(
220-
"${outputFilePath.nameWithoutExtension}-resource-cache"
227+
"${outputFilePath.nameWithoutExtension}-resource-cache",
221228
)
222229

223230
val optionsFile = optionsFile ?: outputFilePath.parentFile.resolve(
224-
"${outputFilePath.nameWithoutExtension}-options.json"
231+
"${outputFilePath.nameWithoutExtension}-options.json",
225232
)
226233

227234
val keystoreFilePath = keystoreFilePath ?: outputFilePath.parentFile
228235
.resolve("${outputFilePath.nameWithoutExtension}.keystore")
229236

230-
val adbManager = deviceSerial?.let { serial -> AdbManager.getAdbManager(serial, mount) }
231-
232237
// endregion
233238

234239
// region Load patches
@@ -238,13 +243,15 @@ internal object PatchCommand : Runnable {
238243
val patches = PatchBundleLoader.Jar(*patchBundles.toTypedArray())
239244

240245
// Warn if a patch can not be found in the supplied patch bundles.
241-
if (warn) patches.map { it.name }.toHashSet().let { availableNames ->
242-
(includedPatches + excludedPatches).filter { name ->
243-
!availableNames.contains(name)
246+
if (warn) {
247+
patches.map { it.name }.toHashSet().let { availableNames ->
248+
(includedPatches + excludedPatches).filter { name ->
249+
!availableNames.contains(name)
250+
}
251+
}.let { unknownPatches ->
252+
if (unknownPatches.isEmpty()) return@let
253+
logger.warning("Unknown input of patches:\n${unknownPatches.joinToString("\n")}")
244254
}
245-
}.let { unknownPatches ->
246-
if (unknownPatches.isEmpty()) return@let
247-
logger.warning("Unknown input of patches:\n${unknownPatches.joinToString("\n")}")
248255
}
249256

250257
// endregion
@@ -255,14 +262,17 @@ internal object PatchCommand : Runnable {
255262
resourceCachePath,
256263
aaptBinaryPath?.path,
257264
resourceCachePath.absolutePath,
258-
true
259-
)
265+
true,
266+
),
260267
).use { patcher ->
261268
val filteredPatches = patcher.filterPatchSelection(patches).also { patches ->
262269
logger.info("Setting patch options")
263270

264-
if (optionsFile.exists()) patches.setOptions(optionsFile)
265-
else Options.serialize(patches, prettyPrint = true).let(optionsFile::writeText)
271+
if (optionsFile.exists()) {
272+
patches.setOptions(optionsFile)
273+
} else {
274+
Options.serialize(patches, prettyPrint = true).let(optionsFile::writeText)
275+
}
266276
}
267277

268278
// region Patch
@@ -292,24 +302,29 @@ internal object PatchCommand : Runnable {
292302
ApkUtils.copyAligned(apk, this, patcherResult)
293303
}
294304

295-
if (!mount) ApkUtils.sign(
296-
alignedFile,
297-
outputFilePath,
298-
ApkUtils.SigningOptions(
299-
keystoreFilePath,
300-
keyStorePassword,
301-
alias,
302-
password,
303-
signer
305+
if (!mount) {
306+
ApkUtils.sign(
307+
alignedFile,
308+
outputFilePath,
309+
ApkUtils.SigningOptions(
310+
keystoreFilePath,
311+
keyStorePassword,
312+
alias,
313+
password,
314+
signer,
315+
),
304316
)
305-
)
306-
else alignedFile.renameTo(outputFilePath)
317+
} else {
318+
alignedFile.renameTo(outputFilePath)
319+
}
307320

308321
// endregion
309322

310323
// region Install
311324

312-
adbManager?.install(AdbManager.Apk(outputFilePath, patcher.context.packageMetadata.packageName))
325+
deviceSerial?.let { serial ->
326+
AdbManager.getAdbManager(deviceSerial = serial.ifEmpty { null }, mount)
327+
}?.install(AdbManager.Apk(outputFilePath, patcher.context.packageMetadata.packageName))
313328

314329
// endregion
315330
}
@@ -320,7 +335,6 @@ internal object PatchCommand : Runnable {
320335
}
321336
}
322337

323-
324338
/**
325339
* Filter the patches to be added to the patcher. The filter is based on the following:
326340
*
@@ -344,17 +358,20 @@ internal object PatchCommand : Runnable {
344358
it.any { version -> version == packageVersion }
345359
} ?: true
346360

347-
if (!matchesVersion) return@patch logger.warning(
348-
"$patchName is incompatible with version $packageVersion. "
349-
+ "This patch is only compatible with version "
350-
+ packages.joinToString(";") { pkg ->
351-
pkg.versions!!.joinToString(", ")
352-
}
353-
)
361+
if (!matchesVersion) {
362+
return@patch logger.warning(
363+
"$patchName is incompatible with version $packageVersion. " +
364+
"This patch is only compatible with version " +
365+
packages.joinToString(";") { pkg ->
366+
pkg.versions!!.joinToString(", ")
367+
},
368+
)
369+
}
354370
} ?: return@patch logger.fine(
355-
"$patchName is incompatible with $packageName. "
356-
+ "This patch is only compatible with "
357-
+ packages.joinToString(", ") { `package` -> `package`.name })
371+
"$patchName is incompatible with $packageName. " +
372+
"This patch is only compatible with " +
373+
packages.joinToString(", ") { `package` -> `package`.name },
374+
)
358375

359376
return@let
360377
} ?: logger.fine("$patchName has no constraint on packages.")
@@ -374,8 +391,11 @@ internal object PatchCommand : Runnable {
374391
}
375392

376393
private fun purge(resourceCachePath: File) {
377-
val result = if (resourceCachePath.deleteRecursively()) "Purged resource cache directory"
378-
else "Failed to purge resource cache directory"
394+
val result = if (resourceCachePath.deleteRecursively()) {
395+
"Purged resource cache directory"
396+
} else {
397+
"Failed to purge resource cache directory"
398+
}
379399
logger.info(result)
380400
}
381-
}
401+
}

0 commit comments

Comments
 (0)