summary refs log tree commit diff
path: root/ripple/fossil/src/bin/extract.rs
diff options
context:
space:
mode:
authoredef <edef@unfathomable.blue>2021-08-14 21:28:14 +0000
committeredef <edef@unfathomable.blue>2021-08-14 21:28:14 +0000
commitdb7c54f92f386a94db8af7a12626d2657b4dd640 (patch)
tree4baba57bac54c68823a834c0f8aa97b24cfec7a2 /ripple/fossil/src/bin/extract.rs
parentdcae0f9c8a94f05bf55cf9b6fbc773502ab5784f (diff)
downloadunf-legacy-db7c54f92f386a94db8af7a12626d2657b4dd640.tar.zst
ripple/fossil: a basic content-addressable store
Fossil stores content-addressed blobs of file contents and
Protobuf-encoded directory listings, backed by Sled.

Change-Id: I8b49de6342218ca00755cec980b1d0cfb18878a7
Diffstat (limited to 'ripple/fossil/src/bin/extract.rs')
-rw-r--r--ripple/fossil/src/bin/extract.rs57
1 files changed, 57 insertions, 0 deletions
diff --git a/ripple/fossil/src/bin/extract.rs b/ripple/fossil/src/bin/extract.rs
new file mode 100644
index 0000000..f83ce0e
--- /dev/null
+++ b/ripple/fossil/src/bin/extract.rs
@@ -0,0 +1,57 @@
+// SPDX-FileCopyrightText: edef <edef@unfathomable.blue>
+// SPDX-License-Identifier: OSL-3.0
+
+use {
+	fossil::{store, Directory},
+	prost::Message,
+	std::{
+		fs,
+		io::{self, Read, Write},
+		os::unix::{fs::symlink, prelude::OpenOptionsExt},
+		path::Path,
+	},
+};
+
+fn main() {
+	let store = fossil::Store::open("fossil.db").unwrap();
+	let root = {
+		let mut stdin = io::stdin();
+
+		let mut bytes = Vec::new();
+		stdin.read_to_end(&mut bytes).unwrap();
+
+		let pb = store::Directory::decode(&*bytes).unwrap();
+		Directory::from_pb(pb)
+	};
+
+	let root_path = Path::new(".");
+	extract(&store, root_path, &root);
+}
+
+fn extract(store: &fossil::Store, path: &Path, dir: &Directory) {
+	for (name, node) in &dir.children {
+		let path = path.join(name);
+		match node.clone() {
+			fossil::Node::Directory { r#ref } => {
+				let blob = store.read_blob(r#ref);
+				let pb = store::Directory::decode(&*blob).unwrap();
+				fs::create_dir(&path).unwrap();
+				extract(store, &path, &Directory::from_pb(pb));
+			}
+			fossil::Node::File { r#ref, executable } => {
+				let mode = if executable { 0o755 } else { 0o644 };
+				let mut f = fs::OpenOptions::new()
+					.write(true)
+					.create_new(true)
+					.mode(mode)
+					.open(path)
+					.unwrap();
+				let blob = store.read_blob(r#ref);
+				f.write_all(&blob).unwrap();
+			}
+			fossil::Node::Link { target } => {
+				symlink(target, path).unwrap();
+			}
+		}
+	}
+}