upleb.uk

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

summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/git_remote_helper.rs90
-rw-r--r--tests/git_remote_helper.rs29
2 files changed, 76 insertions, 43 deletions
diff --git a/src/git_remote_helper.rs b/src/git_remote_helper.rs
index be230b1..ff053f6 100644
--- a/src/git_remote_helper.rs
+++ b/src/git_remote_helper.rs
@@ -287,10 +287,19 @@ async fn list(
287 state.retain(|k, _| !k.starts_with("refs/heads/prs/")); 287 state.retain(|k, _| !k.starts_with("refs/heads/prs/"));
288 288
289 let open_proposals = get_open_proposals(git_repo, repo_ref).await?; 289 let open_proposals = get_open_proposals(git_repo, repo_ref).await?;
290 290 let current_user = get_curent_user(git_repo)?;
291 for (_, (proposal, patches)) in open_proposals { 291 for (_, (proposal, patches)) in open_proposals {
292 if let Ok(cl) = event_to_cover_letter(&proposal) { 292 if let Ok(cl) = event_to_cover_letter(&proposal) {
293 if let Ok(branch_name) = cl.get_branch_name() { 293 if let Ok(mut branch_name) = cl.get_branch_name() {
294 branch_name = if let Some(public_key) = current_user {
295 if proposal.author().eq(&public_key) {
296 cl.branch_name.to_string()
297 } else {
298 branch_name
299 }
300 } else {
301 branch_name
302 };
294 if let Some(patch) = patches.first() { 303 if let Some(patch) = patches.first() {
295 // TODO this isn't resilient because the commit id stated may not be correct 304 // TODO this isn't resilient because the commit id stated may not be correct
296 // we will need to check whether the commit id exists in the repo or apply the 305 // we will need to check whether the commit id exists in the repo or apply the
@@ -435,6 +444,20 @@ async fn get_open_proposals(
435 Ok(open_proposals) 444 Ok(open_proposals)
436} 445}
437 446
447fn get_curent_user(git_repo: &Repo) -> Result<Option<PublicKey>> {
448 Ok(
449 if let Some(npub) = git_repo.get_git_config_item("nostr.npub", None)? {
450 if let Ok(public_key) = PublicKey::parse(npub) {
451 Some(public_key)
452 } else {
453 None
454 }
455 } else {
456 None
457 },
458 )
459}
460
438async fn fetch( 461async fn fetch(
439 git_repo: &Repo, 462 git_repo: &Repo,
440 repo_ref: &RepoRef, 463 repo_ref: &RepoRef,
@@ -487,32 +510,36 @@ async fn fetch(
487 ); 510 );
488 } 511 }
489 512
490 let open_proposals = get_open_proposals(git_repo, repo_ref).await?;
491
492 fetch_batch.retain(|refstr, _| refstr.contains("refs/heads/prs/")); 513 fetch_batch.retain(|refstr, _| refstr.contains("refs/heads/prs/"));
493 514
494 for (refstr, oid) in fetch_batch { 515 if !fetch_batch.is_empty() {
495 if let Some((_, (_, patches))) = 516 let open_proposals = get_open_proposals(git_repo, repo_ref).await?;
496 find_proposal_and_patches_by_branch_name(&refstr, &open_proposals) 517
497 { 518 let current_user = get_curent_user(git_repo)?;
498 if !git_repo.does_commit_exist(&oid)? { 519
499 let mut patches_ancestor_first = patches.clone(); 520 for (refstr, oid) in fetch_batch {
500 patches_ancestor_first.reverse(); 521 if let Some((_, (_, patches))) =
501 if git_repo.does_commit_exist(&tag_value( 522 find_proposal_and_patches_by_branch_name(&refstr, &open_proposals, &current_user)
502 patches_ancestor_first.first().unwrap(), 523 {
503 "parent-commit", 524 if !git_repo.does_commit_exist(&oid)? {
504 )?)? { 525 let mut patches_ancestor_first = patches.clone();
505 for patch in &patches_ancestor_first { 526 patches_ancestor_first.reverse();
506 git_repo.create_commit_from_patch(patch)?; 527 if git_repo.does_commit_exist(&tag_value(
528 patches_ancestor_first.first().unwrap(),
529 "parent-commit",
530 )?)? {
531 for patch in &patches_ancestor_first {
532 git_repo.create_commit_from_patch(patch)?;
533 }
534 } else {
535 term.write_line(
536 format!("WARNING: cannot find parent commit for {refstr}").as_str(),
537 )?;
507 } 538 }
508 } else {
509 term.write_line(
510 format!("WARNING: cannot find parent commit for {refstr}").as_str(),
511 )?;
512 } 539 }
540 } else {
541 term.write_line(format!("WARNING: cannot find proposal for {refstr}").as_str())?;
513 } 542 }
514 } else {
515 term.write_line(format!("WARNING: cannot find proposal for {refstr}").as_str())?;
516 } 543 }
517 } 544 }
518 545
@@ -524,10 +551,20 @@ async fn fetch(
524fn find_proposal_and_patches_by_branch_name<'a>( 551fn find_proposal_and_patches_by_branch_name<'a>(
525 refstr: &'a str, 552 refstr: &'a str,
526 open_proposals: &'a HashMap<EventId, (Event, Vec<Event>)>, 553 open_proposals: &'a HashMap<EventId, (Event, Vec<Event>)>,
554 current_user: &Option<PublicKey>,
527) -> Option<(&'a EventId, &'a (Event, Vec<Event>))> { 555) -> Option<(&'a EventId, &'a (Event, Vec<Event>))> {
528 open_proposals.iter().find(|(_, (proposal, _))| { 556 open_proposals.iter().find(|(_, (proposal, _))| {
529 if let Ok(cl) = event_to_cover_letter(proposal) { 557 if let Ok(cl) = event_to_cover_letter(proposal) {
530 if let Ok(branch_name) = cl.get_branch_name() { 558 if let Ok(mut branch_name) = cl.get_branch_name() {
559 branch_name = if let Some(public_key) = current_user {
560 if proposal.author().eq(public_key) {
561 cl.branch_name.to_string()
562 } else {
563 branch_name
564 }
565 } else {
566 branch_name
567 };
531 branch_name.eq(&refstr.replace("refs/heads/", "")) 568 branch_name.eq(&refstr.replace("refs/heads/", ""))
532 } else { 569 } else {
533 false 570 false
@@ -652,18 +689,19 @@ async fn push(
652 let mut rejected_proposal_refspecs = vec![]; 689 let mut rejected_proposal_refspecs = vec![];
653 if !proposal_refspecs.is_empty() { 690 if !proposal_refspecs.is_empty() {
654 let open_proposals = get_open_proposals(git_repo, repo_ref).await?; 691 let open_proposals = get_open_proposals(git_repo, repo_ref).await?;
692 let current_user = get_curent_user(git_repo)?;
655 693
656 for refspec in &proposal_refspecs { 694 for refspec in &proposal_refspecs {
657 let (from, to) = refspec_to_from_to(refspec).unwrap(); 695 let (from, to) = refspec_to_from_to(refspec).unwrap();
696 let tip_of_pushed_branch = git_repo.get_commit_or_tip_of_reference(from)?;
658 697
659 if let Some((_, (proposal, patches))) = 698 if let Some((_, (proposal, patches))) =
660 find_proposal_and_patches_by_branch_name(to, &open_proposals) 699 find_proposal_and_patches_by_branch_name(to, &open_proposals, &current_user)
661 { 700 {
662 if [repo_ref.maintainers.clone(), vec![proposal.author()]] 701 if [repo_ref.maintainers.clone(), vec![proposal.author()]]
663 .concat() 702 .concat()
664 .contains(&user_ref.public_key) 703 .contains(&user_ref.public_key)
665 { 704 {
666 let tip_of_pushed_branch = git_repo.get_commit_or_tip_of_reference(from)?;
667 if refspec.starts_with('+') { 705 if refspec.starts_with('+') {
668 // force push 706 // force push
669 let (_, main_tip) = git_repo.get_main_or_master_branch()?; 707 let (_, main_tip) = git_repo.get_main_or_master_branch()?;
diff --git a/tests/git_remote_helper.rs b/tests/git_remote_helper.rs
index f768806..7cf6799 100644
--- a/tests/git_remote_helper.rs
+++ b/tests/git_remote_helper.rs
@@ -28,15 +28,20 @@ fn get_nostr_remote_url() -> Result<String> {
28 28
29fn prep_git_repo() -> Result<GitTestRepo> { 29fn prep_git_repo() -> Result<GitTestRepo> {
30 let test_repo = GitTestRepo::without_repo_in_git_config(); 30 let test_repo = GitTestRepo::without_repo_in_git_config();
31 set_git_nostr_login_config(&test_repo)?;
32 test_repo.add_remote(NOSTR_REMOTE_NAME, &get_nostr_remote_url()?)?;
33 test_repo.populate()?;
34 Ok(test_repo)
35}
36
37fn set_git_nostr_login_config(test_repo: &GitTestRepo) -> Result<()> {
31 let mut config = test_repo 38 let mut config = test_repo
32 .git_repo 39 .git_repo
33 .config() 40 .config()
34 .context("cannot open git config")?; 41 .context("cannot open git config")?;
35 config.set_str("nostr.nsec", TEST_KEY_1_NSEC)?; 42 config.set_str("nostr.nsec", TEST_KEY_2_NSEC)?;
36 config.set_str("nostr.npub", TEST_KEY_1_NPUB)?; 43 config.set_str("nostr.npub", TEST_KEY_2_NPUB)?;
37 test_repo.add_remote(NOSTR_REMOTE_NAME, &get_nostr_remote_url()?)?; 44 Ok(())
38 test_repo.populate()?;
39 Ok(test_repo)
40} 45}
41 46
42fn clone_git_repo_with_nostr_url() -> Result<GitTestRepo> { 47fn clone_git_repo_with_nostr_url() -> Result<GitTestRepo> {
@@ -45,23 +50,13 @@ fn clone_git_repo_with_nostr_url() -> Result<GitTestRepo> {
45 CliTester::new_git_with_remote_helper_from_dir(&path, ["clone", &get_nostr_remote_url()?, "."]) 50 CliTester::new_git_with_remote_helper_from_dir(&path, ["clone", &get_nostr_remote_url()?, "."])
46 .expect_end_eventually_and_print()?; 51 .expect_end_eventually_and_print()?;
47 let test_repo = GitTestRepo::open(&path)?; 52 let test_repo = GitTestRepo::open(&path)?;
48 let mut config = test_repo 53 set_git_nostr_login_config(&test_repo)?;
49 .git_repo
50 .config()
51 .context("cannot open git config")?;
52 config.set_str("nostr.nsec", TEST_KEY_1_NSEC)?;
53 config.set_str("nostr.npub", TEST_KEY_1_NPUB)?;
54 Ok(test_repo) 54 Ok(test_repo)
55} 55}
56 56
57fn prep_git_repo_minus_1_commit() -> Result<GitTestRepo> { 57fn prep_git_repo_minus_1_commit() -> Result<GitTestRepo> {
58 let test_repo = GitTestRepo::without_repo_in_git_config(); 58 let test_repo = GitTestRepo::without_repo_in_git_config();
59 let mut config = test_repo 59 set_git_nostr_login_config(&test_repo)?;
60 .git_repo
61 .config()
62 .context("cannot open git config")?;
63 config.set_str("nostr.nsec", TEST_KEY_1_NSEC)?;
64 config.set_str("nostr.npub", TEST_KEY_1_NPUB)?;
65 test_repo.add_remote(NOSTR_REMOTE_NAME, &get_nostr_remote_url()?)?; 60 test_repo.add_remote(NOSTR_REMOTE_NAME, &get_nostr_remote_url()?)?;
66 test_repo.populate_minus_1()?; 61 test_repo.populate_minus_1()?;
67 Ok(test_repo) 62 Ok(test_repo)