|
|
|
@ -21,7 +21,7 @@ use digest::DynDigest; |
|
|
|
use toml::Value; |
|
|
|
use cas_core::{ |
|
|
|
Cas, DefaultPipeline, Error, ObjectId, ObjectMetadata, ObjectType, |
|
|
|
Pipeline, Reader, ReadWrapper, Result, Writer, |
|
|
|
Pipeline, Reader, ReadWrapper, RefStore, Result, Writer, |
|
|
|
}; |
|
|
|
|
|
|
|
use crate::utils::{ |
|
|
|
@ -162,6 +162,57 @@ impl Cas for SimpleCas { |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
impl RefStore for SimpleCas { |
|
|
|
fn get_ref<P: AsRef<Path>>(&self, key: P) -> Result<ObjectId> { |
|
|
|
let path = ref_dir(&self.db_path).join(key.as_ref()); |
|
|
|
if !path.exists() { |
|
|
|
Error::err(format!("reference {} does not exists", key.as_ref().to_string_lossy())) |
|
|
|
} |
|
|
|
else if !path.is_file() { |
|
|
|
Error::err(format!("reference {} is not a file", key.as_ref().to_string_lossy())) |
|
|
|
} |
|
|
|
else { |
|
|
|
let file = std::fs::read(path).or_else(|err| |
|
|
|
Error::err(format!("failed to read reference file for {}: {}", key.as_ref().to_string_lossy(), err)) |
|
|
|
)?; |
|
|
|
Ok( |
|
|
|
ObjectId::from_str( |
|
|
|
std::str::from_utf8(&file).or_else(|err| |
|
|
|
Error::err(format!("invalid reference file at {}: {}", key.as_ref().to_string_lossy(), err)) |
|
|
|
)? |
|
|
|
)? |
|
|
|
) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
fn set_ref<P: AsRef<Path>>(&mut self, key: P, value: &ObjectId) -> Result<()> { |
|
|
|
let path = ref_dir(&self.db_path).join(key.as_ref()); |
|
|
|
std::fs::create_dir_all(path.parent().ok_or_else(|| |
|
|
|
Error::error(format!("reference file {} has no parent dir?", key.as_ref().to_string_lossy())) |
|
|
|
)?).or_else(|err| |
|
|
|
Error::err(format!("failed to create reference dir for {}: {}", key.as_ref().to_string_lossy(), err)) |
|
|
|
)?; |
|
|
|
std::fs::write(path, value.to_string()).or_else(|err| |
|
|
|
Error::err(format!("failed to write reference {}: {}", key.as_ref().to_string_lossy(), err)) |
|
|
|
) |
|
|
|
} |
|
|
|
|
|
|
|
fn remove_ref<P: AsRef<Path>>(&mut self, key: P) -> Result<()> { |
|
|
|
let path = ref_dir(&self.db_path).join(key.as_ref()); |
|
|
|
if !path.exists() { |
|
|
|
Error::err(format!("reference {} does not exists", key.as_ref().to_string_lossy())) |
|
|
|
} |
|
|
|
else if !path.is_file() { |
|
|
|
Error::err(format!("reference {} is not a file", key.as_ref().to_string_lossy())) |
|
|
|
} |
|
|
|
else { |
|
|
|
std::fs::remove_file(path).or_else(|err| |
|
|
|
Error::err(format!("failed to remove reference file {}: {}", key.as_ref().to_string_lossy(), err)) |
|
|
|
) |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
pub struct ObjectIdIterator { |
|
|
|
root_dirs: Vec<PathBuf>, |
|
|
|
@ -560,4 +611,26 @@ mod tests { |
|
|
|
.collect::<Result<Vec<_>>>().unwrap(); |
|
|
|
assert_eq!(objects, oids); |
|
|
|
} |
|
|
|
|
|
|
|
#[test] |
|
|
|
fn test_reference() { |
|
|
|
let dir = tempfile::tempdir().expect("failed to create temp test dir"); |
|
|
|
let cas_path = get_cas_path(dir.path()); |
|
|
|
let config = get_config(); |
|
|
|
|
|
|
|
let mut cas = SimpleCas::create(cas_path.clone(), config) |
|
|
|
.expect("failed to create SimpleCas object"); |
|
|
|
|
|
|
|
let oid_0 = ObjectId::from_str("f731f6bc6a6a73bad170e56452473ef6930b7a0ab33cc54be44221a89b49d786").unwrap(); |
|
|
|
|
|
|
|
assert!(cas.get_ref("foo/bar").is_err()); |
|
|
|
assert!(cas.remove_ref("foo/bar").is_err()); |
|
|
|
|
|
|
|
cas.set_ref("foo/bar", &oid_0).unwrap(); |
|
|
|
assert_eq!(cas.get_ref("foo/bar").unwrap(), oid_0); |
|
|
|
|
|
|
|
cas.remove_ref("foo/bar").unwrap(); |
|
|
|
|
|
|
|
assert!(cas.get_ref("foo/bar").is_err()); |
|
|
|
} |
|
|
|
} |
|
|
|
|