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
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);
|
|
}
|
|
}
|
|
|