Skip to content

Commit

Permalink
feat: add fs copy-on-write support
Browse files Browse the repository at this point in the history
  • Loading branch information
anonrig committed Jul 31, 2023
1 parent 94fcb51 commit 3dd1485
Show file tree
Hide file tree
Showing 6 changed files with 44 additions and 20 deletions.
19 changes: 19 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ elsa = { version = "1.8.1" }
home = { version = "0.5.5" }
futures-util = { version = "0.3.28" }
miette = { version = "5.9.0", features = ["fancy"] }
reflink-copy = { version = "0.1.5" }
reqwest = { version = "0.11", default-features = false, features = [
"json",
"stream",
Expand Down
14 changes: 7 additions & 7 deletions crates/cafs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,19 +36,19 @@ fn content_path_from_hex(file_type: FileType, hex: &str) -> PathBuf {
p.join(format!("{}{}", &hex[2..], extension))
}

pub fn write_sync(store_dir: &Path, buffer: &Vec<u8>) -> Result<String, CafsError> {
pub fn write_sync(store_dir: &Path, buffer: &Vec<u8>) -> Result<PathBuf, CafsError> {
let hex_integrity =
IntegrityOpts::new().algorithm(Algorithm::Sha512).chain(buffer).result().to_hex().1;

let file_path = store_dir.join(content_path_from_hex(FileType::NonExec, &hex_integrity));
let content_path = content_path_from_hex(FileType::NonExec, &hex_integrity);
let file_path = store_dir.join(&content_path);

if !file_path.exists() {
let parent_dir = file_path.parent().unwrap();
fs::create_dir_all(parent_dir)?;
fs::write(&file_path, buffer)?;
}

Ok(file_path.to_string_lossy().into_owned())
Ok(content_path)
}

pub fn prune_sync(store_dir: &Path) -> Result<(), CafsError> {
Expand Down Expand Up @@ -87,9 +87,9 @@ mod tests {
let dir = tempdir().unwrap();
let buffer = vec![0, 1, 2, 3, 4, 5, 6];
let saved_file_path = write_sync(dir.path(), &buffer).unwrap();
let path = PathBuf::from_str(&saved_file_path).unwrap();
assert!(path.exists());
let store_path = dir.path().join(saved_file_path);
assert!(store_path.exists());
prune_sync(dir.path()).unwrap();
assert!(!path.exists());
assert!(!store_path.exists());
}
}
1 change: 1 addition & 0 deletions crates/package_manager/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ async-recursion = { workspace = true }
elsa = { workspace = true }
futures-util = { workspace = true }
miette = { workspace = true }
reflink-copy = { workspace = true }
reqwest = { workspace = true }
reqwest-middleware = { workspace = true }
reqwest-retry = { workspace = true }
Expand Down
21 changes: 12 additions & 9 deletions crates/package_manager/src/package_import.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,26 +7,29 @@ use crate::{symlink::symlink_dir, PackageManager, PackageManagerError};
impl PackageManager {
pub async fn import_packages(
&self,
cas_files: &HashMap<String, Vec<u8>>,
cas_files: &HashMap<String, PathBuf>,
save_path: &PathBuf,
symlink_to: &PathBuf,
) -> Result<(), PackageManagerError> {
match self.config.package_import_method {
PackageImportMethod::Auto => {
for (cleaned_entry, buffer) in cas_files {
for (cleaned_entry, store_path) in cas_files {
let original_path = self.config.store_dir.join(store_path);
let save_with_cleaned_entry = save_path.join(cleaned_entry);

// Create parent folder
if let Some(parent_folder) = save_with_cleaned_entry.parent() {
if !parent_folder.exists() {
fs::create_dir_all(parent_folder)?;
if !save_with_cleaned_entry.exists() {
// Create parent folder
if let Some(parent_folder) = save_with_cleaned_entry.parent() {
if !parent_folder.exists() {
fs::create_dir_all(parent_folder)?;
}
}
}

fs::write(&save_with_cleaned_entry, buffer)?;
reflink_copy::reflink_or_copy(original_path, &save_with_cleaned_entry)?;
}
}

if !symlink_to.exists() {
if !symlink_to.is_symlink() {
fs::create_dir_all(symlink_to.parent().unwrap())?;
symlink_dir(save_path, symlink_to)?;
}
Expand Down
8 changes: 4 additions & 4 deletions crates/tarball/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,8 +90,8 @@ impl TarballManager {
&self,
integrity: &str,
url: &str,
) -> Result<HashMap<String, Vec<u8>>, TarballError> {
let mut cas_files = HashMap::<String, Vec<u8>>::new();
) -> Result<HashMap<String, PathBuf>, TarballError> {
let mut cas_files = HashMap::<String, PathBuf>::new();

let response = self.http_client.get(url).send().await?.bytes().await?;
verify_checksum(&response, integrity)?;
Expand All @@ -107,9 +107,9 @@ impl TarballManager {

let entry_path = entry.path()?;
let cleaned_entry_path = entry_path.components().skip(1).collect::<PathBuf>();
pacquet_cafs::write_sync(&self.store_dir, &buffer)?;
let integrity = pacquet_cafs::write_sync(&self.store_dir, &buffer)?;

cas_files.insert(cleaned_entry_path.to_str().unwrap().to_string(), buffer);
cas_files.insert(cleaned_entry_path.to_str().unwrap().to_string(), integrity);
}

Ok(cas_files)
Expand Down

0 comments on commit 3dd1485

Please sign in to comment.