winbrew_core/
temp_workspace.rs1use std::path::{Path, PathBuf};
8use std::sync::atomic::{AtomicUsize, Ordering};
9
10static TEMP_ROOT_SUFFIX: AtomicUsize = AtomicUsize::new(0);
11
12pub fn build_temp_root(name: &str, version: &str) -> PathBuf {
14 temp_root_base().join(temp_root_name(name, version))
15}
16
17pub fn temp_root_prefix(name: &str, version: &str) -> String {
19 format!(
20 "winbrew-install-{}-{}-",
21 sanitize_component(name),
22 sanitize_component(version)
23 )
24}
25
26pub fn temp_root_base() -> PathBuf {
28 std::env::temp_dir().join("winbrew")
29}
30
31pub fn is_temp_root_for(name: &str, version: &str, path: &Path) -> bool {
33 path.file_name()
34 .and_then(|value| value.to_str())
35 .map(|file_name| file_name.starts_with(&temp_root_prefix(name, version)))
36 .unwrap_or(false)
37}
38
39fn temp_root_name(name: &str, version: &str) -> String {
40 let suffix = TEMP_ROOT_SUFFIX.fetch_add(1, Ordering::Relaxed);
41 let mut segment = String::with_capacity(temp_root_prefix(name, version).len() + 20);
42 segment.push_str(&temp_root_prefix(name, version));
43 segment.push_str(&std::process::id().to_string());
44 segment.push('-');
45 segment.push_str(&suffix.to_string());
46
47 segment
48}
49
50fn sanitize_component(value: &str) -> String {
51 value
52 .chars()
53 .map(|ch| {
54 if ch.is_ascii_alphanumeric() || matches!(ch, '.' | '-' | '_') {
55 ch
56 } else {
57 '_'
58 }
59 })
60 .collect()
61}