]> git.proxmox.com Git - rustc.git/blame - src/doc/book/tools/src/bin/release_listings.rs
New upstream version 1.63.0+dfsg1
[rustc.git] / src / doc / book / tools / src / bin / release_listings.rs
CommitLineData
74b04a01
XL
1#[macro_use]
2extern crate lazy_static;
3
4use regex::Regex;
5use std::error::Error;
6use std::fs;
7use std::fs::File;
8use std::io::prelude::*;
9use std::io::{BufReader, BufWriter};
10use std::path::{Path, PathBuf};
11
12fn main() -> Result<(), Box<dyn Error>> {
13 // Get all listings from the `listings` directory
14 let listings_dir = Path::new("listings");
15
16 // Put the results in the `tmp/listings` directory
17 let out_dir = Path::new("tmp/listings");
18
19 // Clear out any existing content in `tmp/listings`
20 if out_dir.is_dir() {
21 fs::remove_dir_all(out_dir)?;
22 }
23
24 // Create a new, empty `tmp/listings` directory
25 fs::create_dir(out_dir)?;
26
27 // For each chapter in the `listings` directory,
28 for chapter in fs::read_dir(listings_dir)? {
29 let chapter = chapter?;
30 let chapter_path = chapter.path();
31
32 let chapter_name = chapter_path
33 .file_name()
34 .expect("Chapter should've had a name");
35
36 // Create a corresponding chapter dir in `tmp/listings`
37 let output_chapter_path = out_dir.join(chapter_name);
38 fs::create_dir(&output_chapter_path)?;
39
40 // For each listing in the chapter directory,
41 for listing in fs::read_dir(chapter_path)? {
42 let listing = listing?;
43 let listing_path = listing.path();
44
45 let listing_name = listing_path
46 .file_name()
47 .expect("Listing should've had a name");
48
49 // Create a corresponding listing dir in the tmp chapter dir
50 let output_listing_dir = output_chapter_path.join(listing_name);
51 fs::create_dir(&output_listing_dir)?;
52
53 // Copy all the cleaned files in the listing to the tmp directory
54 copy_cleaned_listing_files(listing_path, output_listing_dir)?;
55 }
56 }
57
58 // Create a compressed archive of all the listings
59 let tarfile = File::create("tmp/listings.tar.gz")?;
60 let encoder =
61 flate2::write::GzEncoder::new(tarfile, flate2::Compression::default());
62 let mut archive = tar::Builder::new(encoder);
63 archive.append_dir_all("listings", "tmp/listings")?;
64
65 // Assure whoever is running this that the script exiting successfully, and remind them
66 // where the generated file ends up
67 println!("Release tarball of listings in tmp/listings.tar.gz");
68
69 Ok(())
70}
71
72// Cleaned listings will not contain:
73//
74// - `target` directories
75// - `output.txt` files used to display output in the book
76// - `rustfmt-ignore` files used to signal to update-rustc.sh the listing shouldn't be formatted
77// - anchor comments or snip comments
78// - empty `main` functions in `lib.rs` files used to trick rustdoc
79fn copy_cleaned_listing_files(
80 from: PathBuf,
81 to: PathBuf,
82) -> Result<(), Box<dyn Error>> {
83 for item in fs::read_dir(from)? {
84 let item = item?;
85 let item_path = item.path();
86
87 let item_name =
88 item_path.file_name().expect("Item should've had a name");
89 let output_item = to.join(item_name);
90
91 if item_path.is_dir() {
92 // Don't copy `target` directories
93 if item_name != "target" {
94 fs::create_dir(&output_item)?;
95 copy_cleaned_listing_files(item_path, output_item)?;
96 }
97 } else {
98 // Don't copy output files or files that tell update-rustc.sh not to format
99 if item_name != "output.txt" && item_name != "rustfmt-ignore" {
100 let item_extension = item_path.extension();
101 if item_extension.is_some() && item_extension.unwrap() == "rs" {
102 copy_cleaned_rust_file(
103 item_name,
104 &item_path,
105 &output_item,
106 )?;
107 } else {
108 // Copy any non-Rust files without modification
109 fs::copy(item_path, output_item)?;
110 }
111 }
112 }
113 }
114
115 Ok(())
116}
117
118lazy_static! {
119 static ref ANCHOR_OR_SNIP_COMMENTS: Regex = Regex::new(
120 r"(?x)
121 //\s*ANCHOR:\s*[\w_-]+ # Remove all anchor comments
122 |
123 //\s*ANCHOR_END:\s*[\w_-]+ # Remove all anchor ending comments
124 |
125 //\s*--snip-- # Remove all snip comments
126 "
127 )
128 .unwrap();
129}
130
131lazy_static! {
132 static ref EMPTY_MAIN: Regex = Regex::new(r"fn main\(\) \{}").unwrap();
133}
134
135// Cleaned Rust files will not contain:
136//
137// - anchor comments or snip comments
138// - empty `main` functions in `lib.rs` files used to trick rustdoc
139fn copy_cleaned_rust_file(
140 item_name: &std::ffi::OsStr,
141 from: &PathBuf,
142 to: &PathBuf,
143) -> Result<(), Box<dyn Error>> {
144 let from_buf = BufReader::new(File::open(from)?);
145 let mut to_buf = BufWriter::new(File::create(to)?);
146
147 for line in from_buf.lines() {
148 let line = line?;
923072b8
FG
149 if !ANCHOR_OR_SNIP_COMMENTS.is_match(&line)
150 && (item_name != "lib.rs" || !EMPTY_MAIN.is_match(&line))
151 {
152 writeln!(&mut to_buf, "{}", line)?;
74b04a01
XL
153 }
154 }
155
156 to_buf.flush()?;
157
158 Ok(())
159}