1#![warn(rust_2018_idioms, unused_lifetimes)]
12#![allow(
13 clippy::print_stderr,
14 clippy::print_stdout,
15 clippy::disallowed_methods,
16 clippy::disallowed_types
19)]
20
21mod flags;
22
23mod codegen;
24mod dist;
25mod install;
26mod metrics;
27mod pgo;
28mod publish;
29mod release;
30mod tidy;
31mod util;
32
33use anyhow::bail;
34use std::{env, path::PathBuf};
35use xshell::{Shell, cmd};
36
37fn main() -> anyhow::Result<()> {
38 let flags = flags::Xtask::from_env_or_exit();
39
40 let sh = &Shell::new()?;
41 sh.change_dir(project_root());
42
43 match flags.subcommand {
44 flags::XtaskCmd::Install(cmd) => cmd.run(sh),
45 flags::XtaskCmd::FuzzTests(_) => run_fuzzer(sh),
46 flags::XtaskCmd::Release(cmd) => cmd.run(sh),
47 flags::XtaskCmd::Dist(cmd) => cmd.run(sh),
48 flags::XtaskCmd::PublishReleaseNotes(cmd) => cmd.run(sh),
49 flags::XtaskCmd::Metrics(cmd) => cmd.run(sh),
50 flags::XtaskCmd::Codegen(cmd) => cmd.run(sh),
51 flags::XtaskCmd::Bb(cmd) => {
52 {
53 let _d = sh.push_dir("./crates/rust-analyzer");
54 cmd!(sh, "cargo build --release --features jemalloc").run()?;
55 }
56 sh.copy_file(
57 "./target/release/rust-analyzer",
58 format!("./target/rust-analyzer-{}", cmd.suffix),
59 )?;
60 Ok(())
61 }
62 flags::XtaskCmd::Tidy(cmd) => cmd.run(sh),
63 }
64}
65
66fn project_root() -> PathBuf {
68 let dir =
69 env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| env!("CARGO_MANIFEST_DIR").to_owned());
70 PathBuf::from(dir).parent().unwrap().to_owned()
71}
72
73fn run_fuzzer(sh: &Shell) -> anyhow::Result<()> {
74 let _d = sh.push_dir("./crates/syntax");
75 let _e = sh.push_env("RUSTUP_TOOLCHAIN", "nightly");
76 if cmd!(sh, "cargo fuzz --help").read().is_err() {
77 cmd!(sh, "cargo install --locked cargo-fuzz").run()?;
78 };
79
80 let out = cmd!(sh, "rustc --version").read()?;
82 if !out.contains("nightly") {
83 bail!("fuzz tests require nightly rustc")
84 }
85
86 cmd!(sh, "cargo fuzz run parser").run()?;
87 Ok(())
88}
89
90fn date_iso(sh: &Shell) -> anyhow::Result<String> {
91 let res = cmd!(sh, "date -u +%Y-%m-%d").read()?;
92 Ok(res)
93}
94
95fn is_release_tag(tag: &str) -> bool {
96 tag.len() >= 10
97 && tag.starts_with(|c: char| c.is_ascii_digit())
98 && tag.as_bytes()[4] == b'-'
99 && tag.as_bytes()[7] == b'-'
100}