diff options
| author | DanConwayDev <DanConwayDev@protonmail.com> | 2025-09-10 16:32:18 +0100 |
|---|---|---|
| committer | DanConwayDev <DanConwayDev@protonmail.com> | 2025-09-10 16:32:18 +0100 |
| commit | 732567f85383782851d3c0dd43283d29df0c098f (patch) | |
| tree | 706d3088eef39a8d701c8360ce0291e5f615abc2 /src/bin/ngit/sub_commands/init.rs | |
| parent | 8527646022abdb290222a45314d090eef0871cae (diff) | |
fix(init): when existing origin matches tip
when an existing origin exists and local branch is up-to-date
`git push` wont successfully publish state event and push refs to
other git servers listed.
we now publish the state event during this init function and use
sync to push all refs in state are to all git servers.
Diffstat (limited to 'src/bin/ngit/sub_commands/init.rs')
| -rw-r--r-- | src/bin/ngit/sub_commands/init.rs | 126 |
1 files changed, 118 insertions, 8 deletions
diff --git a/src/bin/ngit/sub_commands/init.rs b/src/bin/ngit/sub_commands/init.rs index 98daee4..1b8268c 100644 --- a/src/bin/ngit/sub_commands/init.rs +++ b/src/bin/ngit/sub_commands/init.rs | |||
| @@ -15,12 +15,14 @@ use ngit::{ | |||
| 15 | PromptChoiceParms, PromptConfirmParms, multi_select_with_custom_value, | 15 | PromptChoiceParms, PromptConfirmParms, multi_select_with_custom_value, |
| 16 | show_multi_input_prompt_success, | 16 | show_multi_input_prompt_success, |
| 17 | }, | 17 | }, |
| 18 | client::{Params, send_events}, | 18 | client::{Params, get_state_from_cache, send_events}, |
| 19 | git::nostr_url::{CloneUrl, NostrUrlDecoded}, | 19 | git::nostr_url::{CloneUrl, NostrUrlDecoded}, |
| 20 | list::list_from_remote, | ||
| 20 | repo_ref::{ | 21 | repo_ref::{ |
| 21 | detect_existing_grasp_servers, extract_npub, extract_pks, | 22 | detect_existing_grasp_servers, extract_npub, extract_pks, |
| 22 | format_grasp_server_url_as_relay_url, normalize_grasp_server_url, save_repo_config_to_yaml, | 23 | format_grasp_server_url_as_relay_url, normalize_grasp_server_url, save_repo_config_to_yaml, |
| 23 | }, | 24 | }, |
| 25 | repo_state::RepoState, | ||
| 24 | }; | 26 | }; |
| 25 | use nostr::{ | 27 | use nostr::{ |
| 26 | FromBech32, PublicKey, ToBech32, | 28 | FromBech32, PublicKey, ToBech32, |
| @@ -754,12 +756,67 @@ pub async fn launch(cli_args: &Cli, args: &SubCommandArgs) -> Result<()> { | |||
| 754 | }; | 756 | }; |
| 755 | let repo_event = repo_ref.to_event(&signer).await?; | 757 | let repo_event = repo_ref.to_event(&signer).await?; |
| 756 | 758 | ||
| 759 | let nostr_url_decoded = repo_ref.to_nostr_git_url(&Some(&git_repo)); | ||
| 760 | |||
| 761 | let mut events = vec![repo_event]; | ||
| 762 | |||
| 763 | let (need_push, need_sync) = if std::env::var("NGITTEST").is_ok() || no_state { | ||
| 764 | // dont push or sync during tests as git-remote-nostr isn't installed during | ||
| 765 | // ngit binary tests | ||
| 766 | (false, false) | ||
| 767 | } else if let Ok(nostr_state) = | ||
| 768 | &get_state_from_cache(Some(git_repo.get_path()?), &repo_ref).await | ||
| 769 | { | ||
| 770 | // issue fresh state event with same state to all (inc. new) repo relays | ||
| 771 | let new_state_event = RepoState::build( | ||
| 772 | repo_ref.identifier.clone(), | ||
| 773 | nostr_state.state.clone(), | ||
| 774 | &signer, | ||
| 775 | ) | ||
| 776 | .await? | ||
| 777 | .event; | ||
| 778 | events.push(new_state_event); | ||
| 779 | println!("publishing repostory state to nostr..."); | ||
| 780 | (false, true) | ||
| 781 | } else if let Ok(remote) = git_repo.git_repo.find_remote("origin") { | ||
| 782 | if let Some(url) = remote.url() { | ||
| 783 | // issue a state event with origin state, to all (inc. new) repo relays | ||
| 784 | if let Ok(mut origin_state) = | ||
| 785 | list_from_remote(&Term::stdout(), &git_repo, url, &nostr_url_decoded, false) | ||
| 786 | { | ||
| 787 | origin_state.retain(|key, _| { | ||
| 788 | key.starts_with("refs/heads/") | ||
| 789 | || key.starts_with("refs/tags/") | ||
| 790 | || key.starts_with("HEAD") | ||
| 791 | }); | ||
| 792 | // TODO ngit sync will error if any of these remote refs are not available | ||
| 793 | // locally | ||
| 794 | let new_state_event = | ||
| 795 | RepoState::build(repo_ref.identifier.clone(), origin_state, &signer) | ||
| 796 | .await? | ||
| 797 | .event; | ||
| 798 | events.push(new_state_event); | ||
| 799 | println!("publishing repostory state to nostr..."); | ||
| 800 | (false, true) | ||
| 801 | } else { | ||
| 802 | // cant reach existing origin so just try push | ||
| 803 | (true, false) | ||
| 804 | } | ||
| 805 | } else { | ||
| 806 | // origin never connected so just try push | ||
| 807 | (true, false) | ||
| 808 | } | ||
| 809 | } else { | ||
| 810 | // no origin so we need to just push | ||
| 811 | (true, false) | ||
| 812 | }; | ||
| 813 | |||
| 757 | client.set_signer(signer).await; | 814 | client.set_signer(signer).await; |
| 758 | 815 | ||
| 759 | send_events( | 816 | send_events( |
| 760 | &client, | 817 | &client, |
| 761 | Some(git_repo_path), | 818 | Some(git_repo_path), |
| 762 | vec![repo_event], | 819 | events, |
| 763 | user_ref.relays.write(), | 820 | user_ref.relays.write(), |
| 764 | relays.clone(), | 821 | relays.clone(), |
| 765 | !cli_args.disable_cli_spinners, | 822 | !cli_args.disable_cli_spinners, |
| @@ -783,7 +840,7 @@ pub async fn launch(cli_args: &Cli, args: &SubCommandArgs) -> Result<()> { | |||
| 783 | )?; | 840 | )?; |
| 784 | 841 | ||
| 785 | // set origin remote | 842 | // set origin remote |
| 786 | let nostr_url = repo_ref.to_nostr_git_url(&Some(&git_repo)).to_string(); | 843 | let nostr_url = nostr_url_decoded.to_string(); |
| 787 | 844 | ||
| 788 | if git_repo.git_repo.find_remote("origin").is_ok() { | 845 | if git_repo.git_repo.find_remote("origin").is_ok() { |
| 789 | git_repo.git_repo.remote_set_url("origin", &nostr_url)?; | 846 | git_repo.git_repo.remote_set_url("origin", &nostr_url)?; |
| @@ -792,12 +849,9 @@ pub async fn launch(cli_args: &Cli, args: &SubCommandArgs) -> Result<()> { | |||
| 792 | } | 849 | } |
| 793 | println!("set remote origin to nostr url"); | 850 | println!("set remote origin to nostr url"); |
| 794 | 851 | ||
| 795 | if std::env::var("NGITTEST").is_err() { | 852 | if need_push { |
| 796 | // ignore during tests as git-remote-nostr isn't installed during ngit binary | ||
| 797 | // tests | ||
| 798 | |||
| 799 | if selected_grasp_servers.is_empty() { | 853 | if selected_grasp_servers.is_empty() { |
| 800 | println!("running `git push` to publish your repository data"); | 854 | println!("running `ngit push` to publish your repository data"); |
| 801 | } else { | 855 | } else { |
| 802 | let countdown_start = 5; | 856 | let countdown_start = 5; |
| 803 | println!( | 857 | println!( |
| @@ -818,6 +872,31 @@ pub async fn launch(cli_args: &Cli, args: &SubCommandArgs) -> Result<()> { | |||
| 818 | ); | 872 | ); |
| 819 | } | 873 | } |
| 820 | } | 874 | } |
| 875 | if need_sync { | ||
| 876 | if selected_grasp_servers.is_empty() { | ||
| 877 | println!( | ||
| 878 | "running `ngit sync` to ensure your repository data is available on repository git servers" | ||
| 879 | ); | ||
| 880 | } else { | ||
| 881 | let countdown_start = 5; | ||
| 882 | println!( | ||
| 883 | "waiting {countdown_start}s for any new grasp servers to create your repo before we sync your data" | ||
| 884 | ); | ||
| 885 | let term = Term::stdout(); | ||
| 886 | for i in (1..=countdown_start).rev() { | ||
| 887 | term.write_line(format!("\rrunning `ngit sync` in {i}s").as_str())?; | ||
| 888 | thread::sleep(Duration::new(1, 0)); // Sleep for 1 second | ||
| 889 | term.clear_last_lines(1)?; | ||
| 890 | } | ||
| 891 | term.flush().unwrap(); // Ensure the output is flushed to the terminal | ||
| 892 | } | ||
| 893 | |||
| 894 | if let Err(err) = run_ngit_sync() { | ||
| 895 | println!( | ||
| 896 | "your repository announcement was published to nostr but 'ngit sync' exited with an error: {err}" | ||
| 897 | ); | ||
| 898 | } | ||
| 899 | } | ||
| 821 | 900 | ||
| 822 | // println!( | 901 | // println!( |
| 823 | // "any remote branches beginning with `pr/` are open PRs from contributors. | 902 | // "any remote branches beginning with `pr/` are open PRs from contributors. |
| @@ -951,3 +1030,34 @@ fn push_main_or_master_branch(git_repo: &Repo) -> Result<()> { | |||
| 951 | bail!("git push process exited with an error: {}", exit_status); | 1030 | bail!("git push process exited with an error: {}", exit_status); |
| 952 | } | 1031 | } |
| 953 | } | 1032 | } |
| 1033 | |||
| 1034 | fn run_ngit_sync() -> Result<()> { | ||
| 1035 | println!("========================================"); | ||
| 1036 | println!(" NGIT SYNC COMMAND "); | ||
| 1037 | println!("========================================"); | ||
| 1038 | |||
| 1039 | let command = "ngit"; | ||
| 1040 | let args = ["sync"]; | ||
| 1041 | |||
| 1042 | // Spawn the process | ||
| 1043 | let mut child = Command::new(command) | ||
| 1044 | .args(args) | ||
| 1045 | .stdout(Stdio::inherit()) // Redirect stdout to the console | ||
| 1046 | .stderr(Stdio::inherit()) // Redirect stderr to the console | ||
| 1047 | .spawn() | ||
| 1048 | .context("Failed to start ngit sync process")?; | ||
| 1049 | |||
| 1050 | // Wait for the process to finish | ||
| 1051 | let exit_status = child.wait().context("Failed to start ngit sync process")?; | ||
| 1052 | |||
| 1053 | println!("========================================"); | ||
| 1054 | println!(" END OF NGIT SYNC OUTPUT"); | ||
| 1055 | println!("========================================"); | ||
| 1056 | |||
| 1057 | // Check the exit status | ||
| 1058 | if exit_status.success() { | ||
| 1059 | Ok(()) | ||
| 1060 | } else { | ||
| 1061 | bail!("ngit sync process exited with an error: {}", exit_status); | ||
| 1062 | } | ||
| 1063 | } | ||