diff --git a/core/src/raw/path_cache.rs b/core/src/raw/path_cache.rs index 249fcb297b44..679f8f60471f 100644 --- a/core/src/raw/path_cache.rs +++ b/core/src/raw/path_cache.rs @@ -93,6 +93,8 @@ impl PathCacher { pub async fn insert(&self, path: &str, id: &str) { let _guard = self.lock().await; + let path = normalize_dir_path(path); + // This should never happen, but let's ignore the insert if happened. if self.cache.contains_key(path) { debug_assert!( @@ -109,6 +111,8 @@ impl PathCacher { pub async fn remove(&self, path: &str) { let _guard = self.lock().await; + let path = normalize_dir_path(path); + self.cache.invalidate(path) } @@ -116,6 +120,8 @@ impl PathCacher { pub async fn get(&self, path: &str) -> Result> { let _guard = self.lock().await; + let path = normalize_dir_path(path); + if let Some(id) = self.cache.get(path) { return Ok(Some(id)); } @@ -158,6 +164,7 @@ impl PathCacher { /// Ensure input dir exists. pub async fn ensure_dir(&self, path: &str) -> Result { let _guard = self.lock().await; + let path = normalize_dir_path(path); let mut tmp = "".to_string(); // All parents that need to check. @@ -177,7 +184,8 @@ impl PathCacher { None => self.query.root().await?, }; for parent in parents { - parent_id = match self.cache.get(&parent) { + let parent = normalize_dir_path(&parent); + parent_id = match self.cache.get(parent) { Some(value) => value, None => { let value = match self.query.query(&parent_id, get_basename(&parent)).await? { @@ -188,7 +196,7 @@ impl PathCacher { .await? } }; - self.cache.insert(parent, value.clone()); + self.cache.insert(parent.to_owned(), value.clone()); value } } @@ -198,9 +206,22 @@ impl PathCacher { } } +/// Normalize the path for dirs +pub fn normalize_dir_path(path: &str) -> &str { + if path == "/" { + path + } else if path.ends_with('/') { + path.split_at(path.len() - 1).0 + } else { + path + } +} + #[cfg(test)] mod tests { + use raw::normalize_dir_path; + use crate::raw::PathCacher; use crate::raw::PathQuery; use crate::*; @@ -241,4 +262,13 @@ mod tests { assert_eq!(actual.as_deref(), expect, "{}", name) } } + + #[test] + fn test_normalize_dir_path() { + assert_eq!(normalize_dir_path("/"), "/"); + assert_eq!(normalize_dir_path("/a"), "/a"); + assert_eq!(normalize_dir_path("/a/"), "/a"); + assert_eq!(normalize_dir_path("/a/b"), "/a/b"); + assert_eq!(normalize_dir_path("/a/b/"), "/a/b"); + } } diff --git a/core/src/services/gdrive/core.rs b/core/src/services/gdrive/core.rs index 91d61c3a8876..4fbf1aea0665 100644 --- a/core/src/services/gdrive/core.rs +++ b/core/src/services/gdrive/core.rs @@ -396,8 +396,8 @@ impl PathQuery for GdrivePathQuery { async fn create_dir(&self, parent_id: &str, name: &str) -> Result { let url = "https://www.googleapis.com/drive/v3/files"; - // trim "/" at the end of name - let name = name.trim_end_matches("/"); + // trim "/" at the end of name because Google Drive API includes "/" in the name of folder + let name = normalize_dir_path(name); let content = serde_json::to_vec(&json!({ "name": name,