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