sapling/eden/mononoke/cmds/dumprev.rs
Alex Hornby 14128ce2dc mononoke: remove unnecessary .version("0.0.0") in clap App setup
Summary: We don't need to declare a fake empty version number

Reviewed By: farnz

Differential Revision: D24757981

fbshipit-source-id: 594c97e225704d783bea723efcbb9dfc4d5d800b
2020-11-06 02:23:46 -08:00

90 lines
2.9 KiB
Rust

/*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This software may be used and distributed according to the terms of the
* GNU General Public License version 2.
*/
use anyhow::{bail, Context, Error, Result};
use clap::App;
use mercurial_revlog::revlog::Revlog;
use std::{fs::File, io::Write, str::FromStr};
fn run() -> Result<()> {
// Define command line args and parse command line
let matches = App::new("dumprev")
.about("extract a revision from a revlog")
.args_from_usage(concat!(
"-d, --data=[DATAFILE] 'Data file if not inline'\n",
"-w, --write=[DUMPFILE] 'Write data to file'\n",
"<IDXFILE> 'index file'\n",
"<REV> 'revision index'"
))
.get_matches();
// Get path of index file; `unwrap()` is safe because parameter is non-optional
let idxpath = matches.value_of("IDXFILE").unwrap();
// Get optional datapath
let datapath = matches.value_of("DATAFILE");
// Also optional dumpfile
let dumpfile = matches.value_of("write");
// Get non-optional revision
let revidx = FromStr::from_str(matches.value_of("REV").unwrap())
.map_err(Error::from)
.context("idx malformed")?;
// Construct a `Revlog`
let revlog =
Revlog::from_idx_with_data(idxpath, datapath).context("failed to load idx and data")?;
println!("made revlog {:?}", revlog.get_header());
let entry = revlog.get_entry(revidx).context("failed to get entry")?;
println!("Revlog[{:?}] = {:?}", revidx, entry);
match revlog.get_rev(revidx) {
Ok(ref rev) => {
if entry.nodeid() != rev.nodeid() {
println!(
"NOTE: hash mismatch: expected {}, got {}",
entry.nodeid(),
rev.nodeid()
)
}
let revdata = rev.as_blob().as_slice();
if let Some(dumpfile) = dumpfile {
let mut file = match File::create(dumpfile) {
Ok(file) => file,
Err(err) => bail!("Failed to create file {}: {:?}", dumpfile, err),
};
println!("Writing rev {:?} to {}", rev.nodeid(), dumpfile);
if let Err(err) = file.write_all(revdata) {
bail!("Failed to write {}: {:?}", dumpfile, err);
}
} else {
println!(
"rev {:?}:\n{}",
rev.nodeid(),
String::from_utf8_lossy(revdata)
);
}
}
Err(err) => bail!("failed to get chunk {:?}: {}", revidx, err),
};
Ok(())
}
fn main() {
if let Err(ref e) = run() {
println!("Failed: {}", e);
for e in e.chain() {
println!("caused by: {}", e);
}
std::process::exit(1);
}
}