1use anyhow::Context;
7use anyhow::Result;
8use cargo_metadata::{Metadata, MetadataCommand, Package};
9use clap::{Args, Parser, Subcommand};
10use once_cell::sync::OnceCell;
11
12mod bump_versions;
13mod versions;
14
15#[derive(Parser)]
16#[command(name = "xtask")]
17#[command(about = "Sched ext repository scripts and helpers")]
18struct Cli {
19 #[arg(short = 'v', long = "verbose", help = "Verbose logging")]
20 verbose: bool,
21
22 #[command(subcommand)]
23 command: Commands,
24}
25
26#[derive(Args)]
27#[group(required = true, multiple = false)]
28struct BumpTarget {
29 #[arg(short = 'p', long = "package", help = "Specific crates to bump")]
30 packages: Vec<String>,
31 #[arg(long, help = "Bump all workspace crates")]
32 all: bool,
33}
34
35#[derive(Subcommand)]
36enum Commands {
37 Versions {
38 #[arg(short = 'f', long = "format", default_value = "json")]
39 format: versions::Format,
40 },
41 BumpVersions {
42 #[command(flatten)]
43 target: BumpTarget,
44 },
45}
46
47fn main() {
48 let cli = Cli::parse();
49
50 let log_level = if cli.verbose {
51 log::LevelFilter::Debug
52 } else {
53 log::LevelFilter::Warn
54 };
55
56 simplelog::TermLogger::init(
57 log_level,
58 simplelog::Config::default(),
59 simplelog::TerminalMode::Stderr,
60 simplelog::ColorChoice::Auto,
61 )
62 .unwrap();
63
64 let res = match cli.command {
65 Commands::Versions { format } => versions::version_command(format),
66 Commands::BumpVersions { target } => {
67 bump_versions::bump_versions_command(target.packages, target.all)
68 }
69 };
70
71 if let Err(e) = res {
72 eprintln!("Failed to run command: {e}");
73 std::process::exit(1);
74 }
75}
76
77fn get_cargo_metadata() -> Result<&'static Metadata> {
78 static CARGO_METADATA: OnceCell<Metadata> = OnceCell::new();
79
80 CARGO_METADATA.get_or_try_init(|| {
81 MetadataCommand::new()
82 .exec()
83 .context("Failed to run cargo metadata")
84 })
85}
86
87pub fn get_workspace_packages() -> Result<Vec<&'static Package>> {
88 let metadata = get_cargo_metadata()?;
89
90 let workspace_packages: Vec<&Package> = metadata
92 .packages
93 .iter()
94 .filter(|package| metadata.workspace_members.contains(&package.id))
95 .collect();
96
97 Ok(workspace_packages)
98}
99
100pub fn get_rust_paths() -> Result<Vec<std::path::PathBuf>> {
101 let packages = get_workspace_packages()?;
102 Ok(packages
103 .iter()
104 .map(|pkg| pkg.manifest_path.as_std_path().to_path_buf())
105 .collect())
106}