forked from lix-project/lix-installer
Uninstalling from /nix/harmonic
works (#100)
* Move binary out of /nix if it is there during uninstall * Add tracing * Stick some random bytes on the end of the tmp exe
This commit is contained in:
parent
ac5660b3e0
commit
cfded4bb8a
16
.github/workflows/ci.yml
vendored
16
.github/workflows/ci.yml
vendored
|
@ -122,9 +122,7 @@ jobs:
|
|||
- name: Initial install
|
||||
run: sudo GITHUB_PATH=$GITHUB_PATH PATH=$PATH:$HOME/bin RUST_LOG=harmonic=trace RUST_BACKTRACE=full ./harmonic install steam-deck --persistence `pwd`/ci-test-nix --extra-conf "access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}" --no-confirm
|
||||
- name: Initial uninstall (without a `nix run` first)
|
||||
run: |
|
||||
cp /nix/harmonic ./harmonic # Since /nix is a mount we must avoid requiring it to remain existing
|
||||
sudo GITHUB_PATH=$GITHUB_PATH PATH=$PATH:$HOME/bin RUST_LOG=harmonic=trace RUST_BACKTRACE=full ./harmonic uninstall --no-confirm
|
||||
run: sudo GITHUB_PATH=$GITHUB_PATH PATH=$PATH:$HOME/bin RUST_LOG=harmonic=trace RUST_BACKTRACE=full /nix/harmonic uninstall --no-confirm
|
||||
- name: Repeated install
|
||||
run: sudo GITHUB_PATH=$GITHUB_PATH PATH=$PATH:$HOME/bin RUST_LOG=harmonic=trace RUST_BACKTRACE=full ./harmonic install steam-deck --persistence `pwd`/ci-test-nix --extra-conf "access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}" --no-confirm
|
||||
- name: echo $PATH
|
||||
|
@ -150,9 +148,7 @@ jobs:
|
|||
# if: success() || failure()
|
||||
# shell: fish --login {0}
|
||||
- name: Repeated uninstall
|
||||
run: |
|
||||
cp /nix/harmonic ./harmonic # Since /nix is a mount we must avoid requiring it to remain existing
|
||||
sudo GITHUB_PATH=$GITHUB_PATH PATH=$PATH:$HOME/bin RUST_LOG=harmonic=trace RUST_BACKTRACE=full ./harmonic uninstall --no-confirm
|
||||
run: sudo GITHUB_PATH=$GITHUB_PATH PATH=$PATH:$HOME/bin RUST_LOG=harmonic=trace RUST_BACKTRACE=full /nix/harmonic uninstall --no-confirm
|
||||
|
||||
build-x86_64-darwin:
|
||||
name: Build x86_64 Darwin
|
||||
|
@ -187,9 +183,7 @@ jobs:
|
|||
- name: Initial install
|
||||
run: sudo GITHUB_PATH=$GITHUB_PATH RUST_LOG=harmonic=trace RUST_BACKTRACE=full ./harmonic install darwin-multi --extra-conf "access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}" --no-confirm
|
||||
- name: Initial uninstall (without a `nix run` first)
|
||||
run: |
|
||||
cp /nix/harmonic ./harmonic # Since /nix is a mount we must avoid requiring it to remain existing
|
||||
sudo GITHUB_PATH=$GITHUB_PATH RUST_LOG=harmonic=trace RUST_BACKTRACE=full ./harmonic uninstall --no-confirm
|
||||
run: sudo GITHUB_PATH=$GITHUB_PATH RUST_LOG=harmonic=trace RUST_BACKTRACE=full /nix/harmonic uninstall --no-confirm
|
||||
- name: Repeated install
|
||||
run: sudo GITHUB_PATH=$GITHUB_PATH RUST_LOG=harmonic=trace RUST_BACKTRACE=full ./harmonic install darwin-multi --extra-conf "access-tokens = github.com=${{ secrets.GITHUB_TOKEN }}" --no-confirm
|
||||
- name: echo $PATH
|
||||
|
@ -214,7 +208,5 @@ jobs:
|
|||
if: success() || failure()
|
||||
shell: fish --login {0}
|
||||
- name: Repeated uninstall
|
||||
run: |
|
||||
cp /nix/harmonic ./harmonic # Since /nix is a mount we must avoid requiring it to remain existing
|
||||
sudo GITHUB_PATH=$GITHUB_PATH RUST_LOG=harmonic=trace RUST_BACKTRACE=full ./harmonic uninstall --no-confirm
|
||||
run: sudo GITHUB_PATH=$GITHUB_PATH RUST_LOG=harmonic=trace RUST_BACKTRACE=full /nix/harmonic uninstall --no-confirm
|
||||
|
|
@ -1,4 +1,8 @@
|
|||
use std::{path::PathBuf, process::ExitCode};
|
||||
use std::{
|
||||
ffi::CString,
|
||||
path::{Path, PathBuf},
|
||||
process::ExitCode,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
cli::{is_root, signal_channel},
|
||||
|
@ -7,6 +11,7 @@ use crate::{
|
|||
};
|
||||
use clap::{ArgAction, Parser};
|
||||
use eyre::{eyre, WrapErr};
|
||||
use rand::Rng;
|
||||
|
||||
use crate::cli::{interaction, CommandExecute};
|
||||
|
||||
|
@ -47,6 +52,47 @@ impl CommandExecute for Uninstall {
|
|||
));
|
||||
}
|
||||
|
||||
// During install, `harmonic` will store a copy of itself in `/nix/harmonic`
|
||||
// If the user opted to run that particular copy of Harmonic to do this uninstall,
|
||||
// well, we have a problem, since the binary would delete itself.
|
||||
// Instead, detect if we're in that location, if so, move the binary and `execv` it.
|
||||
if let Ok(current_exe) = std::env::current_exe() {
|
||||
if current_exe.as_path() == Path::new("/nix/harmonic") {
|
||||
tracing::debug!(
|
||||
"Detected uninstall from `/nix/harmonic`, moving executable and re-executing"
|
||||
);
|
||||
let temp = std::env::temp_dir();
|
||||
let random_trailer: String = {
|
||||
const CHARSET: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ\
|
||||
abcdefghijklmnopqrstuvwxyz\
|
||||
0123456789";
|
||||
const PASSWORD_LEN: usize = 16;
|
||||
let mut rng = rand::thread_rng();
|
||||
|
||||
(0..PASSWORD_LEN)
|
||||
.map(|_| {
|
||||
let idx = rng.gen_range(0..CHARSET.len());
|
||||
CHARSET[idx] as char
|
||||
})
|
||||
.collect()
|
||||
};
|
||||
let temp_exe = temp.join(&format!("harmonic-{random_trailer}"));
|
||||
tokio::fs::copy(¤t_exe, &temp_exe)
|
||||
.await
|
||||
.wrap_err("Copying harmonic to tempdir")?;
|
||||
let args = std::env::args();
|
||||
let mut arg_vec_cstring = vec![];
|
||||
for arg in args {
|
||||
arg_vec_cstring.push(CString::new(arg).wrap_err("Making arg into C string")?);
|
||||
}
|
||||
let temp_exe_cstring = CString::new(temp_exe.to_string_lossy().into_owned())
|
||||
.wrap_err("Making C string of executable path")?;
|
||||
|
||||
nix::unistd::execv(&temp_exe_cstring, &arg_vec_cstring)
|
||||
.wrap_err("Executing copied Harmonic")?;
|
||||
}
|
||||
}
|
||||
|
||||
let install_receipt_string = tokio::fs::read_to_string(receipt)
|
||||
.await
|
||||
.wrap_err("Reading receipt")?;
|
||||
|
|
Loading…
Reference in a new issue