]> git.lizzy.rs Git - rust.git/blob - src/filemap.rs
Merge pull request #162 from cassiersg/sep-mods
[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
12 // TODO tests
13
14 use strings::string_buffer::StringBuffer;
15 use std::collections::HashMap;
16 use std::fs::{self, File};
17 use std::io::{self, Write, stdout};
18 use WriteMode;
19 use NewlineStyle;
20 use config::Config;
21
22 // A map of the files of a crate, with their new content
23 pub type FileMap = HashMap<String, StringBuffer>;
24
25 // Append a newline to the end of each file.
26 pub fn append_newlines(file_map: &mut FileMap) {
27     for (_, s) in file_map.iter_mut() {
28         s.push_str("\n");
29     }
30 }
31
32 pub fn write_all_files(file_map: &FileMap,
33                        mode: WriteMode,
34                        config: &Config)
35                        -> Result<(HashMap<String, String>), io::Error> {
36     let mut result = HashMap::new();
37     for filename in file_map.keys() {
38         let one_result = try!(write_file(&file_map[filename], filename, mode, config));
39         if let Some(r) = one_result {
40             result.insert(filename.clone(), r);
41         }
42     }
43
44     Ok(result)
45 }
46
47 fn write_file(text: &StringBuffer,
48               filename: &str,
49               mode: WriteMode,
50               config: &Config)
51               -> Result<Option<String>, io::Error> {
52
53     // prints all newlines either as `\n` or as `\r\n`
54     fn write_system_newlines<T>(mut writer: T,
55                                 text: &StringBuffer,
56                                 config: &Config)
57                                 -> Result<(), io::Error>
58         where T: Write
59     {
60         match config.newline_style {
61                 NewlineStyle::Unix => write!(writer, "{}", text),
62                 NewlineStyle::Windows => {
63                     for (c, _) in text.chars() {
64                         match c {
65                             '\n' => try!(write!(writer, "\r\n")),
66                             '\r' => continue,
67                             c => try!(write!(writer, "{}", c)),
68                         }
69                     }
70                     Ok(())
71                 },
72             }
73     }
74
75     match mode {
76             WriteMode::Overwrite => {
77                 // Do a little dance to make writing safer - write to a temp file
78                 // rename the original to a .bk, then rename the temp file to the
79                 // original.
80                 let tmp_name = filename.to_owned() + ".tmp";
81                 let bk_name = filename.to_owned() + ".bk";
82                 {
83                     // Write text to temp file
84                     let tmp_file = try!(File::create(&tmp_name));
85                     try!(write_system_newlines(tmp_file, text, config));
86                 }
87
88                 try!(fs::rename(filename, bk_name));
89                 try!(fs::rename(tmp_name, filename));
90             }
91             WriteMode::NewFile(extn) => {
92                 let filename = filename.to_owned() + "." + extn;
93                 let file = try!(File::create(&filename));
94                 try!(write_system_newlines(file, text, config));
95             }
96             WriteMode::Display => {
97                 println!("{}:\n", filename);
98                 let stdout = stdout();
99                 let stdout_lock = stdout.lock();
100                 try!(write_system_newlines(stdout_lock, text, config));
101             }
102             WriteMode::Return(_) => {
103                 // io::Write is not implemented for String, working around with Vec<u8>
104                 let mut v = Vec::new();
105                 try!(write_system_newlines(&mut v, text, config));
106                 // won't panic, we are writing correct utf8
107                 return Ok(Some(String::from_utf8(v).unwrap()));
108             }
109         }
110
111     Ok(None)
112 }