• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

kaspar030 / laze / 23018260404

12 Mar 2026 06:43PM UTC coverage: 79.193% (-0.02%) from 79.212%
23018260404

push

github

web-flow
fix: use relative build_dir path in tab completer (#873)

0 of 3 new or added lines in 1 file covered. (0.0%)

3376 of 4263 relevant lines covered (79.19%)

96.51 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

3.49
/src/cli/completer.rs
1
use std::{
2
    env,
3
    sync::{atomic::AtomicBool, LazyLock, Mutex},
4
};
5

6
use camino::Utf8PathBuf;
7
use clap_complete::CompletionCandidate;
8

9
use crate::model::ContextBag;
10

11
static COMPLETING: AtomicBool = AtomicBool::new(false);
12
static STATE: LazyLock<Mutex<CompleterState>> = LazyLock::new(|| {
×
13
    COMPLETING.store(true, std::sync::atomic::Ordering::Release);
×
14
    Mutex::new(CompleterState::new())
×
15
});
×
16

17
pub fn completing() -> bool {
3✔
18
    COMPLETING.load(std::sync::atomic::Ordering::Acquire)
3✔
19
}
3✔
20

21
#[derive(Default)]
22
struct CompleterState {
23
    contexts: Option<ContextBag>,
24
}
25

26
impl CompleterState {
27
    pub fn new() -> Self {
×
28
        let cwd = Utf8PathBuf::try_from(env::current_dir().unwrap()).expect("cwd not UTF8");
×
29
        let project_root = crate::determine_project_root(&cwd);
×
30
        if let Ok((project_root, project_file)) = project_root {
×
31
            // project_root was previously found by `determine_project_root()`, so we know it
32
            // exists and is a directory. `unwrap()` here is fine, if that fails, something is
33
            // really wrong.
NEW
34
            env::set_current_dir(&project_root).unwrap();
×
35

NEW
36
            let build_dir = "build".into();
×
37
            let project_file = project_root.join(project_file);
×
NEW
38
            let res = crate::data::load(&project_file, build_dir);
×
39
            // TODO: this is where the error is eaten, when this fails. log?
40
            let contexts = res.ok().map(|(contexts, _, _)| contexts);
×
41
            Self { contexts }
×
42
        } else {
43
            Self { contexts: None }
×
44
        }
45
    }
×
46

47
    pub fn builders(&self) -> Vec<CompletionCandidate> {
×
48
        if let Some(contexts) = self.contexts.as_ref() {
×
49
            contexts
×
50
                .builders()
×
51
                .map(|builder| {
×
52
                    CompletionCandidate::new(&builder.name)
×
53
                        .help(builder.help.as_ref().map(|help| help.into()))
×
54
                })
×
55
                .collect()
×
56
        } else {
57
            Vec::new()
×
58
        }
59
    }
×
60

61
    pub fn apps(&self) -> Vec<CompletionCandidate> {
×
62
        if let Some(contexts) = self.contexts.as_ref() {
×
63
            contexts
×
64
                .modules()
×
65
                .filter(|(_, module)| module.is_binary)
×
66
                .map(|(name, module)| {
×
67
                    CompletionCandidate::new(name)
×
68
                        .help(module.help.as_ref().map(|help| help.into()))
×
69
                })
×
70
                .collect()
×
71
        } else {
72
            Vec::new()
×
73
        }
74
    }
×
75

76
    pub fn modules(&self) -> Vec<CompletionCandidate> {
×
77
        if let Some(contexts) = self.contexts.as_ref() {
×
78
            contexts
×
79
                .modules()
×
80
                .map(|(name, module)| {
×
81
                    CompletionCandidate::new(name)
×
82
                        .help(module.help.as_ref().map(|help| help.into()))
×
83
                })
×
84
                .collect()
×
85
        } else {
86
            Vec::new()
×
87
        }
88
    }
×
89

90
    pub fn tasks(&self) -> Vec<CompletionCandidate> {
×
91
        if let Some(contexts) = self.contexts.as_ref() {
×
92
            contexts
×
93
                .modules()
×
94
                .flat_map(|(_name, module)| module.tasks.iter())
×
95
                .chain(
×
96
                    contexts
×
97
                        .contexts
×
98
                        .iter()
×
99
                        .filter_map(|c| c.tasks.as_ref())
×
100
                        .flat_map(|tasks| tasks.iter()),
×
101
                )
102
                .map(|(name, task)| {
×
103
                    CompletionCandidate::new(name).help(task.help.as_ref().map(|help| help.into()))
×
104
                })
×
105
                .collect()
×
106
        } else {
107
            Vec::new()
×
108
        }
109
    }
×
110
}
111

112
pub fn app_completer() -> Vec<CompletionCandidate> {
×
113
    let state = STATE.lock().unwrap();
×
114
    state.apps()
×
115
}
×
116

117
pub fn builder_completer() -> Vec<CompletionCandidate> {
×
118
    let state = STATE.lock().unwrap();
×
119
    state.builders()
×
120
}
×
121

122
pub fn module_completer() -> Vec<CompletionCandidate> {
×
123
    let state = STATE.lock().unwrap();
×
124
    state.modules()
×
125
}
×
126

127
pub fn task_completer() -> Vec<CompletionCandidate> {
×
128
    let state = STATE.lock().unwrap();
×
129
    state.tasks()
×
130
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc