diff options
Diffstat (limited to 'xtask')
-rw-r--r-- | xtask/Cargo.toml | 2 | ||||
-rw-r--r-- | xtask/src/ast_src.rs | 2 | ||||
-rw-r--r-- | xtask/src/codegen.rs | 6 | ||||
-rw-r--r-- | xtask/src/codegen/gen_assists_docs.rs | 11 | ||||
-rw-r--r-- | xtask/src/codegen/gen_syntax.rs | 6 | ||||
-rw-r--r-- | xtask/src/dist.rs | 31 | ||||
-rw-r--r-- | xtask/src/install.rs | 16 | ||||
-rw-r--r-- | xtask/src/lib.rs | 55 | ||||
-rw-r--r-- | xtask/src/main.rs | 28 | ||||
-rw-r--r-- | xtask/src/not_bash.rs | 17 | ||||
-rw-r--r-- | xtask/src/release.rs | 103 | ||||
-rw-r--r-- | xtask/tests/tidy.rs | 87 |
12 files changed, 252 insertions, 112 deletions
diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml index a8b9b010d..d1cfb5909 100644 --- a/xtask/Cargo.toml +++ b/xtask/Cargo.toml | |||
@@ -4,6 +4,7 @@ name = "xtask" | |||
4 | version = "0.1.0" | 4 | version = "0.1.0" |
5 | authors = ["rust-analyzer developers"] | 5 | authors = ["rust-analyzer developers"] |
6 | publish = false | 6 | publish = false |
7 | license = "MIT OR Apache-2.0" | ||
7 | 8 | ||
8 | [lib] | 9 | [lib] |
9 | doctest = false | 10 | doctest = false |
@@ -14,3 +15,4 @@ pico-args = "0.3.1" | |||
14 | quote = "1.0.2" | 15 | quote = "1.0.2" |
15 | proc-macro2 = "1.0.8" | 16 | proc-macro2 = "1.0.8" |
16 | anyhow = "1.0.26" | 17 | anyhow = "1.0.26" |
18 | flate2 = "1.0" | ||
diff --git a/xtask/src/ast_src.rs b/xtask/src/ast_src.rs index f60f0fb16..392648d71 100644 --- a/xtask/src/ast_src.rs +++ b/xtask/src/ast_src.rs | |||
@@ -1707,7 +1707,7 @@ pub(crate) const AST_SRC: AstSrc = AstSrc { | |||
1707 | /// ``` | 1707 | /// ``` |
1708 | /// | 1708 | /// |
1709 | /// [Reference](https://doc.rust-lang.org/reference/items/generics.html#where-clauses) | 1709 | /// [Reference](https://doc.rust-lang.org/reference/items/generics.html#where-clauses) |
1710 | struct WherePred: TypeBoundsOwner { T![lifetime], TypeRef } | 1710 | struct WherePred: TypeBoundsOwner { T![for], TypeParamList, T![lifetime], TypeRef } |
1711 | 1711 | ||
1712 | /// Where clause. | 1712 | /// Where clause. |
1713 | /// | 1713 | /// |
diff --git a/xtask/src/codegen.rs b/xtask/src/codegen.rs index 5511c01d5..f5f4b964a 100644 --- a/xtask/src/codegen.rs +++ b/xtask/src/codegen.rs | |||
@@ -18,8 +18,10 @@ use std::{ | |||
18 | use crate::{not_bash::fs2, project_root, Result}; | 18 | use crate::{not_bash::fs2, project_root, Result}; |
19 | 19 | ||
20 | pub use self::{ | 20 | pub use self::{ |
21 | gen_assists_docs::generate_assists_docs, gen_feature_docs::generate_feature_docs, | 21 | gen_assists_docs::{generate_assists_docs, generate_assists_tests}, |
22 | gen_parser_tests::generate_parser_tests, gen_syntax::generate_syntax, | 22 | gen_feature_docs::generate_feature_docs, |
23 | gen_parser_tests::generate_parser_tests, | ||
24 | gen_syntax::generate_syntax, | ||
23 | }; | 25 | }; |
24 | 26 | ||
25 | const GRAMMAR_DIR: &str = "crates/ra_parser/src/grammar"; | 27 | const GRAMMAR_DIR: &str = "crates/ra_parser/src/grammar"; |
diff --git a/xtask/src/codegen/gen_assists_docs.rs b/xtask/src/codegen/gen_assists_docs.rs index 6c1be5350..526941f73 100644 --- a/xtask/src/codegen/gen_assists_docs.rs +++ b/xtask/src/codegen/gen_assists_docs.rs | |||
@@ -7,16 +7,17 @@ use crate::{ | |||
7 | project_root, rust_files, Result, | 7 | project_root, rust_files, Result, |
8 | }; | 8 | }; |
9 | 9 | ||
10 | pub fn generate_assists_docs(mode: Mode) -> Result<()> { | 10 | pub fn generate_assists_tests(mode: Mode) -> Result<()> { |
11 | let assists = Assist::collect()?; | 11 | let assists = Assist::collect()?; |
12 | generate_tests(&assists, mode)?; | 12 | generate_tests(&assists, mode) |
13 | } | ||
13 | 14 | ||
15 | pub fn generate_assists_docs(mode: Mode) -> Result<()> { | ||
16 | let assists = Assist::collect()?; | ||
14 | let contents = assists.into_iter().map(|it| it.to_string()).collect::<Vec<_>>().join("\n\n"); | 17 | let contents = assists.into_iter().map(|it| it.to_string()).collect::<Vec<_>>().join("\n\n"); |
15 | let contents = contents.trim().to_string() + "\n"; | 18 | let contents = contents.trim().to_string() + "\n"; |
16 | let dst = project_root().join("docs/user/generated_assists.adoc"); | 19 | let dst = project_root().join("docs/user/generated_assists.adoc"); |
17 | codegen::update(&dst, &contents, mode)?; | 20 | codegen::update(&dst, &contents, mode) |
18 | |||
19 | Ok(()) | ||
20 | } | 21 | } |
21 | 22 | ||
22 | #[derive(Debug)] | 23 | #[derive(Debug)] |
diff --git a/xtask/src/codegen/gen_syntax.rs b/xtask/src/codegen/gen_syntax.rs index 19d5594f5..745a25862 100644 --- a/xtask/src/codegen/gen_syntax.rs +++ b/xtask/src/codegen/gen_syntax.rs | |||
@@ -40,7 +40,7 @@ fn generate_tokens(grammar: AstSrc<'_>) -> Result<String> { | |||
40 | pub(crate) syntax: SyntaxToken, | 40 | pub(crate) syntax: SyntaxToken, |
41 | } | 41 | } |
42 | impl std::fmt::Display for #name { | 42 | impl std::fmt::Display for #name { |
43 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { | 43 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
44 | std::fmt::Display::fmt(&self.syntax, f) | 44 | std::fmt::Display::fmt(&self.syntax, f) |
45 | } | 45 | } |
46 | } | 46 | } |
@@ -68,7 +68,7 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> { | |||
68 | .iter() | 68 | .iter() |
69 | .map(|node| { | 69 | .map(|node| { |
70 | let name = format_ident!("{}", node.name); | 70 | let name = format_ident!("{}", node.name); |
71 | let kind = format_ident!("{}", to_upper_snake_case(&name.to_string())); | 71 | let kind = format_ident!("{}", to_upper_snake_case(node.name)); |
72 | let traits = node.traits.iter().map(|trait_name| { | 72 | let traits = node.traits.iter().map(|trait_name| { |
73 | let trait_name = format_ident!("{}", trait_name); | 73 | let trait_name = format_ident!("{}", trait_name); |
74 | quote!(impl ast::#trait_name for #name {}) | 74 | quote!(impl ast::#trait_name for #name {}) |
@@ -199,7 +199,7 @@ fn generate_nodes(kinds: KindsSrc<'_>, grammar: AstSrc<'_>) -> Result<String> { | |||
199 | enum_names.chain(node_names.clone()).map(|it| format_ident!("{}", it)).map(|name| { | 199 | enum_names.chain(node_names.clone()).map(|it| format_ident!("{}", it)).map(|name| { |
200 | quote! { | 200 | quote! { |
201 | impl std::fmt::Display for #name { | 201 | impl std::fmt::Display for #name { |
202 | fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { | 202 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { |
203 | std::fmt::Display::fmt(self.syntax(), f) | 203 | std::fmt::Display::fmt(self.syntax(), f) |
204 | } | 204 | } |
205 | } | 205 | } |
diff --git a/xtask/src/dist.rs b/xtask/src/dist.rs index aef68089e..b8f68027c 100644 --- a/xtask/src/dist.rs +++ b/xtask/src/dist.rs | |||
@@ -1,4 +1,10 @@ | |||
1 | use std::path::PathBuf; | 1 | use flate2::{write::GzEncoder, Compression}; |
2 | use std::{ | ||
3 | env, | ||
4 | fs::File, | ||
5 | io, | ||
6 | path::{Path, PathBuf}, | ||
7 | }; | ||
2 | 8 | ||
3 | use anyhow::Result; | 9 | use anyhow::Result; |
4 | 10 | ||
@@ -16,7 +22,7 @@ pub fn run_dist(nightly: bool, client_version: Option<String>) -> Result<()> { | |||
16 | let release_tag = if nightly { "nightly".to_string() } else { date_iso()? }; | 22 | let release_tag = if nightly { "nightly".to_string() } else { date_iso()? }; |
17 | dist_client(&version, &release_tag)?; | 23 | dist_client(&version, &release_tag)?; |
18 | } | 24 | } |
19 | dist_server(nightly)?; | 25 | dist_server()?; |
20 | Ok(()) | 26 | Ok(()) |
21 | } | 27 | } |
22 | 28 | ||
@@ -46,17 +52,14 @@ fn dist_client(version: &str, release_tag: &str) -> Result<()> { | |||
46 | Ok(()) | 52 | Ok(()) |
47 | } | 53 | } |
48 | 54 | ||
49 | fn dist_server(nightly: bool) -> Result<()> { | 55 | fn dist_server() -> Result<()> { |
50 | if cfg!(target_os = "linux") { | 56 | if cfg!(target_os = "linux") { |
51 | std::env::set_var("CC", "clang"); | 57 | env::set_var("CC", "clang"); |
52 | run!( | 58 | run!( |
53 | "cargo build --manifest-path ./crates/rust-analyzer/Cargo.toml --bin rust-analyzer --release" | 59 | "cargo build --manifest-path ./crates/rust-analyzer/Cargo.toml --bin rust-analyzer --release" |
54 | // We'd want to add, but that requires setting the right linker somehow | 60 | // We'd want to add, but that requires setting the right linker somehow |
55 | // --features=jemalloc | 61 | // --features=jemalloc |
56 | )?; | 62 | )?; |
57 | if !nightly { | ||
58 | run!("strip ./target/release/rust-analyzer")?; | ||
59 | } | ||
60 | } else { | 63 | } else { |
61 | run!("cargo build --manifest-path ./crates/rust-analyzer/Cargo.toml --bin rust-analyzer --release")?; | 64 | run!("cargo build --manifest-path ./crates/rust-analyzer/Cargo.toml --bin rust-analyzer --release")?; |
62 | } | 65 | } |
@@ -71,8 +74,20 @@ fn dist_server(nightly: bool) -> Result<()> { | |||
71 | panic!("Unsupported OS") | 74 | panic!("Unsupported OS") |
72 | }; | 75 | }; |
73 | 76 | ||
74 | fs2::copy(src, dst)?; | 77 | let src = Path::new(src); |
78 | let dst = Path::new(dst); | ||
79 | |||
80 | fs2::copy(&src, &dst)?; | ||
81 | gzip(&src, &dst.with_extension("gz"))?; | ||
82 | |||
83 | Ok(()) | ||
84 | } | ||
75 | 85 | ||
86 | fn gzip(src_path: &Path, dest_path: &Path) -> Result<()> { | ||
87 | let mut encoder = GzEncoder::new(File::create(dest_path)?, Compression::best()); | ||
88 | let mut input = io::BufReader::new(File::open(src_path)?); | ||
89 | io::copy(&mut input, &mut encoder)?; | ||
90 | encoder.finish()?; | ||
76 | Ok(()) | 91 | Ok(()) |
77 | } | 92 | } |
78 | 93 | ||
diff --git a/xtask/src/install.rs b/xtask/src/install.rs index 9ba77a3aa..a0dc0c9c2 100644 --- a/xtask/src/install.rs +++ b/xtask/src/install.rs | |||
@@ -19,7 +19,13 @@ pub enum ClientOpt { | |||
19 | } | 19 | } |
20 | 20 | ||
21 | pub struct ServerOpt { | 21 | pub struct ServerOpt { |
22 | pub jemalloc: bool, | 22 | pub malloc: Malloc, |
23 | } | ||
24 | |||
25 | pub enum Malloc { | ||
26 | System, | ||
27 | Jemalloc, | ||
28 | Mimalloc, | ||
23 | } | 29 | } |
24 | 30 | ||
25 | impl InstallCmd { | 31 | impl InstallCmd { |
@@ -130,8 +136,12 @@ fn install_server(opts: ServerOpt) -> Result<()> { | |||
130 | ) | 136 | ) |
131 | } | 137 | } |
132 | 138 | ||
133 | let jemalloc = if opts.jemalloc { "--features jemalloc" } else { "" }; | 139 | let malloc_feature = match opts.malloc { |
134 | let res = run!("cargo install --path crates/rust-analyzer --locked --force {}", jemalloc); | 140 | Malloc::System => "", |
141 | Malloc::Jemalloc => "--features jemalloc", | ||
142 | Malloc::Mimalloc => "--features mimalloc", | ||
143 | }; | ||
144 | let res = run!("cargo install --path crates/rust-analyzer --locked --force {}", malloc_feature); | ||
135 | 145 | ||
136 | if res.is_err() && old_rust { | 146 | if res.is_err() && old_rust { |
137 | eprintln!( | 147 | eprintln!( |
diff --git a/xtask/src/lib.rs b/xtask/src/lib.rs index 874957885..94d451e23 100644 --- a/xtask/src/lib.rs +++ b/xtask/src/lib.rs | |||
@@ -4,6 +4,7 @@ | |||
4 | 4 | ||
5 | pub mod not_bash; | 5 | pub mod not_bash; |
6 | pub mod install; | 6 | pub mod install; |
7 | pub mod release; | ||
7 | pub mod dist; | 8 | pub mod dist; |
8 | pub mod pre_commit; | 9 | pub mod pre_commit; |
9 | 10 | ||
@@ -19,7 +20,7 @@ use walkdir::{DirEntry, WalkDir}; | |||
19 | 20 | ||
20 | use crate::{ | 21 | use crate::{ |
21 | codegen::Mode, | 22 | codegen::Mode, |
22 | not_bash::{date_iso, fs2, pushd, pushenv, rm_rf, run}, | 23 | not_bash::{fs2, pushd, pushenv, rm_rf}, |
23 | }; | 24 | }; |
24 | 25 | ||
25 | pub use anyhow::{bail, Context as _, Result}; | 26 | pub use anyhow::{bail, Context as _, Result}; |
@@ -153,58 +154,6 @@ pub fn run_pre_cache() -> Result<()> { | |||
153 | Ok(()) | 154 | Ok(()) |
154 | } | 155 | } |
155 | 156 | ||
156 | pub fn run_release(dry_run: bool) -> Result<()> { | ||
157 | if !dry_run { | ||
158 | run!("git switch release")?; | ||
159 | run!("git fetch upstream --tags --force")?; | ||
160 | run!("git reset --hard tags/nightly")?; | ||
161 | run!("git push")?; | ||
162 | } | ||
163 | |||
164 | let website_root = project_root().join("../rust-analyzer.github.io"); | ||
165 | let changelog_dir = website_root.join("./thisweek/_posts"); | ||
166 | |||
167 | let today = date_iso()?; | ||
168 | let commit = run!("git rev-parse HEAD")?; | ||
169 | let changelog_n = fs2::read_dir(changelog_dir.as_path())?.count(); | ||
170 | |||
171 | let contents = format!( | ||
172 | "\ | ||
173 | = Changelog #{} | ||
174 | :sectanchors: | ||
175 | :page-layout: post | ||
176 | |||
177 | Commit: commit:{}[] + | ||
178 | Release: release:{}[] | ||
179 | |||
180 | == New Features | ||
181 | |||
182 | * pr:[] . | ||
183 | |||
184 | == Fixes | ||
185 | |||
186 | == Internal Improvements | ||
187 | ", | ||
188 | changelog_n, commit, today | ||
189 | ); | ||
190 | |||
191 | let path = changelog_dir.join(format!("{}-changelog-{}.adoc", today, changelog_n)); | ||
192 | fs2::write(&path, &contents)?; | ||
193 | |||
194 | for &adoc in ["manual.adoc", "generated_features.adoc", "generated_assists.adoc"].iter() { | ||
195 | let src = project_root().join("./docs/user/").join(adoc); | ||
196 | let dst = website_root.join(adoc); | ||
197 | fs2::copy(src, dst)?; | ||
198 | } | ||
199 | |||
200 | let tags = run!("git tag --list"; echo = false)?; | ||
201 | let prev_tag = tags.lines().filter(|line| is_release_tag(line)).last().unwrap(); | ||
202 | |||
203 | println!("\n git log {}..HEAD --merges --reverse", prev_tag); | ||
204 | |||
205 | Ok(()) | ||
206 | } | ||
207 | |||
208 | fn is_release_tag(tag: &str) -> bool { | 157 | fn is_release_tag(tag: &str) -> bool { |
209 | tag.len() == "2020-02-24".len() && tag.starts_with(|c: char| c.is_ascii_digit()) | 158 | tag.len() == "2020-02-24".len() && tag.starts_with(|c: char| c.is_ascii_digit()) |
210 | } | 159 | } |
diff --git a/xtask/src/main.rs b/xtask/src/main.rs index 9d7cdd114..399ff7204 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs | |||
@@ -14,10 +14,11 @@ use pico_args::Arguments; | |||
14 | use xtask::{ | 14 | use xtask::{ |
15 | codegen::{self, Mode}, | 15 | codegen::{self, Mode}, |
16 | dist::run_dist, | 16 | dist::run_dist, |
17 | install::{ClientOpt, InstallCmd, ServerOpt}, | 17 | install::{ClientOpt, InstallCmd, Malloc, ServerOpt}, |
18 | not_bash::pushd, | 18 | not_bash::pushd, |
19 | pre_commit, project_root, run_clippy, run_fuzzer, run_pre_cache, run_release, run_rustfmt, | 19 | pre_commit, project_root, |
20 | Result, | 20 | release::{PromoteCmd, ReleaseCmd}, |
21 | run_clippy, run_fuzzer, run_pre_cache, run_rustfmt, Result, | ||
21 | }; | 22 | }; |
22 | 23 | ||
23 | fn main() -> Result<()> { | 24 | fn main() -> Result<()> { |
@@ -45,6 +46,7 @@ FLAGS: | |||
45 | --client-code Install only VS Code plugin | 46 | --client-code Install only VS Code plugin |
46 | --server Install only the language server | 47 | --server Install only the language server |
47 | --jemalloc Use jemalloc for server | 48 | --jemalloc Use jemalloc for server |
49 | --mimalloc Use mimalloc for server | ||
48 | -h, --help Prints help information | 50 | -h, --help Prints help information |
49 | " | 51 | " |
50 | ); | 52 | ); |
@@ -60,13 +62,21 @@ FLAGS: | |||
60 | return Ok(()); | 62 | return Ok(()); |
61 | } | 63 | } |
62 | 64 | ||
63 | let jemalloc = args.contains("--jemalloc"); | 65 | let malloc = match (args.contains("--jemalloc"), args.contains("--mimalloc")) { |
66 | (false, false) => Malloc::System, | ||
67 | (true, false) => Malloc::Jemalloc, | ||
68 | (false, true) => Malloc::Mimalloc, | ||
69 | (true, true) => { | ||
70 | eprintln!("error: Cannot use both `--jemalloc` and `--mimalloc`"); | ||
71 | return Ok(()); | ||
72 | } | ||
73 | }; | ||
64 | 74 | ||
65 | args.finish()?; | 75 | args.finish()?; |
66 | 76 | ||
67 | InstallCmd { | 77 | InstallCmd { |
68 | client: if server { None } else { Some(ClientOpt::VsCode) }, | 78 | client: if server { None } else { Some(ClientOpt::VsCode) }, |
69 | server: if client_code { None } else { Some(ServerOpt { jemalloc }) }, | 79 | server: if client_code { None } else { Some(ServerOpt { malloc }) }, |
70 | } | 80 | } |
71 | .run() | 81 | .run() |
72 | } | 82 | } |
@@ -74,6 +84,7 @@ FLAGS: | |||
74 | args.finish()?; | 84 | args.finish()?; |
75 | codegen::generate_syntax(Mode::Overwrite)?; | 85 | codegen::generate_syntax(Mode::Overwrite)?; |
76 | codegen::generate_parser_tests(Mode::Overwrite)?; | 86 | codegen::generate_parser_tests(Mode::Overwrite)?; |
87 | codegen::generate_assists_tests(Mode::Overwrite)?; | ||
77 | codegen::generate_assists_docs(Mode::Overwrite)?; | 88 | codegen::generate_assists_docs(Mode::Overwrite)?; |
78 | codegen::generate_feature_docs(Mode::Overwrite)?; | 89 | codegen::generate_feature_docs(Mode::Overwrite)?; |
79 | Ok(()) | 90 | Ok(()) |
@@ -101,7 +112,12 @@ FLAGS: | |||
101 | "release" => { | 112 | "release" => { |
102 | let dry_run = args.contains("--dry-run"); | 113 | let dry_run = args.contains("--dry-run"); |
103 | args.finish()?; | 114 | args.finish()?; |
104 | run_release(dry_run) | 115 | ReleaseCmd { dry_run }.run() |
116 | } | ||
117 | "promote" => { | ||
118 | let dry_run = args.contains("--dry-run"); | ||
119 | args.finish()?; | ||
120 | PromoteCmd { dry_run }.run() | ||
105 | } | 121 | } |
106 | "dist" => { | 122 | "dist" => { |
107 | let nightly = args.contains("--nightly"); | 123 | let nightly = args.contains("--nightly"); |
diff --git a/xtask/src/not_bash.rs b/xtask/src/not_bash.rs index a6431e586..0f3a56b25 100644 --- a/xtask/src/not_bash.rs +++ b/xtask/src/not_bash.rs | |||
@@ -54,7 +54,8 @@ pub mod fs2 { | |||
54 | } | 54 | } |
55 | } | 55 | } |
56 | 56 | ||
57 | macro_rules! _run { | 57 | #[macro_export] |
58 | macro_rules! run { | ||
58 | ($($expr:expr),*) => { | 59 | ($($expr:expr),*) => { |
59 | run!($($expr),*; echo = true) | 60 | run!($($expr),*; echo = true) |
60 | }; | 61 | }; |
@@ -65,7 +66,7 @@ macro_rules! _run { | |||
65 | $crate::not_bash::run_process(format!($($expr),*), false, Some($stdin)) | 66 | $crate::not_bash::run_process(format!($($expr),*), false, Some($stdin)) |
66 | }; | 67 | }; |
67 | } | 68 | } |
68 | pub(crate) use _run as run; | 69 | pub use crate::run; |
69 | 70 | ||
70 | pub struct Pushd { | 71 | pub struct Pushd { |
71 | _p: (), | 72 | _p: (), |
@@ -153,7 +154,17 @@ fn run_process_inner(cmd: &str, echo: bool, stdin: Option<&[u8]>) -> Result<Stri | |||
153 | 154 | ||
154 | // FIXME: some real shell lexing here | 155 | // FIXME: some real shell lexing here |
155 | fn shelx(cmd: &str) -> Vec<String> { | 156 | fn shelx(cmd: &str) -> Vec<String> { |
156 | cmd.split_whitespace().map(|it| it.to_string()).collect() | 157 | let mut res = Vec::new(); |
158 | for (string_piece, in_quotes) in cmd.split('\'').zip([false, true].iter().copied().cycle()) { | ||
159 | if in_quotes { | ||
160 | res.push(string_piece.to_string()) | ||
161 | } else { | ||
162 | if !string_piece.is_empty() { | ||
163 | res.extend(string_piece.split_ascii_whitespace().map(|it| it.to_string())) | ||
164 | } | ||
165 | } | ||
166 | } | ||
167 | res | ||
157 | } | 168 | } |
158 | 169 | ||
159 | struct Env { | 170 | struct Env { |
diff --git a/xtask/src/release.rs b/xtask/src/release.rs new file mode 100644 index 000000000..530bd8205 --- /dev/null +++ b/xtask/src/release.rs | |||
@@ -0,0 +1,103 @@ | |||
1 | use crate::{ | ||
2 | codegen, is_release_tag, | ||
3 | not_bash::{date_iso, fs2, pushd, run}, | ||
4 | project_root, Mode, Result, | ||
5 | }; | ||
6 | |||
7 | pub struct ReleaseCmd { | ||
8 | pub dry_run: bool, | ||
9 | } | ||
10 | |||
11 | impl ReleaseCmd { | ||
12 | pub fn run(self) -> Result<()> { | ||
13 | if !self.dry_run { | ||
14 | run!("git switch release")?; | ||
15 | run!("git fetch upstream --tags --force")?; | ||
16 | run!("git reset --hard tags/nightly")?; | ||
17 | run!("git push")?; | ||
18 | } | ||
19 | codegen::generate_assists_docs(Mode::Overwrite)?; | ||
20 | codegen::generate_feature_docs(Mode::Overwrite)?; | ||
21 | |||
22 | let website_root = project_root().join("../rust-analyzer.github.io"); | ||
23 | let changelog_dir = website_root.join("./thisweek/_posts"); | ||
24 | |||
25 | let today = date_iso()?; | ||
26 | let commit = run!("git rev-parse HEAD")?; | ||
27 | let changelog_n = fs2::read_dir(changelog_dir.as_path())?.count(); | ||
28 | |||
29 | let contents = format!( | ||
30 | "\ | ||
31 | = Changelog #{} | ||
32 | :sectanchors: | ||
33 | :page-layout: post | ||
34 | |||
35 | Commit: commit:{}[] + | ||
36 | Release: release:{}[] | ||
37 | |||
38 | == Sponsors | ||
39 | |||
40 | **Become a sponsor:** https://opencollective.com/rust-analyzer/[opecollective.com/rust-analyzer] | ||
41 | |||
42 | == New Features | ||
43 | |||
44 | * pr:[] . | ||
45 | |||
46 | == Fixes | ||
47 | |||
48 | == Internal Improvements | ||
49 | ", | ||
50 | changelog_n, commit, today | ||
51 | ); | ||
52 | |||
53 | let path = changelog_dir.join(format!("{}-changelog-{}.adoc", today, changelog_n)); | ||
54 | fs2::write(&path, &contents)?; | ||
55 | |||
56 | for &adoc in ["manual.adoc", "generated_features.adoc", "generated_assists.adoc"].iter() { | ||
57 | let src = project_root().join("./docs/user/").join(adoc); | ||
58 | let dst = website_root.join(adoc); | ||
59 | fs2::copy(src, dst)?; | ||
60 | } | ||
61 | |||
62 | let tags = run!("git tag --list"; echo = false)?; | ||
63 | let prev_tag = tags.lines().filter(|line| is_release_tag(line)).last().unwrap(); | ||
64 | |||
65 | let git_log = run!("git log {}..HEAD --merges --reverse", prev_tag; echo = false)?; | ||
66 | let git_log_dst = website_root.join("git.log"); | ||
67 | fs2::write(git_log_dst, &git_log)?; | ||
68 | |||
69 | Ok(()) | ||
70 | } | ||
71 | } | ||
72 | |||
73 | pub struct PromoteCmd { | ||
74 | pub dry_run: bool, | ||
75 | } | ||
76 | |||
77 | impl PromoteCmd { | ||
78 | pub fn run(self) -> Result<()> { | ||
79 | let _dir = pushd("../rust-rust-analyzer"); | ||
80 | run!("git switch master")?; | ||
81 | run!("git fetch upstream")?; | ||
82 | run!("git reset --hard upstream/master")?; | ||
83 | run!("git submodule update --recursive")?; | ||
84 | |||
85 | let branch = format!("rust-analyzer-{}", date_iso()?); | ||
86 | run!("git switch -c {}", branch)?; | ||
87 | { | ||
88 | let _dir = pushd("src/tools/rust-analyzer"); | ||
89 | run!("git fetch origin")?; | ||
90 | run!("git reset --hard origin/release")?; | ||
91 | } | ||
92 | run!("git add src/tools/rust-analyzer")?; | ||
93 | run!("git commit -m':arrow_up: rust-analyzer'")?; | ||
94 | if !self.dry_run { | ||
95 | run!("git push")?; | ||
96 | run!( | ||
97 | "xdg-open https://github.com/matklad/rust/pull/new/{}?body=r%3F%20%40ghost", | ||
98 | branch | ||
99 | )?; | ||
100 | } | ||
101 | Ok(()) | ||
102 | } | ||
103 | } | ||
diff --git a/xtask/tests/tidy.rs b/xtask/tests/tidy.rs index 4ac5d929f..72088e414 100644 --- a/xtask/tests/tidy.rs +++ b/xtask/tests/tidy.rs | |||
@@ -5,7 +5,7 @@ use std::{ | |||
5 | 5 | ||
6 | use xtask::{ | 6 | use xtask::{ |
7 | codegen::{self, Mode}, | 7 | codegen::{self, Mode}, |
8 | not_bash::fs2, | 8 | not_bash::{fs2, run}, |
9 | project_root, run_rustfmt, rust_files, | 9 | project_root, run_rustfmt, rust_files, |
10 | }; | 10 | }; |
11 | 11 | ||
@@ -25,19 +25,12 @@ fn generated_tests_are_fresh() { | |||
25 | 25 | ||
26 | #[test] | 26 | #[test] |
27 | fn generated_assists_are_fresh() { | 27 | fn generated_assists_are_fresh() { |
28 | if let Err(error) = codegen::generate_assists_docs(Mode::Verify) { | 28 | if let Err(error) = codegen::generate_assists_tests(Mode::Verify) { |
29 | panic!("{}. Please update assists by running `cargo xtask codegen`", error); | 29 | panic!("{}. Please update assists by running `cargo xtask codegen`", error); |
30 | } | 30 | } |
31 | } | 31 | } |
32 | 32 | ||
33 | #[test] | 33 | #[test] |
34 | fn generated_features_are_fresh() { | ||
35 | if let Err(error) = codegen::generate_feature_docs(Mode::Verify) { | ||
36 | panic!("{}. Please update features by running `cargo xtask codegen`", error); | ||
37 | } | ||
38 | } | ||
39 | |||
40 | #[test] | ||
41 | fn check_code_formatting() { | 34 | fn check_code_formatting() { |
42 | if let Err(error) = run_rustfmt(Mode::Verify) { | 35 | if let Err(error) = run_rustfmt(Mode::Verify) { |
43 | panic!("{}. Please format the code by running `cargo format`", error); | 36 | panic!("{}. Please format the code by running `cargo format`", error); |
@@ -56,19 +49,59 @@ fn rust_files_are_tidy() { | |||
56 | tidy_docs.finish(); | 49 | tidy_docs.finish(); |
57 | } | 50 | } |
58 | 51 | ||
52 | #[test] | ||
53 | fn check_licenses() { | ||
54 | let expected = " | ||
55 | 0BSD OR MIT OR Apache-2.0 | ||
56 | Apache-2.0 | ||
57 | Apache-2.0 / MIT | ||
58 | Apache-2.0 OR BSL-1.0 | ||
59 | Apache-2.0 OR MIT | ||
60 | Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT | ||
61 | Apache-2.0/MIT | ||
62 | BSD-2-Clause | ||
63 | BSD-3-Clause | ||
64 | CC0-1.0 | ||
65 | ISC | ||
66 | MIT | ||
67 | MIT / Apache-2.0 | ||
68 | MIT OR Apache-2.0 | ||
69 | MIT/Apache-2.0 | ||
70 | MIT/Apache-2.0 AND BSD-2-Clause | ||
71 | Unlicense OR MIT | ||
72 | Unlicense/MIT | ||
73 | Zlib | ||
74 | " | ||
75 | .lines() | ||
76 | .filter(|it| !it.is_empty()) | ||
77 | .collect::<Vec<_>>(); | ||
78 | |||
79 | let meta = run!("cargo metadata --format-version 1"; echo = false).unwrap(); | ||
80 | let mut licenses = meta | ||
81 | .split(|c| c == ',' || c == '{' || c == '}') | ||
82 | .filter(|it| it.contains(r#""license""#)) | ||
83 | .map(|it| it.trim()) | ||
84 | .map(|it| it[r#""license":"#.len()..].trim_matches('"')) | ||
85 | .collect::<Vec<_>>(); | ||
86 | licenses.sort(); | ||
87 | licenses.dedup(); | ||
88 | assert_eq!(licenses, expected); | ||
89 | } | ||
90 | |||
59 | fn check_todo(path: &Path, text: &str) { | 91 | fn check_todo(path: &Path, text: &str) { |
60 | let whitelist = &[ | 92 | let need_todo = &[ |
61 | // This file itself is whitelisted since this test itself contains matches. | 93 | // This file itself obviously needs to use todo (<- like this!). |
62 | "tests/cli.rs", | 94 | "tests/cli.rs", |
63 | // Some of our assists generate `todo!()` so those files are whitelisted. | 95 | // Some of our assists generate `todo!()`. |
64 | "tests/generated.rs", | 96 | "tests/generated.rs", |
65 | "handlers/add_missing_impl_members.rs", | 97 | "handlers/add_missing_impl_members.rs", |
66 | "handlers/add_function.rs", | ||
67 | "handlers/add_turbo_fish.rs", | 98 | "handlers/add_turbo_fish.rs", |
68 | // To support generating `todo!()` in assists, we have `expr_todo()` in ast::make. | 99 | "handlers/generate_function.rs", |
100 | // To support generating `todo!()` in assists, we have `expr_todo()` in | ||
101 | // `ast::make`. | ||
69 | "ast/make.rs", | 102 | "ast/make.rs", |
70 | ]; | 103 | ]; |
71 | if whitelist.iter().any(|p| path.ends_with(p)) { | 104 | if need_todo.iter().any(|p| path.ends_with(p)) { |
72 | return; | 105 | return; |
73 | } | 106 | } |
74 | if text.contains("TODO") || text.contains("TOOD") || text.contains("todo!") { | 107 | if text.contains("TODO") || text.contains("TOOD") || text.contains("todo!") { |
@@ -146,7 +179,7 @@ impl TidyDocs { | |||
146 | ) | 179 | ) |
147 | } | 180 | } |
148 | 181 | ||
149 | let whitelist = [ | 182 | let poorly_documented = [ |
150 | "ra_hir", | 183 | "ra_hir", |
151 | "ra_hir_expand", | 184 | "ra_hir_expand", |
152 | "ra_ide", | 185 | "ra_ide", |
@@ -160,9 +193,9 @@ impl TidyDocs { | |||
160 | ]; | 193 | ]; |
161 | 194 | ||
162 | let mut has_fixmes = | 195 | let mut has_fixmes = |
163 | whitelist.iter().map(|it| (*it, false)).collect::<HashMap<&str, bool>>(); | 196 | poorly_documented.iter().map(|it| (*it, false)).collect::<HashMap<&str, bool>>(); |
164 | 'outer: for path in self.contains_fixme { | 197 | 'outer: for path in self.contains_fixme { |
165 | for krate in whitelist.iter() { | 198 | for krate in poorly_documented.iter() { |
166 | if path.components().any(|it| it.as_os_str() == *krate) { | 199 | if path.components().any(|it| it.as_os_str() == *krate) { |
167 | has_fixmes.insert(krate, true); | 200 | has_fixmes.insert(krate, true); |
168 | continue 'outer; | 201 | continue 'outer; |
@@ -173,20 +206,18 @@ impl TidyDocs { | |||
173 | 206 | ||
174 | for (krate, has_fixme) in has_fixmes.iter() { | 207 | for (krate, has_fixme) in has_fixmes.iter() { |
175 | if !has_fixme { | 208 | if !has_fixme { |
176 | panic!("crate {} is fully documented, remove it from the white list", krate) | 209 | panic!("crate {} is fully documented :tada:, remove it from the list of poorly documented crates", krate) |
177 | } | 210 | } |
178 | } | 211 | } |
179 | } | 212 | } |
180 | } | 213 | } |
181 | 214 | ||
182 | fn is_exclude_dir(p: &Path, dirs_to_exclude: &[&str]) -> bool { | 215 | fn is_exclude_dir(p: &Path, dirs_to_exclude: &[&str]) -> bool { |
183 | let mut cur_path = p; | 216 | p.strip_prefix(project_root()) |
184 | while let Some(path) = cur_path.parent() { | 217 | .unwrap() |
185 | if dirs_to_exclude.iter().any(|dir| path.ends_with(dir)) { | 218 | .components() |
186 | return true; | 219 | .rev() |
187 | } | 220 | .skip(1) |
188 | cur_path = path; | 221 | .filter_map(|it| it.as_os_str().to_str()) |
189 | } | 222 | .any(|it| dirs_to_exclude.contains(&it)) |
190 | |||
191 | false | ||
192 | } | 223 | } |