From 7719e27fe8ba00cf33177ff11120b2eef5460da6 Mon Sep 17 00:00:00 2001 From: grimhilt Date: Sat, 28 Oct 2023 23:46:12 +0200 Subject: [PATCH] clean main: divide clap config into multiple files, broke clone 70 lines width --- src/main.rs | 214 +++++---------------------------- src/services/copy.rs | 2 +- src/services/move.rs | 2 +- src/subcommands.rs | 9 ++ src/subcommands/add.rs | 38 ++++++ src/subcommands/clone.rs | 59 +++++++++ src/subcommands/config.rs | 29 +++++ src/subcommands/init.rs | 23 ++++ src/subcommands/pull.rs | 23 ++++ src/subcommands/push.rs | 6 + src/subcommands/remote_diff.rs | 24 ++++ src/subcommands/reset.rs | 6 + src/subcommands/status.rs | 30 +++++ 13 files changed, 277 insertions(+), 188 deletions(-) create mode 100644 src/subcommands.rs create mode 100644 src/subcommands/add.rs create mode 100644 src/subcommands/clone.rs create mode 100644 src/subcommands/config.rs create mode 100644 src/subcommands/init.rs create mode 100644 src/subcommands/pull.rs create mode 100644 src/subcommands/push.rs create mode 100644 src/subcommands/remote_diff.rs create mode 100644 src/subcommands/reset.rs create mode 100644 src/subcommands/status.rs diff --git a/src/main.rs b/src/main.rs index c367934..88d7f75 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,9 +1,6 @@ -use clap::{App, Arg, SubCommand}; -use textwrap::{fill, Options}; +use clap::{App, SubCommand}; -use crate::commands::add::AddArgs; -use crate::commands::status::StatusArgs; -use crate::commands::clone::{self, CloneArgs}; +mod subcommands; mod commands; mod utils; @@ -12,193 +9,38 @@ mod global; mod store; fn main() { - let matches = App::new("Nextsync") + let app = App::new("Nextsync") .version("1.0") .author("grimhilt") .about("A git-line command line tool to interact with nextcloud") .setting(clap::AppSettings::SubcommandRequiredElseHelp) - .subcommand( - SubCommand::with_name("clone") - .arg( - Arg::with_name("remote") - .required(true) - .takes_value(true) - .value_name("REMOTE") - .help(&fill( - "The repository to clone from. See the NEXTSYNC URLS section below for more information on specifying repositories.", - Options::new(70).width, - )) - ) - .arg( - Arg::with_name("depth") - .short("d") - .long("depth") - .required(false) - .takes_value(true) - .help(&fill( - &format!("Depth of the recursive fetch of object properties. This value should be lower when there are a lot of files per directory and higher when there are a lot of subdirectories with fewer files. (Default: {})", clone::DEPTH), - Options::new(70).width, - )) - ) - .arg( - Arg::with_name("directory") - .required(false) - .takes_value(true) - .value_name("DIRECTORY") - ) - .about("Clone a repository into a new directory") - .after_help("NEXTSYNC URLS\nThe following syntaxes may be used:\n\t- user@host.xz/path/to/repo\n\t- http[s]://host.xz/apps/files/?dir=/path/to/repo&fileid=111111\n\t- [http[s]://]host.xz/remote.php/dav/files/user/path/to/repo\n") - ) - .subcommand( - SubCommand::with_name("init") - .arg( - Arg::with_name("directory") - .required(false) - .takes_value(true) - .value_name("DIRECTORY") - ) - .about("Create an empty Nextsync repository") // Create an empty Git repository or reinitialize an existing one - ) - .subcommand( - SubCommand::with_name("status") - .arg( - Arg::with_name("directory") - .required(false) - .takes_value(true) - .value_name("DIRECTORY") - ) - .arg( - Arg::with_name("nostyle") - .long("nostyle") - .help("Status with minium information and style"), - ) - .about("Show the working tree status") - ) - .subcommand( - SubCommand::with_name("reset") - .about("Clear the index") - ) - .subcommand( - SubCommand::with_name("push") - .about("Push changes on nextcloud") - ) - .subcommand( - SubCommand::with_name("add") - .arg( - Arg::with_name("files") - .required(true) - .conflicts_with("all") - .multiple(true) - .takes_value(true) - .value_name("FILE") - .help("Files to add"), - ) - .arg( - Arg::with_name("force") - .short("f") - .long("force") - .help("Allow adding otherwise ignored files."), - ) - .arg( - Arg::with_name("all") - .short("A") - .long("all") - .help("This adds, modifies, and removes index entries to match the working tree"), - ) - .about("Add changes to the index") - ) - .subcommand( - SubCommand::with_name("config") - .arg( - Arg::with_name("variable") - .required(true) - .takes_value(true) - .value_name("VARIABLE") - ) - .arg( - Arg::with_name("value") - .required(true) - .takes_value(true) - .value_name("VALUE") - ) - ) - .subcommand( - SubCommand::with_name("remote-diff") - .arg( - Arg::with_name("path") - .required(false) - .takes_value(true) - .value_name("PATH") - .help("The path to pull."), - ) - .about("Fetch new and modifed files from the nextcloud server.") - ) + .subcommand(subcommands::clone::create()) + .subcommand(subcommands::init::create()) + .subcommand(subcommands::status::create()) + .subcommand(subcommands::add::create()) + .subcommand(subcommands::push::create()) + .subcommand(subcommands::reset::create()) + .subcommand(subcommands::config::create()) + .subcommand(subcommands::remote_diff::create()) + .subcommand(subcommands::pull::create()) .subcommand( SubCommand::with_name("test") - ) - .get_matches(); + ); - if let Some(matches) = matches.subcommand_matches("init") { - if let Some(val) = matches.values_of("directory") { - global::global::set_dir_path(String::from(val.clone().next().unwrap())); - } - commands::init::init(); - } else if let Some(matches) = matches.subcommand_matches("status") { - if let Some(val) = matches.values_of("directory") { - global::global::set_dir_path(String::from(val.clone().next().unwrap())); - } - commands::status::status(StatusArgs { - nostyle: matches.is_present("nostyle"), - }); - } else if let Some(matches) = matches.subcommand_matches("add") { - if let Some(files) = matches.values_of("files") { - commands::add::add(AddArgs { - files: Some(files), - force: matches.is_present("force"), - all: matches.is_present("all"), - }); - } else { - commands::add::add(AddArgs { - files: None, - force: matches.is_present("force"), - all: matches.is_present("all"), - }); - } - } else if let Some(_) = matches.subcommand_matches("reset") { - commands::reset::reset(); - } else if let Some(matches) = matches.subcommand_matches("clone") { - if let Some(val) = matches.values_of("directory") { - global::global::set_dir_path(String::from(val.clone().next().unwrap())); - } - if let Some(remote) = matches.values_of("remote") { - commands::clone::clone(CloneArgs { - remote, - depth: matches.values_of("depth").map( - |mut val| val.next().unwrap().to_owned() - ), - }); - } - } else if let Some(_matches) = matches.subcommand_matches("push") { - commands::push::push(); - } else if let Some(matches) = matches.subcommand_matches("config") { - if let Some(mut var) = matches.values_of("variable") { - if let Some(mut val) = matches.values_of("value") { - if commands::config::set(var.next().unwrap(), val.next().unwrap()).is_err() { - eprintln!("fatal: cannot save the value"); - } - } - } - } else if let Some(matches) = matches.subcommand_matches("remote-diff") { - if let Some(val) = matches.values_of("path") { - global::global::set_dir_path(String::from(val.clone().next().unwrap())); - } - commands::remote_diff::remote_diff(); - } else if let Some(matches) = matches.subcommand_matches("pull") { - if let Some(val) = matches.values_of("path") { - global::global::set_dir_path(String::from(val.clone().next().unwrap())); - } - commands::pull::pull(); - } else if let Some(_) = matches.subcommand_matches("test") { - } + let matches = app.get_matches(); + + match matches.subcommand() { + ("init", Some(args)) => subcommands::init::handler(args), + ("status", Some(args)) => subcommands::status::handler(args), + ("add", Some(args)) => subcommands::add::handler(args), + ("reset", Some(_)) => commands::reset::reset(), + ("clone", Some(args)) => subcommands::clone::handler(args), + ("push", Some(_)) => commands::push::push(), + ("config", Some(args)) => subcommands::config::handler(args), + ("remote-diff", Some(args)) => subcommands::remote_diff::handler(args), + ("pull", Some(args)) => subcommands::pull::handler(args), + + (_, _) => {}, + }; } diff --git a/src/services/copy.rs b/src/services/copy.rs index 38093d3..d5bb3a5 100644 --- a/src/services/copy.rs +++ b/src/services/copy.rs @@ -1,6 +1,6 @@ use reqwest::{Method, header::HeaderValue}; use crate::services::api::{ApiBuilder, ApiError}; -use crate::clone::get_url_props; +use crate::commands::clone::get_url_props; use crate::commands::config; use crate::services::api_call::ApiCall; diff --git a/src/services/move.rs b/src/services/move.rs index ab6a76a..8127f61 100644 --- a/src/services/move.rs +++ b/src/services/move.rs @@ -1,6 +1,6 @@ use reqwest::{Method, header::HeaderValue}; use crate::services::api::{ApiBuilder, ApiError}; -use crate::clone::get_url_props; +use crate::commands::clone::get_url_props; use crate::commands::config; use crate::services::api_call::ApiCall; diff --git a/src/subcommands.rs b/src/subcommands.rs new file mode 100644 index 0000000..e49e518 --- /dev/null +++ b/src/subcommands.rs @@ -0,0 +1,9 @@ +pub mod init; +pub mod status; +pub mod add; +pub mod reset; +pub mod clone; +pub mod push; +pub mod config; +pub mod remote_diff; +pub mod pull; diff --git a/src/subcommands/add.rs b/src/subcommands/add.rs new file mode 100644 index 0000000..83dd21a --- /dev/null +++ b/src/subcommands/add.rs @@ -0,0 +1,38 @@ +use clap::{App, Arg, SubCommand, ArgMatches}; + +use crate::commands; +use crate::commands::add::AddArgs; + +pub fn create() -> App<'static, 'static> { + SubCommand::with_name("add") + .arg( + Arg::with_name("files") + .required(true) + .conflicts_with("all") + .multiple(true) + .takes_value(true) + .value_name("FILE") + .help("Files to add"), + ) + .arg( + Arg::with_name("force") + .short("f") + .long("force") + .help("Allow adding otherwise ignored files."), + ) + .arg( + Arg::with_name("all") + .short("A") + .long("all") + .help("This adds, modifies, and removes index entries to match the working tree"), + ) + .about("Add changes to the index") +} + +pub fn handler(args: &ArgMatches<'_>) { + commands::add::add(AddArgs { + files: args.values_of("files"), + force: args.is_present("force"), + all: args.is_present("all"), + }); +} diff --git a/src/subcommands/clone.rs b/src/subcommands/clone.rs new file mode 100644 index 0000000..e785017 --- /dev/null +++ b/src/subcommands/clone.rs @@ -0,0 +1,59 @@ +use clap::{App, Arg, SubCommand, ArgMatches}; +use std::borrow::Cow; +use textwrap::{fill, Options}; + +use crate::commands::clone::{self, CloneArgs}; +use crate::global; +use crate::commands; + +fn sized_str<'a>(content: &'a str) -> &'a str { + fill(content, Options::new(70).width).as_str(); + "ok" +} + +fn test() -> String { + String::from("ok") +} + +pub fn create() -> App<'static, 'static> { + let remote_desc = sized_str(&format!("The repository to clone from. See the NEXTSYNC URLS section below for more information on specifying repositories.")); + let depth_desc = sized_str(&format!("Depth of the recursive fetch of object properties. This value should be lower when there are a lot of files per directory and higher when there are a lot of subdirectories with fewer files. (Default: {})", clone::DEPTH)); + SubCommand::with_name("clone") + .arg( + Arg::with_name("remote") + .required(true) + .takes_value(true) + .value_name("REMOTE") + //.help(_desc) + ) + .arg( + Arg::with_name("depth") + .short("d") + .long("depth") + .required(false) + .takes_value(true) + //.help(&depth_desc) + ) + .arg( + Arg::with_name("directory") + .required(false) + .takes_value(true) + .value_name("DIRECTORY") + ) + .about("Clone a repository into a new directory") + .after_help("NEXTSYNC URLS\nThe following syntaxes may be used:\n\t- user@host.xz/path/to/repo\n\t- http[s]://host.xz/apps/files/?dir=/path/to/repo&fileid=111111\n\t- [http[s]://]host.xz/remote.php/dav/files/user/path/to/repo\n") +} + +pub fn handler(args: &ArgMatches<'_>) { + if let Some(val) = args.values_of("directory") { + global::global::set_dir_path(String::from(val.clone().next().unwrap())); + } + if let Some(remote) = args.values_of("remote") { + commands::clone::clone(CloneArgs { + remote, + depth: args.values_of("depth").map( + |mut val| val.next().unwrap().to_owned() + ), + }); + } +} diff --git a/src/subcommands/config.rs b/src/subcommands/config.rs new file mode 100644 index 0000000..6d6b7ee --- /dev/null +++ b/src/subcommands/config.rs @@ -0,0 +1,29 @@ +use clap::{App, Arg, SubCommand, ArgMatches}; + +use crate::commands; + +pub fn create() -> App<'static, 'static> { + SubCommand::with_name("config") + .arg( + Arg::with_name("variable") + .required(true) + .takes_value(true) + .value_name("VARIABLE") + ) + .arg( + Arg::with_name("value") + .required(true) + .takes_value(true) + .value_name("VALUE") + ) +} + +pub fn handler(args: &ArgMatches<'_>) { + if let Some(mut var) = args.values_of("variable") { + if let Some(mut val) = args.values_of("value") { + if commands::config::set(var.next().unwrap(), val.next().unwrap()).is_err() { + eprintln!("fatal: cannot save the value"); + } + } + } +} diff --git a/src/subcommands/init.rs b/src/subcommands/init.rs new file mode 100644 index 0000000..b4c3658 --- /dev/null +++ b/src/subcommands/init.rs @@ -0,0 +1,23 @@ +use clap::{App, Arg, SubCommand, ArgMatches}; + +use crate::global; +use crate::commands; + +pub fn create() -> App<'static, 'static> { + SubCommand::with_name("init") + .arg( + Arg::with_name("directory") + .required(false) + .takes_value(true) + .value_name("DIRECTORY") + ) + .about("Create an empty Nextsync repository") + // Create an empty nextsync repository or reinitialize an existing one +} + +pub fn handler(args: &ArgMatches<'_>) { + if let Some(val) = args.values_of("directory") { + global::global::set_dir_path(String::from(val.clone().next().unwrap())); + } + commands::init::init(); +} diff --git a/src/subcommands/pull.rs b/src/subcommands/pull.rs new file mode 100644 index 0000000..8684d51 --- /dev/null +++ b/src/subcommands/pull.rs @@ -0,0 +1,23 @@ +use clap::{App, Arg, SubCommand, ArgMatches}; + +use crate::global; +use crate::commands; + +pub fn create() -> App<'static, 'static> { + SubCommand::with_name("pull") + .arg( + Arg::with_name("path") + .required(false) + .takes_value(true) + .value_name("PATH") + .help("The path to pull."), + ) + .about("Fetch and integrate changes from the nextcloud server.") +} + +pub fn handler(args: &ArgMatches<'_>) { + if let Some(val) = args.values_of("path") { + global::global::set_dir_path(String::from(val.clone().next().unwrap())); + } + commands::pull::pull(); +} diff --git a/src/subcommands/push.rs b/src/subcommands/push.rs new file mode 100644 index 0000000..82db1fe --- /dev/null +++ b/src/subcommands/push.rs @@ -0,0 +1,6 @@ +use clap::{App, Arg, SubCommand}; + +pub fn create() -> App<'static, 'static> { + SubCommand::with_name("push") + .about("Push changes on nextcloud") +} diff --git a/src/subcommands/remote_diff.rs b/src/subcommands/remote_diff.rs new file mode 100644 index 0000000..9986c16 --- /dev/null +++ b/src/subcommands/remote_diff.rs @@ -0,0 +1,24 @@ +use clap::{App, Arg, SubCommand, ArgMatches}; + +use crate::global; +use crate::commands; + +pub fn create() -> App<'static, 'static> { + SubCommand::with_name("remote-diff") + .arg( + Arg::with_name("path") + .required(false) + .takes_value(true) + .value_name("PATH") + .help("The path to pull."), + ) + .about("Fetch changes from the nextcloud server.") +} + + +pub fn handler(args: &ArgMatches<'_>) { + if let Some(val) = args.values_of("path") { + global::global::set_dir_path(String::from(val.clone().next().unwrap())); + } + commands::remote_diff::remote_diff(); +} diff --git a/src/subcommands/reset.rs b/src/subcommands/reset.rs new file mode 100644 index 0000000..348ca9d --- /dev/null +++ b/src/subcommands/reset.rs @@ -0,0 +1,6 @@ +use clap::{App, Arg, SubCommand}; + +pub fn create() -> App<'static, 'static> { + SubCommand::with_name("reset") + .about("Clear the index") +} diff --git a/src/subcommands/status.rs b/src/subcommands/status.rs new file mode 100644 index 0000000..aee3884 --- /dev/null +++ b/src/subcommands/status.rs @@ -0,0 +1,30 @@ +use clap::{App, Arg, SubCommand, ArgMatches}; + +use crate::global; +use crate::commands; +use crate::commands::status::StatusArgs; + +pub fn create() -> App<'static, 'static> { + SubCommand::with_name("status") + .arg( + Arg::with_name("directory") + .required(false) + .takes_value(true) + .value_name("DIRECTORY") + ) + .arg( + Arg::with_name("nostyle") + .long("nostyle") + .help("Status with minium information and style"), + ) + .about("Show the working tree status") +} + +pub fn handler(args: &ArgMatches<'_>) { + if let Some(val) = args.values_of("directory") { + global::global::set_dir_path(String::from(val.clone().next().unwrap())); + } + commands::status::status(StatusArgs { + nostyle: args.is_present("nostyle"), + }); +}