mirror of
https://github.com/facebook/sapling.git
synced 2024-10-10 08:47:12 +03:00
mononoke: add the filenode subcommand to the admin tool
Summary: This is useful to inspect the Mercurial filenodes in Mononoke, like in S183272. For example, I intend to use this subcommand to verify how well the future linknode healing works. Reviewed By: krallin Differential Revision: D16621516 fbshipit-source-id: 4266f85bce29b59072bf9c4f3e63777dae09a4f1
This commit is contained in:
parent
1420897ff8
commit
bc985480e9
@ -23,3 +23,4 @@ pub const SKIPLIST_BUILD: &'static str = "build";
|
||||
pub const SKIPLIST_READ: &'static str = "read";
|
||||
pub const ADD_PUBLIC_PHASES: &'static str = "add-public-phases";
|
||||
pub const BLACKLIST: &'static str = "blacklist";
|
||||
pub const FILENODES: &'static str = "filenodes";
|
||||
|
109
cmds/admin/filenodes.rs
Normal file
109
cmds/admin/filenodes.rs
Normal file
@ -0,0 +1,109 @@
|
||||
// Copyright (c) 2004-present, Facebook, Inc.
|
||||
// All Rights Reserved.
|
||||
//
|
||||
// This software may be used and distributed according to the terms of the
|
||||
// GNU General Public License version 2 or any later version.
|
||||
|
||||
use clap::ArgMatches;
|
||||
use cmdlib::args;
|
||||
|
||||
use crate::common::{get_file_nodes, resolve_hg_rev};
|
||||
use cloned::cloned;
|
||||
use context::CoreContext;
|
||||
use failure_ext::{format_err, Error};
|
||||
use filenodes::FilenodeInfo;
|
||||
use futures::future::{join_all, Future};
|
||||
use futures_ext::{try_boxfuture, BoxFuture, FutureExt};
|
||||
use mercurial_types::MPath;
|
||||
use mononoke_types::RepoPath;
|
||||
use slog::{debug, info, Logger};
|
||||
|
||||
pub fn subcommand_filenodes(
|
||||
logger: Logger,
|
||||
matches: &ArgMatches<'_>,
|
||||
sub_m: &ArgMatches<'_>,
|
||||
) -> BoxFuture<(), Error> {
|
||||
let rev = sub_m
|
||||
.value_of("hg-changeset-or-bookmark")
|
||||
.unwrap()
|
||||
.to_string();
|
||||
|
||||
let paths: Result<Vec<_>, Error> = sub_m
|
||||
.values_of("paths")
|
||||
.expect("at least one file")
|
||||
.map(|path| {
|
||||
let mpath = MPath::new(path);
|
||||
match mpath {
|
||||
Ok(mpath) => Ok(mpath),
|
||||
Err(_) => Err(format_err!(
|
||||
"The following path could not be parsed {}",
|
||||
path
|
||||
)),
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
let paths: Vec<_> = try_boxfuture!(paths);
|
||||
let ctx = CoreContext::test_mock();
|
||||
args::init_cachelib(&matches);
|
||||
|
||||
args::open_repo(&logger, &matches)
|
||||
.and_then({
|
||||
cloned!(ctx);
|
||||
move |blobrepo| {
|
||||
resolve_hg_rev(ctx.clone(), &blobrepo, &rev).map(|cs_id| (blobrepo, cs_id))
|
||||
}
|
||||
})
|
||||
.and_then({
|
||||
cloned!(ctx, logger);
|
||||
move |(blobrepo, cs_id)| {
|
||||
debug!(logger, "using commit: {:?}", cs_id);
|
||||
get_file_nodes(ctx.clone(), logger.clone(), &blobrepo, cs_id, paths.clone())
|
||||
.map(|filenode_ids| (blobrepo, paths.into_iter().zip(filenode_ids.into_iter())))
|
||||
}
|
||||
})
|
||||
.and_then({
|
||||
cloned!(ctx);
|
||||
move |(blobrepo, path_filenode_ids)| {
|
||||
join_all(
|
||||
path_filenode_ids
|
||||
.into_iter()
|
||||
.map(move |(path, filenode_id)| {
|
||||
blobrepo.get_filenode(
|
||||
ctx.clone(),
|
||||
&RepoPath::FilePath(path),
|
||||
filenode_id,
|
||||
)
|
||||
}),
|
||||
)
|
||||
}
|
||||
})
|
||||
.map(move |filenodes| {
|
||||
filenodes.into_iter().for_each(|filenode| {
|
||||
let FilenodeInfo {
|
||||
path,
|
||||
filenode,
|
||||
p1,
|
||||
p2,
|
||||
copyfrom,
|
||||
linknode,
|
||||
} = filenode;
|
||||
info!(
|
||||
logger,
|
||||
"Filenode {:?}:\n \
|
||||
-- path: {:?}\n \
|
||||
-- p1: {:?}\n \
|
||||
-- p2: {:?}\n \
|
||||
-- copyfrom: {:?}\n \
|
||||
-- linknode: {:?}",
|
||||
filenode,
|
||||
path,
|
||||
p1,
|
||||
p2,
|
||||
copyfrom,
|
||||
linknode
|
||||
);
|
||||
});
|
||||
})
|
||||
.boxify()
|
||||
}
|
@ -19,11 +19,12 @@ use crate::blobstore_fetch::subcommand_blobstore_fetch;
|
||||
use crate::bonsai_fetch::subcommand_bonsai_fetch;
|
||||
use crate::cmdargs::{
|
||||
ADD_PUBLIC_PHASES, BLACKLIST, BLOBSTORE_FETCH, BONSAI_FETCH, BOOKMARKS, CONTENT_FETCH,
|
||||
HASH_CONVERT, HG_CHANGESET, HG_CHANGESET_DIFF, HG_CHANGESET_RANGE, HG_SYNC_BUNDLE,
|
||||
FILENODES, HASH_CONVERT, HG_CHANGESET, HG_CHANGESET_DIFF, HG_CHANGESET_RANGE, HG_SYNC_BUNDLE,
|
||||
HG_SYNC_FETCH_BUNDLE, HG_SYNC_LAST_PROCESSED, HG_SYNC_REMAINS, HG_SYNC_SHOW, HG_SYNC_VERIFY,
|
||||
SKIPLIST, SKIPLIST_BUILD, SKIPLIST_READ,
|
||||
};
|
||||
use crate::content_fetch::subcommand_content_fetch;
|
||||
use crate::filenodes::subcommand_filenodes;
|
||||
use crate::hash_convert::subcommand_hash_convert;
|
||||
use crate::hg_changeset::subcommand_hg_changeset;
|
||||
use crate::hg_sync::subcommand_process_hg_sync;
|
||||
@ -37,6 +38,7 @@ mod bookmarks_manager;
|
||||
mod cmdargs;
|
||||
mod common;
|
||||
mod content_fetch;
|
||||
mod filenodes;
|
||||
mod hash_convert;
|
||||
mod hg_changeset;
|
||||
mod hg_sync;
|
||||
@ -266,6 +268,22 @@ fn setup_app<'a, 'b>() -> App<'a, 'b> {
|
||||
"#,
|
||||
);
|
||||
|
||||
let filenodes = SubCommand::with_name(FILENODES)
|
||||
.about("fetches hg filenodes information for a commit and one or more paths")
|
||||
.arg(
|
||||
Arg::with_name("hg-changeset-or-bookmark")
|
||||
.required(true)
|
||||
.takes_value(true)
|
||||
.help("hg chageset to lookup filenodes for"),
|
||||
)
|
||||
.arg(
|
||||
Arg::with_name("paths")
|
||||
.required(true)
|
||||
.multiple(true)
|
||||
.takes_value(true)
|
||||
.help("a list of file paths to lookup filenodes for"),
|
||||
);
|
||||
|
||||
let app = args::MononokeApp {
|
||||
safe_writes: false,
|
||||
hide_advanced_args: true,
|
||||
@ -287,6 +305,7 @@ fn setup_app<'a, 'b>() -> App<'a, 'b> {
|
||||
.subcommand(hg_sync)
|
||||
.subcommand(add_public_phases)
|
||||
.subcommand(blacklist)
|
||||
.subcommand(filenodes)
|
||||
}
|
||||
|
||||
fn main() -> Result<()> {
|
||||
@ -314,6 +333,7 @@ fn main() -> Result<()> {
|
||||
(HASH_CONVERT, Some(sub_m)) => subcommand_hash_convert(logger, &matches, sub_m),
|
||||
(ADD_PUBLIC_PHASES, Some(sub_m)) => subcommand_add_public_phases(logger, &matches, sub_m),
|
||||
(BLACKLIST, Some(sub_m)) => subcommand_blacklist(logger, &matches, sub_m),
|
||||
(FILENODES, Some(sub_m)) => subcommand_filenodes(logger, &matches, sub_m),
|
||||
_ => {
|
||||
eprintln!("{}", matches.usage());
|
||||
::std::process::exit(1);
|
||||
|
Loading…
Reference in New Issue
Block a user