1 //! Rustdoc's FileSystem abstraction module.
3 //! On Windows this indirects IO into threads to work around performance issues
4 //! with Defender (and other similar virus scanners that do blocking operations).
5 //! On other platforms this is a thin shim to fs.
7 //! Only calls needed to permit this workaround have been abstracted: thus
8 //! fs::read is still done directly via the fs module; if in future rustdoc
9 //! needs to read-after-write from a file, then it would be added to this
16 macro_rules! try_err {
17 ($e:expr, $file:expr) => {{
20 Err(e) => return Err(E::new(e, $file)),
26 fn new<P: AsRef<Path>>(e: io::Error, path: P) -> Self;
34 pub fn new() -> DocFS {
40 pub fn set_sync_only(&mut self, sync_only: bool) {
41 self.sync_only = sync_only;
44 pub fn create_dir_all<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
45 // For now, dir creation isn't a huge time consideration, do it
46 // synchronously, which avoids needing ordering between write() actions
47 // and directory creation.
48 fs::create_dir_all(path)
51 pub fn write<P, C, E>(&self, path: P, contents: C) -> Result<(), E>
57 if !self.sync_only && cfg!(windows) {
58 // A possible future enhancement after more detailed profiling would
59 // be to create the file sync so errors are reported eagerly.
60 let contents = contents.as_ref().to_vec();
61 let path = path.as_ref().to_path_buf();
63 match fs::write(&path, &contents) {
66 // In principle these should get displayed at the top
67 // level, but just in case, send to stderr as well.
68 eprintln!("\"{}\": {}", path.display(), e);
69 panic!("\"{}\": {}", path.display(), e);
74 Ok(try_err!(fs::write(&path, contents), path))