Files
huskies/server/src/service/project/selection.rs
T

101 lines
2.9 KiB
Rust

//! Pure project-selection logic — no I/O, no async, no side effects.
//!
//! All functions here are deterministic and depend only on their arguments.
/// Promote a project path to the front of the known-projects list.
///
/// Removes any existing occurrence of `path` and inserts it at position 0,
/// so the most-recently-opened project is always first.
pub fn promote_to_front(mut projects: Vec<String>, path: &str) -> Vec<String> {
projects.retain(|p| p != path);
projects.insert(0, path.to_string());
projects
}
#[allow(dead_code)]
/// Extract the display name for a project from its filesystem path.
///
/// Returns the last non-empty path component, or `None` for root or empty input.
pub fn project_name_from_path(path: &str) -> Option<&str> {
path.trim_end_matches('/')
.rsplit('/')
.find(|s| !s.is_empty())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn promote_to_front_inserts_new_path_at_position_zero() {
let result = promote_to_front(vec!["/a".to_string(), "/b".to_string()], "/c");
assert_eq!(result, vec!["/c", "/a", "/b"]);
}
#[test]
fn promote_to_front_moves_existing_entry_to_front() {
let result = promote_to_front(
vec!["/a".to_string(), "/b".to_string(), "/c".to_string()],
"/b",
);
assert_eq!(result, vec!["/b", "/a", "/c"]);
}
#[test]
fn promote_to_front_is_idempotent_when_already_first() {
let result = promote_to_front(vec!["/a".to_string(), "/b".to_string()], "/a");
assert_eq!(result, vec!["/a", "/b"]);
}
#[test]
fn promote_to_front_handles_empty_list() {
let result = promote_to_front(vec![], "/new");
assert_eq!(result, vec!["/new"]);
}
#[test]
fn promote_to_front_deduplicates_single_entry() {
let result = promote_to_front(vec!["/a".to_string()], "/a");
assert_eq!(result, vec!["/a"]);
}
#[test]
fn project_name_from_path_extracts_last_component() {
assert_eq!(
project_name_from_path("/home/user/myproject"),
Some("myproject")
);
}
#[test]
fn project_name_from_path_handles_trailing_slash() {
assert_eq!(
project_name_from_path("/home/user/myproject/"),
Some("myproject")
);
}
#[test]
fn project_name_from_path_returns_none_for_root() {
assert_eq!(project_name_from_path("/"), None);
}
#[test]
fn project_name_from_path_returns_none_for_empty() {
assert_eq!(project_name_from_path(""), None);
}
#[test]
fn project_name_from_path_handles_single_component() {
assert_eq!(project_name_from_path("myproject"), Some("myproject"));
}
#[test]
fn project_name_from_path_handles_deep_path() {
assert_eq!(
project_name_from_path("/a/b/c/d/project-name"),
Some("project-name")
);
}
}