Skip to main content

dealer/
main.rs

1mod backend;
2mod cli;
3mod compiler;
4mod doctor;
5mod error;
6mod messages;
7mod names;
8mod project;
9mod scaffold;
10mod state;
11#[cfg(test)]
12mod test_support;
13mod toolchain;
14mod workflow;
15mod xtazy;
16
17use std::env;
18use std::path::{Path, PathBuf};
19
20fn main() {
21    let args: Vec<String> = env::args().collect();
22    let command = match cli::parse_args(&args) {
23        Ok(parsed) => parsed,
24        Err(message) => {
25            eprintln!("{message}");
26            std::process::exit(1);
27        }
28    };
29
30    match command {
31        cli::CommandKind::Version => {
32            println!("dealer {}", env!("CARGO_PKG_VERSION"));
33        }
34        cli::CommandKind::Check {
35            project: project_arg,
36        } => {
37            let project = validate_project_or_exit(&project_arg);
38            let workspace_root = workspace_root();
39            let toolchain = toolchain::ToolchainSelection::discover(
40                &workspace_root,
41                &toolchain::ToolchainEnv::from_process_env(),
42            );
43            workflow::run_check_or_exit(&project, &toolchain);
44        }
45        cli::CommandKind::Build {
46            project: project_arg,
47            mode,
48        } => {
49            let project = validate_project_or_exit(&project_arg);
50            let workspace_root = workspace_root();
51            let toolchain = toolchain::ToolchainSelection::discover(
52                &workspace_root,
53                &toolchain::ToolchainEnv::from_process_env(),
54            );
55            workflow::run_build_or_exit(&project, &toolchain, mode);
56        }
57        cli::CommandKind::Doctor => {
58            let workspace_root = workspace_root();
59            let toolchain = toolchain::ToolchainSelection::discover(
60                &workspace_root,
61                &toolchain::ToolchainEnv::from_process_env(),
62            );
63            println!("{}", doctor::report(&toolchain));
64        }
65        cli::CommandKind::Fmt { project, check } => not_implemented(&format!(
66            "fmt{} for project '{}'",
67            if check { " --check" } else { "" },
68            project
69        )),
70        cli::CommandKind::Install { package, project } => {
71            if let Some(package) = package {
72                not_implemented(&format!(
73                    "install package '{}' into project '{}'",
74                    package, project
75                ));
76            } else {
77                not_implemented(&format!("install dependencies for project '{}'", project));
78            }
79        }
80        cli::CommandKind::Run { project, mode } => {
81            let project = validate_project_or_exit(&project);
82            let workspace_root = workspace_root();
83            let toolchain = toolchain::ToolchainSelection::discover(
84                &workspace_root,
85                &toolchain::ToolchainEnv::from_process_env(),
86            );
87            workflow::run_project_or_exit(&project, &toolchain, mode);
88        }
89        cli::CommandKind::Clean { project } => {
90            let project = validate_project_or_exit(&project);
91            workflow::run_clean_or_exit(&project);
92        }
93        cli::CommandKind::Init { kind, path } => {
94            let target = path.as_deref().unwrap_or(".");
95            match scaffold::init_project(kind, Path::new(target)) {
96                Ok(root_file) => println!("Created {}", root_file.display()),
97                Err(error) => {
98                    eprintln!("dealer: {error}");
99                    std::process::exit(1);
100                }
101            }
102        }
103        cli::CommandKind::Xtazy { subcommand } => {
104            let workspace_root = workspace_root();
105            match xtazy::run_subcommand(subcommand, &workspace_root) {
106                Ok(message) => println!("{message}"),
107                Err(error) => {
108                    eprintln!("dealer: {error}");
109                    std::process::exit(1);
110                }
111            }
112        }
113        cli::CommandKind::SelfUpdate => not_implemented("self update"),
114    }
115}
116
117fn not_implemented(feature: &str) {
118    println!("dealer: {}", messages::not_implemented(feature));
119}
120
121fn validate_project_or_exit(project_arg: &str) -> project::ProjectRoot {
122    match project::validate_project_root(Path::new(project_arg)) {
123        Ok(project) => project,
124        Err(message) => {
125            eprintln!("dealer: {message}");
126            std::process::exit(1);
127        }
128    }
129}
130
131pub(crate) fn workspace_root() -> PathBuf {
132    // Development fallback root only. Product installs should use `~/.dealer/xtazy/<version>/`
133    // via ToolchainSelection, not this source-tree path.
134    let compiled_workspace = Path::new(env!("CARGO_MANIFEST_DIR"))
135        .parent()
136        .expect("xtazy-dealer should live inside workspace root at build time")
137        .to_path_buf();
138    if compiled_workspace.join("xtazy-dealer").is_dir() {
139        return compiled_workspace;
140    }
141
142    env::current_dir().unwrap_or_else(|_| PathBuf::from("."))
143}