diff options
Diffstat (limited to 'src/git_remote_helper.rs')
| -rw-r--r-- | src/git_remote_helper.rs | 113 |
1 files changed, 91 insertions, 22 deletions
diff --git a/src/git_remote_helper.rs b/src/git_remote_helper.rs index 2fa1aad..8417415 100644 --- a/src/git_remote_helper.rs +++ b/src/git_remote_helper.rs | |||
| @@ -213,38 +213,100 @@ async fn fetching_with_report_for_helper( | |||
| 213 | Ok(()) | 213 | Ok(()) |
| 214 | } | 214 | } |
| 215 | 215 | ||
| 216 | async fn list(git_repo: &Repo, repo_ref: &RepoRef, for_push: bool) -> Result<()> { | 216 | async fn list( |
| 217 | if let Ok(repo_state) = get_state_from_cache(git_repo.get_path()?, repo_ref).await { | 217 | git_repo: &Repo, |
| 218 | for (name, value) in &repo_state.state { | 218 | repo_ref: &RepoRef, |
| 219 | if value.starts_with("ref: ") { | 219 | for_push: bool, |
| 220 | if !for_push { | 220 | ) -> Result<HashMap<String, HashMap<String, String>>> { |
| 221 | println!("{} {name}", value.replace("ref: ", "@")); | 221 | let nostr_state = |
| 222 | if let Ok(nostr_state) = get_state_from_cache(git_repo.get_path()?, repo_ref).await { | ||
| 223 | Some(nostr_state) | ||
| 224 | } else { | ||
| 225 | None | ||
| 226 | }; | ||
| 227 | |||
| 228 | let term = console::Term::stderr(); | ||
| 229 | |||
| 230 | let mut remote_states = HashMap::new(); | ||
| 231 | for url in &repo_ref.git_server { | ||
| 232 | match list_from_remote(git_repo, url) { | ||
| 233 | Ok(remote_state) => { | ||
| 234 | remote_states.insert(url.clone(), remote_state); | ||
| 235 | } | ||
| 236 | Err(error) => { | ||
| 237 | term.write_line( | ||
| 238 | format!("WARNING: failed to list refs git server in nostr events from {url} error: {error}").as_str(), | ||
| 239 | )?; | ||
| 240 | } | ||
| 241 | } | ||
| 242 | } | ||
| 243 | |||
| 244 | let state = if let Some(nostr_state) = nostr_state { | ||
| 245 | let term = console::Term::stderr(); | ||
| 246 | for (name, value) in &nostr_state.state { | ||
| 247 | for (url, remote_state) in &remote_states { | ||
| 248 | if let Some(remote_value) = remote_state.get(name) { | ||
| 249 | if value.ne(remote_value) { | ||
| 250 | term.write_line( | ||
| 251 | format!( | ||
| 252 | "WARNING: git server {url} is out of sync with nostr for {name}" | ||
| 253 | ) | ||
| 254 | .as_str(), | ||
| 255 | )?; | ||
| 256 | } | ||
| 257 | } else { | ||
| 258 | term.write_line( | ||
| 259 | format!("WARNING: git server {url} is out of sync with nostr. it is missing {name}. if you are a maintainer consider pushing it.").as_str(), | ||
| 260 | )?; | ||
| 222 | } | 261 | } |
| 223 | } else { | ||
| 224 | println!("{value} {name}"); | ||
| 225 | } | 262 | } |
| 226 | } | 263 | } |
| 264 | nostr_state.state | ||
| 227 | } else { | 265 | } else { |
| 228 | let git_server_remote_url = repo_ref | 266 | repo_ref |
| 229 | .git_server | 267 | .git_server |
| 268 | .iter() | ||
| 269 | .filter_map(|server| remote_states.get(server)) | ||
| 270 | .cloned() | ||
| 271 | .collect::<Vec<HashMap<String, String>>>() | ||
| 230 | .first() | 272 | .first() |
| 231 | .context("no git server listed in nostr repository announcement")?; | 273 | .context("failed to get refs from git server")? |
| 232 | let mut git_server_remote = git_repo.git_repo.remote_anonymous(git_server_remote_url)?; | 274 | .clone() |
| 233 | git_server_remote.connect(git2::Direction::Fetch)?; | 275 | }; |
| 234 | 276 | ||
| 235 | for head in git_server_remote.list()? { | 277 | for (name, value) in state { |
| 236 | if let Some(symbolic_reference) = head.symref_target() { | 278 | if value.starts_with("ref: ") { |
| 237 | if !for_push { | 279 | if !for_push { |
| 238 | println!("@{} {}", symbolic_reference, head.name()); | 280 | println!("{} {name}", value.replace("ref: ", "@")); |
| 239 | } | ||
| 240 | } else { | ||
| 241 | println!("{} {}", head.oid(), head.name()); | ||
| 242 | } | 281 | } |
| 282 | } else { | ||
| 283 | println!("{value} {name}"); | ||
| 243 | } | 284 | } |
| 244 | git_server_remote.disconnect()?; | ||
| 245 | } | 285 | } |
| 286 | |||
| 246 | println!(); | 287 | println!(); |
| 247 | Ok(()) | 288 | Ok(remote_states) |
| 289 | } | ||
| 290 | |||
| 291 | fn list_from_remote( | ||
| 292 | git_repo: &Repo, | ||
| 293 | git_server_remote_url: &str, | ||
| 294 | ) -> Result<HashMap<String, String>> { | ||
| 295 | let mut git_server_remote = git_repo.git_repo.remote_anonymous(git_server_remote_url)?; | ||
| 296 | git_server_remote.connect(git2::Direction::Fetch)?; | ||
| 297 | let mut state = HashMap::new(); | ||
| 298 | for head in git_server_remote.list()? { | ||
| 299 | if let Some(symbolic_reference) = head.symref_target() { | ||
| 300 | state.insert( | ||
| 301 | head.name().to_string(), | ||
| 302 | format!("ref: {symbolic_reference}"), | ||
| 303 | ); | ||
| 304 | } else { | ||
| 305 | state.insert(head.name().to_string(), head.oid().to_string()); | ||
| 306 | } | ||
| 307 | } | ||
| 308 | git_server_remote.disconnect()?; | ||
| 309 | Ok(state) | ||
| 248 | } | 310 | } |
| 249 | 311 | ||
| 250 | fn fetch(git_repo: &Repository, repo_ref: &RepoRef, stdin: &Stdin, oid: &str) -> Result<()> { | 312 | fn fetch(git_repo: &Repository, repo_ref: &RepoRef, stdin: &Stdin, oid: &str) -> Result<()> { |
| @@ -290,6 +352,13 @@ async fn push( | |||
| 290 | #[cfg(test)] client: &crate::client::MockConnect, | 352 | #[cfg(test)] client: &crate::client::MockConnect, |
| 291 | #[cfg(not(test))] client: &Client, | 353 | #[cfg(not(test))] client: &Client, |
| 292 | ) -> Result<()> { | 354 | ) -> Result<()> { |
| 355 | // TODO check | ||
| 356 | // bail!( | ||
| 357 | // "git server {} tip for branch {} conflicts with nostr and local branch. | ||
| 358 | // to resolve either:\r\n 1. pull from that git server and resolve\r\n 2. | ||
| 359 | // force push your branch to the git server before pushing to nostr remote" | ||
| 360 | // )?; | ||
| 361 | |||
| 293 | // if no state events - create from first git server listed | 362 | // if no state events - create from first git server listed |
| 294 | let refspecs = get_refspecs_from_push_batch(stdin, initial_refspec)?; | 363 | let refspecs = get_refspecs_from_push_batch(stdin, initial_refspec)?; |
| 295 | let git_server_url = repo_ref | 364 | let git_server_url = repo_ref |