about summary refs log tree commit diff
diff options
context:
space:
mode:
authorWesley Norris <repnop@outlook.com>2018-12-08 14:17:50 -0500
committerWesley Norris <repnop@outlook.com>2019-01-17 17:26:00 -0500
commit1318e53ea8a8ed6da271d6130dab71131542ab98 (patch)
tree01efe18de83a90b0deedd163aadff9d281d09f10
parentdaa53a52a2667533d5fe59bfcc5b8614b79c3d31 (diff)
Persist doc test executables to given path.
-rw-r--r--src/librustdoc/config.rs4
-rw-r--r--src/librustdoc/lib.rs5
-rw-r--r--src/librustdoc/markdown.rs2
-rw-r--r--src/librustdoc/test.rs42
4 files changed, 47 insertions, 6 deletions
diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs
index d9913680251..279d3b92134 100644
--- a/src/librustdoc/config.rs
+++ b/src/librustdoc/config.rs
@@ -68,6 +68,8 @@ pub struct Options {
     pub should_test: bool,
     /// List of arguments to pass to the test harness, if running tests.
     pub test_args: Vec<String>,
+    /// Whether to persist the doctest executables.
+    pub persist_doctests: Option<PathBuf>,
 
     // Options that affect the documentation process
 
@@ -431,6 +433,7 @@ impl Options {
         let enable_index_page = matches.opt_present("enable-index-page") || index_page.is_some();
         let static_root_path = matches.opt_str("static-root-path");
         let generate_search_filter = !matches.opt_present("disable-per-crate-search");
+        let persist_doctests = matches.opt_str("persist-doctests").map(PathBuf::from);
 
         let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format);
 
@@ -456,6 +459,7 @@ impl Options {
             manual_passes,
             display_warnings,
             crate_version,
+            persist_doctests,
             render_options: RenderOptions {
                 output,
                 external_html,
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 1b6d7e87192..7fe0999bdca 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -340,6 +340,11 @@ fn opts() -> Vec<RustcOptGroup> {
             o.optflag("",
                       "disable-per-crate-search",
                       "disables generating the crate selector on the search box")
+        unstable("persist-doctests", |o| {
+             o.optopt("",
+                       "persist-doctests",
+                       "Persists the rustdoc test executables",
+                       "PATH")
         }),
     ]
 }
diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs
index da56194c27c..65a96e9001b 100644
--- a/src/librustdoc/markdown.rs
+++ b/src/librustdoc/markdown.rs
@@ -142,7 +142,7 @@ pub fn test(mut options: Options, diag: &errors::Handler) -> isize {
                                        options.libs, options.codegen_options, options.externs,
                                        true, opts, options.maybe_sysroot, None,
                                        Some(options.input),
-                                       options.linker, options.edition);
+                                       options.linker, options.edition, options.persist_doctests);
     collector.set_position(DUMMY_SP);
     let codes = ErrorCodes::from(UnstableFeatures::from_environment().is_nightly_build());
     let res = find_testable_code(&input_str, &mut collector, codes);
diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs
index af47c7d5e8b..03b66759d40 100644
--- a/src/librustdoc/test.rs
+++ b/src/librustdoc/test.rs
@@ -120,7 +120,8 @@ pub fn run(mut options: Options) -> isize {
             Some(source_map),
             None,
             options.linker,
-            options.edition
+            options.edition,
+            options.persist_doctests,
         );
 
         {
@@ -184,7 +185,8 @@ fn run_test(test: &str, cratename: &str, filename: &FileName, line: usize,
             cg: CodegenOptions, externs: Externs,
             should_panic: bool, no_run: bool, as_test_harness: bool,
             compile_fail: bool, mut error_codes: Vec<String>, opts: &TestOptions,
-            maybe_sysroot: Option<PathBuf>, linker: Option<PathBuf>, edition: Edition) {
+            maybe_sysroot: Option<PathBuf>, linker: Option<PathBuf>, edition: Edition,
+            persist_doctests: Option<PathBuf>) {
     // The test harness wants its own `main` and top-level functions, so
     // never wrap the test in `fn main() { ... }`.
     let (test, line_offset) = make_test(test, Some(cratename), as_test_harness, opts);
@@ -249,6 +251,20 @@ fn run_test(test: &str, cratename: &str, filename: &FileName, line: usize,
     let old = io::set_panic(Some(box Sink(data.clone())));
     let _bomb = Bomb(data.clone(), old.unwrap_or(box io::stdout()));
 
+    enum DirState {
+        Temp(tempfile::TempDir),
+        Perm(PathBuf),
+    }
+
+    impl DirState {
+        fn path(&self) -> &std::path::Path {
+            match self {
+                DirState::Temp(t) => t.path(),
+                DirState::Perm(p) => p.as_path(),
+            }
+        }
+    }
+
     let (libdir, outdir, compile_result) = driver::spawn_thread_pool(sessopts, |sessopts| {
         let source_map = Lrc::new(SourceMap::new(sessopts.file_path_mapping()));
         let emitter = errors::emitter::EmitterWriter::new(box Sink(data.clone()),
@@ -267,7 +283,17 @@ fn run_test(test: &str, cratename: &str, filename: &FileName, line: usize,
         rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
 
         let outdir = Mutex::new(
-            TempFileBuilder::new().prefix("rustdoctest").tempdir().expect("rustdoc needs a tempdir")
+            if let Some(mut path) = persist_doctests {
+                path.push(format!("{}_{}", filename.to_string().rsplit('/').next().unwrap().replace(".", "_"), line));
+                std::fs::create_dir_all(&path).expect("Couldn't create directory for doctest executables");
+
+                DirState::Perm(path)
+            } else {
+                DirState::Temp(TempFileBuilder::new()
+                                .prefix("rustdoctest")
+                                .tempdir()
+                                .expect("rustdoc needs a tempdir"))
+            }
         );
         let libdir = sess.target_filesearch(PathKind::All).get_lib_path();
         let mut control = driver::CompileController::basic();
@@ -629,13 +655,15 @@ pub struct Collector {
     filename: Option<PathBuf>,
     linker: Option<PathBuf>,
     edition: Edition,
+    persist_doctests: Option<PathBuf>,
 }
 
 impl Collector {
     pub fn new(cratename: String, cfgs: Vec<String>, libs: Vec<SearchPath>, cg: CodegenOptions,
                externs: Externs, use_headers: bool, opts: TestOptions,
                maybe_sysroot: Option<PathBuf>, source_map: Option<Lrc<SourceMap>>,
-               filename: Option<PathBuf>, linker: Option<PathBuf>, edition: Edition) -> Collector {
+               filename: Option<PathBuf>, linker: Option<PathBuf>, edition: Edition,
+               persist_doctests: Option<PathBuf>) -> Collector {
         Collector {
             tests: Vec::new(),
             names: Vec::new(),
@@ -652,6 +680,7 @@ impl Collector {
             filename,
             linker,
             edition,
+            persist_doctests,
         }
     }
 
@@ -695,6 +724,8 @@ impl Tester for Collector {
         let maybe_sysroot = self.maybe_sysroot.clone();
         let linker = self.linker.clone();
         let edition = config.edition.unwrap_or(self.edition);
+        let persist_doctests = self.persist_doctests.clone();
+
         debug!("Creating test {}: {}", name, test);
         self.tests.push(testing::TestDescAndFn {
             desc: testing::TestDesc {
@@ -727,7 +758,8 @@ impl Tester for Collector {
                                  &opts,
                                  maybe_sysroot,
                                  linker,
-                                 edition)
+                                 edition,
+                                 persist_doctests)
                     }))
                 } {
                     Ok(()) => (),