Skip to main content

xtask/
main.rs

1// Copyright (c) Meta Platforms, Inc. and affiliates.
2//
3// This software may be used and distributed according to the terms of the
4// GNU General Public License version 2.
5
6use 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        #[arg(
45            short = 'm',
46            long = "min-version",
47            help = "Minimum version floor; crates below this are set to it, others bump patch"
48        )]
49        min_version: Option<String>,
50    },
51}
52
53fn main() {
54    let cli = Cli::parse();
55
56    let log_level = if cli.verbose {
57        log::LevelFilter::Debug
58    } else {
59        log::LevelFilter::Warn
60    };
61
62    simplelog::TermLogger::init(
63        log_level,
64        simplelog::Config::default(),
65        simplelog::TerminalMode::Stderr,
66        simplelog::ColorChoice::Auto,
67    )
68    .unwrap();
69
70    let res = match cli.command {
71        Commands::Versions { format } => versions::version_command(format),
72        Commands::BumpVersions {
73            target,
74            min_version,
75        } => bump_versions::bump_versions_command(target.packages, target.all, min_version),
76    };
77
78    if let Err(e) = res {
79        eprintln!("Failed to run command: {e}");
80        std::process::exit(1);
81    }
82}
83
84fn get_cargo_metadata() -> Result<&'static Metadata> {
85    static CARGO_METADATA: OnceCell<Metadata> = OnceCell::new();
86
87    CARGO_METADATA.get_or_try_init(|| {
88        MetadataCommand::new()
89            .exec()
90            .context("Failed to run cargo metadata")
91    })
92}
93
94pub fn get_workspace_packages() -> Result<Vec<&'static Package>> {
95    let metadata = get_cargo_metadata()?;
96
97    // Filter to workspace member packages only
98    let workspace_packages: Vec<&Package> = metadata
99        .packages
100        .iter()
101        .filter(|package| metadata.workspace_members.contains(&package.id))
102        .collect();
103
104    Ok(workspace_packages)
105}
106
107pub fn get_rust_paths() -> Result<Vec<std::path::PathBuf>> {
108    let packages = get_workspace_packages()?;
109    Ok(packages
110        .iter()
111        .map(|pkg| pkg.manifest_path.as_std_path().to_path_buf())
112        .collect())
113}