// SPDX-FileCopyrightText: edef // SPDX-License-Identifier: OSL-3.0 use { clap::StructOpt, fossil::{store, Directory}, prost::Message, std::{ fs, io::{self, Read, Write}, os::unix::{fs::symlink, prelude::OpenOptionsExt}, path::Path, }, }; #[derive(clap::Parser)] struct Args {} fn main() { let _args = Args::parse(); 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(fossil::DirectoryRef { ident, size: _ }) => { let blob = store.read_blob(ident); let pb = store::Directory::decode(&*blob).unwrap(); fs::create_dir(&path).unwrap(); extract(store, &path, &Directory::from_pb(pb)); } fossil::Node::File(fossil::FileRef { ident, executable, size: _, }) => { 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(ident); f.write_all(&blob).unwrap(); } fossil::Node::Link { target } => { symlink(target, path).unwrap(); } } } }