Backup, Synchronize, Versionize
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

106 lines
3.2 KiB

// This file is part of bsv.
//
// bsv is free software: you can redistribute it and/or modify it under the
// terms of the GNU Affero General Public License as published by the Free
// Software Foundation, either version 3 of the License, or (at your option)
// any later version.
//
// bsv is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
// FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
// more details.
//
// You should have received a copy of the Affero GNU General Public License
// along with bsv. If not, see <https://www.gnu.org/licenses/>.
use camino::{Utf8PathBuf};
use cas_core::{
err, Error, ObjectId, Result, Writer,
};
use crate::utils::{obj_path, tmp_dir};
pub struct WFile {
file: tempfile::NamedTempFile,
db_path: Utf8PathBuf,
}
impl WFile {
pub fn new(db_path: Utf8PathBuf) -> Result<Self> {
let file = tempfile::NamedTempFile::new_in(tmp_dir(&db_path)).or_else(|err|
err!("failed to create_file: {}", err))?;
Ok(WFile {
file,
db_path,
})
}
}
impl std::io::Write for WFile {
fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
self.file.write(buf)
}
fn flush(&mut self) -> std::io::Result<()> {
self.file.flush()
}
}
impl Writer for WFile {
fn finalize(self: Box<Self>) -> Result<ObjectId> {
err!("reader pipline has no digest step")
}
fn _finalize(self: Box<Self>, oid: ObjectId) -> Result<ObjectId> {
let path = obj_path(&self.db_path, &oid);
std::fs::create_dir_all(
path.parent().expect("cannot access to object parent directory")
).or_else(|err|
err!("failed to create object dir: {}", err))?;
self.file.persist(path).or_else(|err|
err!("failed to persist file: {}", err))?;
Ok(oid)
}
}
#[cfg(test)]
mod tests {
use std::str::FromStr;
use crate::utils::{obj_dir, obj_path};
use super::*;
#[test]
fn test_wfile() {
use std::io::{Read, Write};
let data = b"Hello World!";
let oid = ObjectId::from_str(
"7f83b1657ff1fc53b92dc18148a1d65dfc2d4b1fa3d677284addd200126d9069"
).expect("invalid object id");
let dir = tempfile::TempDir::new()
.expect("failed to create tmp dir");
std::fs::create_dir(tmp_dir(dir.path().try_into().unwrap())).expect("failed to create db/obj dir");
std::fs::create_dir(obj_dir(dir.path().try_into().unwrap())).expect("failed to create db/tmp dir");
{
let mut writer = Box::new(WFile::new(dir.path().to_path_buf().try_into().unwrap()).expect("failed to create WFile"));
writer.write(data).expect("failed to write to WFile");
let oid2 = writer._finalize(oid.clone()).expect("failed to finalize WFile");
assert_eq!(oid2, oid);
}
let mut file = std::fs::File::open(obj_path(dir.path().try_into().unwrap(), &oid)).expect("failed to open object file");
let mut buf = Vec::new();
file.read_to_end(&mut buf).expect("failed to read object file");
assert_eq!(buf, data);
}
}