use std::path::PathBuf;
use crate::core::paths::FRAMEWORK_DIR_NAME;
pub const DEFAULT_DAEMON_ADDR: &str = "127.0.0.1:7880";
pub const DEFAULT_DAEMON_URL: &str = "http://127.0.0.1:7880";
pub fn default_daemon_addr() -> std::net::SocketAddr {
DEFAULT_DAEMON_ADDR
.parse()
.expect("DEFAULT_DAEMON_ADDR is a valid SocketAddr literal")
}
pub fn lock_file_path() -> PathBuf {
dirs::home_dir()
.unwrap_or_else(|| PathBuf::from("."))
.join(FRAMEWORK_DIR_NAME)
.join("daemon.lock")
}
pub fn resolve_daemon_url(explicit: Option<&str>) -> String {
if let Some(url) = explicit
&& !url.is_empty()
&& url != DEFAULT_DAEMON_URL
{
return url.to_string();
}
if let Some(url) = read_lock_file_url() {
return url;
}
explicit
.filter(|u| !u.is_empty())
.unwrap_or(DEFAULT_DAEMON_URL)
.to_string()
}
fn read_lock_file_url() -> Option<String> {
let path = lock_file_path();
let content = std::fs::read_to_string(&path).ok()?;
let mut addr: Option<String> = None;
let mut pid: Option<u32> = None;
for line in content.lines() {
if let Some(v) = line.strip_prefix("addr = ") {
addr = Some(v.trim_matches('"').to_string());
}
if let Some(v) = line.strip_prefix("pid = ") {
pid = v.trim().parse::<u32>().ok();
}
}
#[cfg(unix)]
if let Some(p) = pid {
if unsafe { libc::kill(p as libc::pid_t, 0) } != 0 {
let _ = std::fs::remove_file(&path);
return None;
}
}
addr
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn explicit_url_wins_over_everything() {
let result = resolve_daemon_url(Some("http://example.com:9999"));
assert_eq!(result, "http://example.com:9999");
}
#[test]
fn empty_explicit_falls_through() {
let result = resolve_daemon_url(Some(""));
assert!(!result.is_empty());
}
#[test]
fn default_returned_when_no_lock_and_no_explicit() {
let result = resolve_daemon_url(None);
assert!(result.starts_with("http"));
}
#[test]
fn default_url_matches_addr() {
assert_eq!(
DEFAULT_DAEMON_URL,
format!("http://{DEFAULT_DAEMON_ADDR}"),
"client default URL and daemon bind addr drifted (issue #1268)"
);
}
#[test]
fn default_addr_parses() {
let addr = default_daemon_addr();
assert_eq!(addr.to_string(), DEFAULT_DAEMON_ADDR);
assert_eq!(addr.port(), 7880);
}
#[test]
fn lock_file_path_is_under_framework_root() {
let path = lock_file_path();
assert!(
path.ends_with(format!("{FRAMEWORK_DIR_NAME}/daemon.lock")),
"lock file path {path:?} is not under the {FRAMEWORK_DIR_NAME} root"
);
assert_eq!(
path.parent().and_then(|p| p.file_name()),
Some(std::ffi::OsStr::new(FRAMEWORK_DIR_NAME))
);
}
}