upleb.uk

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

summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDanConwayDev <DanConwayDev@protonmail.com>2024-08-07 10:20:48 +0100
committerDanConwayDev <DanConwayDev@protonmail.com>2024-08-07 12:13:29 +0100
commit843a3c2dfebf661bd47f0a0faf2849cc660b7349 (patch)
tree97f59116114b3372e7a504526577e8d9f20cbf0b
parent406f6d70f6a71cbd8796268f6c36711e893ab9d5 (diff)
feat(remote): `fetch` applies proposal commits
that have been proposal tips returned by `list` can be found
-rw-r--r--src/git_remote_helper.rs73
-rw-r--r--tests/git_remote_helper.rs100
2 files changed, 159 insertions, 14 deletions
diff --git a/src/git_remote_helper.rs b/src/git_remote_helper.rs
index d7363cf..4cafba1 100644
--- a/src/git_remote_helper.rs
+++ b/src/git_remote_helper.rs
@@ -31,6 +31,7 @@ use sub_commands::{
31 list::{ 31 list::{
32 get_all_proposal_patch_events_from_cache, get_commit_id_from_patch, 32 get_all_proposal_patch_events_from_cache, get_commit_id_from_patch,
33 get_most_recent_patch_with_ancestors, get_proposals_and_revisions_from_cache, status_kinds, 33 get_most_recent_patch_with_ancestors, get_proposals_and_revisions_from_cache, status_kinds,
34 tag_value,
34 }, 35 },
35 send::{event_is_revision_root, event_to_cover_letter, send_events}, 36 send::{event_is_revision_root, event_to_cover_letter, send_events},
36}; 37};
@@ -104,7 +105,7 @@ async fn main() -> Result<()> {
104 println!("unsupported"); 105 println!("unsupported");
105 } 106 }
106 ["fetch", oid, refstr] => { 107 ["fetch", oid, refstr] => {
107 fetch(&git_repo, &repo_ref, &stdin, oid, refstr)?; 108 fetch(&git_repo, &repo_ref, &stdin, oid, refstr).await?;
108 } 109 }
109 ["push", refspec] => { 110 ["push", refspec] => {
110 push( 111 push(
@@ -431,14 +432,14 @@ async fn get_open_proposals(
431 Ok(open_proposals) 432 Ok(open_proposals)
432} 433}
433 434
434fn fetch( 435async fn fetch(
435 git_repo: &Repo, 436 git_repo: &Repo,
436 repo_ref: &RepoRef, 437 repo_ref: &RepoRef,
437 stdin: &Stdin, 438 stdin: &Stdin,
438 oid: &str, 439 oid: &str,
439 refstr: &str, 440 refstr: &str,
440) -> Result<()> { 441) -> Result<()> {
441 let fetch_batch = get_oids_from_fetch_batch(stdin, oid, refstr)?; 442 let mut fetch_batch = get_oids_from_fetch_batch(stdin, oid, refstr)?;
442 443
443 let oids_from_git_servers = fetch_batch 444 let oids_from_git_servers = fetch_batch
444 .iter() 445 .iter()
@@ -465,20 +466,64 @@ fn fetch(
465 )?; 466 )?;
466 errors.insert(short_name.to_string(), e); 467 errors.insert(short_name.to_string(), e);
467 } else { 468 } else {
468 term.flush()?; 469 break;
469 println!();
470 return Ok(());
471 } 470 }
472 } 471 }
472
473 if oids_from_git_servers
474 .iter()
475 .any(|oid| !git_repo.does_commit_exist(oid).unwrap())
476 {
477 bail!(
478 "failed to fetch objects in nostr state event from:\r\n{}",
479 errors
480 .iter()
481 .map(|(url, error)| format!("{url}: {error}"))
482 .collect::<Vec<String>>()
483 .join("\r\n")
484 );
485 }
486
487 let open_proposals = get_open_proposals(git_repo, repo_ref).await?;
488
489 fetch_batch.retain(|refstr, _| refstr.contains("refs/heads/prs/"));
490
491 for (refstr, oid) in fetch_batch {
492 if let Some((_, (_, patches))) = open_proposals.iter().find(|(_, (proposal, _))| {
493 if let Ok(cl) = event_to_cover_letter(proposal) {
494 if let Ok(branch_name) = cl.get_branch_name() {
495 branch_name.eq(&refstr.replace("refs/heads/", ""))
496 } else {
497 false
498 }
499 } else {
500 false
501 }
502 }) {
503 if !git_repo.does_commit_exist(&oid)? {
504 let mut patches_ancestor_first = patches.clone();
505 patches_ancestor_first.reverse();
506 if git_repo.does_commit_exist(&tag_value(
507 patches_ancestor_first.first().unwrap(),
508 "parent-commit",
509 )?)? {
510 for patch in &patches_ancestor_first {
511 git_repo.create_commit_from_patch(patch)?;
512 }
513 } else {
514 term.write_line(
515 format!("WARNING: cannot find parent commit for {refstr}").as_str(),
516 )?;
517 }
518 }
519 } else {
520 term.write_line(format!("WARNING: cannot find proposal for {refstr}").as_str())?;
521 }
522 }
523
473 term.flush()?; 524 term.flush()?;
474 bail!( 525 println!();
475 "failed to fetch objects in nostr state event from:\r\n{}", 526 Ok(())
476 errors
477 .iter()
478 .map(|(url, error)| format!("{url}: {error}"))
479 .collect::<Vec<String>>()
480 .join("\r\n")
481 );
482} 527}
483 528
484fn fetch_from_git_server( 529fn fetch_from_git_server(
diff --git a/tests/git_remote_helper.rs b/tests/git_remote_helper.rs
index bfe0e25..66a0be5 100644
--- a/tests/git_remote_helper.rs
+++ b/tests/git_remote_helper.rs
@@ -154,6 +154,50 @@ async fn generate_repo_with_state_event() -> Result<(nostr::Event, GitTestRepo)>
154 Ok((state_event.clone(), source_git_repo)) 154 Ok((state_event.clone(), source_git_repo))
155} 155}
156 156
157async fn prep_source_repo_and_events_including_proposals()
158-> Result<(Vec<nostr::Event>, GitTestRepo)> {
159 let (state_event, source_git_repo) = generate_repo_with_state_event().await?;
160 let source_path = source_git_repo.dir.to_str().unwrap().to_string();
161
162 let events = vec![
163 generate_test_key_1_metadata_event("fred"),
164 generate_test_key_1_relay_list_event(),
165 generate_repo_ref_event_with_git_server(vec![source_path.to_string()]),
166 state_event,
167 ];
168 // fallback (51,52) user write (53, 55) repo (55, 56) blaster (57)
169 let (mut r51, mut r52, mut r53, mut r55, mut r56, mut r57) = (
170 Relay::new(8051, None, None),
171 Relay::new(8052, None, None),
172 Relay::new(8053, None, None),
173 Relay::new(8055, None, None),
174 Relay::new(8056, None, None),
175 Relay::new(8057, None, None),
176 );
177 r51.events = events.clone();
178 r55.events = events;
179
180 let cli_tester_handle = std::thread::spawn(move || -> Result<()> {
181 cli_tester_create_proposals()?;
182 for p in [51, 52, 53, 55, 56, 57] {
183 relay::shutdown_relay(8000 + p)?;
184 }
185 Ok(())
186 });
187 // launch relays
188 let _ = join!(
189 r51.listen_until_close(),
190 r52.listen_until_close(),
191 r53.listen_until_close(),
192 r55.listen_until_close(),
193 r56.listen_until_close(),
194 r57.listen_until_close(),
195 );
196 cli_tester_handle.join().unwrap()?;
197
198 Ok((r55.events, source_git_repo))
199}
200
157mod initially_runs_fetch { 201mod initially_runs_fetch {
158 202
159 use super::*; 203 use super::*;
@@ -689,6 +733,62 @@ mod fetch {
689 Ok(()) 733 Ok(())
690 } 734 }
691 } 735 }
736
737 #[tokio::test]
738 #[serial]
739 async fn creates_commits_from_open_proposal_with_no_warngins_printed() -> Result<()> {
740 let (events, source_git_repo) = prep_source_repo_and_events_including_proposals().await?;
741 let source_path = source_git_repo.dir.to_str().unwrap().to_string();
742
743 let (mut r51, mut r52, mut r53, mut r55, mut r56, mut r57) = (
744 Relay::new(8051, None, None),
745 Relay::new(8052, None, None),
746 Relay::new(8053, None, None),
747 Relay::new(8055, None, None),
748 Relay::new(8056, None, None),
749 Relay::new(8057, None, None),
750 );
751 r51.events = events.clone();
752 r55.events = events.clone();
753
754 let git_repo = prep_git_repo()?;
755
756 let cli_tester_handle = std::thread::spawn(move || -> Result<()> {
757 let branch_name = get_proposal_branch_name_from_events(&events, FEATURE_BRANCH_NAME_1)?;
758 let proposal_tip = cli_tester_create_proposal_branches_ready_to_send()?
759 .get_tip_of_local_branch(FEATURE_BRANCH_NAME_1)?;
760
761 assert!(git_repo.git_repo.find_commit(proposal_tip).is_err());
762
763 let mut p = cli_tester_after_fetch(&git_repo)?;
764 p.send_line(format!("fetch {proposal_tip} refs/heads/{branch_name}").as_str())?;
765 p.send_line("")?;
766 p.expect(format!("fetching from {source_path}...\r\n").as_str())?;
767 // expect no errors
768 p.expect_after_whitespace("\r\n")?;
769 p.exit()?;
770 for p in [51, 52, 53, 55, 56, 57] {
771 relay::shutdown_relay(8000 + p)?;
772 }
773
774 assert!(git_repo.git_repo.find_commit(proposal_tip).is_ok());
775
776 Ok(())
777 });
778 // launch relays
779 let _ = join!(
780 r51.listen_until_close(),
781 r52.listen_until_close(),
782 r53.listen_until_close(),
783 r55.listen_until_close(),
784 r56.listen_until_close(),
785 r57.listen_until_close(),
786 );
787
788 cli_tester_handle.join().unwrap()?;
789
790 Ok(())
791 }
692} 792}
693 793
694mod push { 794mod push {