Change app-lib io::rename to io::rename_or_move (#3251)

Also add io::is_same_disk and io::create_dir

Co-authored-by: Prospector <6166773+Prospector@users.noreply.github.com>
Co-authored-by: Jai Agrawal <18202329+Geometrically@users.noreply.github.com>
This commit is contained in:
Josiah Glosson 2025-02-24 21:00:17 -06:00 committed by GitHub
parent 701fef08f8
commit a74b2da147
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 79 additions and 38 deletions

View File

@ -209,34 +209,6 @@ impl DirectoryInfo {
} }
} }
fn is_same_disk(
old_dir: &Path,
new_dir: &Path,
) -> crate::Result<bool> {
#[cfg(unix)]
{
use std::os::unix::fs::MetadataExt;
Ok(old_dir.metadata()?.dev() == new_dir.metadata()?.dev())
}
#[cfg(windows)]
{
let old_dir = crate::util::io::canonicalize(old_dir)?;
let new_dir = crate::util::io::canonicalize(new_dir)?;
let old_component = old_dir.components().next();
let new_component = new_dir.components().next();
match (old_component, new_component) {
(
Some(std::path::Component::Prefix(old)),
Some(std::path::Component::Prefix(new)),
) => Ok(old.as_os_str() == new.as_os_str()),
_ => Ok(false),
}
}
}
fn get_disk_usage(path: &Path) -> crate::Result<Option<u64>> { fn get_disk_usage(path: &Path) -> crate::Result<Option<u64>> {
let path = crate::util::io::canonicalize(path)?; let path = crate::util::io::canonicalize(path)?;
@ -335,7 +307,9 @@ impl DirectoryInfo {
let paths_len = paths.len(); let paths_len = paths.len();
if is_same_disk(&prev_dir, &move_dir).unwrap_or(false) { if crate::util::io::is_same_disk(&prev_dir, &move_dir)
.unwrap_or(false)
{
let success_idxs = Arc::new(DashSet::new()); let success_idxs = Arc::new(DashSet::new());
let loader_bar_id = Arc::new(&loader_bar_id); let loader_bar_id = Arc::new(&loader_bar_id);
@ -359,7 +333,7 @@ impl DirectoryInfo {
})?; })?;
} }
crate::util::io::rename( crate::util::io::rename_or_move(
&x.old, &x.old,
&x.new, &x.new,
) )

View File

@ -928,7 +928,8 @@ impl Profile {
format!("{project_path}.disabled") format!("{project_path}.disabled")
}; };
io::rename(&path.join(project_path), &path.join(&new_path)).await?; io::rename_or_move(&path.join(project_path), &path.join(&new_path))
.await?;
Ok(new_path) Ok(new_path)
} }

View File

@ -59,6 +59,19 @@ pub async fn read_dir(
}) })
} }
// create_dir
pub async fn create_dir(
path: impl AsRef<std::path::Path>,
) -> Result<(), IOError> {
let path = path.as_ref();
tokio::fs::create_dir(path)
.await
.map_err(|e| IOError::IOPathError {
source: e,
path: path.to_string_lossy().to_string(),
})
}
// create_dir_all // create_dir_all
pub async fn create_dir_all( pub async fn create_dir_all(
path: impl AsRef<std::path::Path>, path: impl AsRef<std::path::Path>,
@ -150,19 +163,72 @@ fn sync_write(
tmp_path.persist(path)?; tmp_path.persist(path)?;
std::io::Result::Ok(()) std::io::Result::Ok(())
} }
pub fn is_same_disk(old_dir: &Path, new_dir: &Path) -> Result<bool, IOError> {
#[cfg(unix)]
{
use std::os::unix::fs::MetadataExt;
Ok(old_dir.metadata()?.dev() == new_dir.metadata()?.dev())
}
#[cfg(windows)]
{
let old_dir = canonicalize(old_dir)?;
let new_dir = canonicalize(new_dir)?;
let old_component = old_dir.components().next();
let new_component = new_dir.components().next();
match (old_component, new_component) {
(
Some(std::path::Component::Prefix(old)),
Some(std::path::Component::Prefix(new)),
) => Ok(old.as_os_str() == new.as_os_str()),
_ => Ok(false),
}
}
}
// rename // rename
pub async fn rename( pub async fn rename_or_move(
from: impl AsRef<std::path::Path>, from: impl AsRef<std::path::Path>,
to: impl AsRef<std::path::Path>, to: impl AsRef<std::path::Path>,
) -> Result<(), IOError> { ) -> Result<(), IOError> {
let from = from.as_ref(); let from = from.as_ref();
let to = to.as_ref(); let to = to.as_ref();
tokio::fs::rename(from, to)
.await if to
.map_err(|e| IOError::IOPathError { .parent()
source: e, .map_or(Ok(false), |to_dir| is_same_disk(from, to_dir))?
path: from.to_string_lossy().to_string(), {
}) tokio::fs::rename(from, to)
.await
.map_err(|e| IOError::IOPathError {
source: e,
path: from.to_string_lossy().to_string(),
})
} else {
move_recursive(from, to).await
}
}
#[async_recursion::async_recursion]
async fn move_recursive(from: &Path, to: &Path) -> Result<(), IOError> {
if from.is_file() {
copy(from, to).await?;
remove_file(from).await?;
return Ok(());
}
create_dir(to).await?;
let mut dir = read_dir(from).await?;
while let Some(entry) = dir.next_entry().await? {
let new_path = to.join(entry.file_name());
move_recursive(&entry.path(), &new_path).await?;
}
Ok(())
} }
// copy // copy