1use std::path::Path;
4
5use crate::config;
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8pub enum ReviewMode {
9 Comment,
11 App,
13}
14
15impl ReviewMode {
16 fn parse(value: Option<&str>) -> Option<Self> {
17 match value.map(str::trim) {
18 Some("app") => Some(Self::App),
19 Some("comment") => Some(Self::Comment),
20 Some(other) if !other.is_empty() => {
21 tracing::warn!(
22 value = other,
23 "unknown review.mode, expected comment or app"
24 );
25 None
26 }
27 _ => None,
28 }
29 }
30}
31
32pub fn resolve(project: Option<&str>, global: Option<&str>) -> ReviewMode {
34 ReviewMode::parse(project)
35 .or_else(|| ReviewMode::parse(global))
36 .unwrap_or(ReviewMode::Comment)
37}
38
39pub fn for_repo(repo: &str) -> ReviewMode {
41 let project_dir = config::get_projects_with_paths()
42 .ok()
43 .and_then(|projects| projects.into_iter().find(|(r, _)| r == repo))
44 .map(|(_, dir)| dir);
45 for_project_dir(project_dir.as_deref())
46}
47
48pub fn for_project_dir(project_dir: Option<&Path>) -> ReviewMode {
49 let project = project_dir.and_then(|dir| config::get_project_only(dir, "review.mode").ok());
50 let global = config::get_global("review.mode").ok();
51 resolve(project.as_deref(), global.as_deref())
52}
53
54#[cfg(test)]
55mod tests {
56 use std::fs;
57
58 use super::*;
59
60 #[test]
61 fn project_beats_global_and_comment_is_the_default() {
62 assert_eq!(resolve(Some("app"), Some("comment")), ReviewMode::App);
63 assert_eq!(resolve(Some("comment"), Some("app")), ReviewMode::Comment);
64 assert_eq!(resolve(None, Some("app")), ReviewMode::App);
65 assert_eq!(resolve(None, None), ReviewMode::Comment);
66 }
67
68 #[test]
69 fn an_unknown_value_falls_through_to_the_next_source() {
70 assert_eq!(resolve(Some("bogus"), Some("app")), ReviewMode::App);
71 assert_eq!(resolve(Some(" app "), None), ReviewMode::App);
72 assert_eq!(resolve(Some(""), None), ReviewMode::Comment);
73 }
74
75 #[test]
76 fn the_project_file_is_read_without_the_global_fallback() {
77 let dir = tempfile::tempdir().unwrap();
78 fs::write(dir.path().join(".orch.yml"), "review:\n mode: app\n").unwrap();
79 let value = config::get_project_only(dir.path(), "review.mode").unwrap();
80 assert_eq!(value, "app");
81
82 let empty = tempfile::tempdir().unwrap();
83 assert!(config::get_project_only(empty.path(), "review.mode").is_err());
84 }
85}