diff options
author | Dmitry <[email protected]> | 2020-08-14 15:58:04 +0100 |
---|---|---|
committer | Dmitry <[email protected]> | 2020-08-14 15:58:04 +0100 |
commit | 034db28c542c04b22147da6722328bc74ff99386 (patch) | |
tree | 5976d8392b97a58eef9324ebfff2d0548b63664c /xtask/src/codegen/gen_unstable_future_descriptor.rs | |
parent | 4874c559ef5027da5d05c9d46450d602b1f47644 (diff) |
replase sparse-checkout by github api
Diffstat (limited to 'xtask/src/codegen/gen_unstable_future_descriptor.rs')
-rw-r--r-- | xtask/src/codegen/gen_unstable_future_descriptor.rs | 175 |
1 files changed, 159 insertions, 16 deletions
diff --git a/xtask/src/codegen/gen_unstable_future_descriptor.rs b/xtask/src/codegen/gen_unstable_future_descriptor.rs index fee68c365..eaf063371 100644 --- a/xtask/src/codegen/gen_unstable_future_descriptor.rs +++ b/xtask/src/codegen/gen_unstable_future_descriptor.rs | |||
@@ -2,27 +2,81 @@ | |||
2 | 2 | ||
3 | use crate::codegen::update; | 3 | use crate::codegen::update; |
4 | use crate::codegen::{self, project_root, Mode, Result}; | 4 | use crate::codegen::{self, project_root, Mode, Result}; |
5 | use chrono::prelude::*; | ||
6 | use fs::read_to_string; | ||
7 | use graphql_client::*; | ||
8 | use proc_macro2::TokenStream; | ||
5 | use quote::quote; | 9 | use quote::quote; |
10 | use regex::Regex; | ||
11 | use reqwest; | ||
12 | use serde::*; | ||
6 | use std::fs; | 13 | use std::fs; |
14 | use std::fs::File; | ||
15 | use std::io::copy; | ||
16 | use std::io::prelude::*; | ||
17 | use std::path::PathBuf; | ||
7 | use std::process::Command; | 18 | use std::process::Command; |
8 | use walkdir::WalkDir; | 19 | use walkdir::WalkDir; |
9 | 20 | ||
10 | pub fn generate_unstable_future_descriptor(mode: Mode) -> Result<()> { | 21 | type URI = String; |
11 | let path = project_root().join(codegen::STORAGE); | 22 | type DateTime = String; |
12 | fs::create_dir_all(path.clone())?; | ||
13 | 23 | ||
14 | Command::new("git").current_dir(path.clone()).arg("init").output()?; | 24 | #[derive(GraphQLQuery)] |
15 | Command::new("git") | 25 | #[graphql( |
16 | .current_dir(path.clone()) | 26 | schema_path = "src/codegen/schema.graphql", |
17 | .args(&["remote", "add", "-f", "origin", codegen::REPOSITORY_URL]) | 27 | query_path = "src/codegen/last_commit_that_affected_path.graphql" |
18 | .output()?; | 28 | )] |
19 | Command::new("git") | 29 | struct LastCommitThatAffectedPath; |
20 | .current_dir(path.clone()) | 30 | |
21 | .args(&["sparse-checkout", "set", "/src/doc/unstable-book/src/"]) | 31 | fn deep_destructuring( |
22 | .output()?; | 32 | response_body: Response<last_commit_that_affected_path::ResponseData>, |
23 | Command::new("git").current_dir(path.clone()).args(&["pull", "origin", "master"]).output()?; | 33 | ) -> CommitInfo { |
34 | let t = response_body.data.unwrap().repository.unwrap().object.unwrap().on; | ||
35 | |||
36 | use last_commit_that_affected_path::LastCommitThatAffectedPathRepositoryObjectOn::Commit; | ||
37 | let commit = match t { | ||
38 | Commit(data) => data, | ||
39 | _ => panic!("type does not match"), | ||
40 | }; | ||
41 | let edges = commit.history.edges.unwrap(); | ||
42 | let node = edges.first().unwrap().as_ref().unwrap().node.as_ref().unwrap(); | ||
43 | CommitInfo { commit_url: node.commit_url.clone(), committed_date: node.committed_date.clone() } | ||
44 | } | ||
45 | |||
46 | struct CommitInfo { | ||
47 | commit_url: String, | ||
48 | committed_date: String, | ||
49 | } | ||
50 | |||
51 | fn last_update( | ||
52 | owner: &str, | ||
53 | name: &str, | ||
54 | path: &str, | ||
55 | auth_token: Option<&str>, | ||
56 | ) -> Result<CommitInfo> { | ||
57 | let query = | ||
58 | LastCommitThatAffectedPath::build_query(last_commit_that_affected_path::Variables { | ||
59 | owner: owner.to_owned(), | ||
60 | name: name.to_owned(), | ||
61 | path: path.to_owned(), | ||
62 | }); | ||
63 | |||
64 | let client = reqwest::blocking::Client::new(); | ||
65 | let mut headers = reqwest::header::HeaderMap::new(); | ||
66 | headers.insert("User-Agent", "https://github.com/rust-analyzer/rust-analyzer".parse()?); | ||
67 | let mut request = client.post("https://api.github.com/graphql").headers(headers).json(&query); | ||
68 | |||
69 | if auth_token.is_some() { | ||
70 | request = request.bearer_auth(auth_token.unwrap()); | ||
71 | } | ||
72 | |||
73 | let response = request.send()?; | ||
24 | 74 | ||
25 | let src_dir = path.join("src/doc/unstable-book/src"); | 75 | let response_body: Response<last_commit_that_affected_path::ResponseData> = response.json()?; |
76 | Ok(deep_destructuring(response_body)) | ||
77 | } | ||
78 | |||
79 | fn generate_descriptor(src_dir: PathBuf) -> Result<TokenStream> { | ||
26 | let files = WalkDir::new(src_dir.join("language-features")) | 80 | let files = WalkDir::new(src_dir.join("language-features")) |
27 | .into_iter() | 81 | .into_iter() |
28 | .chain(WalkDir::new(src_dir.join("library-features"))) | 82 | .chain(WalkDir::new(src_dir.join("library-features"))) |
@@ -53,9 +107,98 @@ pub fn generate_unstable_future_descriptor(mode: Mode) -> Result<()> { | |||
53 | #(#definitions),* | 107 | #(#definitions),* |
54 | ]; | 108 | ]; |
55 | }; | 109 | }; |
110 | Ok(ts) | ||
111 | } | ||
112 | |||
113 | fn add_anchor(text: impl std::fmt::Display, anchor: &str) -> String { | ||
114 | let anchor_str = format!( | ||
115 | r#"//The anchor is used to check if file is up to date and represent the time | ||
116 | //of the last commit that affected path where located data for generation | ||
117 | //ANCHOR: {}"#, | ||
118 | anchor | ||
119 | ); | ||
120 | format!("{}\n\n{}\n", anchor_str, text) | ||
121 | } | ||
122 | |||
123 | fn is_actual(path: &PathBuf, str_datetime: &str) -> bool { | ||
124 | let re = Regex::new(r"//ANCHOR: (\S*)").unwrap(); | ||
125 | let opt_str = fs::read_to_string(path); | ||
126 | if opt_str.is_err() { | ||
127 | return false; | ||
128 | } | ||
129 | let text = opt_str.unwrap(); | ||
130 | let opt_datetime = re.captures(text.as_str()); | ||
131 | if opt_datetime.is_none() { | ||
132 | return false; | ||
133 | } | ||
134 | let str_file_dt = opt_datetime.unwrap().get(1).unwrap().as_str(); | ||
135 | let file_dt = str_file_dt.parse::<chrono::DateTime<Utc>>().unwrap(); | ||
136 | let datetime = str_datetime.parse::<chrono::DateTime<Utc>>().unwrap(); | ||
137 | |||
138 | file_dt == datetime | ||
139 | } | ||
140 | |||
141 | fn download_tar( | ||
142 | owner: &str, | ||
143 | name: &str, | ||
144 | auth_token: Option<&str>, | ||
145 | destination: &PathBuf, | ||
146 | fname: &str, | ||
147 | ) -> Result<()> { | ||
148 | let mut headers = reqwest::header::HeaderMap::new(); | ||
149 | headers.insert("User-Agent", "https://github.com/rust-analyzer/rust-analyzer".parse()?); | ||
150 | let mut request = reqwest::blocking::Client::new() | ||
151 | .get(format!("https://api.github.com/repos/{}/{}/tarball", owner, name).as_str()) | ||
152 | .headers(headers); | ||
153 | |||
154 | if auth_token.is_some() { | ||
155 | request = request.bearer_auth(auth_token.unwrap()); | ||
156 | } | ||
157 | |||
158 | let response = request.send()?; | ||
159 | let download_url = response.url(); | ||
160 | |||
161 | let mut response = reqwest::blocking::Client::new() | ||
162 | .get(download_url.as_str()) | ||
163 | .send()?; | ||
164 | |||
165 | let mut n = fname.to_string(); | ||
166 | n.push_str(".tar.gz"); | ||
167 | let fpath = destination.join(n); | ||
168 | let mut file = File::create(fpath)?; | ||
169 | response.copy_to(&mut file)?; | ||
170 | |||
171 | Ok(()) | ||
172 | } | ||
173 | |||
174 | pub fn generate_unstable_future_descriptor(mode: Mode) -> Result<()> { | ||
175 | const auth_token: Option<&str> = None; | ||
176 | |||
177 | let path = project_root().join(codegen::STORAGE); | ||
178 | fs::create_dir_all(path.clone())?; | ||
179 | |||
180 | let commit_info = | ||
181 | last_update(codegen::REPO_OWNER, codegen::REPO_NAME, codegen::REPO_PATH, auth_token)?; | ||
182 | |||
183 | if is_actual( | ||
184 | &project_root().join(codegen::GENERATION_DESTINATION), | ||
185 | commit_info.committed_date.as_str(), | ||
186 | ) { | ||
187 | return Ok(()); | ||
188 | } | ||
189 | |||
190 | download_tar(codegen::REPO_OWNER, codegen::REPO_NAME, auth_token, &path, "repository")?; | ||
191 | Command::new("tar") | ||
192 | .args(&["-xvf", concat!("repository",".tar.gz"), "--wildcards", "*/src/doc/unstable-book/src", "--strip=1"]) | ||
193 | .current_dir(codegen::STORAGE) | ||
194 | .output()?; | ||
195 | |||
196 | let src_dir = path.join(codegen::REPO_PATH); | ||
197 | let gen_holder = generate_descriptor(src_dir)?.to_string(); | ||
198 | let gen_holder = add_anchor(gen_holder, commit_info.committed_date.as_str()); | ||
56 | 199 | ||
57 | let destination = project_root().join(codegen::UNSTABLE_FEATURE); | 200 | let destination = project_root().join(codegen::GENERATION_DESTINATION); |
58 | let contents = crate::reformat(ts.to_string())?; | 201 | let contents = crate::reformat(gen_holder)?; |
59 | update(destination.as_path(), &contents, mode)?; | 202 | update(destination.as_path(), &contents, mode)?; |
60 | 203 | ||
61 | Ok(()) | 204 | Ok(()) |