upleb.uk

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

summaryrefslogtreecommitdiff
path: root/src/bin
diff options
context:
space:
mode:
Diffstat (limited to 'src/bin')
-rw-r--r--src/bin/git_remote_nostr/list.rs138
-rw-r--r--src/bin/git_remote_nostr/main.rs18
-rw-r--r--src/bin/git_remote_nostr/push.rs16
3 files changed, 135 insertions, 37 deletions
diff --git a/src/bin/git_remote_nostr/list.rs b/src/bin/git_remote_nostr/list.rs
index 097f070..26f699d 100644
--- a/src/bin/git_remote_nostr/list.rs
+++ b/src/bin/git_remote_nostr/list.rs
@@ -1,25 +1,35 @@
1use core::str; 1use core::str;
2use std::collections::HashMap; 2use std::collections::HashMap;
3 3
4use anyhow::{Context, Result}; 4use 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}; 8use git_events::{event_to_cover_letter, get_commit_id_from_patch};
9use ngit::{client, git, git_events, login::get_curent_user, repo_ref}; 9use ngit::{
10 client,
11 git::{
12 self,
13 nostr_url::{CloneUrl, NostrUrlDecoded, ServerProtocol},
14 },
15 git_events,
16 login::get_curent_user,
17 repo_ref,
18};
10use nostr_sdk::hashes::sha1::Hash as Sha1Hash; 19use nostr_sdk::hashes::sha1::Hash as Sha1Hash;
11use repo_ref::RepoRef; 20use repo_ref::RepoRef;
12 21
13use crate::{ 22use crate::{
14 git::Repo, 23 git::Repo,
15 utils::{ 24 utils::{
16 get_open_proposals, get_short_git_server_name, switch_clone_url_between_ssh_and_https, 25 get_open_proposals, get_read_protocols_to_try, get_short_git_server_name, join_with_and,
17 }, 26 },
18}; 27};
19 28
20pub async fn run_list( 29pub async fn run_list(
21 git_repo: &Repo, 30 git_repo: &Repo,
22 repo_ref: &RepoRef, 31 repo_ref: &RepoRef,
32 decoded_nostr_url: &NostrUrlDecoded,
23 for_push: bool, 33 for_push: bool,
24) -> Result<HashMap<String, HashMap<String, String>>> { 34) -> Result<HashMap<String, HashMap<String, String>>> {
25 let nostr_state = 35 let nostr_state =
@@ -31,7 +41,7 @@ pub async fn run_list(
31 41
32 let term = console::Term::stderr(); 42 let term = console::Term::stderr();
33 43
34 let remote_states = list_from_remotes(&term, git_repo, &repo_ref.git_server)?; 44 let remote_states = list_from_remotes(&term, git_repo, &repo_ref.git_server, decoded_nostr_url);
35 45
36 let mut state = if let Some(nostr_state) = nostr_state { 46 let mut state = if let Some(nostr_state) = nostr_state {
37 for (name, value) in &nostr_state.state { 47 for (name, value) in &nostr_state.state {
@@ -122,41 +132,115 @@ pub fn list_from_remotes(
122 term: &console::Term, 132 term: &console::Term,
123 git_repo: &Repo, 133 git_repo: &Repo,
124 git_servers: &Vec<String>, 134 git_servers: &Vec<String>,
125) -> Result<HashMap<String, HashMap<String, String>>> { 135 decoded_nostr_url: &NostrUrlDecoded, // Add this parameter
136) -> HashMap<String, HashMap<String, String>> {
126 let mut remote_states = HashMap::new(); 137 let mut remote_states = HashMap::new();
138 let mut errors = HashMap::new();
127 for url in git_servers { 139 for url in git_servers {
128 let short_name = get_short_git_server_name(git_repo, url); 140 match list_from_remote(term, git_repo, url, decoded_nostr_url) {
129 term.write_line(format!("fetching refs list: {short_name}...").as_str())?; 141 Err(error) => {
130 match list_from_remote(git_repo, url) { 142 errors.insert(url, error);
131 Ok(remote_state) => {
132 remote_states.insert(url.clone(), remote_state);
133 } 143 }
134 Err(error1) => { 144 Ok(state) => {
135 if let Ok(alternative_url) = switch_clone_url_between_ssh_and_https(url) { 145 remote_states.insert(url.to_string(), state);
136 match list_from_remote(git_repo, &alternative_url) { 146 }
137 Ok(remote_state) => { 147 }
138 remote_states.insert(url.clone(), remote_state); 148 }
139 } 149 remote_states
140 Err(error2) => { 150}
141 term.write_line( 151
142 format!("WARNING: {short_name} failed to list refs error: {error1}\r\nand alternative protocol {alternative_url}: {error2}").as_str(), 152pub fn list_from_remote(
143 )?; 153 term: &console::Term,
144 } 154 git_repo: &Repo,
145 } 155 git_server_url: &str,
146 } else { 156 decoded_nostr_url: &NostrUrlDecoded, // Add this parameter
157) -> Result<HashMap<String, String>> {
158 let server_url = git_server_url.parse::<CloneUrl>()?;
159 let protocols_to_attempt = get_read_protocols_to_try(&server_url, decoded_nostr_url);
160
161 let mut failed_protocols = vec![];
162 let mut remote_state: Option<HashMap<String, String>> = None;
163
164 for protocol in &protocols_to_attempt {
165 term.write_line(
166 format!(
167 "fetching ref list from {} over {protocol}...",
168 server_url.domain(),
169 )
170 .as_str(),
171 )?;
172
173 let formatted_url = server_url.format_as(protocol, &decoded_nostr_url.user)?;
174 let res = if [ServerProtocol::UnauthHttps, ServerProtocol::UnauthHttp].contains(protocol) {
175 list_from_remote_url_unauthenticated(git_repo, &formatted_url)
176 } else {
177 list_from_remote_url(git_repo, &formatted_url)
178 };
179
180 match res {
181 Ok(state) => {
182 remote_state = Some(state);
183 if !failed_protocols.is_empty() {
147 term.write_line( 184 term.write_line(
148 format!("WARNING: {short_name} failed to list refs error: {error1}",) 185 format!(
149 .as_str(), 186 "list: succeeded over {protocol} for {}",
187 server_url.domain(),
188 )
189 .as_str(),
150 )?; 190 )?;
151 } 191 }
192 break;
193 }
194 Err(error) => {
195 term.write_line(
196 format!("list: {formatted_url} failed over {protocol}: {error}").as_str(),
197 )?;
198 failed_protocols.push(protocol);
152 } 199 }
153 } 200 }
154 term.clear_last_lines(1)?; 201 term.clear_last_lines(1)?;
155 } 202 }
156 Ok(remote_states) 203 if let Some(remote_state) = remote_state {
204 Ok(remote_state)
205 } else {
206 let error = anyhow!(
207 "{} failed over {}{}",
208 server_url.domain(),
209 join_with_and(&failed_protocols),
210 if decoded_nostr_url.protocol.is_some() {
211 " and nostr url contains protocol override so no other protocols were attempted"
212 } else {
213 ""
214 },
215 );
216 term.write_line(format!("list: {error}").as_str())?;
217 Err(error)
218 }
219}
220
221fn list_from_remote_url_unauthenticated(
222 git_repo: &Repo,
223 git_server_remote_url: &str,
224) -> Result<HashMap<String, String>> {
225 let mut git_server_remote = git_repo.git_repo.remote_anonymous(git_server_remote_url)?;
226 let remote_callbacks = git2::RemoteCallbacks::new();
227 git_server_remote.connect_auth(git2::Direction::Fetch, Some(remote_callbacks), None)?;
228 let mut state = HashMap::new();
229 for head in git_server_remote.list()? {
230 if let Some(symbolic_reference) = head.symref_target() {
231 state.insert(
232 head.name().to_string(),
233 format!("ref: {symbolic_reference}"),
234 );
235 } else {
236 state.insert(head.name().to_string(), head.oid().to_string());
237 }
238 }
239 git_server_remote.disconnect()?;
240 Ok(state)
157} 241}
158 242
159fn list_from_remote( 243fn list_from_remote_url(
160 git_repo: &Repo, 244 git_repo: &Repo,
161 git_server_remote_url: &str, 245 git_server_remote_url: &str,
162) -> Result<HashMap<String, String>> { 246) -> Result<HashMap<String, String>> {
diff --git a/src/bin/git_remote_nostr/main.rs b/src/bin/git_remote_nostr/main.rs
index a3fc5f8..e2738d2 100644
--- a/src/bin/git_remote_nostr/main.rs
+++ b/src/bin/git_remote_nostr/main.rs
@@ -75,13 +75,21 @@ async fn main() -> Result<()> {
75 println!("unsupported"); 75 println!("unsupported");
76 } 76 }
77 ["fetch", oid, refstr] => { 77 ["fetch", oid, refstr] => {
78 fetch::run_fetch(&git_repo, &repo_ref, &decoded_nostr_url, &stdin, oid, refstr).await?; 78 fetch::run_fetch(
79 &git_repo,
80 &repo_ref,
81 &decoded_nostr_url,
82 &stdin,
83 oid,
84 refstr,
85 )
86 .await?;
79 } 87 }
80 ["push", refspec] => { 88 ["push", refspec] => {
81 push::run_push( 89 push::run_push(
82 &git_repo, 90 &git_repo,
83 &repo_ref, 91 &repo_ref,
84 nostr_remote_url, 92 &decoded_nostr_url,
85 &stdin, 93 &stdin,
86 refspec, 94 refspec,
87 &client, 95 &client,
@@ -90,10 +98,12 @@ async fn main() -> Result<()> {
90 .await?; 98 .await?;
91 } 99 }
92 ["list"] => { 100 ["list"] => {
93 list_outputs = Some(list::run_list(&git_repo, &repo_ref, false).await?); 101 list_outputs =
102 Some(list::run_list(&git_repo, &repo_ref, &decoded_nostr_url, false).await?);
94 } 103 }
95 ["list", "for-push"] => { 104 ["list", "for-push"] => {
96 list_outputs = Some(list::run_list(&git_repo, &repo_ref, true).await?); 105 list_outputs =
106 Some(list::run_list(&git_repo, &repo_ref, &decoded_nostr_url, true).await?);
97 } 107 }
98 [] => { 108 [] => {
99 return Ok(()); 109 return Ok(());
diff --git a/src/bin/git_remote_nostr/push.rs b/src/bin/git_remote_nostr/push.rs
index 441c341..2c9c7e1 100644
--- a/src/bin/git_remote_nostr/push.rs
+++ b/src/bin/git_remote_nostr/push.rs
@@ -15,7 +15,7 @@ use git_events::{
15}; 15};
16use ngit::{ 16use ngit::{
17 client::{self, get_event_from_cache_by_id}, 17 client::{self, get_event_from_cache_by_id},
18 git, 18 git::{self, nostr_url::NostrUrlDecoded},
19 git_events::{self, get_event_root}, 19 git_events::{self, get_event_root},
20 login::{self, get_curent_user}, 20 login::{self, get_curent_user},
21 repo_ref, repo_state, 21 repo_ref, repo_state,
@@ -42,7 +42,7 @@ use crate::{
42pub async fn run_push( 42pub async fn run_push(
43 git_repo: &Repo, 43 git_repo: &Repo,
44 repo_ref: &RepoRef, 44 repo_ref: &RepoRef,
45 nostr_remote_url: &str, 45 decoded_nostr_url: &NostrUrlDecoded,
46 stdin: &Stdin, 46 stdin: &Stdin,
47 initial_refspec: &str, 47 initial_refspec: &str,
48 client: &Client, 48 client: &Client,
@@ -66,7 +66,7 @@ pub async fn run_push(
66 66
67 let list_outputs = match list_outputs { 67 let list_outputs = match list_outputs {
68 Some(outputs) => outputs, 68 Some(outputs) => outputs,
69 _ => list_from_remotes(&term, git_repo, &repo_ref.git_server)?, 69 _ => list_from_remotes(&term, git_repo, &repo_ref.git_server, decoded_nostr_url),
70 }; 70 };
71 71
72 let nostr_state = get_state_from_cache(git_repo.get_path()?, repo_ref).await; 72 let nostr_state = get_state_from_cache(git_repo.get_path()?, repo_ref).await;
@@ -154,7 +154,7 @@ pub async fn run_push(
154 &term, 154 &term,
155 repo_ref, 155 repo_ref,
156 git_repo, 156 git_repo,
157 nostr_remote_url, 157 &decoded_nostr_url.original_string,
158 &signer, 158 &signer,
159 &git_server_refspecs, 159 &git_server_refspecs,
160 ) 160 )
@@ -306,8 +306,12 @@ pub async fn run_push(
306 } 306 }
307 let (_, to) = refspec_to_from_to(refspec)?; 307 let (_, to) = refspec_to_from_to(refspec)?;
308 println!("ok {to}"); 308 println!("ok {to}");
309 update_remote_refs_pushed(&git_repo.git_repo, refspec, nostr_remote_url) 309 update_remote_refs_pushed(
310 .context("could not update remote_ref locally")?; 310 &git_repo.git_repo,
311 refspec,
312 &decoded_nostr_url.original_string,
313 )
314 .context("could not update remote_ref locally")?;
311 } 315 }
312 316
313 // TODO make async - check gitlib2 callbacks work async 317 // TODO make async - check gitlib2 callbacks work async