diff options
| author | DanConwayDev <DanConwayDev@protonmail.com> | 2024-09-17 13:23:22 +0100 |
|---|---|---|
| committer | DanConwayDev <DanConwayDev@protonmail.com> | 2024-09-17 13:23:22 +0100 |
| commit | a4bcaf98cc7a00a71f34ed382dc65414eaec5bff (patch) | |
| tree | 661bcac2b381d232be2488248bc899c48e50fb7e /src/bin/git_remote_nostr | |
| parent | 12fb184cd1a875704d4f187531aa1638513a3dab (diff) | |
feat(remote): store successful protocol in config
if another protocol was tried first and failed
Diffstat (limited to 'src/bin/git_remote_nostr')
| -rw-r--r-- | src/bin/git_remote_nostr/fetch.rs | 10 | ||||
| -rw-r--r-- | src/bin/git_remote_nostr/list.rs | 5 | ||||
| -rw-r--r-- | src/bin/git_remote_nostr/push.rs | 5 | ||||
| -rw-r--r-- | src/bin/git_remote_nostr/utils.rs | 147 |
4 files changed, 132 insertions, 35 deletions
diff --git a/src/bin/git_remote_nostr/fetch.rs b/src/bin/git_remote_nostr/fetch.rs index 33fd959..fed9925 100644 --- a/src/bin/git_remote_nostr/fetch.rs +++ b/src/bin/git_remote_nostr/fetch.rs | |||
| @@ -22,6 +22,7 @@ use ngit::{ | |||
| 22 | use crate::utils::{ | 22 | use crate::utils::{ |
| 23 | fetch_or_list_error_is_not_authentication_failure, find_proposal_and_patches_by_branch_name, | 23 | fetch_or_list_error_is_not_authentication_failure, find_proposal_and_patches_by_branch_name, |
| 24 | get_oids_from_fetch_batch, get_open_proposals, get_read_protocols_to_try, join_with_and, | 24 | get_oids_from_fetch_batch, get_open_proposals, get_read_protocols_to_try, join_with_and, |
| 25 | set_protocol_preference, Direction, | ||
| 25 | }; | 26 | }; |
| 26 | 27 | ||
| 27 | pub async fn run_fetch( | 28 | pub async fn run_fetch( |
| @@ -46,7 +47,7 @@ pub async fn run_fetch( | |||
| 46 | for git_server_url in &repo_ref.git_server { | 47 | for git_server_url in &repo_ref.git_server { |
| 47 | let term = console::Term::stderr(); | 48 | let term = console::Term::stderr(); |
| 48 | if let Err(error) = fetch_from_git_server( | 49 | if let Err(error) = fetch_from_git_server( |
| 49 | &git_repo.git_repo, | 50 | git_repo, |
| 50 | &oids_from_git_servers, | 51 | &oids_from_git_servers, |
| 51 | git_server_url, | 52 | git_server_url, |
| 52 | decoded_nostr_url, | 53 | decoded_nostr_url, |
| @@ -112,7 +113,7 @@ pub async fn run_fetch( | |||
| 112 | } | 113 | } |
| 113 | 114 | ||
| 114 | fn fetch_from_git_server( | 115 | fn fetch_from_git_server( |
| 115 | git_repo: &Repository, | 116 | git_repo: &Repo, |
| 116 | oids: &[String], | 117 | oids: &[String], |
| 117 | git_server_url: &str, | 118 | git_server_url: &str, |
| 118 | decoded_nostr_url: &NostrUrlDecoded, | 119 | decoded_nostr_url: &NostrUrlDecoded, |
| @@ -120,7 +121,7 @@ fn fetch_from_git_server( | |||
| 120 | ) -> Result<()> { | 121 | ) -> Result<()> { |
| 121 | let server_url = git_server_url.parse::<CloneUrl>()?; | 122 | let server_url = git_server_url.parse::<CloneUrl>()?; |
| 122 | 123 | ||
| 123 | let protocols_to_attempt = get_read_protocols_to_try(&server_url, decoded_nostr_url); | 124 | let protocols_to_attempt = get_read_protocols_to_try(git_repo, &server_url, decoded_nostr_url); |
| 124 | 125 | ||
| 125 | let mut failed_protocols = vec![]; | 126 | let mut failed_protocols = vec![]; |
| 126 | let mut success = false; | 127 | let mut success = false; |
| @@ -131,7 +132,7 @@ fn fetch_from_git_server( | |||
| 131 | 132 | ||
| 132 | let formatted_url = server_url.format_as(protocol, &decoded_nostr_url.user)?; | 133 | let formatted_url = server_url.format_as(protocol, &decoded_nostr_url.user)?; |
| 133 | let res = fetch_from_git_server_url( | 134 | let res = fetch_from_git_server_url( |
| 134 | git_repo, | 135 | &git_repo.git_repo, |
| 135 | oids, | 136 | oids, |
| 136 | &formatted_url, | 137 | &formatted_url, |
| 137 | [ServerProtocol::UnauthHttps, ServerProtocol::UnauthHttp].contains(protocol), | 138 | [ServerProtocol::UnauthHttps, ServerProtocol::UnauthHttp].contains(protocol), |
| @@ -152,6 +153,7 @@ fn fetch_from_git_server( | |||
| 152 | success = true; | 153 | success = true; |
| 153 | if !failed_protocols.is_empty() { | 154 | if !failed_protocols.is_empty() { |
| 154 | term.write_line(format!("fetch: succeeded over {protocol}").as_str())?; | 155 | term.write_line(format!("fetch: succeeded over {protocol}").as_str())?; |
| 156 | let _ = set_protocol_preference(git_repo, protocol, &server_url, &Direction::Push); | ||
| 155 | } | 157 | } |
| 156 | break; | 158 | break; |
| 157 | } | 159 | } |
diff --git a/src/bin/git_remote_nostr/list.rs b/src/bin/git_remote_nostr/list.rs index c2bd9d6..959b8c8 100644 --- a/src/bin/git_remote_nostr/list.rs +++ b/src/bin/git_remote_nostr/list.rs | |||
| @@ -24,6 +24,7 @@ use crate::{ | |||
| 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, |
| 26 | get_read_protocols_to_try, get_short_git_server_name, join_with_and, | 26 | get_read_protocols_to_try, get_short_git_server_name, join_with_and, |
| 27 | set_protocol_preference, Direction, | ||
| 27 | }, | 28 | }, |
| 28 | }; | 29 | }; |
| 29 | 30 | ||
| @@ -157,7 +158,7 @@ pub fn list_from_remote( | |||
| 157 | decoded_nostr_url: &NostrUrlDecoded, // Add this parameter | 158 | decoded_nostr_url: &NostrUrlDecoded, // Add this parameter |
| 158 | ) -> Result<HashMap<String, String>> { | 159 | ) -> Result<HashMap<String, String>> { |
| 159 | let server_url = git_server_url.parse::<CloneUrl>()?; | 160 | let server_url = git_server_url.parse::<CloneUrl>()?; |
| 160 | let protocols_to_attempt = get_read_protocols_to_try(&server_url, decoded_nostr_url); | 161 | let protocols_to_attempt = get_read_protocols_to_try(git_repo, &server_url, decoded_nostr_url); |
| 161 | 162 | ||
| 162 | let mut failed_protocols = vec![]; | 163 | let mut failed_protocols = vec![]; |
| 163 | let mut remote_state: Option<HashMap<String, String>> = None; | 164 | let mut remote_state: Option<HashMap<String, String>> = None; |
| @@ -191,6 +192,8 @@ pub fn list_from_remote( | |||
| 191 | ) | 192 | ) |
| 192 | .as_str(), | 193 | .as_str(), |
| 193 | )?; | 194 | )?; |
| 195 | let _ = | ||
| 196 | set_protocol_preference(git_repo, protocol, &server_url, &Direction::Fetch); | ||
| 194 | } | 197 | } |
| 195 | break; | 198 | break; |
| 196 | } | 199 | } |
diff --git a/src/bin/git_remote_nostr/push.rs b/src/bin/git_remote_nostr/push.rs index daa7973..de18828 100644 --- a/src/bin/git_remote_nostr/push.rs +++ b/src/bin/git_remote_nostr/push.rs | |||
| @@ -41,7 +41,7 @@ use crate::{ | |||
| 41 | utils::{ | 41 | utils::{ |
| 42 | find_proposal_and_patches_by_branch_name, get_all_proposals, get_remote_name_by_url, | 42 | find_proposal_and_patches_by_branch_name, get_all_proposals, get_remote_name_by_url, |
| 43 | get_short_git_server_name, get_write_protocols_to_try, join_with_and, | 43 | get_short_git_server_name, get_write_protocols_to_try, join_with_and, |
| 44 | push_error_is_not_authentication_failure, read_line, | 44 | push_error_is_not_authentication_failure, read_line, set_protocol_preference, Direction, |
| 45 | }, | 45 | }, |
| 46 | }; | 46 | }; |
| 47 | 47 | ||
| @@ -351,7 +351,7 @@ fn push_to_remote( | |||
| 351 | term: &Term, | 351 | term: &Term, |
| 352 | ) -> Result<()> { | 352 | ) -> Result<()> { |
| 353 | let server_url = git_server_url.parse::<CloneUrl>()?; | 353 | let server_url = git_server_url.parse::<CloneUrl>()?; |
| 354 | let protocols_to_attempt = get_write_protocols_to_try(&server_url, decoded_nostr_url); | 354 | let protocols_to_attempt = get_write_protocols_to_try(git_repo, &server_url, decoded_nostr_url); |
| 355 | 355 | ||
| 356 | let mut failed_protocols = vec![]; | 356 | let mut failed_protocols = vec![]; |
| 357 | let mut success = false; | 357 | let mut success = false; |
| @@ -373,6 +373,7 @@ fn push_to_remote( | |||
| 373 | success = true; | 373 | success = true; |
| 374 | if !failed_protocols.is_empty() { | 374 | if !failed_protocols.is_empty() { |
| 375 | term.write_line(format!("fetch: succeeded over {protocol}").as_str())?; | 375 | term.write_line(format!("fetch: succeeded over {protocol}").as_str())?; |
| 376 | let _ = set_protocol_preference(git_repo, protocol, &server_url, &Direction::Push); | ||
| 376 | } | 377 | } |
| 377 | } | 378 | } |
| 378 | term.clear_last_lines(1)?; | 379 | term.clear_last_lines(1)?; |
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 @@ | |||
| 1 | use core::str; | 1 | use core::str; |
| 2 | use std::{ | 2 | use std::{ |
| 3 | collections::HashMap, | 3 | collections::HashMap, |
| 4 | fmt, | ||
| 4 | io::{self, Stdin}, | 5 | io::{self, Stdin}, |
| 6 | str::FromStr, | ||
| 5 | }; | 7 | }; |
| 6 | 8 | ||
| 7 | use anyhow::{bail, Context, Result}; | 9 | use 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 |
| 216 | pub fn get_read_protocols_to_try( | 218 | pub 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 |
| 244 | pub fn get_write_protocols_to_try( | 256 | pub 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)] | ||
| 293 | pub enum Direction { | ||
| 294 | Push, | ||
| 295 | Fetch, | ||
| 296 | } | ||
| 297 | impl 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 | |||
| 306 | pub 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 | |||
| 331 | pub 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 |
| 270 | pub fn fetch_or_list_error_is_not_authentication_failure(error: &anyhow::Error) -> bool { | 361 | pub 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) |