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
9595 let mut buf = Vec::new();
9696 let ref_path = self.ref_path(&relative_path);
9797
98− if ref_path.is_dir() {
99− return Ok(None);
100− }
101−
102− match std::fs::File::open(ref_path) {
98+ match std::fs::File::open(&ref_path) {
10399 Err(err) if err.kind() == io::ErrorKind::NotFound => return Ok(None),
104− Err(err) => return Err(err),
105− Ok(mut file) => file.read_to_end(&mut buf)?,
100+ Err(err) => return if ref_path.is_dir() { Ok(None) } else { Err(err) },
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+ }
106106 };
107107 Ok(Some(buf))
108108 }
git-ref/src/store/file/loose/reflog.rs+33−18
@@ -19,10 +19,11 @@ impl file::Store { · 18 unmodified lines
1919 crate::name::Error: From<E>,
2020 {
2121 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) {
2324 Ok(file) => file,
2425 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
2627 };
2728 Ok(Some(log::iter::reverse(file, buf)?))
2829 }
@@ -41,13 +42,16 @@ impl file::Store { · 12 unmodified lines
4142 crate::name::Error: From<E>,
4243 {
4344 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) {
4547 Ok(mut file) => {
4648 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+ }
4852 }
4953 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()) },
5155 };
5256 Ok(Some(log::iter::forward(buf)))
5357 }
@@ -95,20 +99,31 @@ pub mod create_or_update { · 41 unmodified lines
9599 options.create(true);
96100 };
97101
98− let file_for_appending: Option<std::fs::File> = options
99− .open(&log_path)
100− .map(Some)
101− .or_else(|err| {
102− if err.kind() == std::io::ErrorKind::NotFound {
103− Ok(None)
102+ let file_for_appending: Option<std::fs::File> = match options.open(&log_path) {
103+ Ok(f) => Some(f),
104+ Err(err) if err.kind() == std::io::ErrorKind::NotFound => None,
105+ Err(err) => {
106+ #[cfg(target_os = "windows")]
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+ })?
104119 } else {
105− Err(err)
120+ return Err(Error::Append {
121+ err,
122+ reflog_path: log_path,
123+ });
106124 }
107− })
108− .map_err(|err| Error::Append {
109− err,
110− reflog_path: log_path,
111− })?;
125+ }
126+ };
112127
113128 if let Some(mut file) = file_for_appending {
114129 write!(
@@ -294,7 +309,7 @@ pub mod create_or_update { · 179 unmodified lines
294309 let full_name = "refs/heads/other";
295310 let lock = reflock(&store, full_name).unwrap();
296311 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();
298313
299314 store
300315 .reflog_create_or_append(