upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/src/bin/git_remote_nostr/list.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/bin/git_remote_nostr/list.rs')
-rw-r--r--src/bin/git_remote_nostr/list.rs92
1 files changed, 68 insertions, 24 deletions
diff --git a/src/bin/git_remote_nostr/list.rs b/src/bin/git_remote_nostr/list.rs
index 959b8c8..378a124 100644
--- a/src/bin/git_remote_nostr/list.rs
+++ b/src/bin/git_remote_nostr/list.rs
@@ -5,14 +5,13 @@ use anyhow::{anyhow, Context, Result};
5use auth_git2::GitAuthenticator; 5use auth_git2::GitAuthenticator;
6use client::get_state_from_cache; 6use client::get_state_from_cache;
7use git::RepoActions; 7use git::RepoActions;
8use git_events::{event_to_cover_letter, get_commit_id_from_patch};
9use ngit::{ 8use ngit::{
10 client, 9 client,
11 git::{ 10 git::{
12 self, 11 self,
13 nostr_url::{CloneUrl, NostrUrlDecoded, ServerProtocol}, 12 nostr_url::{CloneUrl, NostrUrlDecoded, ServerProtocol},
14 }, 13 },
15 git_events, 14 git_events::event_to_cover_letter,
16 login::get_curent_user, 15 login::get_curent_user,
17 repo_ref, 16 repo_ref,
18}; 17};
@@ -20,6 +19,7 @@ use nostr_sdk::hashes::sha1::Hash as Sha1Hash;
20use repo_ref::RepoRef; 19use repo_ref::RepoRef;
21 20
22use crate::{ 21use crate::{
22 fetch::{fetch_from_git_server, make_commits_for_proposal},
23 git::Repo, 23 git::Repo,
24 utils::{ 24 utils::{
25 fetch_or_list_error_is_not_authentication_failure, get_open_proposals, 25 fetch_or_list_error_is_not_authentication_failure, get_open_proposals,
@@ -88,6 +88,61 @@ pub async fn run_list(
88 88
89 state.retain(|k, _| !k.starts_with("refs/heads/pr/")); 89 state.retain(|k, _| !k.starts_with("refs/heads/pr/"));
90 90
91 let proposals_state =
92 get_open_proposals_state(&term, git_repo, repo_ref, decoded_nostr_url, &remote_states)
93 .await?;
94
95 state.extend(proposals_state);
96
97 // TODO 'for push' should we check with the git servers to see if any of them
98 // allow push from the user?
99 for (name, value) in state {
100 if value.starts_with("ref: ") {
101 if !for_push {
102 println!("{} {name}", value.replace("ref: ", "@"));
103 }
104 } else {
105 println!("{value} {name}");
106 }
107 }
108
109 println!();
110 Ok(remote_states)
111}
112
113async fn get_open_proposals_state(
114 term: &console::Term,
115 git_repo: &Repo,
116 repo_ref: &RepoRef,
117 decoded_nostr_url: &NostrUrlDecoded,
118 remote_states: &HashMap<String, HashMap<String, String>>,
119) -> Result<HashMap<String, String>> {
120 // we cannot use commit_id in the latest patch in a proposal because:
121 // 1) the `commit` tag is optional
122 // 2) if the commit tag is wrong, it will cause errors which stop clone from
123 // working
124
125 // without trusting commit_id we must apply each patch which requires the oid of
126 // the parent so we much do a fetch
127 for (git_server_url, oids_from_git_servers) in remote_states {
128 if fetch_from_git_server(
129 git_repo,
130 &oids_from_git_servers
131 .values()
132 .filter(|v| !v.starts_with("ref: "))
133 .cloned()
134 .collect::<Vec<String>>(),
135 git_server_url,
136 decoded_nostr_url,
137 term,
138 )
139 .is_ok()
140 {
141 break;
142 }
143 }
144
145 let mut state = HashMap::new();
91 let open_proposals = get_open_proposals(git_repo, repo_ref).await?; 146 let open_proposals = get_open_proposals(git_repo, repo_ref).await?;
92 let current_user = get_curent_user(git_repo)?; 147 let current_user = get_curent_user(git_repo)?;
93 for (_, (proposal, patches)) in open_proposals { 148 for (_, (proposal, patches)) in open_proposals {
@@ -102,32 +157,21 @@ pub async fn run_list(
102 } else { 157 } else {
103 branch_name 158 branch_name
104 }; 159 };
105 if let Some(patch) = patches.first() { 160 match make_commits_for_proposal(git_repo, repo_ref, &patches) {
106 // TODO this isn't resilient because the commit id stated may not be correct 161 Ok(tip) => {
107 // we will need to check whether the commit id exists in the repo or apply the 162 state.insert(format!("refs/heads/{branch_name}"), tip);
108 // proposal and each patch to check
109 if let Ok(commit_id) = get_commit_id_from_patch(patch) {
110 state.insert(format!("refs/heads/{branch_name}"), commit_id);
111 } 163 }
112 } 164 Err(error) => {
113 } 165 let _ = term.write_line(
114 } 166 format!("WARNING: cannot fetch branch {branch_name} error: {error}")
115 } 167 .as_str(),
116 168 );
117 // TODO 'for push' should we check with the git servers to see if any of them 169 }
118 // allow push from the user? 170 };
119 for (name, value) in state {
120 if value.starts_with("ref: ") {
121 if !for_push {
122 println!("{} {name}", value.replace("ref: ", "@"));
123 } 171 }
124 } else {
125 println!("{value} {name}");
126 } 172 }
127 } 173 }
128 174 Ok(state)
129 println!();
130 Ok(remote_states)
131} 175}
132 176
133pub fn list_from_remotes( 177pub fn list_from_remotes(