From 949c6459aa7683453a7160423b689ceadb08954b Mon Sep 17 00:00:00 2001 From: DanConwayDev Date: Wed, 4 Sep 2024 08:04:48 +0100 Subject: refactor: organise into lib and bin structure the make the code more readable this commit just moves the files, the next commit should fix the imports --- src/sub_commands/init.rs | 385 ----------------------------------------------- 1 file changed, 385 deletions(-) delete mode 100644 src/sub_commands/init.rs (limited to 'src/sub_commands/init.rs') diff --git a/src/sub_commands/init.rs b/src/sub_commands/init.rs deleted file mode 100644 index 5b7e03d..0000000 --- a/src/sub_commands/init.rs +++ /dev/null @@ -1,385 +0,0 @@ -use std::collections::HashMap; - -use anyhow::{Context, Result}; -use nostr::{nips::nip01::Coordinate, FromBech32, PublicKey, ToBech32}; -use nostr_sdk::Kind; - -use super::send::send_events; -#[cfg(not(test))] -use crate::client::Client; -#[cfg(test)] -use crate::client::MockConnect; -use crate::{ - cli::Cli, - cli_interactor::{Interactor, InteractorPrompt, PromptInputParms}, - client::{fetching_with_report, get_repo_ref_from_cache, Connect}, - git::{convert_clone_url_to_https, Repo, RepoActions}, - login, - repo_ref::{ - extract_pks, get_repo_config_from_yaml, save_repo_config_to_yaml, - try_and_get_repo_coordinates, RepoRef, - }, -}; - -#[derive(Debug, clap::Args)] -pub struct SubCommandArgs { - #[clap(short, long)] - /// name of repository - title: Option, - #[clap(short, long)] - /// optional description - description: Option, - #[clap(long)] - /// git server url users can clone from - clone_url: Vec, - #[clap(short, long, value_parser, num_args = 1..)] - /// homepage - web: Vec, - #[clap(short, long, value_parser, num_args = 1..)] - /// relays contributors push patches and comments to - relays: Vec, - #[clap(short, long, value_parser, num_args = 1..)] - /// npubs of other maintainers - other_maintainers: Vec, - #[clap(long)] - /// usually root commit but will be more recent commit for forks - earliest_unique_commit: Option, - #[clap(short, long)] - /// shortname with no spaces or special characters - identifier: Option, -} - -#[allow(clippy::too_many_lines)] -pub async fn launch(cli_args: &Cli, args: &SubCommandArgs) -> Result<()> { - let git_repo = Repo::discover().context("cannot find a git repository")?; - let git_repo_path = git_repo.get_path()?; - - let root_commit = git_repo - .get_root_commit() - .context("failed to get root commit of the repository")?; - - // TODO: check for empty repo - // TODO: check for existing maintaiers file - - #[cfg(not(test))] - let mut client = Client::default(); - #[cfg(test)] - let mut client = ::default(); - - let repo_coordinates = if let Ok(repo_coordinates) = - try_and_get_repo_coordinates(&git_repo, &client, false).await - { - Some(repo_coordinates) - } else { - None - }; - - let repo_ref = if let Some(repo_coordinates) = repo_coordinates { - fetching_with_report(git_repo_path, &client, &repo_coordinates).await?; - Some(get_repo_ref_from_cache(git_repo_path, &repo_coordinates).await?) - } else { - None - }; - - let (signer, user_ref) = login::launch( - &git_repo, - &cli_args.bunker_uri, - &cli_args.bunker_app_key, - &cli_args.nsec, - &cli_args.password, - Some(&client), - false, - false, - ) - .await?; - - let repo_config_result = get_repo_config_from_yaml(&git_repo); - // TODO: check for other claims - - let name = match &args.title { - Some(t) => t.clone(), - None => Interactor::default().input( - PromptInputParms::default() - .with_prompt("name") - .with_default(if let Some(repo_ref) = &repo_ref { - repo_ref.name.clone() - } else { - String::new() - }), - )?, - }; - - let identifier = match &args.identifier { - Some(t) => t.clone(), - None => Interactor::default().input( - PromptInputParms::default() - .with_prompt("identifier") - .with_default(if let Some(repo_ref) = &repo_ref { - repo_ref.identifier.clone() - } else { - let fallback = name - .clone() - .replace(' ', "-") - .chars() - .map(|c| { - if c.is_ascii_alphanumeric() || c.eq(&'/') { - c - } else { - '-' - } - }) - .collect(); - if let Ok(config) = &repo_config_result { - if let Some(identifier) = &config.identifier { - identifier.to_string() - } else { - fallback - } - } else { - fallback - } - }), - )?, - }; - - let description = match &args.description { - Some(t) => t.clone(), - None => Interactor::default().input( - PromptInputParms::default() - .with_prompt("description") - .with_default(if let Some(repo_ref) = &repo_ref { - repo_ref.description.clone() - } else { - String::new() - }), - )?, - }; - - let git_server = if args.clone_url.is_empty() { - Interactor::default() - .input( - PromptInputParms::default() - .with_prompt("clone url (for fetch)") - .with_default(if let Some(repo_ref) = &repo_ref { - repo_ref.git_server.clone().join(" ") - } else if let Ok(url) = git_repo.get_origin_url() { - if let Ok(fetch_url) = convert_clone_url_to_https(&url) { - fetch_url - } else { - // local repo or custom protocol - url - } - } else { - String::new() - }), - )? - .split(' ') - .map(std::string::ToString::to_string) - .collect() - } else { - args.clone_url.clone() - }; - - let web: Vec = if args.web.is_empty() { - Interactor::default() - .input( - PromptInputParms::default() - .with_prompt("web") - .optional() - .with_default(if let Some(repo_ref) = &repo_ref { - repo_ref.web.clone().join(" ") - } else { - format!("https://gitworkshop.dev/repo/{}", &identifier) - }), - )? - .split(' ') - .map(std::string::ToString::to_string) - .collect() - } else { - args.web.clone() - }; - - let maintainers: Vec = { - let mut dont_ask = !args.other_maintainers.is_empty(); - let mut maintainers_string = if !args.other_maintainers.is_empty() { - [args.other_maintainers.clone()].concat().join(" ") - } else if repo_ref.is_none() && repo_config_result.is_err() { - signer.public_key().await?.to_bech32()? - } else { - let maintainers = if let Ok(config) = &repo_config_result { - config.maintainers.clone() - } else if let Some(repo_ref) = &repo_ref { - repo_ref - .maintainers - .clone() - .iter() - .map(|k| k.to_bech32().unwrap()) - .collect() - } else { - //unreachable - vec![signer.public_key().await?.to_bech32()?] - }; - // add current user if not present - if maintainers.iter().any(|m| { - if let Ok(m_pubkey) = PublicKey::from_bech32(m) { - user_ref.public_key.eq(&m_pubkey) - } else { - false - } - }) { - maintainers.join(" ") - } else { - [maintainers, vec![signer.public_key().await?.to_bech32()?]] - .concat() - .join(" ") - } - }; - 'outer: loop { - if !dont_ask { - println!("{}", &maintainers_string); - maintainers_string = Interactor::default().input( - PromptInputParms::default() - .with_prompt("maintainers") - .with_default(maintainers_string), - )?; - } - let mut maintainers: Vec = vec![]; - for m in maintainers_string.split(' ') { - if let Ok(m_pubkey) = PublicKey::from_bech32(m) { - maintainers.push(m_pubkey); - } else { - println!("not a valid set of npubs seperated by a space"); - dont_ask = false; - continue 'outer; - } - } - // add current user incase removed - if !maintainers.iter().any(|m| user_ref.public_key.eq(m)) { - maintainers.push(signer.public_key().await?); - } - break maintainers; - } - }; - - // TODO: check if relays are free to post to so contributors can submit patches - // TODO: recommend some reliable free ones - let relays: Vec = if args.relays.is_empty() { - Interactor::default() - .input( - PromptInputParms::default() - .with_prompt("relays") - .with_default(if let Ok(config) = &repo_config_result { - config.relays.clone().join(" ") - } else if let Some(repo_ref) = &repo_ref { - repo_ref.relays.clone().join(" ") - } else { - user_ref.relays.write().join(" ") - }), - )? - .split(' ') - .map(std::string::ToString::to_string) - .collect() - } else { - args.relays.clone() - }; - - let earliest_unique_commit = match &args.earliest_unique_commit { - Some(t) => t.clone(), - None => { - let mut earliest_unique_commit = if let Some(repo_ref) = &repo_ref { - repo_ref.root_commit.clone() - } else { - root_commit.to_string() - }; - loop { - earliest_unique_commit = Interactor::default().input( - PromptInputParms::default() - .with_prompt("earliest unique commit") - .with_default(earliest_unique_commit.clone()), - )?; - if let Ok(exists) = git_repo.does_commit_exist(&earliest_unique_commit) { - if exists { - break earliest_unique_commit; - } - println!("commit does not exist on current repository"); - } else { - println!("commit id not formatted correctly"); - } - if earliest_unique_commit.len().ne(&40) { - println!("commit id must be 40 characters long"); - } - } - } - }; - - println!("publishing repostory reference..."); - - let repo_ref = RepoRef { - identifier: identifier.clone(), - name, - description, - root_commit: earliest_unique_commit, - git_server, - web, - relays: relays.clone(), - maintainers: maintainers.clone(), - events: HashMap::new(), - }; - let repo_event = repo_ref.to_event(&signer).await?; - - client.set_signer(signer).await; - - send_events( - &client, - git_repo_path, - vec![repo_event], - user_ref.relays.write(), - relays.clone(), - !cli_args.disable_cli_spinners, - false, - ) - .await?; - - git_repo.save_git_config_item( - "nostr.repo", - &Coordinate { - kind: Kind::GitRepoAnnouncement, - public_key: user_ref.public_key, - identifier: identifier.clone(), - relays: vec![], - } - .to_bech32()?, - false, - )?; - - // if yaml file doesnt exist or needs updating - if match &repo_config_result { - Ok(config) => { - ! as Clone>::clone(&config.identifier) - .unwrap_or_default() - .eq(&identifier) - || !extract_pks(config.maintainers.clone())?.eq(&maintainers) - || !config.relays.eq(&relays) - } - Err(_) => true, - } { - save_repo_config_to_yaml( - &git_repo, - identifier.clone(), - maintainers.clone(), - relays.clone(), - )?; - println!( - "maintainers.yaml {}. commit and push.", - if repo_config_result.is_err() { - "created" - } else { - "updated" - } - ); - println!( - "this optional file helps in identifying who the maintainers are over time through the commit history" - ); - } - Ok(()) -} -- cgit v1.2.3