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