sapling/eden/mononoke/cmds/admin/subcommand_fsnodes.rs
Yan Soares Couto 302131bd5f Allow cli commands to build any "repo object"
Summary:
The important change on this diff is in this file: `eden/mononoke/cmdlib/src/args/mod.rs`

On this diff I change that file's repo-building functions to be able to build both `BlobRepo` and `InnerRepo` (added on D28748221 (e4b6fd3751)). In fact, they are now able to build any facet container that can be built by the `RepoFactory` factory, so each binary can specify their own subset of needed "attributes" and only build those ones.

For now, they're all still using BlobRepo, this diff is only a refactor that enables easily changing the repo attributes you need.

The rest of the diff is mostly giving hints to the compiler, as in several places it couldn't infer it should use `BlobRepo` directly, so I had to add type hints.

## High level goal

This is part of the blobrepo refactoring effort.

I am also doing this in order to:
1. Make sure every place that builds `SkiplistIndex` uses `RepoFactory` for that.
2. Then add a `BlobstoreGetOps` trait for blobstores, and use the factory to feed it to skiplist index, so it can query the blobstore while skipping cache. (see [this thread](https://www.internalfb.com/diff/D28681737 (850a1a41b7)?dst_version_fbid=283910610084973&transaction_fbid=106742464866346))

Reviewed By: StanislavGlebik

Differential Revision: D28877887

fbshipit-source-id: b5e0093449aac734591a19d915b6459b1779360a
2021-06-09 05:16:13 -07:00

105 lines
3.0 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 crate::error::SubcommandError;
use anyhow::Error;
use blobrepo::BlobRepo;
use clap::{App, Arg, ArgMatches, SubCommand};
use cmdlib::{
args::{self, MononokeMatches},
helpers,
};
use context::CoreContext;
use derived_data::BonsaiDerived;
use fbinit::FacebookInit;
use futures::{compat::Future01CompatExt, stream::StreamExt};
use manifest::{Entry, ManifestOps, PathOrPrefix};
use fsnodes::RootFsnodeId;
use mononoke_types::{ChangesetId, MPath};
use slog::{info, Logger};
pub const FSNODES: &str = "fsnodes";
const COMMAND_TREE: &str = "tree";
const ARG_CSID: &str = "csid";
const ARG_PATH: &str = "path";
pub fn build_subcommand<'a, 'b>() -> App<'a, 'b> {
SubCommand::with_name(FSNODES)
.about("inspect fsnodes")
.subcommand(
SubCommand::with_name(COMMAND_TREE)
.about("recursively list all fsnode entries starting with prefix")
.arg(
Arg::with_name(ARG_CSID)
.help("{hg|bonsai} changeset id or bookmark name")
.required(true),
)
.arg(Arg::with_name(ARG_PATH).help("path")),
)
}
pub async fn subcommand_fsnodes<'a>(
fb: FacebookInit,
logger: Logger,
matches: &'a MononokeMatches<'_>,
sub_matches: &'a ArgMatches<'_>,
) -> Result<(), SubcommandError> {
let repo: BlobRepo = args::open_repo(fb, &logger, &matches).await?;
let ctx = CoreContext::new_with_logger(fb, logger.clone());
match sub_matches.subcommand() {
(COMMAND_TREE, Some(matches)) => {
let hash_or_bookmark = String::from(matches.value_of(ARG_CSID).unwrap());
let path = matches.value_of(ARG_PATH).map(MPath::new).transpose()?;
let csid = helpers::csid_resolve(ctx.clone(), repo.clone(), hash_or_bookmark)
.compat()
.await?;
subcommand_tree(&ctx, &repo, csid, path).await?;
Ok(())
}
_ => Err(SubcommandError::InvalidArgs),
}
}
async fn subcommand_tree(
ctx: &CoreContext,
repo: &BlobRepo,
csid: ChangesetId,
path: Option<MPath>,
) -> Result<(), Error> {
let root = RootFsnodeId::derive(ctx, repo, csid).await?;
info!(ctx.logger(), "ROOT: {:?}", root);
info!(ctx.logger(), "PATH: {:?}", path);
let mut stream = root.fsnode_id().find_entries(
ctx.clone(),
repo.get_blobstore(),
vec![PathOrPrefix::Prefix(path)],
);
while let Some((path, entry)) = stream.next().await.transpose()? {
match entry {
Entry::Tree(..) => {}
Entry::Leaf(file) => {
println!(
"{}\t{}\t{}\t{}",
MPath::display_opt(path.as_ref()),
file.content_id(),
file.file_type(),
file.size(),
);
}
};
}
Ok(())
}