upleb.uk

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

summaryrefslogtreecommitdiff
path: root/src/bin/git_remote_nostr/utils.rs
diff options
context:
space:
mode:
authorDanConwayDev <DanConwayDev@protonmail.com>2024-09-17 13:23:22 +0100
committerDanConwayDev <DanConwayDev@protonmail.com>2024-09-17 13:23:22 +0100
commita4bcaf98cc7a00a71f34ed382dc65414eaec5bff (patch)
tree661bcac2b381d232be2488248bc899c48e50fb7e /src/bin/git_remote_nostr/utils.rs
parent12fb184cd1a875704d4f187531aa1638513a3dab (diff)
feat(remote): store successful protocol in config
if another protocol was tried first and failed
Diffstat (limited to 'src/bin/git_remote_nostr/utils.rs')
-rw-r--r--src/bin/git_remote_nostr/utils.rs147
1 files changed, 119 insertions, 28 deletions
diff --git a/src/bin/git_remote_nostr/utils.rs b/src/bin/git_remote_nostr/utils.rs
index a13d398..3ae1bab 100644
--- a/src/bin/git_remote_nostr/utils.rs
+++ b/src/bin/git_remote_nostr/utils.rs
@@ -1,7 +1,9 @@
1use core::str; 1use core::str;
2use std::{ 2use std::{
3 collections::HashMap, 3 collections::HashMap,
4 fmt,
4 io::{self, Stdin}, 5 io::{self, Stdin},
6 str::FromStr,
5}; 7};
6 8
7use anyhow::{bail, Context, Result}; 9use anyhow::{bail, Context, Result};
@@ -214,6 +216,7 @@ pub fn join_with_and<T: ToString>(items: &[T]) -> String {
214 216
215/// get an ordered vector of server protocols to attempt 217/// get an ordered vector of server protocols to attempt
216pub fn get_read_protocols_to_try( 218pub fn get_read_protocols_to_try(
219 git_repo: &Repo,
217 server_url: &CloneUrl, 220 server_url: &CloneUrl,
218 decoded_nostr_url: &NostrUrlDecoded, 221 decoded_nostr_url: &NostrUrlDecoded,
219) -> Vec<ServerProtocol> { 222) -> Vec<ServerProtocol> {
@@ -221,27 +224,37 @@ pub fn get_read_protocols_to_try(
221 vec![(ServerProtocol::Filesystem)] 224 vec![(ServerProtocol::Filesystem)]
222 } else if let Some(protocol) = &decoded_nostr_url.protocol { 225 } else if let Some(protocol) = &decoded_nostr_url.protocol {
223 vec![protocol.clone()] 226 vec![protocol.clone()]
224 } else if server_url.protocol() == ServerProtocol::Http {
225 vec![
226 ServerProtocol::UnauthHttp,
227 ServerProtocol::Ssh,
228 // note: list and fetch stop here if ssh was authenticated
229 ServerProtocol::Http,
230 ]
231 } else if server_url.protocol() == ServerProtocol::Ftp {
232 vec![ServerProtocol::Ftp, ServerProtocol::Ssh]
233 } else { 227 } else {
234 vec![ 228 let mut list = if server_url.protocol() == ServerProtocol::Http {
235 ServerProtocol::UnauthHttps, 229 vec![
236 ServerProtocol::Ssh, 230 ServerProtocol::UnauthHttp,
237 // note: list and fetch stop here if ssh was authenticated 231 ServerProtocol::Ssh,
238 ServerProtocol::Https, 232 // note: list and fetch stop here if ssh was authenticated
239 ] 233 ServerProtocol::Http,
234 ]
235 } else if server_url.protocol() == ServerProtocol::Ftp {
236 vec![ServerProtocol::Ftp, ServerProtocol::Ssh]
237 } else {
238 vec![
239 ServerProtocol::UnauthHttps,
240 ServerProtocol::Ssh,
241 // note: list and fetch stop here if ssh was authenticated
242 ServerProtocol::Https,
243 ]
244 };
245 if let Some(protocol) = get_protocol_preference(git_repo, server_url, &Direction::Fetch) {
246 if let Some(pos) = list.iter().position(|p| *p == protocol) {
247 list.remove(pos);
248 list.insert(0, protocol);
249 }
250 }
251 list
240 } 252 }
241} 253}
242 254
243/// get an ordered vector of server protocols to attempt 255/// get an ordered vector of server protocols to attempt
244pub fn get_write_protocols_to_try( 256pub fn get_write_protocols_to_try(
257 git_repo: &Repo,
245 server_url: &CloneUrl, 258 server_url: &CloneUrl,
246 decoded_nostr_url: &NostrUrlDecoded, 259 decoded_nostr_url: &NostrUrlDecoded,
247) -> Vec<ServerProtocol> { 260) -> Vec<ServerProtocol> {
@@ -249,23 +262,101 @@ pub fn get_write_protocols_to_try(
249 vec![(ServerProtocol::Filesystem)] 262 vec![(ServerProtocol::Filesystem)]
250 } else if let Some(protocol) = &decoded_nostr_url.protocol { 263 } else if let Some(protocol) = &decoded_nostr_url.protocol {
251 vec![protocol.clone()] 264 vec![protocol.clone()]
252 } else if server_url.protocol() == ServerProtocol::Http {
253 vec![
254 ServerProtocol::Ssh,
255 // note: list and fetch stop here if ssh was authenticated
256 ServerProtocol::Http,
257 ]
258 } else if server_url.protocol() == ServerProtocol::Ftp {
259 vec![ServerProtocol::Ssh, ServerProtocol::Ftp]
260 } else { 265 } else {
261 vec![ 266 let mut list = if server_url.protocol() == ServerProtocol::Http {
262 ServerProtocol::Ssh, 267 vec![
263 // note: list and fetch stop here if ssh was authenticated 268 ServerProtocol::Ssh,
264 ServerProtocol::Https, 269 // note: list and fetch stop here if ssh was authenticated
265 ] 270 ServerProtocol::Http,
271 ]
272 } else if server_url.protocol() == ServerProtocol::Ftp {
273 vec![ServerProtocol::Ssh, ServerProtocol::Ftp]
274 } else {
275 vec![
276 ServerProtocol::Ssh,
277 // note: list and fetch stop here if ssh was authenticated
278 ServerProtocol::Https,
279 ]
280 };
281 if let Some(protocol) = get_protocol_preference(git_repo, server_url, &Direction::Push) {
282 if let Some(pos) = list.iter().position(|p| *p == protocol) {
283 list.remove(pos);
284 list.insert(0, protocol);
285 }
286 }
287
288 list
266 } 289 }
267} 290}
268 291
292#[derive(Debug, PartialEq)]
293pub enum Direction {
294 Push,
295 Fetch,
296}
297impl fmt::Display for Direction {
298 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
299 match self {
300 Direction::Push => write!(f, "push"),
301 Direction::Fetch => write!(f, "fetch"),
302 }
303 }
304}
305
306pub fn get_protocol_preference(
307 git_repo: &Repo,
308 server_url: &CloneUrl,
309 direction: &Direction,
310) -> Option<ServerProtocol> {
311 let server_short_name = server_url.short_name();
312 if let Ok(Some(list)) =
313 git_repo.get_git_config_item(format!("nostr.protocol-{direction}").as_str(), Some(false))
314 {
315 for item in list.split(';') {
316 let pair = item.split(',').collect::<Vec<&str>>();
317 if let Some(url) = pair.get(1) {
318 if *url == server_short_name {
319 if let Some(protocol) = pair.first() {
320 if let Ok(protocol) = ServerProtocol::from_str(protocol) {
321 return Some(protocol);
322 }
323 }
324 }
325 }
326 }
327 }
328 None
329}
330
331pub fn set_protocol_preference(
332 git_repo: &Repo,
333 protocol: &ServerProtocol,
334 server_url: &CloneUrl,
335 direction: &Direction,
336) -> Result<()> {
337 let server_short_name = server_url.short_name();
338 let mut new = String::new();
339 if let Some(list) =
340 git_repo.get_git_config_item(format!("nostr.protocol-{direction}").as_str(), Some(false))?
341 {
342 for item in list.split(';') {
343 let pair = item.split(',').collect::<Vec<&str>>();
344 if let Some(url) = pair.get(1) {
345 if *url != server_short_name && !item.is_empty() {
346 new.push_str(format!("{item};").as_str());
347 }
348 }
349 }
350 }
351 new.push_str(format!("{protocol},{server_short_name};").as_str());
352
353 git_repo.save_git_config_item(
354 format!("nostr.protocol-{direction}").as_str(),
355 new.as_str(),
356 false,
357 )
358}
359
269/// to understand whether to try over another protocol 360/// to understand whether to try over another protocol
270pub fn fetch_or_list_error_is_not_authentication_failure(error: &anyhow::Error) -> bool { 361pub fn fetch_or_list_error_is_not_authentication_failure(error: &anyhow::Error) -> bool {
271 !error_might_be_authentication_related(error) 362 !error_might_be_authentication_related(error)