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 install;
14mod versions;
15
16#[derive(Parser)]
17#[command(name = "xtask")]
18#[command(about = "Sched ext repository scripts and helpers")]
19struct Cli {
20    #[arg(short = 'v', long = "verbose", help = "Verbose logging")]
21    verbose: bool,
22
23    #[command(subcommand)]
24    command: Commands,
25}
26
27#[derive(Args)]
28#[group(required = true, multiple = false)]
29struct BumpTarget {
30    #[arg(short = 'p', long = "package", help = "Specific crates to bump")]
31    packages: Vec<String>,
32    #[arg(long, help = "Bump all workspace crates")]
33    all: bool,
34}
35
36#[derive(Subcommand)]
37enum Commands {
38    Versions {
39        #[arg(short = 'f', long = "format", default_value = "json")]
40        format: versions::Format,
41    },
42    BumpVersions {
43        #[command(flatten)]
44        target: BumpTarget,
45        #[arg(
46            short = 'm',
47            long = "min-version",
48            help = "Minimum version floor; crates below this are set to it, others bump patch"
49        )]
50        min_version: Option<String>,
51    },
52    /// Install scx.service, /etc/default/scx, the shipped scheduler
53    /// catalog and the scxcli polkit policy; copies files only, no binaries
54    Install(install::InstallArgs),
55}
56
57fn main() {
58    let cli = Cli::parse();
59
60    let log_level = if cli.verbose {
61        log::LevelFilter::Debug
62    } else {
63        log::LevelFilter::Warn
64    };
65
66    simplelog::TermLogger::init(
67        log_level,
68        simplelog::Config::default(),
69        simplelog::TerminalMode::Stderr,
70        simplelog::ColorChoice::Auto,
71    )
72    .unwrap();
73
74    let res = match cli.command {
75        Commands::Versions { format } => versions::version_command(format),
76        Commands::BumpVersions {
77            target,
78            min_version,
79        } => bump_versions::bump_versions_command(target.packages, target.all, min_version),
80        Commands::Install(args) => install::install_command(args),
81    };
82
83    if let Err(e) = res {
84        eprintln!("Failed to run command: {e}");
85        std::process::exit(1);
86    }
87}
88
89pub fn get_cargo_metadata() -> Result<&'static Metadata> {
90    static CARGO_METADATA: OnceCell<Metadata> = OnceCell::new();
91
92    CARGO_METADATA.get_or_try_init(|| {
93        MetadataCommand::new()
94            .exec()
95            .context("Failed to run cargo metadata")
96    })
97}
98
99pub fn get_workspace_packages() -> Result<Vec<&'static Package>> {
100    let metadata = get_cargo_metadata()?;
101
102    // Filter to workspace member packages only
103    let workspace_packages: Vec<&Package> = metadata
104        .packages
105        .iter()
106        .filter(|package| metadata.workspace_members.contains(&package.id))
107        .collect();
108
109    Ok(workspace_packages)
110}
111
112pub fn get_rust_paths() -> Result<Vec<std::path::PathBuf>> {
113    let packages = get_workspace_packages()?;
114    Ok(packages
115        .iter()
116        .map(|pkg| pkg.manifest_path.as_std_path().to_path_buf())
117        .collect())
118}