]> git.lizzy.rs Git - rust.git/blob - src/tools/rustbook/src/main.rs
Auto merge of #62452 - Centril:rollup-5jww3h7, r=Centril
[rust.git] / src / tools / rustbook / src / main.rs
1 #![deny(rust_2018_idioms)]
2
3 use clap::{crate_version};
4
5 use std::env;
6 use std::path::{Path, PathBuf};
7
8 use clap::{App, ArgMatches, SubCommand, AppSettings};
9
10 use mdbook_1::{MDBook as MDBook1};
11 use mdbook_1::errors::{Result as Result1};
12
13 use mdbook::MDBook;
14 use mdbook::errors::{Result as Result3};
15
16 #[cfg(all(target_arch = "x86_64", target_os = "linux"))]
17 use mdbook::renderer::RenderContext;
18
19 #[cfg(all(target_arch = "x86_64", target_os = "linux"))]
20 use mdbook_linkcheck::{self, errors::BrokenLinks};
21 use failure::Error;
22
23 fn main() {
24     let d_message = "-d, --dest-dir=[dest-dir]
25 'The output directory for your book{n}(Defaults to ./book when omitted)'";
26     let dir_message = "[dir]
27 'A directory for your book{n}(Defaults to Current Directory when omitted)'";
28     let vers_message = "-m, --mdbook-vers=[md-version]
29 'The version of mdbook to use for your book{n}(Defaults to 1 when omitted)'";
30
31     let matches = App::new("rustbook")
32                     .about("Build a book with mdBook")
33                     .author("Steve Klabnik <steve@steveklabnik.com>")
34                     .version(&*format!("v{}", crate_version!()))
35                     .setting(AppSettings::SubcommandRequired)
36                     .subcommand(SubCommand::with_name("build")
37                         .about("Build the book from the markdown files")
38                         .arg_from_usage(d_message)
39                         .arg_from_usage(dir_message)
40                         .arg_from_usage(vers_message))
41                     .subcommand(SubCommand::with_name("linkcheck")
42                         .about("Run linkcheck with mdBook 3")
43                         .arg_from_usage(dir_message))
44                     .get_matches();
45
46     // Check which subcomamnd the user ran...
47     match matches.subcommand() {
48         ("build", Some(sub_matches)) => {
49             match sub_matches.value_of("mdbook-vers") {
50                 None | Some("1") => {
51                     if let Err(e) = build_1(sub_matches) {
52                         eprintln!("Error: {}", e);
53
54                         for cause in e.iter().skip(1) {
55                             eprintln!("\tCaused By: {}", cause);
56                         }
57
58                         ::std::process::exit(101);
59                     }
60                 }
61                 Some("2") | Some("3") => {
62                     if let Err(e) = build(sub_matches) {
63                         eprintln!("Error: {}", e);
64
65                         for cause in e.iter().skip(1) {
66                             eprintln!("\tCaused By: {}", cause);
67                         }
68
69                         ::std::process::exit(101);
70                     }
71                 }
72                 _ => {
73                     panic!("Invalid mdBook version! Select '1' or '2' or '3'");
74                 }
75             };
76         },
77         ("linkcheck", Some(sub_matches)) => {
78             if let Err(err) = linkcheck(sub_matches) {
79                 eprintln!("Error: {}", err);
80
81                 #[cfg(all(target_arch = "x86_64", target_os = "linux"))]
82                 {
83                     if let Ok(broken_links) = err.downcast::<BrokenLinks>() {
84                         for cause in broken_links.links().iter() {
85                             eprintln!("\tCaused By: {}", cause);
86                         }
87                     }
88                 }
89
90                 ::std::process::exit(101);
91             }
92         },
93         (_, _) => unreachable!(),
94     };
95 }
96
97 #[cfg(all(target_arch = "x86_64", target_os = "linux"))]
98 pub fn linkcheck(args: &ArgMatches<'_>) -> Result<(), Error> {
99     let book_dir = get_book_dir(args);
100     let book = MDBook::load(&book_dir).unwrap();
101     let cfg = book.config;
102     let render_ctx = RenderContext::new(&book_dir, book.book, cfg, &book_dir);
103
104     mdbook_linkcheck::check_links(&render_ctx)
105 }
106
107 #[cfg(not(all(target_arch = "x86_64", target_os = "linux")))]
108 pub fn linkcheck(_args: &ArgMatches<'_>) -> Result<(), Error> {
109     println!("mdbook-linkcheck only works on x86_64 linux targets.");
110     Ok(())
111 }
112
113 // Build command implementation
114 pub fn build_1(args: &ArgMatches<'_>) -> Result1<()> {
115     let book_dir = get_book_dir(args);
116     let mut book = MDBook1::load(&book_dir)?;
117
118     // Set this to allow us to catch bugs in advance.
119     book.config.build.create_missing = false;
120
121     if let Some(dest_dir) = args.value_of("dest-dir") {
122         book.config.build.build_dir = PathBuf::from(dest_dir);
123     }
124
125     book.build()?;
126
127     Ok(())
128 }
129
130 // Build command implementation
131 pub fn build(args: &ArgMatches<'_>) -> Result3<()> {
132     let book_dir = get_book_dir(args);
133     let mut book = MDBook::load(&book_dir)?;
134
135     // Set this to allow us to catch bugs in advance.
136     book.config.build.create_missing = false;
137
138     if let Some(dest_dir) = args.value_of("dest-dir") {
139         book.config.build.build_dir = PathBuf::from(dest_dir);
140     }
141
142     book.build()?;
143
144     Ok(())
145 }
146
147 fn get_book_dir(args: &ArgMatches<'_>) -> PathBuf {
148     if let Some(dir) = args.value_of("dir") {
149         // Check if path is relative from current dir, or absolute...
150         let p = Path::new(dir);
151         if p.is_relative() {
152             env::current_dir().unwrap().join(dir)
153         } else {
154             p.to_path_buf()
155         }
156     } else {
157         env::current_dir().unwrap()
158     }
159 }