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 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}