-
-
Notifications
You must be signed in to change notification settings - Fork 23
chore: add validations to RootInstaller #66
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: dev
Are you sure you want to change the base?
Conversation
laur89
commented
Apr 20, 2025
- add extra sanity check to mount script - bail if package is still mounted after unmount execution
- RootInstaller:
- install():
- ensure mount script installation exits w/ 0;
- ensure mount script execution exits w/ 0;
- uninstall():
- bail if package-to-be-unmounted is not mounted; indicates likely error on user part
- ensure unmount script exits w/ 0;
- install():
- related to feat: Improve unmount validation revanced-cli#362
- add extra sanity check to mount script - bail if package is still mounted after unmount execution - RootInstaller: - install(): - ensure mount script installation exits w/ 0; - ensure mount script execution exits w/ 0; - uninstall(): - bail if package-to-be-unmounted is not mounted; indicates likely error on user part - ensure unmount script exits w/ 0; - related to ReVanced/revanced-cli#362
src/commonMain/kotlin/app/revanced/library/installation/installer/Constants.kt
Outdated
Show resolved
Hide resolved
if (MOUNT_GREP(packageName)().exitCode != 0) { | ||
throw NotMountedException() | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is to fail if user tries to unmount a pkg that's not mounted to begin with. IMHO indicates a user error that should be marked as such.
As a downside makes the unmount command non-idempotent. Still has my vote though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think, if the user tries to uninstall an app that isn't installed, it's better to do it in good terms than in bad. An error is a bad term. Uninstallation finishing without doing anything, because nothing is mounted is a good term.
@@ -71,13 +68,17 @@ abstract class RootInstaller internal constructor( | |||
} | |||
|
|||
override suspend fun uninstall(packageName: String): RootInstallerResult { | |||
packageName.assertInstalled() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Attempting to unmount a pkg that's not even installed should surely throw.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This line would need to be present in all implementations of Installer. This doesn't sound correctly abstracted
const val MOUNT_APK = | ||
"base_path=\"$MOUNTED_APK_PATH\" && " + | ||
"base_path='$MOUNTED_APK_PATH' && " + | ||
"mv $TMP_FILE_PATH \$base_path && " + | ||
"chmod 644 \$base_path && " + | ||
"chown system:system \$base_path && " + | ||
"chcon u:object_r:apk_data_file:s0 \$base_path" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could use multiline string here and in other constants so that && can be removed, the line length reduced and readability improved. Also escaping " wont be needed anymore. .trimIndent() should be used then.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Already did that change and then reverted it. Think current code is readable enough and &&
-chaining has the benefit of failing fast and returning the failure code.
Single quotes for base_path
var are ok here, as everything is expanded on java side, no need for shell-side expansion anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
and &&-chaining has the benefit of failing fast and returning the failure code.
What do you mean? Wouldn't running the commands in a new line also return the failure code
Short multiple lines rather than a single long one is more readable, ideally this is applied here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't running the commands in a new line also return the failure code
By default, without the set -e
(which as discussed somewhere else I don't know whether shell on android supports), no. E.g.
command1
command2
command3
would return 0 if only command2
failed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not if command 1 or 3 failed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If only command1 and/or command2 failed, then the script would succeed as its exit code would be that of command3's - meaning successful.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't command1 failing exit the script? From what I know if a line fails the lines below arent run.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not familiar with android, but in dash or bash, with default settings - no. That's what the set -e
is for.
src/commonMain/kotlin/app/revanced/library/installation/installer/Constants.kt
Show resolved
Hide resolved
src/commonMain/kotlin/app/revanced/library/installation/installer/Constants.kt
Outdated
Show resolved
Hide resolved
src/commonMain/kotlin/app/revanced/library/installation/installer/Constants.kt
Outdated
Show resolved
Hide resolved
src/commonMain/kotlin/app/revanced/library/installation/installer/Constants.kt
Outdated
Show resolved
Hide resolved
val packageName = apk.packageName?.also { it.assertInstalled() } ?: throw PackageNameRequiredException() | ||
logger.info("Installing ${apk.packageName} by mounting") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The throw should happen after the log as it would indicate that the attempt of the installation failed. This way this log would never occur when the throw would happen.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd rather not see that log message prior to exception, as that can leave user confused as to whether any installation took place or not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd rather not see that log message prior to exception, as that can leave user confused as to whether any installation took place or not.
The exception is raised. If not caught without logging anything, after the installation log, the exception will be shown. Otherwise the exception will be shown prior to letting the user know it occurred while installation.
@@ -41,10 +41,14 @@ class AdbShellCommandRunner : ShellCommandRunner { | |||
override fun waitFor() { | |||
process.waitFor() | |||
} | |||
|
|||
override fun ensureSuccess() { | |||
if (exitCode != 0) throw ShellCmdFailure() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is already a exitCode field. This function is not necessary in this class. You can add this to the invoke extension if necessary.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's continue discussion about it here
src/commonMain/kotlin/app/revanced/library/installation/command/AdbShellCommandRunner.kt
Show resolved
Hide resolved
src/commonMain/kotlin/app/revanced/library/installation/command/AdbShellCommandRunner.kt
Outdated
Show resolved
Hide resolved
src/commonMain/kotlin/app/revanced/library/installation/command/AdbShellCommandRunner.kt
Outdated
Show resolved
Hide resolved
@@ -56,4 +60,6 @@ class AdbShellCommandRunner : ShellCommandRunner { | |||
* @param targetFilePath The target file path. | |||
*/ | |||
override fun move(file: File, targetFilePath: String) = device.push(file, RemoteFile(targetFilePath)) | |||
|
|||
internal class ShellCmdFailure internal constructor() : Exception("Shell command execution failure") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't believe the command runner classes should raise exceptions. A shell returning 0 and 1 is both controlled and expected behaviour. The classes using this such as the installers can treat 1 and 0 exits accordingly and handle it by raising an exception if according to requirement.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This exception and ensureSuccess()
were created for convenience.
I suppose instead of executing commands such as
UMOUNT(packageName)().ensureSuccess()
perhaps we should change invoke extension to enforce every command to return w/ exit code 0?
Then again, workflows such as
if (MOUNT_GREP(packageName)().exitCode != 0) {
throw NotMountedException()
}
would then become impossible.
So in short, my vote is still on ensureSuccess()
in its current form. Open to suggestions.
39c78ef
to
62b99e9
Compare
src/commonMain/kotlin/app/revanced/library/installation/installer/Constants.kt
Outdated
Show resolved
Hide resolved
val packageName = apk.packageName?.also { it.assertInstalled() } ?: throw PackageNameRequiredException() | ||
logger.info("Installing ${apk.packageName} by mounting") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd rather not see that log message prior to exception, as that can leave user confused as to whether any installation took place or not.
The exception is raised. If not caught without logging anything, after the installation log, the exception will be shown. Otherwise the exception will be shown prior to letting the user know it occurred while installation.
@@ -71,13 +68,17 @@ abstract class RootInstaller internal constructor( | |||
} | |||
|
|||
override suspend fun uninstall(packageName: String): RootInstallerResult { | |||
packageName.assertInstalled() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This line would need to be present in all implementations of Installer. This doesn't sound correctly abstracted
if (MOUNT_GREP(packageName)().exitCode != 0) { | ||
throw NotMountedException() | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think, if the user tries to uninstall an app that isn't installed, it's better to do it in good terms than in bad. An error is a bad term. Uninstallation finishing without doing anything, because nothing is mounted is a good term.
* | ||
* @throws ShellCommandRunnerException if given [RunResult] exited unsuccessfully. | ||
*/ | ||
fun ensureSuccess() {} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we don't need this as well as the exception because this looks like a high level API that isn't specific to commands or command runs. The installers can check for the exit code themselves or you can add a helper function to them to raise an exception.
Sounds like a dud, closing. |
Some changes looked fine, may be worth it to keep the PR open with those changes |