summary refs log tree commit diff
diff options
context:
space:
mode:
authoredef <edef@unfathomable.blue>2022-05-03 21:09:59 +0000
committeredef <edef@unfathomable.blue>2022-05-03 21:21:50 +0000
commite7b80cca1c93efda1576e19846ebf089ff6cfa95 (patch)
tree691707333e1d090c77c7e719281fc25a76c7ec56
parent31211f84c2a2467a3b4b1a400d16c7195485b9d6 (diff)
ripple/fossil: handle missing blobs more gracefully
Change-Id: I8a928b57ecc81bea31d757e73b9ece9474628db4
-rw-r--r--ripple/fossil/src/bin/extract.rs6
-rw-r--r--ripple/fossil/src/bin/mount.rs15
-rw-r--r--ripple/fossil/src/lib.rs20
3 files changed, 20 insertions, 21 deletions
diff --git a/ripple/fossil/src/bin/extract.rs b/ripple/fossil/src/bin/extract.rs
index 64e27d4..0a7d0c7 100644
--- a/ripple/fossil/src/bin/extract.rs
+++ b/ripple/fossil/src/bin/extract.rs
@@ -26,7 +26,7 @@ fn main() {
 
 	let store = fossil::Store::open(args.store).unwrap();
 	let root = {
-		let bytes = store.read_blob(args.root);
+		let bytes = store.read_blob(args.root).expect("blob not found");
 		let pb = store::Directory::decode(&*bytes).unwrap();
 
 		Directory::from_pb(pb)
@@ -41,7 +41,7 @@ fn extract(store: &fossil::Store, path: &Path, dir: &Directory) {
 		let path = path.join(name);
 		match node.clone() {
 			fossil::Node::Directory(fossil::DirectoryRef { ident, size: _ }) => {
-				let blob = store.read_blob(ident);
+				let blob = store.read_blob(ident).expect("blob not found");
 				let pb = store::Directory::decode(&*blob).unwrap();
 				fs::create_dir(&path).unwrap();
 				extract(store, &path, &Directory::from_pb(pb));
@@ -58,7 +58,7 @@ fn extract(store: &fossil::Store, path: &Path, dir: &Directory) {
 					.mode(mode)
 					.open(path)
 					.unwrap();
-				let blob = store.read_blob(ident);
+				let blob = store.read_blob(ident).expect("blob not found");
 				f.write_all(&blob).unwrap();
 			}
 			fossil::Node::Link { target } => {
diff --git a/ripple/fossil/src/bin/mount.rs b/ripple/fossil/src/bin/mount.rs
index 846e543..9e0e8aa 100644
--- a/ripple/fossil/src/bin/mount.rs
+++ b/ripple/fossil/src/bin/mount.rs
@@ -132,7 +132,7 @@ impl Filesystem {
 				(inode, &self.roots[&inode])
 			}
 			hash_map::Entry::Vacant(e) => {
-				let root = memtree::load_root(&self.store, ident);
+				let root = memtree::load_root(&self.store, ident)?;
 				let inode = self.inode_tail;
 				self.inode_tail += inode + 1 + root.size() as u64;
 
@@ -241,7 +241,10 @@ impl fuser::Filesystem for Filesystem {
 	fn open(&mut self, _req: &fuser::Request<'_>, ino: u64, _flags: i32, reply: fuser::ReplyOpen) {
 		match self.find(ino) {
 			Some(memtree::Node::File(f)) => {
-				let contents = self.store.open_blob(f.ident);
+				let contents = self
+					.store
+					.open_blob(f.ident)
+					.expect("file points at missing blob");
 				let fh = Box::new(Handle::File {
 					contents: RefCell::new(contents),
 				});
@@ -823,9 +826,9 @@ mod memtree {
 		}
 	}
 
-	pub fn load_root(store: &fossil::Store, ident: Digest) -> Directory {
+	pub fn load_root(store: &fossil::Store, ident: Digest) -> Option<Directory> {
 		let pb = {
-			let bytes = store.read_blob(ident);
+			let bytes = store.read_blob(ident)?;
 			store::Directory::decode(&*bytes).unwrap()
 		};
 		let mut children = BTreeMap::new();
@@ -836,7 +839,7 @@ mod memtree {
 			size: _,
 		} in pb.directories
 		{
-			let child = load_root(store, fossil::digest_from_bytes(&r#ref));
+			let child = load_root(store, fossil::digest_from_bytes(&r#ref))?;
 			children.insert(name, NodeBuf::Directory(child));
 		}
 
@@ -859,7 +862,7 @@ mod memtree {
 			children.insert(name, NodeBuf::Link { target });
 		}
 
-		Directory::from_children(children)
+		Some(Directory::from_children(children))
 	}
 
 	impl Directory {
diff --git a/ripple/fossil/src/lib.rs b/ripple/fossil/src/lib.rs
index 004cf45..007a771 100644
--- a/ripple/fossil/src/lib.rs
+++ b/ripple/fossil/src/lib.rs
@@ -207,18 +207,14 @@ impl Store {
 		Some(store::Chunk::decode(&*buf).unwrap())
 	}
 
-	pub fn read_blob(&self, ident: Digest) -> Vec<u8> {
+	pub fn read_blob(&self, ident: Digest) -> Option<Vec<u8>> {
 		let mut buffer = Vec::new();
-		self.open_blob(ident).read_to_end(&mut buffer).unwrap();
-		buffer
+		self.open_blob(ident)?.read_to_end(&mut buffer).unwrap();
+		Some(buffer)
 	}
 
-	pub fn open_blob(&self, ident: Digest) -> Blob {
-		let buf = self
-			.blobs
-			.get(&*ident.as_bytes())
-			.unwrap()
-			.expect("blob not found");
+	pub fn open_blob(&self, ident: Digest) -> Option<Blob> {
+		let buf = self.blobs.get(&*ident.as_bytes()).unwrap()?;
 
 		let store::Blob {
 			mut chunks,
@@ -241,7 +237,7 @@ impl Store {
 			})
 			.collect();
 
-		Blob(bao::decode::Decoder::new_outboard(
+		Some(Blob(bao::decode::Decoder::new_outboard(
 			RawBlob {
 				store: self,
 				chunks,
@@ -250,7 +246,7 @@ impl Store {
 			},
 			io::Cursor::new(bao_inline),
 			&ident,
-		))
+		)))
 	}
 }
 
@@ -537,5 +533,5 @@ fn read_write() {
 	// TODO(edef): use a temporary file
 	let store = Store::open("fossil.db").unwrap();
 	let ident = store.write_blob(&data);
-	assert_eq!(data, store.read_blob(ident));
+	assert_eq!(Some(data), store.read_blob(ident));
 }