]> git.lizzy.rs Git - rust.git/blob - src/tools/rustbook/src/main.rs
Simplify SaveHandler trait
[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::MDBook;
11 use mdbook::errors::{Result as Result3};
12
13 #[cfg(all(target_arch = "x86_64", target_os = "linux"))]
14 use mdbook::renderer::RenderContext;
15
16 #[cfg(all(target_arch = "x86_64", target_os = "linux"))]
17 use mdbook_linkcheck::{self, errors::BrokenLinks};
18 use failure::Error;
19
20 fn main() {
21     let d_message = "-d, --dest-dir=[dest-dir]
22 'The output directory for your book{n}(Defaults to ./book when omitted)'";
23     let dir_message = "[dir]
24 'A directory for your book{n}(Defaults to Current Directory when omitted)'";
25
26     let matches = App::new("rustbook")
27                     .about("Build a book with mdBook")
28                     .author("Steve Klabnik <steve@steveklabnik.com>")
29                     .version(&*format!("v{}", crate_version!()))
30                     .setting(AppSettings::SubcommandRequired)
31                     .subcommand(SubCommand::with_name("build")
32                         .about("Build the book from the markdown files")
33                         .arg_from_usage(d_message)
34                         .arg_from_usage(dir_message))
35                     .subcommand(SubCommand::with_name("linkcheck")
36                         .about("Run linkcheck with mdBook 3")
37                         .arg_from_usage(dir_message))
38                     .get_matches();
39
40     // Check which subcomamnd the user ran...
41     match matches.subcommand() {
42         ("build", Some(sub_matches)) => {
43             if let Err(e) = build(sub_matches) {
44                 eprintln!("Error: {}", e);
45
46                 for cause in e.iter().skip(1) {
47                     eprintln!("\tCaused By: {}", cause);
48                 }
49
50                 ::std::process::exit(101);
51             }
52         },
53         ("linkcheck", Some(sub_matches)) => {
54             if let Err(err) = linkcheck(sub_matches) {
55                 eprintln!("Error: {}", err);
56
57                 #[cfg(all(target_arch = "x86_64", target_os = "linux"))]
58                 {
59                     if let Ok(broken_links) = err.downcast::<BrokenLinks>() {
60                         for cause in broken_links.links().iter() {
61                             eprintln!("\tCaused By: {}", cause);
62                         }
63                     }
64                 }
65
66                 ::std::process::exit(101);
67             }
68         },
69         (_, _) => unreachable!(),
70     };
71 }
72
73 #[cfg(all(target_arch = "x86_64", target_os = "linux"))]
74 pub fn linkcheck(args: &ArgMatches<'_>) -> Result<(), Error> {
75     let book_dir = get_book_dir(args);
76     let book = MDBook::load(&book_dir).unwrap();
77     let cfg = book.config;
78     let render_ctx = RenderContext::new(&book_dir, book.book, cfg, &book_dir);
79
80     mdbook_linkcheck::check_links(&render_ctx)
81 }
82
83 #[cfg(not(all(target_arch = "x86_64", target_os = "linux")))]
84 pub fn linkcheck(_args: &ArgMatches<'_>) -> Result<(), Error> {
85     println!("mdbook-linkcheck only works on x86_64 linux targets.");
86     Ok(())
87 }
88
89 // Build command implementation
90 pub fn build(args: &ArgMatches<'_>) -> Result3<()> {
91     let book_dir = get_book_dir(args);
92     let mut book = MDBook::load(&book_dir)?;
93
94     // Set this to allow us to catch bugs in advance.
95     book.config.build.create_missing = false;
96
97     if let Some(dest_dir) = args.value_of("dest-dir") {
98         book.config.build.build_dir = PathBuf::from(dest_dir);
99     }
100
101     book.build()?;
102
103     Ok(())
104 }
105
106 fn get_book_dir(args: &ArgMatches<'_>) -> PathBuf {
107     if let Some(dir) = args.value_of("dir") {
108         // Check if path is relative from current dir, or absolute...
109         let p = Path::new(dir);
110         if p.is_relative() {
111             env::current_dir().unwrap().join(dir)
112         } else {
113             p.to_path_buf()
114         }
115     } else {
116         env::current_dir().unwrap()
117     }
118 }