mirror of
https://github.com/facebook/sapling.git
synced 2025-01-07 14:10:42 +03:00
clidispatch: initial migration to define_flags!
Summary: Use `define_flags!` to auto generate conversion from `ParseOutput`. A side effect is `args` is moved to the struct, and function signature becomes simpler. Currently, `args` will also include the command name itself. This might be useful when multiple commands share a similar implementation (ex. `next`, `prev`). Reviewed By: sfilipco Differential Revision: D16733269 fbshipit-source-id: fe32e41fe48a97d2d2f5a122522a17fa3c5f5f82
This commit is contained in:
parent
76cb250fcd
commit
8ec9e492ff
@ -8,11 +8,9 @@ use crate::repo::Repo;
|
||||
use cliparser::parser::{Flag, ParseOutput};
|
||||
|
||||
pub enum CommandType {
|
||||
NoRepo(Box<dyn Fn(ParseOutput, Vec<String>, &mut IO) -> Result<u8, DispatchError>>),
|
||||
InferRepo(
|
||||
Box<dyn Fn(ParseOutput, Vec<String>, &mut IO, Option<Repo>) -> Result<u8, DispatchError>>,
|
||||
),
|
||||
Repo(Box<dyn Fn(ParseOutput, Vec<String>, &mut IO, Repo) -> Result<u8, DispatchError>>),
|
||||
NoRepo(Box<dyn Fn(ParseOutput, &mut IO) -> Result<u8, DispatchError>>),
|
||||
InferRepo(Box<dyn Fn(ParseOutput, &mut IO, Option<Repo>) -> Result<u8, DispatchError>>),
|
||||
Repo(Box<dyn Fn(ParseOutput, &mut IO, Repo) -> Result<u8, DispatchError>>),
|
||||
}
|
||||
|
||||
pub struct CommandDefinition {
|
||||
|
@ -413,8 +413,6 @@ impl Dispatcher {
|
||||
|
||||
Dispatcher::last_chance_to_abort(&result)?;
|
||||
|
||||
let command_length = command_name.split(" ").count();
|
||||
|
||||
let handler = self.command_table.get(&command_name).unwrap();
|
||||
|
||||
let res = match handler {
|
||||
@ -427,8 +425,7 @@ impl Dispatcher {
|
||||
})?;
|
||||
|
||||
r.set_config(config_set);
|
||||
let args = result.args().iter().skip(command_length).cloned().collect();
|
||||
f(result, args, io, r)
|
||||
f(result, io, r)
|
||||
}
|
||||
CommandType::InferRepo(f) => {
|
||||
let r = match repo {
|
||||
@ -438,13 +435,9 @@ impl Dispatcher {
|
||||
}
|
||||
None => None,
|
||||
};
|
||||
let args = args.iter().skip(command_length).cloned().collect();
|
||||
f(result, args, io, r)
|
||||
}
|
||||
CommandType::NoRepo(f) => {
|
||||
let args = result.args().clone();
|
||||
f(result, args, io)
|
||||
f(result, io, r)
|
||||
}
|
||||
CommandType::NoRepo(f) => f(result, io),
|
||||
};
|
||||
|
||||
res
|
||||
@ -458,13 +451,13 @@ pub trait Register<FN, T> {
|
||||
// No Repo
|
||||
impl<S, FN> Register<FN, (S,)> for Dispatcher
|
||||
where
|
||||
S: From<ParseOutput>,
|
||||
FN: Fn(S, Vec<String>, &mut IO) -> Result<u8, DispatchError> + 'static,
|
||||
S: From<ParseOutput> + StructFlags,
|
||||
FN: Fn(S, &mut IO) -> Result<u8, DispatchError> + 'static,
|
||||
{
|
||||
fn register(&mut self, command: CommandDefinition, inner_func: FN) {
|
||||
let wrapped = move |opts: ParseOutput, args: Vec<String>, io: &mut IO| {
|
||||
let wrapped = move |opts: ParseOutput, io: &mut IO| {
|
||||
let translated_opts = opts.into();
|
||||
inner_func(translated_opts, args, io)
|
||||
inner_func(translated_opts, io)
|
||||
};
|
||||
self.command_table.insert(
|
||||
command.name().to_owned(),
|
||||
@ -477,15 +470,14 @@ where
|
||||
// Infer Repo
|
||||
impl<S, FN> Register<FN, ((), (((S,),),))> for Dispatcher
|
||||
where
|
||||
S: From<ParseOutput>,
|
||||
FN: Fn(S, Vec<String>, &mut IO, Option<Repo>) -> Result<u8, DispatchError> + 'static,
|
||||
S: From<ParseOutput> + StructFlags,
|
||||
FN: Fn(S, &mut IO, Option<Repo>) -> Result<u8, DispatchError> + 'static,
|
||||
{
|
||||
fn register(&mut self, command: CommandDefinition, inner_func: FN) {
|
||||
let wrapped =
|
||||
move |opts: ParseOutput, args: Vec<String>, io: &mut IO, repo: Option<Repo>| {
|
||||
let translated_opts = opts.into();
|
||||
inner_func(translated_opts, args, io, repo)
|
||||
};
|
||||
let wrapped = move |opts: ParseOutput, io: &mut IO, repo: Option<Repo>| {
|
||||
let translated_opts = opts.into();
|
||||
inner_func(translated_opts, io, repo)
|
||||
};
|
||||
self.command_table.insert(
|
||||
command.name().to_owned(),
|
||||
CommandType::InferRepo(Box::new(wrapped)),
|
||||
@ -497,13 +489,13 @@ where
|
||||
// Repo
|
||||
impl<S, FN> Register<FN, ((), (), ((S,),))> for Dispatcher
|
||||
where
|
||||
S: From<ParseOutput>,
|
||||
FN: Fn(S, Vec<String>, &mut IO, Repo) -> Result<u8, DispatchError> + 'static,
|
||||
S: From<ParseOutput> + StructFlags,
|
||||
FN: Fn(S, &mut IO, Repo) -> Result<u8, DispatchError> + 'static,
|
||||
{
|
||||
fn register(&mut self, command: CommandDefinition, inner_func: FN) {
|
||||
let wrapped = move |opts: ParseOutput, args: Vec<String>, io: &mut IO, repo: Repo| {
|
||||
let wrapped = move |opts: ParseOutput, io: &mut IO, repo: Repo| {
|
||||
let translated_opts = opts.into();
|
||||
inner_func(translated_opts, args, io, repo)
|
||||
inner_func(translated_opts, io, repo)
|
||||
};
|
||||
self.command_table.insert(
|
||||
command.name().to_owned(),
|
||||
|
@ -5,7 +5,8 @@ use clidispatch::dispatch::*;
|
||||
use clidispatch::errors::DispatchError;
|
||||
use clidispatch::io::IO;
|
||||
use clidispatch::repo::Repo;
|
||||
use cliparser::parser::ParseOutput;
|
||||
use cliparser::define_flags;
|
||||
use cliparser::parser::StructFlags;
|
||||
|
||||
use revisionstore::{DataPackStore, DataStore, IndexedLogDataStore, UnionDataStore};
|
||||
use types::{Key, Node, RepoPathBuf};
|
||||
@ -30,7 +31,7 @@ pub fn dispatch(dispatcher: &mut Dispatcher) -> Result<u8, DispatchError> {
|
||||
|
||||
fn root_command() -> CommandDefinition {
|
||||
let command = CommandDefinition::new("root")
|
||||
.add_flag((' ', "shared", "show root of the shared repo", false))
|
||||
.add_flag(RootOpts::flags()[0].clone())
|
||||
.with_doc(
|
||||
r#"print the root (top) of the current working directory
|
||||
|
||||
@ -44,25 +45,27 @@ fn root_command() -> CommandDefinition {
|
||||
command
|
||||
}
|
||||
|
||||
pub struct RootCommand {
|
||||
shared: bool,
|
||||
}
|
||||
define_flags! {
|
||||
pub struct RootOpts {
|
||||
/// show root of the shared repo
|
||||
shared: bool,
|
||||
|
||||
impl From<ParseOutput> for RootCommand {
|
||||
fn from(opts: ParseOutput) -> Self {
|
||||
let shared: bool = opts.pick("shared");
|
||||
#[args]
|
||||
args: Vec<String>,
|
||||
}
|
||||
|
||||
RootCommand { shared }
|
||||
pub struct DebugstoreOpts {
|
||||
/// print blob contents
|
||||
content: bool,
|
||||
|
||||
#[args]
|
||||
args: Vec<String>,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn root(
|
||||
cmd: RootCommand,
|
||||
args: Vec<String>,
|
||||
io: &mut IO,
|
||||
repo: Repo,
|
||||
) -> Result<u8, DispatchError> {
|
||||
if args.len() > 0 {
|
||||
pub fn root(opts: RootOpts, io: &mut IO, repo: Repo) -> Result<u8, DispatchError> {
|
||||
let args = opts.args;
|
||||
if args != vec!["root"] {
|
||||
return Err(DispatchError::InvalidArguments {
|
||||
command_name: "root".to_string(),
|
||||
}); // root doesn't support arguments
|
||||
@ -70,7 +73,7 @@ pub fn root(
|
||||
|
||||
let shared = repo.sharedpath()?;
|
||||
|
||||
let path = if cmd.shared {
|
||||
let path = if opts.shared {
|
||||
shared.unwrap_or(repo.path().to_owned())
|
||||
} else {
|
||||
repo.path().to_owned()
|
||||
@ -93,25 +96,9 @@ fn debugstore_command() -> CommandDefinition {
|
||||
command
|
||||
}
|
||||
|
||||
pub struct DebugstoreCommand {
|
||||
content: bool,
|
||||
}
|
||||
|
||||
impl From<ParseOutput> for DebugstoreCommand {
|
||||
fn from(opts: ParseOutput) -> Self {
|
||||
let content: bool = opts.pick("shared");
|
||||
|
||||
DebugstoreCommand { content }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn debugstore(
|
||||
cmd: DebugstoreCommand,
|
||||
args: Vec<String>,
|
||||
io: &mut IO,
|
||||
repo: Repo,
|
||||
) -> Result<u8, DispatchError> {
|
||||
if args.len() != 2 || !cmd.content {
|
||||
pub fn debugstore(opts: DebugstoreOpts, io: &mut IO, repo: Repo) -> Result<u8, DispatchError> {
|
||||
let args = opts.args;
|
||||
if args.len() != 2 || !opts.content {
|
||||
return Err(DispatchError::InvalidArguments {
|
||||
command_name: "debugstore".to_string(),
|
||||
}); // debugstore requires arguments
|
||||
|
Loading…
Reference in New Issue
Block a user