Implement InMemoryFs::rename

This commit is contained in:
Antonio Scandurra 2021-07-09 17:02:42 +02:00
parent 63e76e426a
commit 3d799fe8e7

View file

@ -204,14 +204,15 @@ struct InMemoryFsState {
impl InMemoryFsState { impl InMemoryFsState {
fn validate_path(&self, path: &Path) -> Result<()> { fn validate_path(&self, path: &Path) -> Result<()> {
if path if path.is_absolute()
&& path
.parent() .parent()
.and_then(|path| self.entries.get(path)) .and_then(|path| self.entries.get(path))
.map_or(false, |e| e.is_dir) .map_or(false, |e| e.is_dir)
{ {
Ok(()) Ok(())
} else { } else {
Err(anyhow!("invalid ")) Err(anyhow!("invalid path {:?}", path))
} }
} }
@ -277,22 +278,36 @@ impl InMemoryFs {
pub async fn remove(&self, path: &Path) -> Result<()> { pub async fn remove(&self, path: &Path) -> Result<()> {
let mut state = self.state.write().await; let mut state = self.state.write().await;
state.validate_path(path)?; state.validate_path(path)?;
state.entries.retain(|path, _| !path.starts_with(path));
state.emit_event(&path).await;
Ok(())
}
let mut paths = Vec::new(); pub async fn rename(&self, source: &Path, target: &Path) -> Result<()> {
state.entries.retain(|path, _| { let mut state = self.state.write().await;
if path.starts_with(path) { state.validate_path(source)?;
paths.push(path.to_path_buf()); state.validate_path(target)?;
if state.entries.contains_key(target) {
Err(anyhow!("target path already exists"))
} else {
let mut removed = Vec::new();
state.entries.retain(|path, entry| {
if let Ok(relative_path) = path.strip_prefix(source) {
removed.push((relative_path.to_path_buf(), entry.clone()));
false false
} else { } else {
true true
} }
}); });
for path in paths {
state.emit_event(&path).await; for (relative_path, entry) in removed {
let new_path = target.join(relative_path);
state.entries.insert(new_path, entry);
} }
Ok(()) Ok(())
} }
}
pub async fn events(&self) -> broadcast::Receiver<fsevent::Event> { pub async fn events(&self) -> broadcast::Receiver<fsevent::Event> {
self.state.read().await.events_tx.subscribe() self.state.read().await.events_tx.subscribe()