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