1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
|
use std::{
env::{self, set_current_dir},
ffi::CString,
fs,
io::Write,
panic,
process::Command,
ptr,
sync::atomic::{AtomicBool, Ordering},
};
static RELOAD: AtomicBool = AtomicBool::new(false);
fn exe_path() -> String {
env::current_exe()
.unwrap()
.to_string_lossy()
.replace(" (deleted)", "")
}
fn cargo_path() -> Option<String> {
let exe = exe_path();
let parts: Vec<_> = exe.split('/').collect();
for i in (0..parts.len()).rev() {
let base_dir = format!("/{}", parts[0..i].join("/"));
let toml_path = format!("/{base_dir}/Cargo.toml");
if fs::exists(toml_path).unwrap() {
return Some(base_dir);
}
}
None
}
pub fn begin_reload() {
let Some(cargo_path) = cargo_path() else {
return;
};
set_current_dir(cargo_path).unwrap();
let Ok(status) = Command::new("cargo").arg("build").status() else {
return;
};
if !status.success() {
return;
}
RELOAD.store(true, Ordering::SeqCst);
panic::resume_unwind(Box::new(42));
}
/// # Safety
/// ONLY TO BE CALLED FROM MAIN WHEN NOT A SINGLE RESOURCE IS HELD
pub unsafe fn continue_reload() {
if !RELOAD.load(Ordering::SeqCst) {
return;
}
eprintln!("reloading...");
let _ = std::io::stdout().lock().flush();
unsafe { exec() }
eprintln!("exec failed.");
}
unsafe fn exec() {
// path to this executable
let exe_c = CString::new(exe_path()).unwrap();
// argv
let args: Vec<CString> = env::args().map(|a| CString::new(a).unwrap()).collect();
let mut argv: Vec<*const libc::c_char> = args.iter().map(|a| a.as_ptr()).collect();
argv.push(ptr::null());
unsafe {
libc::execv(exe_c.as_ptr(), argv.as_ptr());
}
}
|