]> git.lizzy.rs Git - rust.git/blob - src/source_file.rs
Merge pull request #3266 from wada314/fix-2973
[rust.git] / src / source_file.rs
1 // Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
4 //
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
10
11 use std::fs;
12 use std::io::{self, Write};
13
14 use checkstyle::output_checkstyle_file;
15 use config::{Config, EmitMode, FileName, Verbosity};
16 use rustfmt_diff::{make_diff, output_modified, print_diff};
17
18 #[cfg(test)]
19 use formatting::FileRecord;
20
21 // Append a newline to the end of each file.
22 pub fn append_newline(s: &mut String) {
23     s.push_str("\n");
24 }
25
26 #[cfg(test)]
27 pub(crate) fn write_all_files<T>(
28     source_file: &[FileRecord],
29     out: &mut T,
30     config: &Config,
31 ) -> Result<(), io::Error>
32 where
33     T: Write,
34 {
35     if config.emit_mode() == EmitMode::Checkstyle {
36         write!(out, "{}", ::checkstyle::header())?;
37     }
38     for &(ref filename, ref text) in source_file {
39         write_file(text, filename, out, config)?;
40     }
41     if config.emit_mode() == EmitMode::Checkstyle {
42         write!(out, "{}", ::checkstyle::footer())?;
43     }
44
45     Ok(())
46 }
47
48 pub fn write_file<T>(
49     formatted_text: &str,
50     filename: &FileName,
51     out: &mut T,
52     config: &Config,
53 ) -> Result<bool, io::Error>
54 where
55     T: Write,
56 {
57     let filename_to_path = || match *filename {
58         FileName::Real(ref path) => path,
59         _ => panic!("cannot format `{}` and emit to files", filename),
60     };
61
62     match config.emit_mode() {
63         EmitMode::Files if config.make_backup() => {
64             let filename = filename_to_path();
65             let ori = fs::read_to_string(filename)?;
66             if ori != formatted_text {
67                 // Do a little dance to make writing safer - write to a temp file
68                 // rename the original to a .bk, then rename the temp file to the
69                 // original.
70                 let tmp_name = filename.with_extension("tmp");
71                 let bk_name = filename.with_extension("bk");
72
73                 fs::write(&tmp_name, formatted_text)?;
74                 fs::rename(filename, bk_name)?;
75                 fs::rename(tmp_name, filename)?;
76             }
77         }
78         EmitMode::Files => {
79             // Write text directly over original file if there is a diff.
80             let filename = filename_to_path();
81             let ori = fs::read_to_string(filename)?;
82             if ori != formatted_text {
83                 fs::write(filename, formatted_text)?;
84             }
85         }
86         EmitMode::Stdout | EmitMode::Coverage => {
87             if config.verbose() != Verbosity::Quiet {
88                 println!("{}:\n", filename);
89             }
90             write!(out, "{}", formatted_text)?;
91         }
92         EmitMode::ModifiedLines => {
93             let filename = filename_to_path();
94             let ori = fs::read_to_string(filename)?;
95             let mismatch = make_diff(&ori, formatted_text, 0);
96             let has_diff = !mismatch.is_empty();
97             output_modified(out, mismatch);
98             return Ok(has_diff);
99         }
100         EmitMode::Checkstyle => {
101             let filename = filename_to_path();
102             let ori = fs::read_to_string(filename)?;
103             let diff = make_diff(&ori, formatted_text, 3);
104             output_checkstyle_file(out, filename, diff)?;
105         }
106         EmitMode::Diff => {
107             let filename = filename_to_path();
108             let ori = fs::read_to_string(filename)?;
109             let mismatch = make_diff(&ori, formatted_text, 3);
110             let has_diff = !mismatch.is_empty();
111             print_diff(
112                 mismatch,
113                 |line_num| format!("Diff in {} at line {}:", filename.display(), line_num),
114                 config,
115             );
116             return Ok(has_diff);
117         }
118     }
119
120     // when we are not in diff mode, don't indicate differing files
121     Ok(false)
122 }