History

[ref] handle existng empty directories more gracefully…

…and push the cost for checking if it's a directory or not to the error case, instead of doing it beforehand like in `find_one()`.

Sebastian Thiel committed 5 years ago

Commit 0849c701 parent d967e302 files · +40 −25Browse files

Unified · Split

2 files
  1. git-ref/src/store/file/loose/find_one.rs +7 −7
  2. git-ref/src/store/file/loose/reflog.rs +33 −18
git-ref/src/store/file/loose/find_one.rs+7−7
@@ -95,14 +95,14 @@ impl file::Store { · 94 unmodified lines
95 let mut buf = Vec::new();95 let mut buf = Vec::new();
96 let ref_path = self.ref_path(&relative_path);96 let ref_path = self.ref_path(&relative_path);
97 97
98 if ref_path.is_dir() {98 match std::fs::File::open(&ref_path) {
99 return Ok(None);
100 }
101
102 match std::fs::File::open(ref_path) {
103 Err(err) if err.kind() == io::ErrorKind::NotFound => return Ok(None),99 Err(err) if err.kind() == io::ErrorKind::NotFound => return Ok(None),
104 Err(err) => return Err(err),100 Err(err) => return if ref_path.is_dir() { Ok(None) } else { Err(err) },
105 Ok(mut file) => file.read_to_end(&mut buf)?,101 Ok(mut file) => {
102 if let Err(err) = file.read_to_end(&mut buf) {
103 return if ref_path.is_dir() { Ok(None) } else { Err(err) };
104 }
105 }
106 };106 };
107 Ok(Some(buf))107 Ok(Some(buf))
108 }108 }
git-ref/src/store/file/loose/reflog.rs+33−18
@@ -19,10 +19,11 @@ impl file::Store { · 18 unmodified lines
19 crate::name::Error: From<E>,19 crate::name::Error: From<E>,
20 {20 {
21 let name: FullName<'_> = name.try_into().map_err(|err| Error::RefnameValidation(err.into()))?;21 let name: FullName<'_> = name.try_into().map_err(|err| Error::RefnameValidation(err.into()))?;
22 let file = match std::fs::File::open(self.reflog_path(name)) {22 let path = self.reflog_path(name);
23 let file = match std::fs::File::open(&path) {
23 Ok(file) => file,24 Ok(file) => file,
24 Err(err) if err.kind() == std::io::ErrorKind::NotFound => return Ok(None),25 Err(err) if err.kind() == std::io::ErrorKind::NotFound => return Ok(None),
25 Err(err) => return Err(err.into()),26 Err(err) => return if path.is_dir() { Ok(None) } else { Err(err.into()) }, // TODO: a test to validate this
26 };27 };
27 Ok(Some(log::iter::reverse(file, buf)?))28 Ok(Some(log::iter::reverse(file, buf)?))
28 }29 }
@@ -41,13 +42,16 @@ impl file::Store { · 12 unmodified lines
41 crate::name::Error: From<E>,42 crate::name::Error: From<E>,
42 {43 {
43 let name: FullName<'_> = name.try_into().map_err(|err| Error::RefnameValidation(err.into()))?;44 let name: FullName<'_> = name.try_into().map_err(|err| Error::RefnameValidation(err.into()))?;
44 match std::fs::File::open(self.reflog_path(name)) {45 let path = self.reflog_path(name);
46 match std::fs::File::open(&path) {
45 Ok(mut file) => {47 Ok(mut file) => {
46 buf.clear();48 buf.clear();
47 file.read_to_end(buf)?;49 if let Err(err) = file.read_to_end(buf) {
50 return if path.is_dir() { Ok(None) } else { Err(err.into()) };
51 }
48 }52 }
49 Err(err) if err.kind() == std::io::ErrorKind::NotFound => return Ok(None),53 Err(err) if err.kind() == std::io::ErrorKind::NotFound => return Ok(None),
50 Err(err) => return Err(err.into()),54 Err(err) => return if path.is_dir() { Ok(None) } else { Err(err.into()) },
51 };55 };
52 Ok(Some(log::iter::forward(buf)))56 Ok(Some(log::iter::forward(buf)))
53 }57 }
@@ -95,20 +99,31 @@ pub mod create_or_update { · 41 unmodified lines
95 options.create(true);99 options.create(true);
96 };100 };
97 101
98 let file_for_appending: Option<std::fs::File> = options102 let file_for_appending: Option<std::fs::File> = match options.open(&log_path) {
99 .open(&log_path)103 Ok(f) => Some(f),
100 .map(Some)104 Err(err) if err.kind() == std::io::ErrorKind::NotFound => None,
101 .or_else(|err| {105 Err(err) => {
102 if err.kind() == std::io::ErrorKind::NotFound {106 #[cfg(target_os = "windows")]
103 Ok(None)107 let special_kind = std::io::ErrorKind::PermissionDenied;
108 #[cfg(not(target_os = "windows"))]
109 let special_kind = std::io::ErrorKind::Other;
110
111 if err.kind() == special_kind {
112 std::fs::remove_dir(&log_path)
113 .and_then(|_| options.open(&log_path))
114 .map(Some)
115 .map_err(|_| Error::Append {
116 err,
117 reflog_path: self.reflock_resource_to_log_path(lock),
118 })?
104 } else {119 } else {
105 Err(err)120 return Err(Error::Append {
121 err,
122 reflog_path: log_path,
123 });
106 }124 }
107 })125 }
108 .map_err(|err| Error::Append {126 };
109 err,
110 reflog_path: log_path,
111 })?;
112 127
113 if let Some(mut file) = file_for_appending {128 if let Some(mut file) = file_for_appending {
114 write!(129 write!(
@@ -294,7 +309,7 @@ pub mod create_or_update { · 179 unmodified lines
294 let full_name = "refs/heads/other";309 let full_name = "refs/heads/other";
295 let lock = reflock(&store, full_name).unwrap();310 let lock = reflock(&store, full_name).unwrap();
296 let reflog_path = store.reflog_path_inner(Path::new(full_name));311 let reflog_path = store.reflog_path_inner(Path::new(full_name));
297 std::fs::create_dir(&reflog_path).unwrap();312 std::fs::create_dir_all(&reflog_path).unwrap();
298 313
299 store314 store
300 .reflog_create_or_append(315 .reflog_create_or_append(