1use std::fs;
9use std::io::ErrorKind;
10use std::path::Path;
11
12use anyhow::{Context as _, Result};
13
14pub fn read(path: impl AsRef<Path>) -> Result<Option<String>> {
16 let path = path.as_ref();
17 match fs::read_to_string(path) {
18 Ok(s) => {
19 let trimmed = s.trim();
20 if trimmed.is_empty() {
21 Ok(None)
22 } else {
23 Ok(Some(trimmed.to_string()))
24 }
25 }
26 Err(e) if e.kind() == ErrorKind::NotFound => Ok(None),
27 Err(e) => Err(e).with_context(|| format!("read {}", path.display())),
28 }
29}
30
31pub fn write(path: impl AsRef<Path>, id: &str) -> Result<()> {
33 let path = path.as_ref();
34 if let Some(parent) = path.parent() {
35 fs::create_dir_all(parent).with_context(|| format!("create {}", parent.display()))?;
36 }
37 fs::write(path, format!("{id}\n")).with_context(|| format!("write {}", path.display()))?;
38 Ok(())
39}
40
41pub fn clear(path: impl AsRef<Path>) -> Result<()> {
43 match fs::remove_file(path.as_ref()) {
44 Ok(()) => Ok(()),
45 Err(e) if e.kind() == ErrorKind::NotFound => Ok(()),
46 Err(e) => Err(e).context("remove active-session"),
47 }
48}
49
50#[cfg(test)]
51mod tests {
52 use super::*;
53
54 #[test]
55 fn round_trip() {
56 let dir = tempfile::tempdir().unwrap();
57 let path = dir.path().join("active-session");
58 assert!(read(&path).unwrap().is_none());
59 write(&path, "s_abc").unwrap();
60 assert_eq!(read(&path).unwrap().as_deref(), Some("s_abc"));
61 clear(&path).unwrap();
62 assert!(read(&path).unwrap().is_none());
63 clear(&path).unwrap();
65 }
66
67 #[test]
68 fn empty_file_returns_none() {
69 let dir = tempfile::tempdir().unwrap();
70 let path = dir.path().join("active-session");
71 std::fs::write(&path, "\n \n").unwrap();
72 assert!(read(&path).unwrap().is_none());
73 }
74}