waterui_cli/toolchain/
dxc.rs1use std::path::PathBuf;
8
9use crate::toolchain::{
10 Host, Installation, Toolchain, ToolchainError,
11 managed_tool::{self, ManagedToolError},
12};
13
14#[derive(Debug, Clone, Copy, Default)]
16pub struct Dxc;
17
18impl Dxc {
19 pub async fn path(&self, host: &Host) -> Option<PathBuf> {
22 if let Ok(path) = host.which("dxc").await {
23 return Some(path);
24 }
25 managed_tool::dxc().binary_path(host)
26 }
27}
28
29impl Toolchain for Dxc {
30 type Installation = DxcInstallation;
31
32 async fn check(&self, host: &Host) -> Result<(), ToolchainError<Self::Installation>> {
33 if self.path(host).await.is_some() {
34 Ok(())
35 } else {
36 Err(ToolchainError::fixable(DxcInstallation))
37 }
38 }
39}
40
41#[derive(Debug, Clone, Copy)]
44pub struct DxcInstallation;
45
46#[derive(Debug, thiserror::Error)]
48#[error(transparent)]
49pub struct FailToInstallDxc(#[from] ManagedToolError);
50
51impl Installation for DxcInstallation {
52 type Error = FailToInstallDxc;
53
54 async fn install(&self, host: &Host) -> Result<(), Self::Error> {
55 managed_tool::dxc().install(host).await?;
56 Ok(())
57 }
58}
59
60#[cfg(test)]
61mod tests {
62 use super::Dxc;
63 use crate::toolchain::testing::TestMachine;
64 use crate::toolchain::{Toolchain, ToolchainError};
65
66 #[test]
67 fn missing_reports_fixable() {
68 let machine = TestMachine::new();
69 let host = machine.host(Vec::<(String, String)>::new());
70 let result = smol::block_on(Dxc.check(&host));
71 assert!(
72 matches!(result, Err(ToolchainError::Fixable(_))),
73 "a host without dxc must report fixable: {result:?}"
74 );
75 }
76
77 #[test]
78 fn ok_when_dxc_on_path() {
79 let machine = TestMachine::new();
80 machine.install("dxc");
81 let host = machine.host(Vec::<(String, String)>::new());
82 smol::block_on(Dxc.check(&host)).expect("dxc on PATH must be ok");
83 }
84
85 #[test]
86 fn ok_when_dxc_is_managed() {
87 let machine = TestMachine::new();
88 let dxc = crate::toolchain::managed_tool::dxc();
89 let install_dir = dxc
90 .install_dir(&machine.host(Vec::<(String, String)>::new()))
91 .unwrap();
92 let binary = install_dir.join(&dxc.binary);
93 std::fs::create_dir_all(binary.parent().unwrap()).unwrap();
94 std::fs::write(&binary, b"").unwrap();
95
96 let host = machine.host(Vec::<(String, String)>::new());
97 smol::block_on(Dxc.check(&host)).expect("a managed dxc must satisfy the check");
98 }
99
100 #[test]
101 fn install_reuses_an_unpacked_copy() {
102 let machine = TestMachine::new();
103 let dxc = crate::toolchain::managed_tool::dxc();
104 let host = machine.host(Vec::<(String, String)>::new());
105 let install_dir = dxc.install_dir(&host).unwrap();
106 let binary = install_dir.join(&dxc.binary);
107 std::fs::create_dir_all(binary.parent().unwrap()).unwrap();
108 std::fs::write(&binary, b"").unwrap();
109
110 let dir = smol::block_on(dxc.install(&host)).expect("install must succeed");
114 assert_eq!(dir, binary.parent().unwrap());
115 assert_eq!(std::fs::read(&binary).unwrap(), b"");
116 }
117}