blob: f66a18547c3b5c414e99b50f55bd0e88425aeb6b [file] [log] [blame]
// Copyright 2017 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! Auto-generate stub docs for the unstable book
#![deny(warnings)]
extern crate tidy;
use tidy::features::{Feature, Features, collect_lib_features, collect_lang_features};
use tidy::unstable_book::{collect_unstable_feature_names, collect_unstable_book_section_file_names,
PATH_STR, LANG_FEATURES_DIR, LIB_FEATURES_DIR};
use std::collections::BTreeSet;
use std::io::Write;
use std::fs::{self, File};
use std::env;
use std::path::Path;
/// A helper macro to `unwrap` a result except also print out details like:
///
/// * The file/line of the panic
/// * The expression that failed
/// * The error itself
macro_rules! t {
($e:expr) => (match $e {
Ok(e) => e,
Err(e) => panic!("{} failed with {}", stringify!($e), e),
})
}
fn generate_stub_issue(path: &Path, name: &str, issue: u32) {
let mut file = t!(File::create(path));
t!(file.write_fmt(format_args!(include_str!("stub-issue.md"),
name = name,
issue = issue)));
}
fn generate_stub_no_issue(path: &Path, name: &str) {
let mut file = t!(File::create(path));
t!(file.write_fmt(format_args!(include_str!("stub-no-issue.md"),
name = name)));
}
fn set_to_summary_str(set: &BTreeSet<String>, dir: &str
) -> String {
set
.iter()
.map(|ref n| format!(" - [{}]({}/{}.md)",
n,
dir,
n.replace('_', "-")))
.fold("".to_owned(), |s, a| s + &a + "\n")
}
fn generate_summary(path: &Path, lang_features: &Features, lib_features: &Features) {
let compiler_flags = collect_unstable_book_section_file_names(
&path.join("compiler-flags"));
let compiler_flags_str = set_to_summary_str(&compiler_flags,
"compiler-flags");
let unstable_lang_features = collect_unstable_feature_names(&lang_features);
let unstable_lib_features = collect_unstable_feature_names(&lib_features);
let lang_features_str = set_to_summary_str(&unstable_lang_features,
LANG_FEATURES_DIR);
let lib_features_str = set_to_summary_str(&unstable_lib_features,
LIB_FEATURES_DIR);
let mut file = t!(File::create(&path.join("SUMMARY.md")));
t!(file.write_fmt(format_args!(include_str!("SUMMARY.md"),
compiler_flags = compiler_flags_str,
language_features = lang_features_str,
library_features = lib_features_str)));
}
fn has_valid_tracking_issue(f: &Feature) -> bool {
if let Some(n) = f.tracking_issue {
if n > 0 {
return true;
}
}
false
}
fn generate_unstable_book_files(src :&Path, out: &Path, features :&Features) {
let unstable_features = collect_unstable_feature_names(features);
let unstable_section_file_names = collect_unstable_book_section_file_names(src);
t!(fs::create_dir_all(&out));
for feature_name in &unstable_features - &unstable_section_file_names {
let file_name = format!("{}.md", feature_name.replace('_', "-"));
let out_file_path = out.join(&file_name);
let feature = &features[&feature_name];
if has_valid_tracking_issue(&feature) {
generate_stub_issue(&out_file_path, &feature_name, feature.tracking_issue.unwrap());
} else {
generate_stub_no_issue(&out_file_path, &feature_name);
}
}
}
fn copy_recursive(path: &Path, to: &Path) {
for entry in t!(fs::read_dir(path)) {
let e = t!(entry);
let t = t!(e.metadata());
let dest = &to.join(e.file_name());
if t.is_file() {
t!(fs::copy(&e.path(), dest));
} else if t.is_dir() {
t!(fs::create_dir_all(dest));
copy_recursive(&e.path(), dest);
}
}
}
fn main() {
let src_path_str = env::args_os().skip(1).next().expect("source path required");
let dest_path_str = env::args_os().skip(2).next().expect("destination path required");
let src_path = Path::new(&src_path_str);
let dest_path = Path::new(&dest_path_str).join("src");
let lang_features = collect_lang_features(src_path);
let lib_features = collect_lib_features(src_path).into_iter().filter(|&(ref name, _)| {
!lang_features.contains_key(name)
}).collect();
let doc_src_path = src_path.join(PATH_STR);
t!(fs::create_dir_all(&dest_path));
generate_unstable_book_files(&doc_src_path.join(LANG_FEATURES_DIR),
&dest_path.join(LANG_FEATURES_DIR),
&lang_features);
generate_unstable_book_files(&doc_src_path.join(LIB_FEATURES_DIR),
&dest_path.join(LIB_FEATURES_DIR),
&lib_features);
copy_recursive(&doc_src_path, &dest_path);
generate_summary(&dest_path, &lang_features, &lib_features);
}