diff options
| author | DanConwayDev <DanConwayDev@protonmail.com> | 2024-09-23 10:46:26 +0100 |
|---|---|---|
| committer | DanConwayDev <DanConwayDev@protonmail.com> | 2024-09-23 13:36:53 +0100 |
| commit | 2cdbb8c7ac6c98af6e36c4458c08bef2299794e1 (patch) | |
| tree | fcf7c56d2f5eda0776643f8a52090965f1de06a8 | |
| parent | 51358320c50afece31fc25945a09e3d7aac8f39c (diff) | |
fix(remote): add resilience to `prs`
make poorly formatted patches fail silently. we stop trusting that the
`commit` tag in the latest patch can be produced by apply the patches.
to achieve this we must recreate the commit during the list command,
which require fetching the parent oids.
support patches without optional `commit` and `parent-commit` tags.
| -rw-r--r-- | src/bin/git_remote_nostr/fetch.rs | 117 | ||||
| -rw-r--r-- | src/bin/git_remote_nostr/list.rs | 92 | ||||
| -rw-r--r-- | src/lib/git/mod.rs | 82 | ||||
| -rw-r--r-- | tests/git_remote_nostr/fetch.rs | 4 | ||||
| -rw-r--r-- | tests/git_remote_nostr/list.rs | 8 |
5 files changed, 207 insertions, 96 deletions
diff --git a/src/bin/git_remote_nostr/fetch.rs b/src/bin/git_remote_nostr/fetch.rs index 2e16297..46e7ad3 100644 --- a/src/bin/git_remote_nostr/fetch.rs +++ b/src/bin/git_remote_nostr/fetch.rs | |||
| @@ -1,11 +1,12 @@ | |||
| 1 | use core::str; | 1 | use core::str; |
| 2 | use std::{ | 2 | use std::{ |
| 3 | collections::HashMap, | ||
| 3 | io::Stdin, | 4 | io::Stdin, |
| 4 | sync::{Arc, Mutex}, | 5 | sync::{Arc, Mutex}, |
| 5 | time::Instant, | 6 | time::Instant, |
| 6 | }; | 7 | }; |
| 7 | 8 | ||
| 8 | use anyhow::{anyhow, bail, Result}; | 9 | use anyhow::{anyhow, bail, Context, Result}; |
| 9 | use auth_git2::GitAuthenticator; | 10 | use auth_git2::GitAuthenticator; |
| 10 | use git2::{Progress, Repository}; | 11 | use git2::{Progress, Repository}; |
| 11 | use ngit::{ | 12 | use ngit::{ |
| @@ -19,7 +20,7 @@ use ngit::{ | |||
| 19 | repo_ref::RepoRef, | 20 | repo_ref::RepoRef, |
| 20 | }; | 21 | }; |
| 21 | use nostr::nips::nip19; | 22 | use nostr::nips::nip19; |
| 22 | use nostr_sdk::ToBech32; | 23 | use nostr_sdk::{Event, ToBech32}; |
| 23 | 24 | ||
| 24 | use crate::utils::{ | 25 | use crate::utils::{ |
| 25 | count_lines_per_msg_vec, fetch_or_list_error_is_not_authentication_failure, | 26 | count_lines_per_msg_vec, fetch_or_list_error_is_not_authentication_failure, |
| @@ -78,65 +79,97 @@ pub async fn run_fetch( | |||
| 78 | 79 | ||
| 79 | fetch_batch.retain(|refstr, _| refstr.contains("refs/heads/pr/")); | 80 | fetch_batch.retain(|refstr, _| refstr.contains("refs/heads/pr/")); |
| 80 | 81 | ||
| 81 | if !fetch_batch.is_empty() { | 82 | fetch_proposals(git_repo, &term, repo_ref, &fetch_batch).await?; |
| 83 | term.flush()?; | ||
| 84 | println!(); | ||
| 85 | Ok(()) | ||
| 86 | } | ||
| 87 | |||
| 88 | pub fn make_commits_for_proposal( | ||
| 89 | git_repo: &Repo, | ||
| 90 | repo_ref: &RepoRef, | ||
| 91 | patches_ancestor_last: &[Event], | ||
| 92 | ) -> Result<String> { | ||
| 93 | let patches_ancestor_first: Vec<&Event> = patches_ancestor_last.iter().rev().collect(); | ||
| 94 | let mut tip_commit_id = if let Ok(parent_commit) = tag_value( | ||
| 95 | patches_ancestor_first | ||
| 96 | .first() | ||
| 97 | .context("proposal should have at least one patch")?, | ||
| 98 | "parent-commit", | ||
| 99 | ) { | ||
| 100 | parent_commit | ||
| 101 | } else { | ||
| 102 | // TODO choose most recent commit on master before patch timestamp so it doesnt | ||
| 103 | // constantly get rebased | ||
| 104 | let (_, hash) = git_repo.get_main_or_master_branch()?; | ||
| 105 | hash.to_string() | ||
| 106 | }; | ||
| 107 | |||
| 108 | for patch in &patches_ancestor_first { | ||
| 109 | let commit_id = git_repo | ||
| 110 | .create_commit_from_patch(patch, Some(tip_commit_id.clone())) | ||
| 111 | .context(format!( | ||
| 112 | "cannot create commit for patch {}", | ||
| 113 | nip19::Nip19Event { | ||
| 114 | event_id: patch.id(), | ||
| 115 | author: Some(patch.author()), | ||
| 116 | kind: Some(patch.kind()), | ||
| 117 | relays: if let Some(relay) = repo_ref.relays.first() { | ||
| 118 | vec![relay.to_string()] | ||
| 119 | } else { | ||
| 120 | vec![] | ||
| 121 | }, | ||
| 122 | } | ||
| 123 | .to_bech32() | ||
| 124 | .unwrap_or_default() | ||
| 125 | ))?; | ||
| 126 | tip_commit_id = commit_id.to_string(); | ||
| 127 | } | ||
| 128 | Ok(tip_commit_id) | ||
| 129 | } | ||
| 130 | |||
| 131 | async fn fetch_proposals( | ||
| 132 | git_repo: &Repo, | ||
| 133 | term: &console::Term, | ||
| 134 | repo_ref: &RepoRef, | ||
| 135 | proposal_refs: &HashMap<String, String>, | ||
| 136 | ) -> Result<()> { | ||
| 137 | if !proposal_refs.is_empty() { | ||
| 82 | let open_proposals = get_open_proposals(git_repo, repo_ref).await?; | 138 | let open_proposals = get_open_proposals(git_repo, repo_ref).await?; |
| 83 | 139 | ||
| 84 | let current_user = get_curent_user(git_repo)?; | 140 | let current_user = get_curent_user(git_repo)?; |
| 85 | 141 | ||
| 86 | for (refstr, oid) in fetch_batch { | 142 | for refstr in proposal_refs.keys() { |
| 87 | if let Some((_, (_, patches))) = | 143 | if let Some((_, (_, patches))) = |
| 88 | find_proposal_and_patches_by_branch_name(&refstr, &open_proposals, ¤t_user) | 144 | find_proposal_and_patches_by_branch_name(refstr, &open_proposals, ¤t_user) |
| 89 | { | 145 | { |
| 90 | if !git_repo.does_commit_exist(&oid)? { | 146 | if let Err(error) = make_commits_for_proposal(git_repo, repo_ref, patches) { |
| 91 | let mut patches_ancestor_first = patches.clone(); | 147 | term.write_line( |
| 92 | patches_ancestor_first.reverse(); | 148 | format!("WARNING: cannot create branch for {refstr}, error: {error}",) |
| 93 | if git_repo.does_commit_exist(&tag_value( | 149 | .as_str(), |
| 94 | patches_ancestor_first.first().unwrap(), | 150 | )?; |
| 95 | "parent-commit", | 151 | break; |
| 96 | )?)? { | ||
| 97 | for patch in &patches_ancestor_first { | ||
| 98 | if let Err(error) = git_repo.create_commit_from_patch(patch) { | ||
| 99 | term.write_line( | ||
| 100 | format!( | ||
| 101 | "WARNING: cannot create branch for {refstr}, error: {error} for patch {}", | ||
| 102 | nip19::Nip19Event { | ||
| 103 | event_id: patch.id(), | ||
| 104 | author: Some(patch.author()), | ||
| 105 | kind: Some(patch.kind()), | ||
| 106 | relays: if let Some(relay) = repo_ref.relays.first() { | ||
| 107 | vec![relay.to_string()] | ||
| 108 | } else { vec![]}, | ||
| 109 | }.to_bech32().unwrap_or_default() | ||
| 110 | ) | ||
| 111 | .as_str(), | ||
| 112 | )?; | ||
| 113 | break; | ||
| 114 | } | ||
| 115 | } | ||
| 116 | } else { | ||
| 117 | term.write_line( | ||
| 118 | format!("WARNING: cannot find parent commit for {refstr}").as_str(), | ||
| 119 | )?; | ||
| 120 | } | ||
| 121 | } | 152 | } |
| 122 | } else { | ||
| 123 | term.write_line(format!("WARNING: cannot find proposal for {refstr}").as_str())?; | ||
| 124 | } | 153 | } |
| 125 | } | 154 | } |
| 126 | } | 155 | } |
| 127 | |||
| 128 | term.flush()?; | ||
| 129 | println!(); | ||
| 130 | Ok(()) | 156 | Ok(()) |
| 131 | } | 157 | } |
| 132 | 158 | ||
| 133 | fn fetch_from_git_server( | 159 | pub fn fetch_from_git_server( |
| 134 | git_repo: &Repo, | 160 | git_repo: &Repo, |
| 135 | oids: &[String], | 161 | oids: &[String], |
| 136 | git_server_url: &str, | 162 | git_server_url: &str, |
| 137 | decoded_nostr_url: &NostrUrlDecoded, | 163 | decoded_nostr_url: &NostrUrlDecoded, |
| 138 | term: &console::Term, | 164 | term: &console::Term, |
| 139 | ) -> Result<()> { | 165 | ) -> Result<()> { |
| 166 | let already_have_oids = oids | ||
| 167 | .iter() | ||
| 168 | .all(|oid| git_repo.does_commit_exist(oid).is_ok_and(|outcome| outcome)); | ||
| 169 | if already_have_oids { | ||
| 170 | return Ok(()); | ||
| 171 | } | ||
| 172 | |||
| 140 | let server_url = git_server_url.parse::<CloneUrl>()?; | 173 | let server_url = git_server_url.parse::<CloneUrl>()?; |
| 141 | 174 | ||
| 142 | let protocols_to_attempt = get_read_protocols_to_try(git_repo, &server_url, decoded_nostr_url); | 175 | let protocols_to_attempt = get_read_protocols_to_try(git_repo, &server_url, decoded_nostr_url); |
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}; | |||
| 5 | use auth_git2::GitAuthenticator; | 5 | use auth_git2::GitAuthenticator; |
| 6 | use client::get_state_from_cache; | 6 | use client::get_state_from_cache; |
| 7 | use git::RepoActions; | 7 | use git::RepoActions; |
| 8 | use git_events::{event_to_cover_letter, get_commit_id_from_patch}; | ||
| 9 | use ngit::{ | 8 | use 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; | |||
| 20 | use repo_ref::RepoRef; | 19 | use repo_ref::RepoRef; |
| 21 | 20 | ||
| 22 | use crate::{ | 21 | use 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 | |||
| 113 | async 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 | ||
| 133 | pub fn list_from_remotes( | 177 | pub fn list_from_remotes( |
diff --git a/src/lib/git/mod.rs b/src/lib/git/mod.rs index 7ebdefd..05186b0 100644 --- a/src/lib/git/mod.rs +++ b/src/lib/git/mod.rs | |||
| @@ -79,7 +79,11 @@ pub trait RepoActions { | |||
| 79 | branch_name: &str, | 79 | branch_name: &str, |
| 80 | patch_and_ancestors: Vec<nostr::Event>, | 80 | patch_and_ancestors: Vec<nostr::Event>, |
| 81 | ) -> Result<Vec<nostr::Event>>; | 81 | ) -> Result<Vec<nostr::Event>>; |
| 82 | fn create_commit_from_patch(&self, patch: &nostr::Event) -> Result<Oid>; | 82 | fn create_commit_from_patch( |
| 83 | &self, | ||
| 84 | patch: &nostr::Event, | ||
| 85 | parent_commit_id_override: Option<String>, | ||
| 86 | ) -> Result<Oid>; | ||
| 83 | fn parse_starting_commits(&self, starting_commits: &str) -> Result<Vec<Sha1Hash>>; | 87 | fn parse_starting_commits(&self, starting_commits: &str) -> Result<Vec<Sha1Hash>>; |
| 84 | fn ancestor_of(&self, decendant: &Sha1Hash, ancestor: &Sha1Hash) -> Result<bool>; | 88 | fn ancestor_of(&self, decendant: &Sha1Hash, ancestor: &Sha1Hash) -> Result<bool>; |
| 85 | fn get_git_config_item(&self, item: &str, global: Option<bool>) -> Result<Option<String>>; | 89 | fn get_git_config_item(&self, item: &str, global: Option<bool>) -> Result<Option<String>>; |
| @@ -540,19 +544,30 @@ impl RepoActions for Repo { | |||
| 540 | let commit_id = get_commit_id_from_patch(patch)?; | 544 | let commit_id = get_commit_id_from_patch(patch)?; |
| 541 | // only create new commits - otherwise make them the tip | 545 | // only create new commits - otherwise make them the tip |
| 542 | if !self.does_commit_exist(&commit_id)? { | 546 | if !self.does_commit_exist(&commit_id)? { |
| 543 | self.create_commit_from_patch(patch)?; | 547 | self.create_commit_from_patch(patch, None)?; |
| 544 | } | 548 | } |
| 545 | self.create_branch_at_commit(branch_name, &commit_id)?; | 549 | self.create_branch_at_commit(branch_name, &commit_id)?; |
| 546 | self.checkout(branch_name)?; | 550 | self.checkout(branch_name)?; |
| 547 | } | 551 | } |
| 548 | Ok(patches_to_apply) | 552 | Ok(patches_to_apply) |
| 549 | } | 553 | } |
| 550 | fn create_commit_from_patch(&self, patch: &nostr::Event) -> Result<Oid> { | 554 | fn create_commit_from_patch( |
| 551 | let commit_id = get_commit_id_from_patch(patch)?; | 555 | &self, |
| 552 | if self.does_commit_exist(&commit_id)? { | 556 | patch: &nostr::Event, |
| 553 | return Ok(Oid::from_str(&commit_id)?); | 557 | parent_commit_id_override: Option<String>, |
| 558 | ) -> Result<Oid> { | ||
| 559 | let commit_id = get_commit_id_from_patch(patch); | ||
| 560 | if let Ok(commit_id) = &commit_id { | ||
| 561 | if self.does_commit_exist(commit_id).unwrap_or(false) { | ||
| 562 | return Ok(Oid::from_str(commit_id)?); | ||
| 563 | } | ||
| 554 | } | 564 | } |
| 555 | let parent_commit_id = tag_value(patch, "parent-commit")?; | 565 | |
| 566 | let parent_commit_id = if let Some(commit_id) = parent_commit_id_override.clone() { | ||
| 567 | commit_id | ||
| 568 | } else { | ||
| 569 | tag_value(patch, "parent-commit")? | ||
| 570 | }; | ||
| 556 | 571 | ||
| 557 | let parent_commit = self | 572 | let parent_commit = self |
| 558 | .git_repo | 573 | .git_repo |
| @@ -604,25 +619,38 @@ impl RepoActions for Repo { | |||
| 604 | // were identical when in a scenario when they should be different but I dont | 619 | // were identical when in a scenario when they should be different but I dont |
| 605 | // think we have a test case for it. surely we should be using the | 620 | // think we have a test case for it. surely we should be using the |
| 606 | // extract_sig_from_patch_tags outputs to address this? | 621 | // extract_sig_from_patch_tags outputs to address this? |
| 607 | if !applied_oid.to_string().eq(&commit_id) { | 622 | let custom_parent = if let Some(ovderride_parent) = parent_commit_id_override { |
| 608 | let commit = self.git_repo.find_commit(applied_oid)?; | 623 | if let Ok(tag_parent) = tag_value(patch, "parent-commit") { |
| 609 | applied_oid = commit | 624 | ovderride_parent != tag_parent |
| 610 | .amend( | 625 | } else { |
| 611 | None, | 626 | true |
| 612 | Some(&commit.author()), | 627 | } |
| 613 | Some(&commit.committer()), | 628 | } else { |
| 614 | None, | 629 | false |
| 615 | None, | 630 | }; |
| 616 | None, | 631 | if !custom_parent { |
| 617 | ) | 632 | if let Ok(commit_id) = &commit_id { |
| 618 | .context("cannot amend commit to produce new oid")?; | 633 | if !applied_oid.to_string().eq(commit_id) { |
| 619 | } | 634 | let commit = self.git_repo.find_commit(applied_oid)?; |
| 620 | if !applied_oid.to_string().eq(&commit_id) { | 635 | applied_oid = commit |
| 621 | bail!( | 636 | .amend( |
| 622 | "when applied the patch commit id ({}) doesn't match the one specified in the event tag ({})", | 637 | None, |
| 623 | applied_oid.to_string(), | 638 | Some(&commit.author()), |
| 624 | get_commit_id_from_patch(patch)?, | 639 | Some(&commit.committer()), |
| 625 | ); | 640 | None, |
| 641 | None, | ||
| 642 | None, | ||
| 643 | ) | ||
| 644 | .context("cannot amend commit to produce new oid")?; | ||
| 645 | } | ||
| 646 | if !applied_oid.to_string().eq(commit_id) { | ||
| 647 | bail!( | ||
| 648 | "when applied the patch commit id ({}) doesn't match the one specified in the event tag ({})", | ||
| 649 | applied_oid.to_string(), | ||
| 650 | get_commit_id_from_patch(patch)?, | ||
| 651 | ); | ||
| 652 | } | ||
| 653 | } | ||
| 626 | } | 654 | } |
| 627 | self.git_repo.set_index(&mut existing_index)?; | 655 | self.git_repo.set_index(&mut existing_index)?; |
| 628 | Ok(applied_oid) | 656 | Ok(applied_oid) |
| @@ -1651,7 +1679,7 @@ mod tests { | |||
| 1651 | test_repo.populate()?; | 1679 | test_repo.populate()?; |
| 1652 | let git_repo = Repo::from_path(&test_repo.dir)?; | 1680 | let git_repo = Repo::from_path(&test_repo.dir)?; |
| 1653 | println!("{:?}", &patch_event); | 1681 | println!("{:?}", &patch_event); |
| 1654 | git_repo.create_commit_from_patch(&patch_event)?; | 1682 | git_repo.create_commit_from_patch(&patch_event, None)?; |
| 1655 | let commit_id = tag_value(&patch_event, "commit")?; | 1683 | let commit_id = tag_value(&patch_event, "commit")?; |
| 1656 | // does commit with id exist? | 1684 | // does commit with id exist? |
| 1657 | assert!(git_repo.does_commit_exist(&commit_id)?); | 1685 | assert!(git_repo.does_commit_exist(&commit_id)?); |
diff --git a/tests/git_remote_nostr/fetch.rs b/tests/git_remote_nostr/fetch.rs index 26d0b5b..17fd6d4 100644 --- a/tests/git_remote_nostr/fetch.rs +++ b/tests/git_remote_nostr/fetch.rs | |||
| @@ -140,8 +140,7 @@ mod when_first_git_server_fails_ { | |||
| 140 | #[tokio::test] | 140 | #[tokio::test] |
| 141 | #[serial] | 141 | #[serial] |
| 142 | async fn creates_commits_from_open_proposal_with_no_warnings_printed() -> Result<()> { | 142 | async fn creates_commits_from_open_proposal_with_no_warnings_printed() -> Result<()> { |
| 143 | let (events, source_git_repo) = prep_source_repo_and_events_including_proposals().await?; | 143 | let (events, _) = prep_source_repo_and_events_including_proposals().await?; |
| 144 | let source_path = source_git_repo.dir.to_str().unwrap().to_string(); | ||
| 145 | 144 | ||
| 146 | let (mut r51, mut r52, mut r53, mut r55, mut r56, mut r57) = ( | 145 | let (mut r51, mut r52, mut r53, mut r55, mut r56, mut r57) = ( |
| 147 | Relay::new(8051, None, None), | 146 | Relay::new(8051, None, None), |
| @@ -166,7 +165,6 @@ async fn creates_commits_from_open_proposal_with_no_warnings_printed() -> Result | |||
| 166 | let mut p = cli_tester_after_fetch(&git_repo)?; | 165 | let mut p = cli_tester_after_fetch(&git_repo)?; |
| 167 | p.send_line(format!("fetch {proposal_tip} refs/heads/{branch_name}").as_str())?; | 166 | p.send_line(format!("fetch {proposal_tip} refs/heads/{branch_name}").as_str())?; |
| 168 | p.send_line("")?; | 167 | p.send_line("")?; |
| 169 | p.expect(format!("fetching {source_path} over filesystem...\r\n").as_str())?; | ||
| 170 | // expect no errors | 168 | // expect no errors |
| 171 | p.expect_after_whitespace("\r\n")?; | 169 | p.expect_after_whitespace("\r\n")?; |
| 172 | p.exit()?; | 170 | p.exit()?; |
diff --git a/tests/git_remote_nostr/list.rs b/tests/git_remote_nostr/list.rs index d173cc7..37cff30 100644 --- a/tests/git_remote_nostr/list.rs +++ b/tests/git_remote_nostr/list.rs | |||
| @@ -52,6 +52,10 @@ mod without_state_announcement { | |||
| 52 | assert_eq!( | 52 | assert_eq!( |
| 53 | res.split("\r\n") | 53 | res.split("\r\n") |
| 54 | .map(|e| e.to_string()) | 54 | .map(|e| e.to_string()) |
| 55 | .filter(|s| !s.contains("remote: ") | ||
| 56 | && !s.contains("Receiving objects") | ||
| 57 | && !s.contains("Resolving deltas") | ||
| 58 | && !s.contains("fetching /")) | ||
| 55 | .collect::<HashSet<String>>(), | 59 | .collect::<HashSet<String>>(), |
| 56 | HashSet::from([ | 60 | HashSet::from([ |
| 57 | "@refs/heads/main HEAD".to_string(), | 61 | "@refs/heads/main HEAD".to_string(), |
| @@ -220,6 +224,10 @@ mod with_state_announcement { | |||
| 220 | assert_eq!( | 224 | assert_eq!( |
| 221 | res.split("\r\n") | 225 | res.split("\r\n") |
| 222 | .map(|e| e.to_string()) | 226 | .map(|e| e.to_string()) |
| 227 | .filter(|s| !s.contains("remote: ") | ||
| 228 | && !s.contains("Receiving objects") | ||
| 229 | && !s.contains("Resolving deltas") | ||
| 230 | && !s.contains("fetching /")) | ||
| 223 | .collect::<HashSet<String>>(), | 231 | .collect::<HashSet<String>>(), |
| 224 | HashSet::from([ | 232 | HashSet::from([ |
| 225 | "@refs/heads/main HEAD".to_string(), | 233 | "@refs/heads/main HEAD".to_string(), |