1#![forbid(unsafe_code)]
12
13use anyhow::Context;
14use clap::Parser;
15use clap::Subcommand;
16use std::path::Path;
17use std::path::PathBuf;
18
19mod completions;
20pub mod fs_helpers;
21pub mod tasks;
22
23pub const XTASK_PATH_FILE: &str = "./target/xtask-path";
29
30#[derive(Clone)]
32pub struct XtaskCtx {
33 pub root: PathBuf,
35 pub in_git_hook: bool,
37 pub in_run_on_save: bool,
39}
40
41pub trait Xtask: Parser {
43 fn run(self, ctx: XtaskCtx) -> anyhow::Result<()>;
50}
51
52#[derive(Parser)]
53#[clap(name = "xtask", about = "HvLite repo automation")]
54struct Cli {
55 #[clap(subcommand)]
56 command: Commands,
57
58 #[clap(long)]
63 custom_root: Option<PathBuf>,
64
65 #[clap(long)]
76 run_on_save: bool,
77}
78
79#[derive(Subcommand)]
80enum Commands {
81 #[clap(hide = true)]
82 Hook(tasks::RunGitHook),
83 #[clap(hide = true)]
84 Complete(clap_dyn_complete::Complete),
85 Completions(completions::Completions),
86
87 Fmt(tasks::Fmt),
88 Fuzz(tasks::Fuzz),
89 GuestTest(tasks::GuestTest),
90 InstallGitHooks(tasks::InstallGitHooks),
91 VerifySize(tasks::VerifySize),
92}
93
94fn main() {
95 ci_logger::init("XTASK_LOG").unwrap();
96
97 if let Err(e) = try_main() {
98 log::error!("Error: {:#}", e);
99 std::process::exit(-1);
100 }
101}
102
103fn try_main() -> anyhow::Result<()> {
104 let cli = Cli::parse();
105
106 let orig_root = Path::new(&env!("CARGO_MANIFEST_DIR"))
107 .ancestors()
108 .nth(1)
109 .unwrap()
110 .to_path_buf();
111
112 let root = cli
113 .custom_root
114 .map(std::path::absolute)
115 .transpose()?
116 .unwrap_or(orig_root.clone());
117
118 std::env::set_current_dir(&root)?;
120
121 if let Ok(path) = std::env::current_exe() {
125 if let Err(e) = fs_err::write(orig_root.join(XTASK_PATH_FILE), path.display().to_string()) {
126 log::debug!("Unable to create XTASK_PATH_FILE: {:#}", e)
127 }
128 }
129
130 if !matches!(cli.command, Commands::Complete(..)) {
131 tasks::update_hooks(&root).context("failed to update git hooks")?;
132 }
133
134 let ctx = XtaskCtx {
135 root,
136 in_git_hook: matches!(cli.command, Commands::Hook(..)),
137 in_run_on_save: cli.run_on_save,
138 };
139
140 match cli.command {
141 Commands::Hook(task) => task.run(ctx),
142 Commands::Completions(task) => task.run(),
143 Commands::Complete(task) => {
144 futures::executor::block_on(task.println_to_stub_script::<Cli>(
145 Some("cargo"),
146 completions::XtaskCompleteFactory { ctx },
147 ));
148 Ok(())
149 }
150
151 Commands::Fmt(task) => task.run(ctx),
152 Commands::Fuzz(task) => task.run(ctx),
153 Commands::GuestTest(task) => task.run(ctx),
154 Commands::InstallGitHooks(task) => task.run(ctx),
155 Commands::VerifySize(task) => task.run(ctx),
156 }
157}