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