summaryrefslogtreecommitdiff
path: root/src/bin/jv.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/bin/jv.rs')
-rw-r--r--src/bin/jv.rs322
1 files changed, 303 insertions, 19 deletions
diff --git a/src/bin/jv.rs b/src/bin/jv.rs
index f67b37b..3a22528 100644
--- a/src/bin/jv.rs
+++ b/src/bin/jv.rs
@@ -1,4 +1,16 @@
-use std::{net::SocketAddr, str::FromStr};
+use std::{env::current_dir, net::SocketAddr, path::PathBuf, str::FromStr};
+
+use just_enough_vcs::{
+ utils::cfg_file::config::ConfigFile,
+ vcs::{
+ current::current_local_path,
+ data::{
+ local::{LocalWorkspace, config::LocalConfig},
+ member::Member,
+ user::UserDirectory,
+ },
+ },
+};
use clap::{Parser, Subcommand, arg, command};
use just_enough_vcs::{
@@ -8,6 +20,7 @@ use just_enough_vcs::{
};
use just_enough_vcs_cli::utils::{lang_selector::current_locales, md_colored::md};
use rust_i18n::{set_locale, t};
+use tokio::fs;
// Import i18n files
rust_i18n::i18n!("locales", fallback = "en");
@@ -29,7 +42,7 @@ struct JustEnoughVcsWorkspace {
enum JustEnoughVcsWorkspaceCommand {
// Member management
/// Manage your local accounts
- #[command(subcommand)]
+ #[command(subcommand, alias = "acc")]
Account(AccountManage),
/// Create an empty workspace
@@ -96,7 +109,19 @@ enum AccountManage {
Add(AccountAddArgs),
/// Remove a account from this computer
+ #[command(alias = "rm")]
Remove(AccountRemoveArgs),
+
+ /// List all accounts in this computer
+ #[command(alias = "ls")]
+ List(AccountListArgs),
+
+ /// Set current local workspace account
+ As(SetLocalWorkspaceAccountArgs),
+
+ /// Move private key file to account
+ #[command(alias = "mvkey", alias = "mvk")]
+ MoveKey(MoveKeyToAccountArgs),
}
#[derive(Subcommand, Debug)]
@@ -107,36 +132,85 @@ enum SheetManage {
}
#[derive(Parser, Debug)]
+struct CreateWorkspaceArgs {
+ /// Show help information
+ #[arg(short, long)]
+ help: bool,
+
+ /// Workspace directory path
+ path: PathBuf,
+
+ /// Force create, ignore files in the directory
+ #[arg(short, long)]
+ force: bool,
+}
+
+#[derive(Parser, Debug)]
+struct InitWorkspaceArgs {
+ /// Show help information
+ #[arg(short, long)]
+ help: bool,
+
+ /// Force create, ignore files in the directory
+ #[arg(short, long)]
+ force: bool,
+}
+
+#[derive(Parser, Debug)]
+struct HereArgs {
+ /// Show help information
+ #[arg(short, long)]
+ help: bool,
+}
+
+#[derive(Parser, Debug)]
struct AccountAddArgs {
- /// Member name
- member_name: String,
+ /// Show help information
+ #[arg(short, long)]
+ help: bool,
+
+ /// Account name
+ account_name: String,
}
#[derive(Parser, Debug)]
struct AccountRemoveArgs {
- /// Member name
- member_name: String,
+ /// Show help information
+ #[arg(short, long)]
+ help: bool,
+
+ /// Account name
+ account_name: String,
}
#[derive(Parser, Debug)]
-struct CreateWorkspaceArgs {
+struct AccountListArgs {
/// Show help information
#[arg(short, long)]
help: bool,
}
#[derive(Parser, Debug)]
-struct InitWorkspaceArgs {
+struct SetLocalWorkspaceAccountArgs {
/// Show help information
#[arg(short, long)]
help: bool,
+
+ /// Account name
+ account_name: String,
}
#[derive(Parser, Debug)]
-struct HereArgs {
+struct MoveKeyToAccountArgs {
/// Show help information
#[arg(short, long)]
help: bool,
+
+ /// Account name
+ account_name: String,
+
+ /// Private key file path
+ key_path: PathBuf,
}
#[derive(Parser, Debug)]
@@ -220,13 +294,56 @@ async fn main() {
};
match parser.command {
- JustEnoughVcsWorkspaceCommand::Account(account_manage) => match account_manage {
- AccountManage::Help => {
- println!("{}", md(t!("jv.account")));
+ JustEnoughVcsWorkspaceCommand::Account(account_manage) => {
+ let user_dir = match UserDirectory::current_doc_dir() {
+ Some(dir) => dir,
+ None => {
+ eprintln!("{}", t!("jv.fail.account.no_user_dir"));
+ return;
+ }
+ };
+
+ match account_manage {
+ AccountManage::Help => {
+ println!("{}", md(t!("jv.account")));
+ }
+ AccountManage::Add(account_add_args) => {
+ if account_add_args.help {
+ println!("{}", md(t!("jv.account")));
+ return;
+ }
+ jv_account_add(user_dir, account_add_args).await;
+ }
+ AccountManage::Remove(account_remove_args) => {
+ if account_remove_args.help {
+ println!("{}", md(t!("jv.account")));
+ return;
+ }
+ jv_account_remove(user_dir, account_remove_args).await;
+ }
+ AccountManage::List(account_list_args) => {
+ if account_list_args.help {
+ println!("{}", md(t!("jv.account")));
+ return;
+ }
+ jv_account_list(user_dir, account_list_args).await;
+ }
+ AccountManage::As(set_local_workspace_account_args) => {
+ if set_local_workspace_account_args.help {
+ println!("{}", md(t!("jv.account")));
+ return;
+ }
+ jv_account_as(user_dir, set_local_workspace_account_args).await;
+ }
+ AccountManage::MoveKey(move_key_to_account_args) => {
+ if move_key_to_account_args.help {
+ println!("{}", md(t!("jv.account")));
+ return;
+ }
+ jv_account_move_key(user_dir, move_key_to_account_args).await;
+ }
}
- AccountManage::Add(account_add_args) => todo!(),
- AccountManage::Remove(account_remove_args) => todo!(),
- },
+ }
JustEnoughVcsWorkspaceCommand::Create(create_workspace_args) => {
if create_workspace_args.help {
println!("{}", md(t!("jv.create")));
@@ -320,12 +437,53 @@ async fn main() {
}
}
-async fn jv_create(_args: CreateWorkspaceArgs) {
- todo!()
+async fn jv_create(args: CreateWorkspaceArgs) {
+ let path = args.path;
+
+ if !args.force && path.exists() && !is_directory_empty(&path).await {
+ eprintln!("{}", t!("jv.fail.init_create_dir_not_empty").trim());
+ return;
+ }
+
+ match LocalWorkspace::setup_local_workspace(path).await {
+ Ok(_) => {
+ println!("{}", t!("jv.success.create"));
+ }
+ Err(e) => {
+ eprintln!("{}", t!("jv.fail.create", error = e.to_string()));
+ }
+ }
}
-async fn jv_init(_args: InitWorkspaceArgs) {
- todo!()
+async fn jv_init(args: InitWorkspaceArgs) {
+ let path = match current_dir() {
+ Ok(path) => path,
+ Err(e) => {
+ eprintln!("{}", t!("jv.fail.get_current_dir", error = e.to_string()));
+ return;
+ }
+ };
+
+ if !args.force && path.exists() && !is_directory_empty(&path).await {
+ eprintln!("{}", t!("jv.fail.init_create_dir_not_empty").trim());
+ return;
+ }
+
+ match LocalWorkspace::setup_local_workspace(path).await {
+ Ok(_) => {
+ println!("{}", t!("jv.success.init"));
+ }
+ Err(e) => {
+ eprintln!("{}", t!("jv.fail.init", error = e.to_string()));
+ }
+ }
+}
+
+async fn is_directory_empty(path: &PathBuf) -> bool {
+ match fs::read_dir(path).await {
+ Ok(mut entries) => entries.next_entry().await.unwrap().is_none(),
+ Err(_) => false,
+ }
}
async fn jv_here(_args: HereArgs) {
@@ -356,6 +514,132 @@ async fn jv_import(_args: ImportFileArgs) {
todo!()
}
+async fn jv_account_add(user_dir: UserDirectory, args: AccountAddArgs) {
+ let member = Member::new(args.account_name.clone());
+
+ match user_dir.register_account(member).await {
+ Ok(_) => {
+ println!(
+ "{}",
+ t!("jv.success.account.add", account = args.account_name)
+ );
+ }
+ Err(_) => {
+ eprintln!("{}", t!("jv.fail.account.add", account = args.account_name));
+ }
+ }
+}
+
+async fn jv_account_remove(user_dir: UserDirectory, args: AccountRemoveArgs) {
+ match user_dir.remove_account(&args.account_name) {
+ Ok(_) => {
+ println!(
+ "{}",
+ t!("jv.success.account.remove", account = args.account_name)
+ );
+ }
+ Err(_) => {
+ eprintln!(
+ "{}",
+ t!("jv.fail.account.remove", account = args.account_name)
+ );
+ }
+ }
+}
+
+async fn jv_account_list(user_dir: UserDirectory, _args: AccountListArgs) {
+ match user_dir.account_ids() {
+ Ok(account_ids) => {
+ println!(
+ "{}",
+ md(t!(
+ "jv.success.account.list.header",
+ num = account_ids.len()
+ ))
+ );
+
+ let mut i = 0;
+ for account_id in account_ids {
+ println!("{}. {} {}", i + 1, &account_id, {
+ if user_dir.has_private_key(&account_id) {
+ t!("jv.success.account.list.status_has_key")
+ } else {
+ std::borrow::Cow::Borrowed("")
+ }
+ });
+ i += 1;
+ }
+ }
+ Err(_) => {
+ eprintln!("{}", t!("jv.fail.account.list"));
+ }
+ }
+}
+
+async fn jv_account_as(user_dir: UserDirectory, args: SetLocalWorkspaceAccountArgs) {
+ // Account exist
+ let Ok(member) = user_dir.account(&args.account_name).await else {
+ eprintln!(
+ "{}",
+ t!("jv.fail.account.not_found", account = args.account_name)
+ );
+ return;
+ };
+
+ let Some(_local_dir) = current_local_path() else {
+ eprintln!("{}", t!("jv.fail.workspace_not_found").trim());
+ return;
+ };
+
+ let Ok(mut local_cfg) = LocalConfig::read().await else {
+ eprintln!("{}", md(t!("jv.fail.read_cfg")));
+ return;
+ };
+
+ local_cfg.set_current_account(member.id());
+
+ let Ok(_) = LocalConfig::write(&local_cfg).await else {
+ eprintln!("{}", t!("jv.fail.write_cfg").trim());
+ return;
+ };
+
+ println!(
+ "{}",
+ t!("jv.success.account.as", account = member.id()).trim()
+ );
+}
+
+async fn jv_account_move_key(user_dir: UserDirectory, args: MoveKeyToAccountArgs) {
+ // Key file exist
+ if !args.key_path.exists() {
+ eprintln!(
+ "{}",
+ t!("jv.fail.path_not_found", path = args.key_path.display())
+ );
+ return;
+ }
+
+ // Account exist
+ let Ok(_member) = user_dir.account(&args.account_name).await else {
+ eprintln!(
+ "{}",
+ t!("jv.fail.account.not_found", account = args.account_name)
+ );
+ return;
+ };
+
+ // Rename key file
+ match fs::rename(
+ args.key_path,
+ user_dir.account_private_key_path(&args.account_name),
+ )
+ .await
+ {
+ Ok(_) => println!("{}", t!("jv.success.account.move_key")),
+ Err(_) => eprintln!("{}", t!("jv.fail.account.move_key")),
+ }
+}
+
async fn jv_direct(args: DirectArgs) {
let pool = client_registry::client_action_pool();
let upstream = match SocketAddr::from_str(&args.upstream) {