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