]> git.proxmox.com Git - rustc.git/blob - vendor/wasm-bindgen/publish.rs
New upstream version 1.70.0+dfsg2
[rustc.git] / vendor / wasm-bindgen / publish.rs
1 //! Helper script to publish the wasm-bindgen suite of crates
2 //!
3 //! Usage:
4 //!
5 //! * First, compile this script
6 //! * Next, set cwd to the root of the wasm-bindgen repository
7 //! * Execute `./publish bump` to bump versions
8 //! * Send a PR
9 //! * Merge when green
10 //! * Execute `./publish publish` to publish crates
11
12 use std::collections::HashMap;
13 use std::env;
14 use std::fs;
15 use std::io;
16 use std::path::{Path, PathBuf};
17 use std::process::Command;
18
19 // note that this list must be topologically sorted by dependencies
20 const CRATES_TO_PUBLISH: &[&str] = &[
21 "wasm-bindgen-shared",
22 "wasm-bindgen-backend",
23 "wasm-bindgen-macro-support",
24 "wasm-bindgen-macro",
25 "wasm-bindgen-test-macro",
26 "wasm-bindgen-test",
27 "wasm-bindgen-wasm-interpreter",
28 "wasm-bindgen-wasm-conventions",
29 "wasm-bindgen-threads-xform",
30 "wasm-bindgen-multi-value-xform",
31 "wasm-bindgen-externref-xform",
32 "wasm-bindgen-cli-support",
33 "wasm-bindgen-cli",
34 "wasm-bindgen",
35 "wasm-bindgen-futures",
36 "js-sys",
37 "web-sys",
38 ];
39
40 const CRATES_TO_AVOID_PUBLISH: &[&str] = &[
41 // We'll publish these when they're ready one day
42 "wasm-bindgen-typescript",
43 // These are internal crates, unlikely to ever be published
44 "ui-tests",
45 "sample",
46 "webidl-tests",
47 "typescript-tests",
48 "wasm-bindgen-webidl",
49 "example-tests",
50 ];
51
52 struct Crate {
53 manifest: PathBuf,
54 name: String,
55 version: String,
56 next_version: String,
57 }
58
59 fn main() {
60 let mut crates = Vec::new();
61 crates.push(read_crate("./Cargo.toml".as_ref()));
62 find_crates("crates".as_ref(), &mut crates);
63 find_crates("examples".as_ref(), &mut crates);
64
65 let pos = CRATES_TO_PUBLISH
66 .iter()
67 .chain(CRATES_TO_AVOID_PUBLISH)
68 .enumerate()
69 .map(|(i, c)| (*c, i))
70 .collect::<HashMap<_, _>>();
71 crates.sort_by_key(|krate| pos.get(&krate.name[..]));
72
73 match &env::args().nth(1).expect("must have one argument")[..] {
74 "bump" => {
75 for krate in crates.iter() {
76 bump_version(&krate, &crates);
77 }
78 }
79
80 "publish" => {
81 for krate in crates.iter() {
82 publish(&krate);
83 }
84 }
85
86 s => panic!("unknown command: {}", s),
87 }
88 }
89
90 fn find_crates(dir: &Path, dst: &mut Vec<Crate>) {
91 if dir.join("Cargo.toml").exists() {
92 let krate = read_crate(&dir.join("Cargo.toml"));
93 if CRATES_TO_PUBLISH
94 .iter()
95 .chain(CRATES_TO_AVOID_PUBLISH)
96 .any(|c| krate.name == *c)
97 {
98 dst.push(krate);
99 } else if dir.iter().any(|s| s == "examples") {
100 dst.push(krate);
101 } else {
102 panic!("failed to find {:?} in whitelist or blacklist", krate.name);
103 }
104 }
105
106 for entry in dir.read_dir().unwrap() {
107 let entry = entry.unwrap();
108 if entry.file_type().unwrap().is_dir() {
109 find_crates(&entry.path(), dst);
110 }
111 }
112 }
113
114 fn read_crate(manifest: &Path) -> Crate {
115 let mut name = None;
116 let mut version = None;
117 for line in fs::read_to_string(manifest).unwrap().lines() {
118 if name.is_none() && line.starts_with("name = \"") {
119 name = Some(
120 line.replace("name = \"", "")
121 .replace("\"", "")
122 .trim()
123 .to_string(),
124 );
125 }
126 if version.is_none() && line.starts_with("version = \"") {
127 version = Some(
128 line.replace("version = \"", "")
129 .replace("\"", "")
130 .trim()
131 .to_string(),
132 );
133 }
134 }
135 let name = name.unwrap();
136 let version = version.unwrap();
137 let next_version = if CRATES_TO_PUBLISH.contains(&&name[..]) {
138 bump(&version)
139 } else {
140 version.clone()
141 };
142 Crate {
143 manifest: manifest.to_path_buf(),
144 name,
145 version,
146 next_version,
147 }
148 }
149
150 fn bump_version(krate: &Crate, crates: &[Crate]) {
151 let contents = fs::read_to_string(&krate.manifest).unwrap();
152
153 let mut new_manifest = String::new();
154 let mut is_deps = false;
155 for line in contents.lines() {
156 let mut rewritten = false;
157 if line.starts_with("version =") {
158 if CRATES_TO_PUBLISH.contains(&&krate.name[..]) {
159 println!(
160 "bump `{}` {} => {}",
161 krate.name, krate.version, krate.next_version
162 );
163 new_manifest.push_str(&line.replace(&krate.version, &krate.next_version));
164 rewritten = true;
165 }
166 }
167
168 is_deps = if line.starts_with("[") {
169 line.contains("dependencies")
170 } else {
171 is_deps
172 };
173
174 for other in crates {
175 if !is_deps || !line.starts_with(&format!("{} ", other.name)) {
176 continue;
177 }
178 if !line.contains(&other.version) {
179 if !line.contains("version =") {
180 continue;
181 }
182 panic!(
183 "{:?} has a dep on {} but doesn't list version {}",
184 krate.manifest, other.name, other.version
185 );
186 }
187 rewritten = true;
188 new_manifest.push_str(&line.replace(&other.version, &other.next_version));
189 break;
190 }
191 if !rewritten {
192 new_manifest.push_str(line);
193 }
194 new_manifest.push_str("\n");
195 }
196 fs::write(&krate.manifest, new_manifest).unwrap();
197 }
198
199 fn bump(version: &str) -> String {
200 let mut iter = version.split('.').map(|s| s.parse::<u32>().unwrap());
201 let major = iter.next().expect("major version");
202 let minor = iter.next().expect("minor version");
203 let patch = iter.next().expect("patch version");
204 format!("{}.{}.{}", major, minor, patch + 1)
205 }
206
207 fn publish(krate: &Crate) {
208 if !CRATES_TO_PUBLISH.iter().any(|s| *s == krate.name) {
209 return;
210 }
211 let status = Command::new("cargo")
212 .arg("publish")
213 .current_dir(krate.manifest.parent().unwrap())
214 .arg("--no-verify")
215 .arg("--allow-dirty")
216 .status()
217 .expect("failed to run cargo");
218 if !status.success() {
219 println!("FAIL: failed to publish `{}`: {}", krate.name, status);
220 }
221 }