mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-11-10 07:04:22 +00:00
Switch from not_bash to xshell
This commit is contained in:
parent
f0412da4a2
commit
49a90d4c31
14 changed files with 181 additions and 325 deletions
23
Cargo.lock
generated
23
Cargo.lock
generated
|
@ -421,12 +421,6 @@ dependencies = [
|
|||
"toolchain",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fs-err"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bcd1163ae48bda72a20ae26d66a04d3094135cadab911cff418ae5e33f253431"
|
||||
|
||||
[[package]]
|
||||
name = "fsevent"
|
||||
version = "2.0.2"
|
||||
|
@ -1920,17 +1914,32 @@ dependencies = [
|
|||
"winapi-build",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "xshell"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f7f756f2faab73adb00db44db716598ab2c9e4bce4a875c053022291bd3cab4"
|
||||
dependencies = [
|
||||
"xshell-macros",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "xshell-macros"
|
||||
version = "0.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "51b020c2f3132b34067e2f6ebc58f0f210624898713a8186b8cdb75d3b8c3001"
|
||||
|
||||
[[package]]
|
||||
name = "xtask"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"flate2",
|
||||
"fs-err",
|
||||
"pico-args",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"ungrammar",
|
||||
"walkdir",
|
||||
"write-json",
|
||||
"xshell",
|
||||
]
|
||||
|
|
|
@ -18,5 +18,5 @@ quote = "1.0.2"
|
|||
ungrammar = "1.1.3"
|
||||
walkdir = "2.3.1"
|
||||
write-json = "0.1.0"
|
||||
fs-err = "2.3"
|
||||
xshell = "0.1"
|
||||
# Avoid adding more dependencies to this crate
|
||||
|
|
|
@ -15,12 +15,9 @@ use std::{
|
|||
fmt, mem,
|
||||
path::{Path, PathBuf},
|
||||
};
|
||||
use xshell::{cmd, pushenv, read_file, write_file};
|
||||
|
||||
use crate::{
|
||||
ensure_rustfmt,
|
||||
not_bash::{fs2, pushenv, run},
|
||||
project_root, Result,
|
||||
};
|
||||
use crate::{ensure_rustfmt, project_root, Result};
|
||||
|
||||
pub use self::{
|
||||
gen_assists_docs::{generate_assists_docs, generate_assists_tests},
|
||||
|
@ -57,7 +54,7 @@ impl CodegenCmd {
|
|||
/// A helper to update file on disk if it has changed.
|
||||
/// With verify = false,
|
||||
fn update(path: &Path, contents: &str, mode: Mode) -> Result<()> {
|
||||
match fs2::read_to_string(path) {
|
||||
match read_file(path) {
|
||||
Ok(old_contents) if normalize(&old_contents) == normalize(contents) => {
|
||||
return Ok(());
|
||||
}
|
||||
|
@ -67,7 +64,7 @@ fn update(path: &Path, contents: &str, mode: Mode) -> Result<()> {
|
|||
anyhow::bail!("`{}` is not up-to-date", path.display());
|
||||
}
|
||||
eprintln!("updating {}", path.display());
|
||||
fs2::write(path, contents)?;
|
||||
write_file(path, contents)?;
|
||||
return Ok(());
|
||||
|
||||
fn normalize(s: &str) -> String {
|
||||
|
@ -80,10 +77,10 @@ const PREAMBLE: &str = "Generated file, do not edit by hand, see `xtask/src/code
|
|||
fn reformat(text: &str) -> Result<String> {
|
||||
let _e = pushenv("RUSTUP_TOOLCHAIN", "stable");
|
||||
ensure_rustfmt()?;
|
||||
let stdout = run!(
|
||||
"rustfmt --config-path {} --config fn_single_line=true", project_root().join("rustfmt.toml").display();
|
||||
<text.as_bytes()
|
||||
)?;
|
||||
let rustfmt_toml = project_root().join("rustfmt.toml");
|
||||
let stdout = cmd!("rustfmt --config-path {rustfmt_toml} --config fn_single_line=true")
|
||||
.stdin(text)
|
||||
.read()?;
|
||||
Ok(format!("//! {}\n\n{}\n", PREAMBLE, stdout))
|
||||
}
|
||||
|
||||
|
|
|
@ -3,15 +3,13 @@ use std::path::{Path, PathBuf};
|
|||
|
||||
use quote::quote;
|
||||
use walkdir::WalkDir;
|
||||
use xshell::{cmd, read_file};
|
||||
|
||||
use crate::{
|
||||
codegen::{project_root, reformat, update, Mode, Result},
|
||||
not_bash::{fs2, run},
|
||||
};
|
||||
use crate::codegen::{project_root, reformat, update, Mode, Result};
|
||||
|
||||
pub fn generate_features(mode: Mode) -> Result<()> {
|
||||
if !Path::new("./target/rust").exists() {
|
||||
run!("git clone https://github.com/rust-lang/rust ./target/rust")?;
|
||||
cmd!("git clone https://github.com/rust-lang/rust ./target/rust").run()?;
|
||||
}
|
||||
|
||||
let contents = generate_descriptor("./target/rust/src/doc/unstable-book/src".into())?;
|
||||
|
@ -34,7 +32,7 @@ fn generate_descriptor(src_dir: PathBuf) -> Result<String> {
|
|||
.map(|entry| {
|
||||
let path = entry.path();
|
||||
let feature_ident = path.file_stem().unwrap().to_str().unwrap().replace("-", "_");
|
||||
let doc = fs2::read_to_string(path).unwrap();
|
||||
let doc = read_file(path).unwrap();
|
||||
|
||||
quote! { LintCompletion { label: #feature_ident, description: #doc } }
|
||||
});
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
use flate2::{write::GzEncoder, Compression};
|
||||
use std::{
|
||||
env,
|
||||
fs::File,
|
||||
|
@ -7,11 +6,10 @@ use std::{
|
|||
};
|
||||
|
||||
use anyhow::Result;
|
||||
use flate2::{write::GzEncoder, Compression};
|
||||
use xshell::{cmd, cp, mkdir_p, pushd, read_file, rm_rf, write_file};
|
||||
|
||||
use crate::{
|
||||
not_bash::{date_iso, fs2, pushd, rm_rf, run},
|
||||
project_root,
|
||||
};
|
||||
use crate::{date_iso, project_root};
|
||||
|
||||
pub struct DistCmd {
|
||||
pub nightly: bool,
|
||||
|
@ -22,7 +20,7 @@ impl DistCmd {
|
|||
pub fn run(self) -> Result<()> {
|
||||
let dist = project_root().join("dist");
|
||||
rm_rf(&dist)?;
|
||||
fs2::create_dir_all(&dist)?;
|
||||
mkdir_p(&dist)?;
|
||||
|
||||
if let Some(version) = self.client_version {
|
||||
let release_tag = if self.nightly { "nightly".to_string() } else { date_iso()? };
|
||||
|
@ -34,7 +32,7 @@ impl DistCmd {
|
|||
}
|
||||
|
||||
fn dist_client(version: &str, release_tag: &str) -> Result<()> {
|
||||
let _d = pushd("./editors/code");
|
||||
let _d = pushd("./editors/code")?;
|
||||
let nightly = release_tag == "nightly";
|
||||
|
||||
let mut patch = Patch::new("./package.json")?;
|
||||
|
@ -54,20 +52,16 @@ fn dist_client(version: &str, release_tag: &str) -> Result<()> {
|
|||
}
|
||||
patch.commit()?;
|
||||
|
||||
run!("npm ci")?;
|
||||
run!("npx vsce package -o ../../dist/rust-analyzer.vsix")?;
|
||||
cmd!("npm ci").run()?;
|
||||
cmd!("npx vsce package -o ../../dist/rust-analyzer.vsix").run()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn dist_server() -> Result<()> {
|
||||
if cfg!(target_os = "linux") {
|
||||
env::set_var("CC", "clang");
|
||||
run!(
|
||||
"cargo build --manifest-path ./crates/rust-analyzer/Cargo.toml --bin rust-analyzer --release"
|
||||
)?;
|
||||
} else {
|
||||
run!("cargo build --manifest-path ./crates/rust-analyzer/Cargo.toml --bin rust-analyzer --release")?;
|
||||
}
|
||||
cmd!("cargo build --manifest-path ./crates/rust-analyzer/Cargo.toml --bin rust-analyzer --release").run()?;
|
||||
|
||||
let (src, dst) = if cfg!(target_os = "linux") {
|
||||
("./target/release/rust-analyzer", "./dist/rust-analyzer-linux")
|
||||
|
@ -82,7 +76,7 @@ fn dist_server() -> Result<()> {
|
|||
let src = Path::new(src);
|
||||
let dst = Path::new(dst);
|
||||
|
||||
fs2::copy(&src, &dst)?;
|
||||
cp(&src, &dst)?;
|
||||
gzip(&src, &dst.with_extension("gz"))?;
|
||||
|
||||
Ok(())
|
||||
|
@ -105,7 +99,7 @@ struct Patch {
|
|||
impl Patch {
|
||||
fn new(path: impl Into<PathBuf>) -> Result<Patch> {
|
||||
let path = path.into();
|
||||
let contents = fs2::read_to_string(&path)?;
|
||||
let contents = read_file(&path)?;
|
||||
Ok(Patch { path, original_contents: contents.clone(), contents })
|
||||
}
|
||||
|
||||
|
@ -115,13 +109,14 @@ impl Patch {
|
|||
self
|
||||
}
|
||||
|
||||
fn commit(&self) -> io::Result<()> {
|
||||
fs2::write(&self.path, &self.contents)
|
||||
fn commit(&self) -> Result<()> {
|
||||
write_file(&self.path, &self.contents)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Patch {
|
||||
fn drop(&mut self) {
|
||||
fs2::write(&self.path, &self.original_contents).unwrap();
|
||||
write_file(&self.path, &self.original_contents).unwrap();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,8 +3,7 @@
|
|||
use std::{env, path::PathBuf, str};
|
||||
|
||||
use anyhow::{bail, format_err, Context, Result};
|
||||
|
||||
use crate::not_bash::{pushd, run};
|
||||
use xshell::{cmd, pushd};
|
||||
|
||||
// Latest stable, feel free to send a PR if this lags behind.
|
||||
const REQUIRED_RUST_VERSION: u32 = 47;
|
||||
|
@ -76,7 +75,7 @@ fn fix_path_for_mac() -> Result<()> {
|
|||
}
|
||||
|
||||
fn install_client(ClientOpt::VsCode: ClientOpt) -> Result<()> {
|
||||
let _dir = pushd("./editors/code");
|
||||
let _dir = pushd("./editors/code")?;
|
||||
|
||||
let find_code = |f: fn(&str) -> bool| -> Result<&'static str> {
|
||||
["code", "code-insiders", "codium", "code-oss"]
|
||||
|
@ -89,24 +88,25 @@ fn install_client(ClientOpt::VsCode: ClientOpt) -> Result<()> {
|
|||
};
|
||||
|
||||
let installed_extensions = if cfg!(unix) {
|
||||
run!("npm --version").context("`npm` is required to build the VS Code plugin")?;
|
||||
run!("npm install")?;
|
||||
cmd!("npm --version").run().context("`npm` is required to build the VS Code plugin")?;
|
||||
cmd!("npm install").run()?;
|
||||
|
||||
run!("npm run package --scripts-prepend-node-path")?;
|
||||
cmd!("npm run package --scripts-prepend-node-path").run()?;
|
||||
|
||||
let code = find_code(|bin| run!("{} --version", bin).is_ok())?;
|
||||
run!("{} --install-extension rust-analyzer.vsix --force", code)?;
|
||||
run!("{} --list-extensions", code; echo = false)?
|
||||
let code = find_code(|bin| cmd!("{bin} --version").read().is_ok())?;
|
||||
cmd!("{code} --install-extension rust-analyzer.vsix --force").run()?;
|
||||
cmd!("{code} --list-extensions").read()?
|
||||
} else {
|
||||
run!("cmd.exe /c npm --version")
|
||||
cmd!("cmd.exe /c npm --version")
|
||||
.run()
|
||||
.context("`npm` is required to build the VS Code plugin")?;
|
||||
run!("cmd.exe /c npm install")?;
|
||||
cmd!("cmd.exe /c npm install").run()?;
|
||||
|
||||
run!("cmd.exe /c npm run package")?;
|
||||
cmd!("cmd.exe /c npm run package").run()?;
|
||||
|
||||
let code = find_code(|bin| run!("cmd.exe /c {}.cmd --version", bin).is_ok())?;
|
||||
run!(r"cmd.exe /c {}.cmd --install-extension rust-analyzer.vsix --force", code)?;
|
||||
run!("cmd.exe /c {}.cmd --list-extensions", code; echo = false)?
|
||||
let code = find_code(|bin| cmd!("cmd.exe /c {bin}.cmd --version").read().is_ok())?;
|
||||
cmd!("cmd.exe /c {code}.cmd --install-extension rust-analyzer.vsix --force").run()?;
|
||||
cmd!("cmd.exe /c {code}.cmd --list-extensions").read()?
|
||||
};
|
||||
|
||||
if !installed_extensions.contains("rust-analyzer") {
|
||||
|
@ -122,7 +122,7 @@ fn install_client(ClientOpt::VsCode: ClientOpt) -> Result<()> {
|
|||
|
||||
fn install_server(opts: ServerOpt) -> Result<()> {
|
||||
let mut old_rust = false;
|
||||
if let Ok(stdout) = run!("cargo --version") {
|
||||
if let Ok(stdout) = cmd!("cargo --version").read() {
|
||||
if !check_version(&stdout, REQUIRED_RUST_VERSION) {
|
||||
old_rust = true;
|
||||
}
|
||||
|
@ -134,12 +134,13 @@ fn install_server(opts: ServerOpt) -> Result<()> {
|
|||
REQUIRED_RUST_VERSION,
|
||||
)
|
||||
}
|
||||
|
||||
let malloc_feature = match opts.malloc {
|
||||
Malloc::System => "",
|
||||
Malloc::Mimalloc => "--features mimalloc",
|
||||
let features = match opts.malloc {
|
||||
Malloc::System => &[][..],
|
||||
Malloc::Mimalloc => &["--features", "mimalloc"],
|
||||
};
|
||||
let res = run!("cargo install --path crates/rust-analyzer --locked --force {}", malloc_feature);
|
||||
|
||||
let cmd = cmd!("cargo install --path crates/rust-analyzer --locked --force {features...}");
|
||||
let res = cmd.run();
|
||||
|
||||
if res.is_err() && old_rust {
|
||||
eprintln!(
|
||||
|
@ -148,7 +149,8 @@ fn install_server(opts: ServerOpt) -> Result<()> {
|
|||
);
|
||||
}
|
||||
|
||||
res.map(drop)
|
||||
res?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn check_version(version_output: &str, min_minor_version: u32) -> bool {
|
||||
|
|
|
@ -2,7 +2,6 @@
|
|||
//!
|
||||
//! See https://github.com/matklad/cargo-xtask/
|
||||
|
||||
pub mod not_bash;
|
||||
pub mod codegen;
|
||||
mod ast_src;
|
||||
|
||||
|
@ -19,11 +18,9 @@ use std::{
|
|||
};
|
||||
|
||||
use walkdir::{DirEntry, WalkDir};
|
||||
use xshell::{cmd, pushd, pushenv};
|
||||
|
||||
use crate::{
|
||||
codegen::Mode,
|
||||
not_bash::{pushd, pushenv},
|
||||
};
|
||||
use crate::codegen::Mode;
|
||||
|
||||
pub use anyhow::{bail, Context as _, Result};
|
||||
|
||||
|
@ -53,18 +50,19 @@ pub fn rust_files(path: &Path) -> impl Iterator<Item = PathBuf> {
|
|||
}
|
||||
|
||||
pub fn run_rustfmt(mode: Mode) -> Result<()> {
|
||||
let _dir = pushd(project_root());
|
||||
let _dir = pushd(project_root())?;
|
||||
let _e = pushenv("RUSTUP_TOOLCHAIN", "stable");
|
||||
ensure_rustfmt()?;
|
||||
match mode {
|
||||
Mode::Overwrite => run!("cargo fmt"),
|
||||
Mode::Verify => run!("cargo fmt -- --check"),
|
||||
}?;
|
||||
let check = match mode {
|
||||
Mode::Overwrite => &[][..],
|
||||
Mode::Verify => &["--", "--check"],
|
||||
};
|
||||
cmd!("cargo fmt {check...}").run()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn ensure_rustfmt() -> Result<()> {
|
||||
let out = run!("rustfmt --version")?;
|
||||
let out = cmd!("rustfmt --version").read()?;
|
||||
if !out.contains("stable") {
|
||||
bail!(
|
||||
"Failed to run rustfmt from toolchain 'stable'. \
|
||||
|
@ -75,40 +73,46 @@ fn ensure_rustfmt() -> Result<()> {
|
|||
}
|
||||
|
||||
pub fn run_clippy() -> Result<()> {
|
||||
if run!("cargo clippy --version").is_err() {
|
||||
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 = [
|
||||
"clippy::collapsible_if",
|
||||
"clippy::needless_pass_by_value",
|
||||
"clippy::nonminimal_bool",
|
||||
"clippy::redundant_pattern_matching",
|
||||
];
|
||||
run!("cargo clippy --all-features --all-targets -- -A {}", allowed_lints.join(" -A "))?;
|
||||
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 _d = pushd("./crates/syntax")?;
|
||||
let _e = pushenv("RUSTUP_TOOLCHAIN", "nightly");
|
||||
if run!("cargo fuzz --help").is_err() {
|
||||
run!("cargo install cargo-fuzz")?;
|
||||
if cmd!("cargo fuzz --help").read().is_err() {
|
||||
cmd!("cargo install cargo-fuzz").run()?;
|
||||
};
|
||||
|
||||
// Expecting nightly rustc
|
||||
let out = run!("rustc --version")?;
|
||||
let out = cmd!("rustc --version").read()?;
|
||||
if !out.contains("nightly") {
|
||||
bail!("fuzz tests require nightly rustc")
|
||||
}
|
||||
|
||||
run!("cargo fuzz run parser")?;
|
||||
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())
|
||||
}
|
||||
|
|
|
@ -12,12 +12,12 @@ use std::env;
|
|||
|
||||
use codegen::CodegenCmd;
|
||||
use pico_args::Arguments;
|
||||
use xshell::pushd;
|
||||
use xtask::{
|
||||
codegen::{self, Mode},
|
||||
dist::DistCmd,
|
||||
install::{ClientOpt, InstallCmd, Malloc, ServerOpt},
|
||||
metrics::MetricsCmd,
|
||||
not_bash::pushd,
|
||||
pre_cache::PreCacheCmd,
|
||||
pre_commit, project_root,
|
||||
release::{PromoteCmd, ReleaseCmd},
|
||||
|
@ -29,7 +29,7 @@ fn main() -> Result<()> {
|
|||
return pre_commit::run_hook();
|
||||
}
|
||||
|
||||
let _d = pushd(project_root());
|
||||
let _d = pushd(project_root())?;
|
||||
|
||||
let mut args = Arguments::from_env();
|
||||
let subcommand = args.subcommand()?.unwrap_or_default();
|
||||
|
|
|
@ -7,8 +7,7 @@ use std::{
|
|||
};
|
||||
|
||||
use anyhow::{bail, format_err, Result};
|
||||
|
||||
use crate::not_bash::{fs2, pushd, pushenv, rm_rf, run};
|
||||
use xshell::{cmd, mkdir_p, pushd, pushenv, read_file, rm_rf};
|
||||
|
||||
type Unit = String;
|
||||
|
||||
|
@ -23,12 +22,13 @@ impl MetricsCmd {
|
|||
rm_rf("./target/release")?;
|
||||
}
|
||||
if !Path::new("./target/rustc-perf").exists() {
|
||||
fs2::create_dir_all("./target/rustc-perf")?;
|
||||
run!("git clone https://github.com/rust-lang/rustc-perf.git ./target/rustc-perf")?;
|
||||
mkdir_p("./target/rustc-perf")?;
|
||||
cmd!("git clone https://github.com/rust-lang/rustc-perf.git ./target/rustc-perf")
|
||||
.run()?;
|
||||
}
|
||||
{
|
||||
let _d = pushd("./target/rustc-perf");
|
||||
run!("git reset --hard 1d9288b0da7febf2599917da1b57dc241a1af033")?;
|
||||
let _d = pushd("./target/rustc-perf")?;
|
||||
cmd!("git reset --hard 1d9288b0da7febf2599917da1b57dc241a1af033").run()?;
|
||||
}
|
||||
|
||||
let _env = pushenv("RA_METRICS", "1");
|
||||
|
@ -39,17 +39,20 @@ impl MetricsCmd {
|
|||
metrics.measure_analysis_stats("webrender")?;
|
||||
|
||||
if !self.dry_run {
|
||||
let _d = pushd("target");
|
||||
let _d = pushd("target")?;
|
||||
let metrics_token = env::var("METRICS_TOKEN").unwrap();
|
||||
let repo = format!("https://{}@github.com/rust-analyzer/metrics.git", metrics_token);
|
||||
run!("git clone --depth 1 {}", repo)?;
|
||||
let _d = pushd("metrics");
|
||||
cmd!(
|
||||
"git clone --depth 1 https://{metrics_token}@github.com/rust-analyzer/metrics.git"
|
||||
)
|
||||
.run()?;
|
||||
let _d = pushd("metrics")?;
|
||||
|
||||
let mut file = std::fs::OpenOptions::new().append(true).open("metrics.json")?;
|
||||
writeln!(file, "{}", metrics.json())?;
|
||||
run!("git add .")?;
|
||||
run!("git -c user.name=Bot -c user.email=dummy@example.com commit --message 📈")?;
|
||||
run!("git push origin master")?;
|
||||
cmd!("git add .").run()?;
|
||||
cmd!("git -c user.name=Bot -c user.email=dummy@example.com commit --message 📈")
|
||||
.run()?;
|
||||
cmd!("git push origin master").run()?;
|
||||
}
|
||||
eprintln!("{:#?}", metrics);
|
||||
Ok(())
|
||||
|
@ -59,10 +62,10 @@ impl MetricsCmd {
|
|||
impl Metrics {
|
||||
fn measure_build(&mut self) -> Result<()> {
|
||||
eprintln!("\nMeasuring build");
|
||||
run!("cargo fetch")?;
|
||||
cmd!("cargo fetch").run()?;
|
||||
|
||||
let time = Instant::now();
|
||||
run!("cargo build --release --package rust-analyzer --bin rust-analyzer")?;
|
||||
cmd!("cargo build --release --package rust-analyzer --bin rust-analyzer").run()?;
|
||||
let time = time.elapsed();
|
||||
self.report("build", time.as_millis() as u64, "ms".into());
|
||||
Ok(())
|
||||
|
@ -78,7 +81,7 @@ impl Metrics {
|
|||
}
|
||||
fn measure_analysis_stats_path(&mut self, name: &str, path: &str) -> Result<()> {
|
||||
eprintln!("\nMeasuring analysis-stats/{}", name);
|
||||
let output = run!("./target/release/rust-analyzer analysis-stats --quiet {}", path)?;
|
||||
let output = cmd!("./target/release/rust-analyzer analysis-stats --quiet {path}").read()?;
|
||||
for (metric, value, unit) in parse_metrics(&output) {
|
||||
self.report(&format!("analysis-stats/{}/{}", name, metric), value, unit.into());
|
||||
}
|
||||
|
@ -118,7 +121,7 @@ impl Metrics {
|
|||
fn new() -> Result<Metrics> {
|
||||
let host = Host::new()?;
|
||||
let timestamp = SystemTime::now();
|
||||
let revision = run!("git rev-parse HEAD")?;
|
||||
let revision = cmd!("git rev-parse HEAD").read()?;
|
||||
Ok(Metrics { host, timestamp, revision, metrics: BTreeMap::new() })
|
||||
}
|
||||
|
||||
|
@ -160,7 +163,7 @@ impl Host {
|
|||
return Ok(Host { os, cpu, mem });
|
||||
|
||||
fn read_field<'a>(path: &str, field: &str) -> Result<String> {
|
||||
let text = fs2::read_to_string(path)?;
|
||||
let text = read_file(path)?;
|
||||
|
||||
let line = text
|
||||
.lines()
|
||||
|
|
|
@ -1,169 +0,0 @@
|
|||
//! A bad shell -- small cross platform module for writing glue code
|
||||
|
||||
use std::{
|
||||
cell::RefCell,
|
||||
env,
|
||||
ffi::OsString,
|
||||
io::{self, Write},
|
||||
path::{Path, PathBuf},
|
||||
process::{Command, Stdio},
|
||||
};
|
||||
|
||||
use anyhow::{bail, Context, Result};
|
||||
|
||||
pub use fs_err as fs2;
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! run {
|
||||
($($expr:expr),*) => {
|
||||
run!($($expr),*; echo = true)
|
||||
};
|
||||
($($expr:expr),* ; echo = $echo:expr) => {
|
||||
$crate::not_bash::run_process(format!($($expr),*), $echo, None)
|
||||
};
|
||||
($($expr:expr),* ; <$stdin:expr) => {
|
||||
$crate::not_bash::run_process(format!($($expr),*), false, Some($stdin))
|
||||
};
|
||||
}
|
||||
pub use crate::run;
|
||||
|
||||
pub struct Pushd {
|
||||
_p: (),
|
||||
}
|
||||
|
||||
pub fn pushd(path: impl Into<PathBuf>) -> Pushd {
|
||||
Env::with(|env| env.pushd(path.into()));
|
||||
Pushd { _p: () }
|
||||
}
|
||||
|
||||
impl Drop for Pushd {
|
||||
fn drop(&mut self) {
|
||||
Env::with(|env| env.popd())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Pushenv {
|
||||
_p: (),
|
||||
}
|
||||
|
||||
pub fn pushenv(var: &str, value: &str) -> Pushenv {
|
||||
Env::with(|env| env.pushenv(var.into(), value.into()));
|
||||
Pushenv { _p: () }
|
||||
}
|
||||
|
||||
impl Drop for Pushenv {
|
||||
fn drop(&mut self) {
|
||||
Env::with(|env| env.popenv())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn rm_rf(path: impl AsRef<Path>) -> io::Result<()> {
|
||||
let path = path.as_ref();
|
||||
if !path.exists() {
|
||||
return Ok(());
|
||||
}
|
||||
if path.is_file() {
|
||||
fs2::remove_file(path)
|
||||
} else {
|
||||
fs2::remove_dir_all(path)
|
||||
}
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
pub fn run_process(cmd: String, echo: bool, stdin: Option<&[u8]>) -> Result<String> {
|
||||
run_process_inner(&cmd, echo, stdin).with_context(|| format!("process `{}` failed", cmd))
|
||||
}
|
||||
|
||||
pub fn date_iso() -> Result<String> {
|
||||
run!("date --iso --utc")
|
||||
}
|
||||
|
||||
fn run_process_inner(cmd: &str, echo: bool, stdin: Option<&[u8]>) -> Result<String> {
|
||||
let mut args = shelx(cmd);
|
||||
let binary = args.remove(0);
|
||||
let current_dir = Env::with(|it| it.cwd().to_path_buf());
|
||||
|
||||
if echo {
|
||||
println!("> {}", cmd)
|
||||
}
|
||||
|
||||
let mut command = Command::new(binary);
|
||||
command.args(args).current_dir(current_dir).stderr(Stdio::inherit());
|
||||
let output = match stdin {
|
||||
None => command.stdin(Stdio::null()).output(),
|
||||
Some(stdin) => {
|
||||
command.stdin(Stdio::piped()).stdout(Stdio::piped());
|
||||
let mut process = command.spawn()?;
|
||||
process.stdin.take().unwrap().write_all(stdin)?;
|
||||
process.wait_with_output()
|
||||
}
|
||||
}?;
|
||||
let stdout = String::from_utf8(output.stdout)?;
|
||||
|
||||
if echo {
|
||||
print!("{}", stdout)
|
||||
}
|
||||
|
||||
if !output.status.success() {
|
||||
bail!("{}", output.status)
|
||||
}
|
||||
|
||||
Ok(stdout.trim().to_string())
|
||||
}
|
||||
|
||||
// FIXME: some real shell lexing here
|
||||
fn shelx(cmd: &str) -> Vec<String> {
|
||||
let mut res = Vec::new();
|
||||
for (string_piece, in_quotes) in cmd.split('\'').zip([false, true].iter().copied().cycle()) {
|
||||
if in_quotes {
|
||||
res.push(string_piece.to_string())
|
||||
} else {
|
||||
if !string_piece.is_empty() {
|
||||
res.extend(string_piece.split_ascii_whitespace().map(|it| it.to_string()))
|
||||
}
|
||||
}
|
||||
}
|
||||
res
|
||||
}
|
||||
|
||||
struct Env {
|
||||
pushd_stack: Vec<PathBuf>,
|
||||
pushenv_stack: Vec<(OsString, Option<OsString>)>,
|
||||
}
|
||||
|
||||
impl Env {
|
||||
fn with<F: FnOnce(&mut Env) -> T, T>(f: F) -> T {
|
||||
thread_local! {
|
||||
static ENV: RefCell<Env> = RefCell::new(Env {
|
||||
pushd_stack: vec![env::current_dir().unwrap()],
|
||||
pushenv_stack: vec![],
|
||||
});
|
||||
}
|
||||
ENV.with(|it| f(&mut *it.borrow_mut()))
|
||||
}
|
||||
|
||||
fn pushd(&mut self, dir: PathBuf) {
|
||||
let dir = self.cwd().join(dir);
|
||||
self.pushd_stack.push(dir);
|
||||
env::set_current_dir(self.cwd())
|
||||
.unwrap_or_else(|err| panic!("Failed to set cwd to {}: {}", self.cwd().display(), err));
|
||||
}
|
||||
fn popd(&mut self) {
|
||||
self.pushd_stack.pop().unwrap();
|
||||
env::set_current_dir(self.cwd()).unwrap();
|
||||
}
|
||||
fn pushenv(&mut self, var: OsString, value: OsString) {
|
||||
self.pushenv_stack.push((var.clone(), env::var_os(&var)));
|
||||
env::set_var(var, value)
|
||||
}
|
||||
fn popenv(&mut self) {
|
||||
let (var, value) = self.pushenv_stack.pop().unwrap();
|
||||
match value {
|
||||
None => env::remove_var(var),
|
||||
Some(value) => env::set_var(var, value),
|
||||
}
|
||||
}
|
||||
fn cwd(&self) -> &Path {
|
||||
self.pushd_stack.last().unwrap()
|
||||
}
|
||||
}
|
|
@ -4,8 +4,7 @@ use std::{
|
|||
};
|
||||
|
||||
use anyhow::Result;
|
||||
|
||||
use crate::not_bash::{fs2, rm_rf};
|
||||
use xshell::rm_rf;
|
||||
|
||||
pub struct PreCacheCmd;
|
||||
|
||||
|
@ -26,7 +25,7 @@ impl PreCacheCmd {
|
|||
}
|
||||
}
|
||||
|
||||
fs2::remove_file("./target/.rustc_info.json")?;
|
||||
rm_rf("./target/.rustc_info.json")?;
|
||||
|
||||
let to_delete = read_dir("./crates", FileType::is_dir)?
|
||||
.into_iter()
|
||||
|
|
|
@ -3,19 +3,21 @@
|
|||
use std::{fs, path::PathBuf};
|
||||
|
||||
use anyhow::{bail, Result};
|
||||
use xshell::cmd;
|
||||
|
||||
use crate::{not_bash::run, project_root, run_rustfmt, Mode};
|
||||
use crate::{project_root, run_rustfmt, Mode};
|
||||
|
||||
// FIXME: if there are changed `.ts` files, also reformat TypeScript (by
|
||||
// shelling out to `npm fmt`).
|
||||
pub fn run_hook() -> Result<()> {
|
||||
run_rustfmt(Mode::Overwrite)?;
|
||||
|
||||
let diff = run!("git diff --diff-filter=MAR --name-only --cached")?;
|
||||
let diff = cmd!("git diff --diff-filter=MAR --name-only --cached").read()?;
|
||||
|
||||
let root = project_root();
|
||||
for line in diff.lines() {
|
||||
run!("git update-index --add {}", root.join(line).display())?;
|
||||
let file = root.join(line);
|
||||
cmd!("git update-index --add {file}").run()?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
|
|
@ -1,8 +1,6 @@
|
|||
use crate::{
|
||||
codegen, is_release_tag,
|
||||
not_bash::{date_iso, fs2, pushd, run},
|
||||
project_root, Mode, Result,
|
||||
};
|
||||
use xshell::{cmd, cp, pushd, read_dir, write_file};
|
||||
|
||||
use crate::{codegen, date_iso, is_release_tag, project_root, Mode, Result};
|
||||
|
||||
pub struct ReleaseCmd {
|
||||
pub dry_run: bool,
|
||||
|
@ -11,10 +9,10 @@ pub struct ReleaseCmd {
|
|||
impl ReleaseCmd {
|
||||
pub fn run(self) -> Result<()> {
|
||||
if !self.dry_run {
|
||||
run!("git switch release")?;
|
||||
run!("git fetch upstream --tags --force")?;
|
||||
run!("git reset --hard tags/nightly")?;
|
||||
run!("git push")?;
|
||||
cmd!("git switch release").run()?;
|
||||
cmd!("git fetch upstream --tags --force").run()?;
|
||||
cmd!("git reset --hard tags/nightly").run()?;
|
||||
cmd!("git push").run()?;
|
||||
}
|
||||
codegen::generate_assists_docs(Mode::Overwrite)?;
|
||||
codegen::generate_feature_docs(Mode::Overwrite)?;
|
||||
|
@ -23,8 +21,8 @@ impl ReleaseCmd {
|
|||
let changelog_dir = website_root.join("./thisweek/_posts");
|
||||
|
||||
let today = date_iso()?;
|
||||
let commit = run!("git rev-parse HEAD")?;
|
||||
let changelog_n = fs2::read_dir(changelog_dir.as_path())?.count();
|
||||
let commit = cmd!("git rev-parse HEAD").read()?;
|
||||
let changelog_n = read_dir(changelog_dir.as_path())?.len();
|
||||
|
||||
let contents = format!(
|
||||
"\
|
||||
|
@ -52,20 +50,20 @@ https://github.com/sponsors/rust-analyzer[GitHub Sponsors].
|
|||
);
|
||||
|
||||
let path = changelog_dir.join(format!("{}-changelog-{}.adoc", today, changelog_n));
|
||||
fs2::write(&path, &contents)?;
|
||||
write_file(&path, &contents)?;
|
||||
|
||||
for &adoc in ["manual.adoc", "generated_features.adoc", "generated_assists.adoc"].iter() {
|
||||
let src = project_root().join("./docs/user/").join(adoc);
|
||||
let dst = website_root.join(adoc);
|
||||
fs2::copy(src, dst)?;
|
||||
cp(src, dst)?;
|
||||
}
|
||||
|
||||
let tags = run!("git tag --list"; echo = false)?;
|
||||
let tags = cmd!("git tag --list").read()?;
|
||||
let prev_tag = tags.lines().filter(|line| is_release_tag(line)).last().unwrap();
|
||||
|
||||
let git_log = run!("git log {}..HEAD --merges --reverse", prev_tag; echo = false)?;
|
||||
let git_log = cmd!("git log {prev_tag}..HEAD --merges --reverse").read()?;
|
||||
let git_log_dst = website_root.join("git.log");
|
||||
fs2::write(git_log_dst, &git_log)?;
|
||||
write_file(git_log_dst, &git_log)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
@ -77,27 +75,25 @@ pub struct PromoteCmd {
|
|||
|
||||
impl PromoteCmd {
|
||||
pub fn run(self) -> Result<()> {
|
||||
let _dir = pushd("../rust-rust-analyzer");
|
||||
run!("git switch master")?;
|
||||
run!("git fetch upstream")?;
|
||||
run!("git reset --hard upstream/master")?;
|
||||
run!("git submodule update --recursive")?;
|
||||
let _dir = pushd("../rust-rust-analyzer")?;
|
||||
cmd!("git switch master").run()?;
|
||||
cmd!("git fetch upstream").run()?;
|
||||
cmd!("git reset --hard upstream/master").run()?;
|
||||
cmd!("git submodule update --recursive").run()?;
|
||||
|
||||
let branch = format!("rust-analyzer-{}", date_iso()?);
|
||||
run!("git switch -c {}", branch)?;
|
||||
cmd!("git switch -c {branch}").run()?;
|
||||
{
|
||||
let _dir = pushd("src/tools/rust-analyzer");
|
||||
run!("git fetch origin")?;
|
||||
run!("git reset --hard origin/release")?;
|
||||
let _dir = pushd("src/tools/rust-analyzer")?;
|
||||
cmd!("git fetch origin").run()?;
|
||||
cmd!("git reset --hard origin/release").run()?;
|
||||
}
|
||||
run!("git add src/tools/rust-analyzer")?;
|
||||
run!("git commit -m':arrow_up: rust-analyzer'")?;
|
||||
cmd!("git add src/tools/rust-analyzer").run()?;
|
||||
cmd!("git commit -m':arrow_up: rust-analyzer'").run()?;
|
||||
if !self.dry_run {
|
||||
run!("git push")?;
|
||||
run!(
|
||||
"xdg-open https://github.com/matklad/rust/pull/new/{}?body=r%3F%20%40ghost",
|
||||
branch
|
||||
)?;
|
||||
cmd!("git push").run()?;
|
||||
cmd!("xdg-open https://github.com/matklad/rust/pull/new/{branch}?body=r%3F%20%40ghost")
|
||||
.run()?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -3,9 +3,9 @@ use std::{
|
|||
path::{Path, PathBuf},
|
||||
};
|
||||
|
||||
use xshell::{cmd, read_file};
|
||||
use xtask::{
|
||||
codegen::{self, Mode},
|
||||
not_bash::{fs2, run},
|
||||
project_root, run_rustfmt, rust_files,
|
||||
};
|
||||
|
||||
|
@ -48,14 +48,13 @@ fn smoke_test_docs_generation() {
|
|||
fn check_lsp_extensions_docs() {
|
||||
let expected_hash = {
|
||||
let lsp_ext_rs =
|
||||
fs2::read_to_string(project_root().join("crates/rust-analyzer/src/lsp_ext.rs"))
|
||||
.unwrap();
|
||||
read_file(project_root().join("crates/rust-analyzer/src/lsp_ext.rs")).unwrap();
|
||||
stable_hash(lsp_ext_rs.as_str())
|
||||
};
|
||||
|
||||
let actual_hash = {
|
||||
let lsp_extensions_md =
|
||||
fs2::read_to_string(project_root().join("docs/dev/lsp-extensions.md")).unwrap();
|
||||
read_file(project_root().join("docs/dev/lsp-extensions.md")).unwrap();
|
||||
let text = lsp_extensions_md
|
||||
.lines()
|
||||
.find_map(|line| line.strip_prefix("lsp_ext.rs hash:"))
|
||||
|
@ -83,7 +82,7 @@ Please adjust docs/dev/lsp-extensions.md.
|
|||
fn rust_files_are_tidy() {
|
||||
let mut tidy_docs = TidyDocs::default();
|
||||
for path in rust_files(&project_root().join("crates")) {
|
||||
let text = fs2::read_to_string(&path).unwrap();
|
||||
let text = read_file(&path).unwrap();
|
||||
check_todo(&path, &text);
|
||||
check_trailing_ws(&path, &text);
|
||||
deny_clippy(&path, &text);
|
||||
|
@ -94,8 +93,10 @@ fn rust_files_are_tidy() {
|
|||
|
||||
#[test]
|
||||
fn check_merge_commits() {
|
||||
let stdout = run!("git rev-list --merges --invert-grep --author 'bors\\[bot\\]' HEAD~19.."; echo = false)
|
||||
.unwrap();
|
||||
let stdout =
|
||||
dbg!(cmd!("git rev-list --merges --invert-grep --author 'bors\\[bot\\]' HEAD~19.."))
|
||||
.read()
|
||||
.unwrap();
|
||||
if !stdout.is_empty() {
|
||||
panic!(
|
||||
"
|
||||
|
@ -168,7 +169,7 @@ Zlib OR Apache-2.0 OR MIT
|
|||
.filter(|it| !it.is_empty())
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let meta = run!("cargo metadata --format-version 1"; echo = false).unwrap();
|
||||
let meta = cmd!("cargo metadata --format-version 1").read().unwrap();
|
||||
let mut licenses = meta
|
||||
.split(|c| c == ',' || c == '{' || c == '}')
|
||||
.filter(|it| it.contains(r#""license""#))
|
||||
|
@ -177,6 +178,25 @@ Zlib OR Apache-2.0 OR MIT
|
|||
.collect::<Vec<_>>();
|
||||
licenses.sort();
|
||||
licenses.dedup();
|
||||
if licenses != expected {
|
||||
let mut diff = String::new();
|
||||
|
||||
diff += &format!("New Licenses:\n");
|
||||
for &l in licenses.iter() {
|
||||
if !expected.contains(&l) {
|
||||
diff += &format!(" {}\n", l)
|
||||
}
|
||||
}
|
||||
|
||||
diff += &format!("\nMissing Licenses:\n");
|
||||
for &l in expected.iter() {
|
||||
if !licenses.contains(&l) {
|
||||
diff += &format!(" {}\n", l)
|
||||
}
|
||||
}
|
||||
|
||||
panic!("different set of licenses!\n{}", diff);
|
||||
}
|
||||
assert_eq!(licenses, expected);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue