1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
|
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
// TODO: add tests
use strings::string_buffer::StringBuffer;
use std::collections::HashMap;
use std::fs::{self, File};
use std::io::{self, Write, Read, stdout};
use WriteMode;
use config::{NewlineStyle, Config};
use rustfmt_diff::{make_diff, print_diff};
// A map of the files of a crate, with their new content
pub type FileMap = HashMap<String, StringBuffer>;
// Append a newline to the end of each file.
pub fn append_newlines(file_map: &mut FileMap) {
for (_, s) in file_map.iter_mut() {
s.push_str("\n");
}
}
pub fn write_all_files(file_map: &FileMap,
mode: WriteMode,
config: &Config)
-> Result<(HashMap<String, String>), io::Error> {
let mut result = HashMap::new();
for filename in file_map.keys() {
let one_result = try!(write_file(&file_map[filename], filename, mode, config));
if let Some(r) = one_result {
result.insert(filename.clone(), r);
}
}
Ok(result)
}
pub fn write_file(text: &StringBuffer,
filename: &str,
mode: WriteMode,
config: &Config)
-> Result<Option<String>, io::Error> {
// prints all newlines either as `\n` or as `\r\n`
fn write_system_newlines<T>(mut writer: T,
text: &StringBuffer,
config: &Config)
-> Result<(), io::Error>
where T: Write
{
let style = if config.newline_style == NewlineStyle::Native {
if cfg!(windows) {
NewlineStyle::Windows
} else {
NewlineStyle::Unix
}
} else {
config.newline_style
};
match style {
NewlineStyle::Unix => write!(writer, "{}", text),
NewlineStyle::Windows => {
for (c, _) in text.chars() {
match c {
'\n' => try!(write!(writer, "\r\n")),
'\r' => continue,
c => try!(write!(writer, "{}", c)),
}
}
Ok(())
}
NewlineStyle::Native => unreachable!(),
}
}
match mode {
WriteMode::Replace => {
// Do a little dance to make writing safer - write to a temp file
// rename the original to a .bk, then rename the temp file to the
// original.
let tmp_name = filename.to_owned() + ".tmp";
let bk_name = filename.to_owned() + ".bk";
{
// Write text to temp file
let tmp_file = try!(File::create(&tmp_name));
try!(write_system_newlines(tmp_file, text, config));
}
try!(fs::rename(filename, bk_name));
try!(fs::rename(tmp_name, filename));
}
WriteMode::Overwrite => {
// Write text directly over original file.
let file = try!(File::create(filename));
try!(write_system_newlines(file, text, config));
}
WriteMode::NewFile(extn) => {
let filename = filename.to_owned() + "." + extn;
let file = try!(File::create(&filename));
try!(write_system_newlines(file, text, config));
}
WriteMode::Plain => {
let stdout = stdout();
let stdout = stdout.lock();
try!(write_system_newlines(stdout, text, config));
}
WriteMode::Display | WriteMode::Coverage => {
println!("{}:\n", filename);
let stdout = stdout();
let stdout = stdout.lock();
try!(write_system_newlines(stdout, text, config));
}
WriteMode::Diff => {
println!("Diff of {}:\n", filename);
let mut f = try!(File::open(filename));
let mut ori_text = String::new();
try!(f.read_to_string(&mut ori_text));
let mut v = Vec::new();
try!(write_system_newlines(&mut v, text, config));
let fmt_text = String::from_utf8(v).unwrap();
let diff = make_diff(&ori_text, &fmt_text, 3);
print_diff(diff, |line_num| format!("\nDiff at line {}:", line_num));
}
WriteMode::Return => {
// io::Write is not implemented for String, working around with
// Vec<u8>
let mut v = Vec::new();
try!(write_system_newlines(&mut v, text, config));
// won't panic, we are writing correct utf8
return Ok(Some(String::from_utf8(v).unwrap()));
}
}
Ok(None)
}
|