diff options
author | edef <edef@unfathomable.blue> | 2021-08-14 21:28:14 +0000 |
---|---|---|
committer | edef <edef@unfathomable.blue> | 2021-08-14 21:28:14 +0000 |
commit | db7c54f92f386a94db8af7a12626d2657b4dd640 (patch) | |
tree | 4baba57bac54c68823a834c0f8aa97b24cfec7a2 /ripple/fossil/src/bin/extract.rs | |
parent | dcae0f9c8a94f05bf55cf9b6fbc773502ab5784f (diff) | |
download | unf-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.rs | 57 |
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(); + } + } + } +} |