Simplify xtask

lib/bin/test separation isn't really needed.
This commit is contained in:
Aleksey Kladov 2021-03-01 20:16:23 +03:00
parent c17f2bf2a2
commit d9dcfd81c5
17 changed files with 167 additions and 180 deletions

View file

@ -6,9 +6,6 @@ authors = ["rust-analyzer developers"]
publish = false publish = false
license = "MIT OR Apache-2.0" license = "MIT OR Apache-2.0"
[lib]
doctest = false
[dependencies] [dependencies]
anyhow = "1.0.26" anyhow = "1.0.26"
flate2 = "1.0" flate2 = "1.0"

View file

@ -20,7 +20,7 @@ use xshell::{cmd, pushenv, read_file, write_file};
use crate::{ensure_rustfmt, project_root, Result}; use crate::{ensure_rustfmt, project_root, Result};
pub use self::{ pub(crate) use self::{
gen_assists_docs::{generate_assists_docs, generate_assists_tests}, gen_assists_docs::{generate_assists_docs, generate_assists_tests},
gen_diagnostic_docs::generate_diagnostic_docs, gen_diagnostic_docs::generate_diagnostic_docs,
gen_feature_docs::generate_feature_docs, gen_feature_docs::generate_feature_docs,
@ -30,17 +30,17 @@ pub use self::{
}; };
#[derive(Debug, PartialEq, Eq, Clone, Copy)] #[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum Mode { pub(crate) enum Mode {
Overwrite, Overwrite,
Verify, Verify,
} }
pub struct CodegenCmd { pub(crate) struct CodegenCmd {
pub features: bool, pub(crate) features: bool,
} }
impl CodegenCmd { impl CodegenCmd {
pub fn run(self) -> Result<()> { pub(crate) fn run(self) -> Result<()> {
if self.features { if self.features {
generate_lint_completions(Mode::Overwrite)?; generate_lint_completions(Mode::Overwrite)?;
} }

View file

@ -7,12 +7,12 @@ use crate::{
project_root, rust_files_in, Result, project_root, rust_files_in, Result,
}; };
pub fn generate_assists_tests(mode: Mode) -> Result<()> { pub(crate) fn generate_assists_tests(mode: Mode) -> Result<()> {
let assists = Assist::collect()?; let assists = Assist::collect()?;
generate_tests(&assists, mode) generate_tests(&assists, mode)
} }
pub fn generate_assists_docs(mode: Mode) -> Result<()> { pub(crate) fn generate_assists_docs(mode: Mode) -> Result<()> {
let assists = Assist::collect()?; let assists = Assist::collect()?;
let contents = assists.into_iter().map(|it| it.to_string()).collect::<Vec<_>>().join("\n\n"); let contents = assists.into_iter().map(|it| it.to_string()).collect::<Vec<_>>().join("\n\n");
let contents = format!("//{}\n{}\n", PREAMBLE, contents.trim()); let contents = format!("//{}\n{}\n", PREAMBLE, contents.trim());

View file

@ -7,7 +7,7 @@ use crate::{
project_root, rust_files, Result, project_root, rust_files, Result,
}; };
pub fn generate_diagnostic_docs(mode: Mode) -> Result<()> { pub(crate) fn generate_diagnostic_docs(mode: Mode) -> Result<()> {
let diagnostics = Diagnostic::collect()?; let diagnostics = Diagnostic::collect()?;
let contents = let contents =
diagnostics.into_iter().map(|it| it.to_string()).collect::<Vec<_>>().join("\n\n"); diagnostics.into_iter().map(|it| it.to_string()).collect::<Vec<_>>().join("\n\n");

View file

@ -7,7 +7,7 @@ use crate::{
project_root, rust_files, Result, project_root, rust_files, Result,
}; };
pub fn generate_feature_docs(mode: Mode) -> Result<()> { pub(crate) fn generate_feature_docs(mode: Mode) -> Result<()> {
let features = Feature::collect()?; let features = Feature::collect()?;
let contents = features.into_iter().map(|it| it.to_string()).collect::<Vec<_>>().join("\n\n"); let contents = features.into_iter().map(|it| it.to_string()).collect::<Vec<_>>().join("\n\n");
let contents = format!("//{}\n{}\n", PREAMBLE, contents.trim()); let contents = format!("//{}\n{}\n", PREAMBLE, contents.trim());

View file

@ -10,7 +10,7 @@ use crate::{
run_rustfmt, run_rustfmt,
}; };
pub fn generate_lint_completions(mode: Mode) -> Result<()> { pub(crate) fn generate_lint_completions(mode: Mode) -> Result<()> {
if !Path::new("./target/rust").exists() { if !Path::new("./target/rust").exists() {
cmd!("git clone --depth=1 https://github.com/rust-lang/rust ./target/rust").run()?; cmd!("git clone --depth=1 https://github.com/rust-lang/rust ./target/rust").run()?;
} }

View file

@ -12,7 +12,7 @@ use crate::{
project_root, Result, project_root, Result,
}; };
pub fn generate_parser_tests(mode: Mode) -> Result<()> { pub(crate) fn generate_parser_tests(mode: Mode) -> Result<()> {
let tests = tests_from_dir(&project_root().join(Path::new("crates/parser/src/grammar")))?; let tests = tests_from_dir(&project_root().join(Path::new("crates/parser/src/grammar")))?;
fn install_tests(tests: &HashMap<String, Test>, into: &str, mode: Mode) -> Result<()> { fn install_tests(tests: &HashMap<String, Test>, into: &str, mode: Mode) -> Result<()> {
let tests_dir = project_root().join(into); let tests_dir = project_root().join(into);

View file

@ -18,7 +18,7 @@ use crate::{
project_root, Result, project_root, Result,
}; };
pub fn generate_syntax(mode: Mode) -> Result<()> { pub(crate) fn generate_syntax(mode: Mode) -> Result<()> {
let grammar = rust_grammar(); let grammar = rust_grammar();
let ast = lower(&grammar); let ast = lower(&grammar);

View file

@ -11,13 +11,13 @@ use xshell::{cmd, cp, mkdir_p, pushd, read_file, rm_rf, write_file};
use crate::{date_iso, project_root}; use crate::{date_iso, project_root};
pub struct DistCmd { pub(crate) struct DistCmd {
pub nightly: bool, pub(crate) nightly: bool,
pub client_version: Option<String>, pub(crate) client_version: Option<String>,
} }
impl DistCmd { impl DistCmd {
pub fn run(self) -> Result<()> { pub(crate) fn run(self) -> Result<()> {
let dist = project_root().join("dist"); let dist = project_root().join("dist");
rm_rf(&dist)?; rm_rf(&dist)?;
mkdir_p(&dist)?; mkdir_p(&dist)?;

View file

@ -8,13 +8,13 @@ use xshell::{cmd, pushd};
// Latest stable, feel free to send a PR if this lags behind. // Latest stable, feel free to send a PR if this lags behind.
const REQUIRED_RUST_VERSION: u32 = 50; const REQUIRED_RUST_VERSION: u32 = 50;
pub struct InstallCmd { pub(crate) struct InstallCmd {
pub client: Option<ClientOpt>, pub(crate) client: Option<ClientOpt>,
pub server: Option<ServerOpt>, pub(crate) server: Option<ServerOpt>,
} }
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
pub enum ClientOpt { pub(crate) enum ClientOpt {
VsCode, VsCode,
VsCodeExploration, VsCodeExploration,
VsCodeInsiders, VsCodeInsiders,
@ -24,7 +24,7 @@ pub enum ClientOpt {
} }
impl ClientOpt { impl ClientOpt {
pub const fn as_cmds(&self) -> &'static [&'static str] { pub(crate) const fn as_cmds(&self) -> &'static [&'static str] {
match self { match self {
ClientOpt::VsCode => &["code"], ClientOpt::VsCode => &["code"],
ClientOpt::VsCodeExploration => &["code-exploration"], ClientOpt::VsCodeExploration => &["code-exploration"],
@ -60,18 +60,18 @@ impl std::str::FromStr for ClientOpt {
} }
} }
pub struct ServerOpt { pub(crate) struct ServerOpt {
pub malloc: Malloc, pub(crate) malloc: Malloc,
} }
pub enum Malloc { pub(crate) enum Malloc {
System, System,
Mimalloc, Mimalloc,
Jemalloc, Jemalloc,
} }
impl InstallCmd { impl InstallCmd {
pub fn run(self) -> Result<()> { pub(crate) fn run(self) -> Result<()> {
if cfg!(target_os = "macos") { if cfg!(target_os = "macos") {
fix_path_for_mac().context("Fix path for mac")? fix_path_for_mac().context("Fix path for mac")?
} }

View file

@ -1,131 +0,0 @@
//! Support library for `cargo xtask` command.
//!
//! See https://github.com/matklad/cargo-xtask/
pub mod codegen;
mod ast_src;
pub mod install;
pub mod release;
pub mod dist;
pub mod pre_commit;
pub mod metrics;
pub mod pre_cache;
use std::{
env,
path::{Path, PathBuf},
};
use walkdir::{DirEntry, WalkDir};
use xshell::{cmd, pushd, pushenv};
use crate::codegen::Mode;
pub use anyhow::{bail, Context as _, Result};
pub fn project_root() -> PathBuf {
Path::new(
&env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| env!("CARGO_MANIFEST_DIR").to_owned()),
)
.ancestors()
.nth(1)
.unwrap()
.to_path_buf()
}
pub fn rust_files() -> impl Iterator<Item = PathBuf> {
rust_files_in(&project_root().join("crates"))
}
pub fn cargo_files() -> impl Iterator<Item = PathBuf> {
files_in(&project_root(), "toml")
.filter(|path| path.file_name().map(|it| it == "Cargo.toml").unwrap_or(false))
}
pub fn rust_files_in(path: &Path) -> impl Iterator<Item = PathBuf> {
files_in(path, "rs")
}
pub fn run_rustfmt(mode: Mode) -> Result<()> {
let _dir = pushd(project_root())?;
let _e = pushenv("RUSTUP_TOOLCHAIN", "stable");
ensure_rustfmt()?;
let check = match mode {
Mode::Overwrite => &[][..],
Mode::Verify => &["--", "--check"],
};
cmd!("cargo fmt {check...}").run()?;
Ok(())
}
fn ensure_rustfmt() -> Result<()> {
let out = cmd!("rustfmt --version").read()?;
if !out.contains("stable") {
bail!(
"Failed to run rustfmt from toolchain 'stable'. \
Please run `rustup component add rustfmt --toolchain stable` to install it.",
)
}
Ok(())
}
pub fn run_clippy() -> Result<()> {
if cmd!("cargo clippy --version").read().is_err() {
bail!(
"Failed run cargo clippy. \
Please run `rustup component add clippy` to install it.",
)
}
let allowed_lints = "
-A clippy::collapsible_if
-A clippy::needless_pass_by_value
-A clippy::nonminimal_bool
-A clippy::redundant_pattern_matching
"
.split_ascii_whitespace();
cmd!("cargo clippy --all-features --all-targets -- {allowed_lints...}").run()?;
Ok(())
}
pub fn run_fuzzer() -> Result<()> {
let _d = pushd("./crates/syntax")?;
let _e = pushenv("RUSTUP_TOOLCHAIN", "nightly");
if cmd!("cargo fuzz --help").read().is_err() {
cmd!("cargo install cargo-fuzz").run()?;
};
// Expecting nightly rustc
let out = cmd!("rustc --version").read()?;
if !out.contains("nightly") {
bail!("fuzz tests require nightly rustc")
}
cmd!("cargo fuzz run parser").run()?;
Ok(())
}
fn date_iso() -> Result<String> {
let res = cmd!("date --iso --utc").read()?;
Ok(res)
}
fn is_release_tag(tag: &str) -> bool {
tag.len() == "2020-02-24".len() && tag.starts_with(|c: char| c.is_ascii_digit())
}
fn files_in(path: &Path, ext: &'static str) -> impl Iterator<Item = PathBuf> {
let iter = WalkDir::new(path);
return iter
.into_iter()
.filter_entry(|e| !is_hidden(e))
.map(|e| e.unwrap())
.filter(|e| !e.file_type().is_dir())
.map(|e| e.into_path())
.filter(move |path| path.extension().map(|it| it == ext).unwrap_or(false));
fn is_hidden(entry: &DirEntry) -> bool {
entry.file_name().to_str().map(|s| s.starts_with('.')).unwrap_or(false)
}
}

View file

@ -7,22 +7,35 @@
//! //!
//! This binary is integrated into the `cargo` command line by using an alias in //! This binary is integrated into the `cargo` command line by using an alias in
//! `.cargo/config`. //! `.cargo/config`.
mod codegen;
mod ast_src;
#[cfg(test)]
mod tidy;
use std::env; mod install;
mod release;
mod dist;
mod pre_commit;
mod metrics;
mod pre_cache;
use anyhow::bail; use anyhow::{bail, Result};
use codegen::CodegenCmd; use codegen::CodegenCmd;
use pico_args::Arguments; use pico_args::Arguments;
use xshell::{cmd, cp, pushd}; use std::{
use xtask::{ env,
codegen::{self, Mode}, path::{Path, PathBuf},
};
use walkdir::{DirEntry, WalkDir};
use xshell::{cmd, cp, pushd, pushenv};
use crate::{
codegen::Mode,
dist::DistCmd, dist::DistCmd,
install::{InstallCmd, Malloc, ServerOpt}, install::{InstallCmd, Malloc, ServerOpt},
metrics::MetricsCmd, metrics::MetricsCmd,
pre_cache::PreCacheCmd, pre_cache::PreCacheCmd,
pre_commit, project_root,
release::{PromoteCmd, ReleaseCmd}, release::{PromoteCmd, ReleaseCmd},
run_clippy, run_fuzzer, run_rustfmt, Result,
}; };
fn main() -> Result<()> { fn main() -> Result<()> {
@ -172,3 +185,110 @@ fn finish_args(args: Arguments) -> Result<()> {
} }
Ok(()) Ok(())
} }
fn project_root() -> PathBuf {
Path::new(
&env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| env!("CARGO_MANIFEST_DIR").to_owned()),
)
.ancestors()
.nth(1)
.unwrap()
.to_path_buf()
}
fn rust_files() -> impl Iterator<Item = PathBuf> {
rust_files_in(&project_root().join("crates"))
}
#[cfg(test)]
fn cargo_files() -> impl Iterator<Item = PathBuf> {
files_in(&project_root(), "toml")
.filter(|path| path.file_name().map(|it| it == "Cargo.toml").unwrap_or(false))
}
fn rust_files_in(path: &Path) -> impl Iterator<Item = PathBuf> {
files_in(path, "rs")
}
fn run_rustfmt(mode: Mode) -> Result<()> {
let _dir = pushd(project_root())?;
let _e = pushenv("RUSTUP_TOOLCHAIN", "stable");
ensure_rustfmt()?;
let check = match mode {
Mode::Overwrite => &[][..],
Mode::Verify => &["--", "--check"],
};
cmd!("cargo fmt {check...}").run()?;
Ok(())
}
fn ensure_rustfmt() -> Result<()> {
let out = cmd!("rustfmt --version").read()?;
if !out.contains("stable") {
bail!(
"Failed to run rustfmt from toolchain 'stable'. \
Please run `rustup component add rustfmt --toolchain stable` to install it.",
)
}
Ok(())
}
fn run_clippy() -> Result<()> {
if cmd!("cargo clippy --version").read().is_err() {
bail!(
"Failed run cargo clippy. \
Please run `rustup component add clippy` to install it.",
)
}
let allowed_lints = "
-A clippy::collapsible_if
-A clippy::needless_pass_by_value
-A clippy::nonminimal_bool
-A clippy::redundant_pattern_matching
"
.split_ascii_whitespace();
cmd!("cargo clippy --all-features --all-targets -- {allowed_lints...}").run()?;
Ok(())
}
fn run_fuzzer() -> Result<()> {
let _d = pushd("./crates/syntax")?;
let _e = pushenv("RUSTUP_TOOLCHAIN", "nightly");
if cmd!("cargo fuzz --help").read().is_err() {
cmd!("cargo install cargo-fuzz").run()?;
};
// Expecting nightly rustc
let out = cmd!("rustc --version").read()?;
if !out.contains("nightly") {
bail!("fuzz tests require nightly rustc")
}
cmd!("cargo fuzz run parser").run()?;
Ok(())
}
fn date_iso() -> Result<String> {
let res = cmd!("date --iso --utc").read()?;
Ok(res)
}
fn is_release_tag(tag: &str) -> bool {
tag.len() == "2020-02-24".len() && tag.starts_with(|c: char| c.is_ascii_digit())
}
fn files_in(path: &Path, ext: &'static str) -> impl Iterator<Item = PathBuf> {
let iter = WalkDir::new(path);
return iter
.into_iter()
.filter_entry(|e| !is_hidden(e))
.map(|e| e.unwrap())
.filter(|e| !e.file_type().is_dir())
.map(|e| e.into_path())
.filter(move |path| path.extension().map(|it| it == ext).unwrap_or(false));
fn is_hidden(entry: &DirEntry) -> bool {
entry.file_name().to_str().map(|s| s.starts_with('.')).unwrap_or(false)
}
}

View file

@ -11,12 +11,12 @@ use xshell::{cmd, mkdir_p, pushd, pushenv, read_file, rm_rf};
type Unit = String; type Unit = String;
pub struct MetricsCmd { pub(crate) struct MetricsCmd {
pub dry_run: bool, pub(crate) dry_run: bool,
} }
impl MetricsCmd { impl MetricsCmd {
pub fn run(self) -> Result<()> { pub(crate) fn run(self) -> Result<()> {
let mut metrics = Metrics::new()?; let mut metrics = Metrics::new()?;
if !self.dry_run { if !self.dry_run {
rm_rf("./target/release")?; rm_rf("./target/release")?;

View file

@ -6,12 +6,12 @@ use std::{
use anyhow::Result; use anyhow::Result;
use xshell::rm_rf; use xshell::rm_rf;
pub struct PreCacheCmd; pub(crate) struct PreCacheCmd;
impl PreCacheCmd { impl PreCacheCmd {
/// Cleans the `./target` dir after the build such that only /// Cleans the `./target` dir after the build such that only
/// dependencies are cached on CI. /// dependencies are cached on CI.
pub fn run(self) -> Result<()> { pub(crate) fn run(self) -> Result<()> {
let slow_tests_cookie = Path::new("./target/.slow_tests_cookie"); let slow_tests_cookie = Path::new("./target/.slow_tests_cookie");
if !slow_tests_cookie.exists() { if !slow_tests_cookie.exists() {
panic!("slow tests were skipped on CI!") panic!("slow tests were skipped on CI!")

View file

@ -9,7 +9,7 @@ use crate::{project_root, run_rustfmt, Mode};
// FIXME: if there are changed `.ts` files, also reformat TypeScript (by // FIXME: if there are changed `.ts` files, also reformat TypeScript (by
// shelling out to `npm fmt`). // shelling out to `npm fmt`).
pub fn run_hook() -> Result<()> { pub(crate) fn run_hook() -> Result<()> {
run_rustfmt(Mode::Overwrite)?; run_rustfmt(Mode::Overwrite)?;
let diff = cmd!("git diff --diff-filter=MAR --name-only --cached").read()?; let diff = cmd!("git diff --diff-filter=MAR --name-only --cached").read()?;
@ -23,7 +23,7 @@ pub fn run_hook() -> Result<()> {
Ok(()) Ok(())
} }
pub fn install_hook() -> Result<()> { pub(crate) fn install_hook() -> Result<()> {
let hook_path: PathBuf = let hook_path: PathBuf =
format!("./.git/hooks/pre-commit{}", std::env::consts::EXE_SUFFIX).into(); format!("./.git/hooks/pre-commit{}", std::env::consts::EXE_SUFFIX).into();

View file

@ -4,12 +4,12 @@ use xshell::{cmd, cp, pushd, read_dir, write_file};
use crate::{codegen, date_iso, is_release_tag, project_root, Mode, Result}; use crate::{codegen, date_iso, is_release_tag, project_root, Mode, Result};
pub struct ReleaseCmd { pub(crate) struct ReleaseCmd {
pub dry_run: bool, pub(crate) dry_run: bool,
} }
impl ReleaseCmd { impl ReleaseCmd {
pub fn run(self) -> Result<()> { pub(crate) fn run(self) -> Result<()> {
if !self.dry_run { if !self.dry_run {
cmd!("git switch release").run()?; cmd!("git switch release").run()?;
cmd!("git fetch upstream --tags --force").run()?; cmd!("git fetch upstream --tags --force").run()?;
@ -86,12 +86,12 @@ https://github.com/sponsors/rust-analyzer[GitHub Sponsors].
} }
} }
pub struct PromoteCmd { pub(crate) struct PromoteCmd {
pub dry_run: bool, pub(crate) dry_run: bool,
} }
impl PromoteCmd { impl PromoteCmd {
pub fn run(self) -> Result<()> { pub(crate) fn run(self) -> Result<()> {
let _dir = pushd("../rust-rust-analyzer")?; let _dir = pushd("../rust-rust-analyzer")?;
cmd!("git switch master").run()?; cmd!("git switch master").run()?;
cmd!("git fetch upstream").run()?; cmd!("git fetch upstream").run()?;

View file

@ -4,7 +4,8 @@ use std::{
}; };
use xshell::{cmd, read_file}; use xshell::{cmd, read_file};
use xtask::{
use crate::{
cargo_files, cargo_files,
codegen::{self, Mode}, codegen::{self, Mode},
project_root, run_rustfmt, rust_files, project_root, run_rustfmt, rust_files,