]> git.proxmox.com Git - rustc.git/blame - src/doc/book/tools/src/bin/concat_chapters.rs
New upstream version 1.60.0+dfsg1
[rustc.git] / src / doc / book / tools / src / bin / concat_chapters.rs
CommitLineData
74b04a01
XL
1#[macro_use]
2extern crate lazy_static;
13cf67c4 3
74b04a01 4use std::collections::BTreeMap;
13cf67c4 5use std::env;
74b04a01 6use std::fs::{create_dir, read_dir, File};
13cf67c4
XL
7use std::io;
8use std::io::{Read, Write};
13cf67c4 9use std::path::{Path, PathBuf};
74b04a01 10use std::process::exit;
13cf67c4
XL
11
12use regex::Regex;
13
14static PATTERNS: &'static [(&'static str, &'static str)] = &[
15 (r"ch(\d\d)-\d\d-.*\.md", "chapter$1.md"),
16 (r"appendix-(\d\d).*\.md", "appendix.md"),
17];
18
19lazy_static! {
20 static ref MATCHERS: Vec<(Regex, &'static str)> = {
74b04a01
XL
21 PATTERNS
22 .iter()
13cf67c4
XL
23 .map(|&(expr, repl)| (Regex::new(expr).unwrap(), repl))
24 .collect()
25 };
26}
27
28fn main() {
29 let args: Vec<String> = env::args().collect();
30
31 if args.len() < 3 {
32 println!("Usage: {} <src-dir> <target-dir>", args[0]);
33 exit(1);
34 }
35
36 let source_dir = ensure_dir_exists(&args[1]).unwrap();
37 let target_dir = ensure_dir_exists(&args[2]).unwrap();
38
39 let mut matched_files = match_files(source_dir, target_dir);
40 matched_files.sort();
41
42 for (target_path, source_paths) in group_by_target(matched_files) {
43 concat_files(source_paths, target_path).unwrap();
44 }
45}
46
74b04a01
XL
47fn match_files(
48 source_dir: &Path,
49 target_dir: &Path,
50) -> Vec<(PathBuf, PathBuf)> {
13cf67c4
XL
51 read_dir(source_dir)
52 .expect("Unable to read source directory")
53 .filter_map(|maybe_entry| maybe_entry.ok())
54 .filter_map(|entry| {
55 let source_filename = entry.file_name();
74b04a01
XL
56 let source_filename =
57 &source_filename.to_string_lossy().into_owned();
13cf67c4
XL
58 for &(ref regex, replacement) in MATCHERS.iter() {
59 if regex.is_match(source_filename) {
74b04a01
XL
60 let target_filename =
61 regex.replace_all(source_filename, replacement);
13cf67c4
XL
62 let source_path = entry.path();
63 let mut target_path = PathBuf::from(&target_dir);
74b04a01 64 target_path.push(target_filename.to_string());
13cf67c4
XL
65 return Some((source_path, target_path));
66 }
67 }
68 None
69 })
70 .collect()
71}
72
74b04a01
XL
73fn group_by_target(
74 matched_files: Vec<(PathBuf, PathBuf)>,
75) -> BTreeMap<PathBuf, Vec<PathBuf>> {
13cf67c4
XL
76 let mut grouped: BTreeMap<PathBuf, Vec<PathBuf>> = BTreeMap::new();
77 for (source, target) in matched_files {
78 if let Some(source_paths) = grouped.get_mut(&target) {
79 source_paths.push(source);
80 continue;
81 }
82 let source_paths = vec![source];
83 grouped.insert(target.clone(), source_paths);
84 }
85 grouped
86}
87
74b04a01
XL
88fn concat_files(
89 source_paths: Vec<PathBuf>,
90 target_path: PathBuf,
91) -> io::Result<()> {
13cf67c4 92 println!("Concatenating into {}:", target_path.to_string_lossy());
9fa01778 93 let mut target = File::create(target_path)?;
5099ac24
FG
94
95 write!(target, "\
96<!-- DO NOT EDIT THIS FILE.
97
98This file is periodically generated from the content in the `/src/`
99directory, so all fixes need to be made in `/src/`.
100-->
101
102[TOC]
103")?;
13cf67c4
XL
104
105 for path in source_paths {
106 println!(" {}", path.to_string_lossy());
9fa01778 107 let mut source = File::open(path)?;
13cf67c4 108 let mut contents: Vec<u8> = Vec::new();
9fa01778 109 source.read_to_end(&mut contents)?;
13cf67c4 110
9fa01778
XL
111 target.write_all(b"\n")?;
112 target.write_all(&contents)?;
113 target.write_all(b"\n")?;
13cf67c4
XL
114 }
115 Ok(())
116}
117
118fn ensure_dir_exists(dir_string: &str) -> io::Result<&Path> {
119 let path = Path::new(dir_string);
120 if !path.exists() {
9fa01778 121 create_dir(path)?;
13cf67c4
XL
122 }
123 Ok(&path)
124}