pub fn session_id() -> String {
let ppid = unsafe { libc::getppid() };
ppid.to_string()
}
pub fn project_id() -> String {
#[cfg(feature = "vipune-store")]
{
vipune::detect_project(None)
}
#[cfg(not(feature = "vipune-store"))]
{
detect_project_fallback()
}
}
#[cfg(not(feature = "vipune-store"))]
fn detect_project_fallback() -> String {
if let Ok(output) = std::process::Command::new("git")
.args(["remote", "get-url", "origin"])
.output()
{
if output.status.success() {
let url = String::from_utf8_lossy(&output.stdout).trim().to_string();
if let Some(name) = url.rsplit('/').next() {
let name = name.strip_suffix(".git").unwrap_or(name);
if !name.is_empty() {
return name.to_string();
}
}
}
}
if let Ok(output) = std::process::Command::new("git")
.args(["rev-parse", "--show-toplevel"])
.output()
{
if output.status.success() {
let path = String::from_utf8_lossy(&output.stdout).trim().to_string();
if let Some(name) = path.rsplit('/').next() {
if !name.is_empty() {
return name.to_string();
}
}
}
}
if let Ok(cwd) = std::env::current_dir() {
if let Some(name) = cwd.file_name() {
return name.to_string_lossy().to_string();
}
}
"unknown".to_string()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_session_id_is_nonzero() {
let id = session_id();
let pid: u32 = id.parse().expect("session_id should be numeric");
assert!(pid > 0);
}
#[test]
fn test_session_id_stable() {
assert_eq!(session_id(), session_id());
}
#[test]
fn test_project_id_nonempty() {
let id = project_id();
assert!(!id.is_empty());
}
#[test]
fn test_project_id_is_string() {
let id = project_id();
assert!(!id.is_empty(), "project_id must not be empty");
assert!(
id.is_ascii() || !id.is_empty(),
"project_id must be a string"
);
}
#[test]
fn test_project_id_no_newlines() {
let id = project_id();
assert!(
!id.contains('\n'),
"project_id must not contain newlines, got: {id:?}"
);
}
#[test]
#[cfg(not(feature = "vipune-store"))]
fn test_detect_project_fallback_cwd_fallback() {
let tmp = tempfile::tempdir().expect("tempdir");
let original = std::env::current_dir().expect("cwd");
std::env::set_current_dir(tmp.path()).expect("set_current_dir");
let id = detect_project_fallback();
std::env::set_current_dir(&original).expect("restore cwd");
assert!(!id.is_empty(), "fallback must not be empty");
}
}