From b01878aadfa96eaf895a853c6acc9daa0cbda184 Mon Sep 17 00:00:00 2001 From: Marshall Bowers Date: Mon, 13 May 2024 18:52:12 -0400 Subject: [PATCH] Add `xtask` for finding crates with missing licenses (#11776) This PR adds a new `cargo xtask licenses` command for finding crates with missing license files. A number of crates were uncovered that were missing a license file, and have had the appropriate license file added. Release Notes: - N/A --- Cargo.lock | 12 +++++ Cargo.toml | 1 + crates/dev_server_projects/LICENSE-GPL | 1 + crates/image_viewer/LICENSE-GPL | 1 + crates/markdown/LICENSE-GPL | 1 + crates/supermaven/LICENSE-GPL | 1 + crates/supermaven_api/LICENSE-GPL | 1 + extensions/ocaml/LICENSE-APACHE | 1 + tooling/xtask/Cargo.toml | 2 + tooling/xtask/src/main.rs | 70 +++----------------------- tooling/xtask/src/tasks.rs | 2 + tooling/xtask/src/tasks/clippy.rs | 63 +++++++++++++++++++++++ tooling/xtask/src/tasks/licenses.rs | 39 ++++++++++++++ tooling/xtask/src/workspace.rs | 17 +++++++ 14 files changed, 149 insertions(+), 63 deletions(-) create mode 120000 crates/dev_server_projects/LICENSE-GPL create mode 120000 crates/image_viewer/LICENSE-GPL create mode 120000 crates/markdown/LICENSE-GPL create mode 120000 crates/supermaven/LICENSE-GPL create mode 120000 crates/supermaven_api/LICENSE-GPL create mode 120000 extensions/ocaml/LICENSE-APACHE create mode 100644 tooling/xtask/src/tasks.rs create mode 100644 tooling/xtask/src/tasks/clippy.rs create mode 100644 tooling/xtask/src/tasks/licenses.rs create mode 100644 tooling/xtask/src/workspace.rs diff --git a/Cargo.lock b/Cargo.lock index 2592f2e7d5..d1072953b7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1887,6 +1887,16 @@ dependencies = [ "winx", ] +[[package]] +name = "cargo_toml" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8cb1d556b8b8f36e5ca74938008be3ac102f5dcb5b68a0477e4249ae2291cd3" +dependencies = [ + "serde", + "toml 0.8.10", +] + [[package]] name = "cast" version = "0.3.0" @@ -12810,7 +12820,9 @@ name = "xtask" version = "0.1.0" dependencies = [ "anyhow", + "cargo_toml", "clap 4.4.4", + "toml 0.8.10", ] [[package]] diff --git a/Cargo.toml b/Cargo.toml index 9ca5beb6cd..cb4b12a1e0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -265,6 +265,7 @@ bitflags = "2.4.2" blade-graphics = { git = "https://github.com/kvark/blade", rev = "e35b2d41f221a48b75f7cf2e78a81e7ecb7a383c" } blade-macros = { git = "https://github.com/kvark/blade", rev = "e35b2d41f221a48b75f7cf2e78a81e7ecb7a383c" } cap-std = "3.0" +cargo_toml = "0.20" chrono = { version = "0.4", features = ["serde"] } clap = { version = "4.4", features = ["derive"] } clickhouse = { version = "0.11.6" } diff --git a/crates/dev_server_projects/LICENSE-GPL b/crates/dev_server_projects/LICENSE-GPL new file mode 120000 index 0000000000..89e542f750 --- /dev/null +++ b/crates/dev_server_projects/LICENSE-GPL @@ -0,0 +1 @@ +../../LICENSE-GPL \ No newline at end of file diff --git a/crates/image_viewer/LICENSE-GPL b/crates/image_viewer/LICENSE-GPL new file mode 120000 index 0000000000..89e542f750 --- /dev/null +++ b/crates/image_viewer/LICENSE-GPL @@ -0,0 +1 @@ +../../LICENSE-GPL \ No newline at end of file diff --git a/crates/markdown/LICENSE-GPL b/crates/markdown/LICENSE-GPL new file mode 120000 index 0000000000..89e542f750 --- /dev/null +++ b/crates/markdown/LICENSE-GPL @@ -0,0 +1 @@ +../../LICENSE-GPL \ No newline at end of file diff --git a/crates/supermaven/LICENSE-GPL b/crates/supermaven/LICENSE-GPL new file mode 120000 index 0000000000..89e542f750 --- /dev/null +++ b/crates/supermaven/LICENSE-GPL @@ -0,0 +1 @@ +../../LICENSE-GPL \ No newline at end of file diff --git a/crates/supermaven_api/LICENSE-GPL b/crates/supermaven_api/LICENSE-GPL new file mode 120000 index 0000000000..89e542f750 --- /dev/null +++ b/crates/supermaven_api/LICENSE-GPL @@ -0,0 +1 @@ +../../LICENSE-GPL \ No newline at end of file diff --git a/extensions/ocaml/LICENSE-APACHE b/extensions/ocaml/LICENSE-APACHE new file mode 120000 index 0000000000..1cd601d0a3 --- /dev/null +++ b/extensions/ocaml/LICENSE-APACHE @@ -0,0 +1 @@ +../../LICENSE-APACHE \ No newline at end of file diff --git a/tooling/xtask/Cargo.toml b/tooling/xtask/Cargo.toml index 11f0036c74..c83a7f083d 100644 --- a/tooling/xtask/Cargo.toml +++ b/tooling/xtask/Cargo.toml @@ -10,4 +10,6 @@ workspace = true [dependencies] anyhow.workspace = true +cargo_toml.workspace = true clap = { workspace = true, features = ["derive"] } +toml.workspace = true diff --git a/tooling/xtask/src/main.rs b/tooling/xtask/src/main.rs index 103a841fb0..cb7e84f5ae 100644 --- a/tooling/xtask/src/main.rs +++ b/tooling/xtask/src/main.rs @@ -1,6 +1,7 @@ -use std::process::Command; +mod tasks; +mod workspace; -use anyhow::{bail, Context, Result}; +use anyhow::Result; use clap::{Parser, Subcommand}; #[derive(Parser)] @@ -13,72 +14,15 @@ struct Args { #[derive(Subcommand)] enum CliCommand { /// Runs `cargo clippy`. - Clippy(ClippyArgs), + Clippy(tasks::clippy::ClippyArgs), + Licenses(tasks::licenses::LicensesArgs), } fn main() -> Result<()> { let args = Args::parse(); match args.command { - CliCommand::Clippy(args) => run_clippy(args), + CliCommand::Clippy(args) => tasks::clippy::run_clippy(args), + CliCommand::Licenses(args) => tasks::licenses::run_licenses(args), } } - -#[derive(Parser)] -struct ClippyArgs { - /// Automatically apply lint suggestions (`clippy --fix`). - #[arg(long)] - fix: bool, - - /// The package to run Clippy against (`cargo -p clippy`). - #[arg(long, short)] - package: Option, -} - -fn run_clippy(args: ClippyArgs) -> Result<()> { - let cargo = std::env::var("CARGO").unwrap_or_else(|_| "cargo".to_string()); - - let mut clippy_command = Command::new(&cargo); - clippy_command.arg("clippy"); - - if let Some(package) = args.package.as_ref() { - clippy_command.args(["--package", package]); - } else { - clippy_command.arg("--workspace"); - } - - clippy_command - .arg("--release") - .arg("--all-targets") - .arg("--all-features"); - - if args.fix { - clippy_command.arg("--fix"); - } - - clippy_command.arg("--"); - - // Deny all warnings. - clippy_command.args(["--deny", "warnings"]); - - eprintln!( - "running: {cargo} {}", - clippy_command - .get_args() - .map(|arg| arg.to_str().unwrap()) - .collect::>() - .join(" ") - ); - - let exit_status = clippy_command - .spawn() - .context("failed to spawn child process")? - .wait() - .context("failed to wait for child process")?; - - if !exit_status.success() { - bail!("clippy failed: {}", exit_status); - } - - Ok(()) -} diff --git a/tooling/xtask/src/tasks.rs b/tooling/xtask/src/tasks.rs new file mode 100644 index 0000000000..a13bdcaeaa --- /dev/null +++ b/tooling/xtask/src/tasks.rs @@ -0,0 +1,2 @@ +pub mod clippy; +pub mod licenses; diff --git a/tooling/xtask/src/tasks/clippy.rs b/tooling/xtask/src/tasks/clippy.rs new file mode 100644 index 0000000000..85d0adf583 --- /dev/null +++ b/tooling/xtask/src/tasks/clippy.rs @@ -0,0 +1,63 @@ +use std::process::Command; + +use anyhow::{bail, Context, Result}; +use clap::Parser; + +#[derive(Parser)] +pub struct ClippyArgs { + /// Automatically apply lint suggestions (`clippy --fix`). + #[arg(long)] + fix: bool, + + /// The package to run Clippy against (`cargo -p clippy`). + #[arg(long, short)] + package: Option, +} + +pub fn run_clippy(args: ClippyArgs) -> Result<()> { + let cargo = std::env::var("CARGO").unwrap_or_else(|_| "cargo".to_string()); + + let mut clippy_command = Command::new(&cargo); + clippy_command.arg("clippy"); + + if let Some(package) = args.package.as_ref() { + clippy_command.args(["--package", package]); + } else { + clippy_command.arg("--workspace"); + } + + clippy_command + .arg("--release") + .arg("--all-targets") + .arg("--all-features"); + + if args.fix { + clippy_command.arg("--fix"); + } + + clippy_command.arg("--"); + + // Deny all warnings. + clippy_command.args(["--deny", "warnings"]); + + eprintln!( + "running: {cargo} {}", + clippy_command + .get_args() + .map(|arg| arg.to_str().unwrap()) + .collect::>() + .join(" ") + ); + + let exit_status = clippy_command + .spawn() + .context("failed to spawn child process")? + .wait() + .context("failed to wait for child process")?; + + if !exit_status.success() { + bail!("clippy failed: {}", exit_status); + } + + Ok(()) +} diff --git a/tooling/xtask/src/tasks/licenses.rs b/tooling/xtask/src/tasks/licenses.rs new file mode 100644 index 0000000000..fc9832a4b0 --- /dev/null +++ b/tooling/xtask/src/tasks/licenses.rs @@ -0,0 +1,39 @@ +use std::path::{Path, PathBuf}; + +use anyhow::Result; +use clap::Parser; + +use crate::workspace::load_workspace; + +#[derive(Parser)] +pub struct LicensesArgs {} + +pub fn run_licenses(_args: LicensesArgs) -> Result<()> { + let workspace = load_workspace()?; + + for member in workspace.members { + let crate_dir = PathBuf::from(&member); + + if has_any_license_file( + &crate_dir, + &["LICENSE-APACHE", "LICENSE-GPL", "LICENSE-AGPL"], + ) { + continue; + } + + println!("Missing license: {member}"); + } + + Ok(()) +} + +fn has_any_license_file(path: &Path, license_files: &[&str]) -> bool { + for license_file in license_files { + let path_to_license = path.join(license_file); + if path_to_license.exists() { + return true; + } + } + + false +} diff --git a/tooling/xtask/src/workspace.rs b/tooling/xtask/src/workspace.rs new file mode 100644 index 0000000000..23cb161f83 --- /dev/null +++ b/tooling/xtask/src/workspace.rs @@ -0,0 +1,17 @@ +use std::fs; + +use anyhow::{anyhow, Result}; +use cargo_toml::{Manifest, Workspace}; +use toml; + +/// Returns the Cargo workspace. +pub fn load_workspace() -> Result { + let workspace_cargo_toml = fs::read_to_string("Cargo.toml")?; + let workspace_cargo_toml: Manifest = toml::from_str(&workspace_cargo_toml)?; + + let workspace = workspace_cargo_toml + .workspace + .ok_or_else(|| anyhow!("top-level Cargo.toml is not a Cargo workspace"))?; + + Ok(workspace) +}