justjavac/replace_self is a native MoonBit package for two closely related
deployment tasks:
- replacing the executable file of the currently running process
- deleting the executable file of the currently running process
It is designed for self-updating desktop applications, single-file CLI tools, installers, and bootstrap launchers that need a small cross-platform primitive instead of a full updater framework.
- Linux: atomically replaces the current executable with
rename(2)and deletes it withunlink(2) - macOS: uses the same Unix strategy as Linux
- Windows: launches a detached helper script that waits for process exit and then performs the final move or delete
- Small API surface with typed errors
- Native-only implementation with no JavaScript or WebAssembly fallback
- Integration tests that exercise real executable replacement and deletion
Add the dependency to your moon.mod.json:
{
"deps": {
"justjavac/replace_self": "0.1.1"
}
}This package only supports the native backend. Set "preferred-target": "native"
for the smoothest workflow when building command-line tools or desktop apps.
pub fn replace_self(new_executable : String) -> Result[Unit, ReplaceSelfError]Replaces the executable file of the currently running process.
Requirements:
new_executablemust be a non-empty absolute path- the replacement file must already exist
- the replacement path must not be the same as the current executable path
Platform semantics:
- Linux and macOS complete the replacement before the function returns
- Windows returns after scheduling the replacement helper; the current process should exit soon afterward so the helper can finish the move
pub fn delete_self() -> Result[Unit, ReplaceSelfError]Deletes the executable file of the currently running process.
Platform semantics:
- Linux and macOS unlink the file immediately
- Windows schedules deletion through the detached helper and expects the current process to exit shortly afterward
pub enum ReplaceSelfError {
EmptyReplacementPath
RelativeReplacementPath(String)
ReplacementMatchesCurrentExecutable(String)
ExecutablePathUnavailable
UnsupportedPlatform(Platform)
NativeFailure(action~ : String, message~ : String)
}NativeFailure preserves the backend action label together with the best
platform error message the package could extract from the operating system.
match @replace_self.replace_self("/opt/my-app/my-app.next") {
Ok(()) => ()
Err(error) => {
println("update failed: \{error}")
}
}match @replace_self.delete_self() {
Ok(()) => ()
Err(error) => {
println("self-delete failed: \{error}")
}
}Windows does not let a running process overwrite or delete its own .exe
directly. This package handles that by writing a temporary helper script into
the system temp directory and launching it with cmd.exe.
That helper:
- waits until the current process exits and the executable is unlocked
- performs the final delete or move
- removes the temporary script file
Because of that, Ok(()) on Windows means "scheduled successfully", not "the
file is already gone or replaced".
Run the native test suite:
moon test --target nativeThe test suite includes:
- validation tests for path rules and error behavior
- white-box helper tests for path joining and polling
- integration tests that launch a temporary fixture executable and verify that
replace_self()anddelete_self()affect a real copied binary on disk
Generate a local native coverage report:
moon coverage clean
moon coverage analyze -p justjavac/replace_self -- -f cobertura -o coverage.xmlGitHub Actions uploads coverage from Linux, macOS, and Windows to Codecov, and
the badges at the top of this README update after Codecov finishes processing
the latest main branch reports.
- Unix replacement is implemented with a same-path
rename, which is atomic on a single filesystem - Windows replacement and deletion use an external helper script because the running executable remains locked
- All public API docs live in the source files so
moon docand Mooncakes show the same behavior notes as this README
MIT