Implement rollback-safe tree mutations
This commit is contained in:
@@ -631,6 +631,50 @@ impl Repository {
|
||||
Ok(removed)
|
||||
}
|
||||
|
||||
pub(crate) fn ensure_directory(
|
||||
&self,
|
||||
path: &DirectoryPath,
|
||||
) -> Result<Vec<DirectoryPath>, RepositoryError> {
|
||||
let (_, created) = self.create_directory_path(path)?;
|
||||
Ok(created.into_iter().map(DirectoryPath).collect())
|
||||
}
|
||||
|
||||
pub(crate) fn remove_empty_directory(
|
||||
&self,
|
||||
directory: &DirectoryPath,
|
||||
) -> Result<bool, RepositoryError> {
|
||||
let Some(parent) = directory.parent() else {
|
||||
return Ok(false);
|
||||
};
|
||||
let parent_handle = self.open_directory(parent.as_path())?;
|
||||
let name = directory
|
||||
.as_path()
|
||||
.file_name()
|
||||
.expect("non-root directory has a file name");
|
||||
reject_entry_directory_collision(&parent_handle, name, parent.as_path())?;
|
||||
let Some(metadata) = child_metadata(&parent_handle, name, directory.as_path())? else {
|
||||
return Ok(false);
|
||||
};
|
||||
require_directory(metadata, directory.as_path())?;
|
||||
match parent_handle.remove_dir(name) {
|
||||
Ok(()) => {
|
||||
sync_directory(&parent_handle, parent.as_path()).map_err(|_| {
|
||||
RepositoryError::DurabilityUncertain {
|
||||
path: directory.as_path().to_owned(),
|
||||
}
|
||||
})?;
|
||||
Ok(true)
|
||||
}
|
||||
Err(error) if error.kind() == io::ErrorKind::DirectoryNotEmpty => Ok(false),
|
||||
Err(error) if error.kind() == io::ErrorKind::NotFound => Ok(false),
|
||||
Err(error) => Err(io_error(
|
||||
"remove empty repository directory",
|
||||
directory.as_path(),
|
||||
error,
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
fn open_entry_parent(&self, path: &EntryPath) -> Result<(Dir, OsString), RepositoryError> {
|
||||
let mut directory = self
|
||||
.root
|
||||
|
||||
Reference in New Issue
Block a user