Skip to content

Commit 85618ab

Browse files
authored
Merge pull request #12 from tutao/fix-temp-file-copy
create temp subdir before copying file, fix #13 We were trying to copy into a nonexistent directory, so we need to create it first.
2 parents 648885e + 719a2f0 commit 85618ab

File tree

1 file changed

+74
-20
lines changed

1 file changed

+74
-20
lines changed

src/structs/file_descriptor.rs

Lines changed: 74 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
use std::convert::{From, TryFrom};
22
#[cfg(not(test))]
33
use std::fs;
4-
use std::path::PathBuf;
4+
use std::path::{Path, PathBuf};
55

6+
use crate::commands::log_to_file;
67
use crate::environment::make_subfolder_name_from_content;
78
use crate::ffi::conversion;
89
use crate::file_path::FilePath;
910
use crate::flags::MapiFileFlags;
1011
use crate::types::*;
1112

13+
const FALLBACK_TMP_SUBDIR_PATH: &str = "xxxxxxxx";
14+
1215
#[repr(C)]
1316
#[derive(Debug)]
1417
pub struct RawMapiFileTagExt {
@@ -142,7 +145,6 @@ impl FileDescriptor {
142145
/// tmp_path + basename(self.path_name) otherwise.
143146
///
144147
/// return the path that points to the file to be attached
145-
#[cfg(not(test))]
146148
pub fn consolidate_into(&self, tmp_path: &Option<PathBuf>) -> PathBuf {
147149
if tmp_path.is_some() {
148150
let trg_path_cloned = tmp_path.as_ref().unwrap().clone();
@@ -152,43 +154,95 @@ impl FileDescriptor {
152154
} else {
153155
self.path_name.file_name().into()
154156
};
155-
let sub_name = make_subfolder_name_from_content(&self.path_name)
156-
.unwrap_or_else(|_| "xxxxxxxx".to_owned());
157-
let new_path = trg_path_cloned.join(sub_name).join(trg_name_cloned);
158-
if fs::copy(&self.path_name, &new_path).is_ok() {
157+
158+
if let Some(new_path) = self.copy_file_to_tmp_subdir(&trg_path_cloned, &trg_name_cloned)
159+
{
159160
return new_path;
160161
}
161162
}
162163

163164
self.path_name.clone().into()
164165
}
165166

166-
#[cfg(test)]
167-
pub fn consolidate_into(&self, tmp_path: &Option<PathBuf>) -> PathBuf {
168-
if tmp_path.is_some() {
169-
let trg_path_cloned = tmp_path.as_ref().unwrap().clone();
170-
let trg_name_cloned = if self.needs_new_name() {
171-
// unwrap is OK because needs_new_name returns false when file_name is None.
172-
self.file_name.as_ref().unwrap().clone()
173-
} else {
174-
self.path_name.file_name().into()
175-
};
176-
let new_path = trg_path_cloned.join(&"xxxxxxxx").join(trg_name_cloned);
177-
return new_path;
167+
#[cfg(not(test))]
168+
fn copy_file_to_tmp_subdir(&self, tmp_path: &Path, tmp_name: &Path) -> Option<PathBuf> {
169+
let sub_name = make_subfolder_name_from_content(&self.path_name)
170+
.unwrap_or_else(|_| FALLBACK_TMP_SUBDIR_PATH.to_owned());
171+
let tmp_subdir_path = tmp_path.join(sub_name);
172+
173+
if fs::create_dir_all(&tmp_subdir_path).is_err() {
174+
log_to_file(
175+
"FileDescriptor::copy_file_to_tmp_subdir",
176+
"failed to create temporary directory for attachment",
177+
);
178+
return None;
178179
}
179180

180-
self.path_name.clone().into()
181+
let dest = tmp_subdir_path.join(tmp_name);
182+
183+
if fs::copy(&self.path_name, &dest).is_err() {
184+
log_to_file(
185+
"FileDescriptor::copy_file_to_tmp_subdir",
186+
"failed to copy file",
187+
);
188+
return None;
189+
}
190+
191+
Some(dest)
192+
}
193+
194+
#[cfg(test)]
195+
fn copy_file_to_tmp_subdir(&self, tmp_path: &PathBuf, tmp_name: &PathBuf) -> Option<PathBuf> {
196+
Some(tmp_path.join(FALLBACK_TMP_SUBDIR_PATH).join(tmp_name))
181197
}
182198
}
183199

184200
#[cfg(test)]
185201
mod tests {
202+
use std::path::PathBuf;
203+
204+
use crate::structs::file_descriptor::FALLBACK_TMP_SUBDIR_PATH;
186205
use crate::structs::FileDescriptor;
187206

188207
#[test]
189208
fn needs_new_name_works() {
190-
assert!(!FileDescriptor::new(&"C:\\hello.txt", Some("hello.txt")).needs_new_name());
191209
assert!(FileDescriptor::new(&"C:\\hello.txt", Some("ciao.txt")).needs_new_name());
210+
211+
assert!(!FileDescriptor::new(&"C:\\hello.txt", Some("hello.txt")).needs_new_name());
192212
assert!(!FileDescriptor::new(&"C:\\hello.txt", None).needs_new_name());
193213
}
214+
215+
#[test]
216+
// TODO test the case where copying the file fails (would require some kind of refactoring, or just a static variable hack)
217+
fn consolidate_into_works() {
218+
assert_eq!(
219+
FileDescriptor::new(&"C:\\User\\Doccies\\hello.txt", Some("hello.txt"))
220+
.consolidate_into(&Some("C:\\User\\TmpDir".into())),
221+
PathBuf::from(format!(
222+
"C:\\User\\TmpDir\\{}\\hello.txt",
223+
FALLBACK_TMP_SUBDIR_PATH
224+
)),
225+
"If the same file name is given, then it is copied with the same filename"
226+
);
227+
228+
assert_eq!(
229+
FileDescriptor::new(&"C:\\User\\Doccies\\hello.txt", Some("ciao.txt"))
230+
.consolidate_into(&Some("C:\\User\\TmpDir".into())),
231+
PathBuf::from(format!(
232+
"C:\\User\\TmpDir\\{}\\ciao.txt",
233+
FALLBACK_TMP_SUBDIR_PATH
234+
)),
235+
"If a different file name is given, then it copies with the new filename",
236+
);
237+
238+
assert_eq!(
239+
FileDescriptor::new(&"C:\\User\\Doccies\\hello.txt", None)
240+
.consolidate_into(&Some("C:\\User\\TmpDir".into())),
241+
PathBuf::from(format!(
242+
"C:\\User\\TmpDir\\{}\\hello.txt",
243+
FALLBACK_TMP_SUBDIR_PATH
244+
)),
245+
"If no file name is given, then it copies with the original filename"
246+
);
247+
}
194248
}

0 commit comments

Comments
 (0)