upleb.uk

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

summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorDanConwayDev <DanConwayDev@protonmail.com>2024-08-08 17:34:40 +0100
committerDanConwayDev <DanConwayDev@protonmail.com>2024-08-08 17:36:44 +0100
commit9971f23a184d57600ea9b1962910d32bf6aec185 (patch)
treee4a82036c4785ddb8080be9e99e116cd3a7d10fa /src
parentfa2ab4b0dfc31e315d53bd9e36ada41ca95ec2d6 (diff)
feat(remote): `push` force push proposal
will issue a proposal revision
Diffstat (limited to 'src')
-rw-r--r--src/git_remote_helper.rs102
1 files changed, 72 insertions, 30 deletions
diff --git a/src/git_remote_helper.rs b/src/git_remote_helper.rs
index f36b23b..be230b1 100644
--- a/src/git_remote_helper.rs
+++ b/src/git_remote_helper.rs
@@ -33,7 +33,10 @@ use sub_commands::{
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 tag_value,
35 }, 35 },
36 send::{event_is_revision_root, event_to_cover_letter, generate_patch_event, send_events}, 36 send::{
37 event_is_revision_root, event_to_cover_letter, generate_cover_letter_and_patch_events,
38 generate_patch_event, send_events,
39 },
37}; 40};
38 41
39#[cfg(not(test))] 42#[cfg(not(test))]
@@ -656,21 +659,42 @@ async fn push(
656 if let Some((_, (proposal, patches))) = 659 if let Some((_, (proposal, patches))) =
657 find_proposal_and_patches_by_branch_name(to, &open_proposals) 660 find_proposal_and_patches_by_branch_name(to, &open_proposals)
658 { 661 {
659 if to.starts_with('+') { 662 if [repo_ref.maintainers.clone(), vec![proposal.author()]]
660 // TODO do force push - issue as revision 663 .concat()
661 } else { 664 .contains(&user_ref.public_key)
662 let tip_patch = patches.first().unwrap(); 665 {
663 let tip_of_proposal = get_commit_id_from_patch(tip_patch)?;
664 let tip_of_proposal_commit =
665 git_repo.get_commit_or_tip_of_reference(&tip_of_proposal)?;
666 let tip_of_pushed_branch = git_repo.get_commit_or_tip_of_reference(from)?; 666 let tip_of_pushed_branch = git_repo.get_commit_or_tip_of_reference(from)?;
667 let (mut ahead, behind) = git_repo 667 if refspec.starts_with('+') {
668 .get_commits_ahead_behind(&tip_of_proposal_commit, &tip_of_pushed_branch)?; 668 // force push
669 if behind.is_empty() { 669 let (_, main_tip) = git_repo.get_main_or_master_branch()?;
670 if [repo_ref.maintainers.clone(), vec![proposal.author()]] 670 let (mut ahead, _) =
671 .concat() 671 git_repo.get_commits_ahead_behind(&main_tip, &tip_of_pushed_branch)?;
672 .contains(&user_ref.public_key) 672 ahead.reverse();
673 for patch in generate_cover_letter_and_patch_events(
674 None,
675 git_repo,
676 &ahead,
677 &signer,
678 repo_ref,
679 &Some(proposal.id().to_string()),
680 &[],
681 )
682 .await?
673 { 683 {
684 events.push(patch);
685 }
686 } else {
687 // fast forward push
688 let tip_patch = patches.first().unwrap();
689 let tip_of_proposal = get_commit_id_from_patch(tip_patch)?;
690 let tip_of_proposal_commit =
691 git_repo.get_commit_or_tip_of_reference(&tip_of_proposal)?;
692
693 let (mut ahead, behind) = git_repo.get_commits_ahead_behind(
694 &tip_of_proposal_commit,
695 &tip_of_pushed_branch,
696 )?;
697 if behind.is_empty() {
674 let thread_id = if let Ok(root_event_id) = get_event_root(tip_patch) { 698 let thread_id = if let Ok(root_event_id) = get_event_root(tip_patch) {
675 root_event_id 699 root_event_id
676 } else { 700 } else {
@@ -702,25 +726,25 @@ async fn push(
702 parent_patch = new_patch; 726 parent_patch = new_patch;
703 } 727 }
704 } else { 728 } else {
729 // we shouldn't get here
730 term.write_line(
731 format!(
732 "WARNING: failed to push {from} as nostr proposal. Try and force push ",
733 )
734 .as_str(),
735 )
736 .unwrap();
705 println!( 737 println!(
706 "error {to} permission denied. you are not the proposal author or a repo maintainer" 738 "error {to} cannot fastforward as newer patches found on proposal"
707 ); 739 );
708 rejected_proposal_refspecs.push(refspec.to_string()); 740 rejected_proposal_refspecs.push(refspec.to_string());
709 } 741 }
710 } else {
711 // we shouldn't get here
712 term.write_line(
713 format!(
714 "WARNING: failed to push {from} as nostr proposal. Try and force push ",
715 )
716 .as_str(),
717 )
718 .unwrap();
719 println!(
720 "error {to} cannot fastforward as newer patches found on proposal"
721 );
722 rejected_proposal_refspecs.push(refspec.to_string());
723 } 742 }
743 } else {
744 println!(
745 "error {to} permission denied. you are not the proposal author or a repo maintainer"
746 );
747 rejected_proposal_refspecs.push(refspec.to_string());
724 } 748 }
725 } else { 749 } else {
726 // TODO new proposal / proposal no longer open 750 // TODO new proposal / proposal no longer open
@@ -1046,7 +1070,14 @@ fn refspec_to_from_to(refspec: &str) -> Result<(&str, &str)> {
1046 ); 1070 );
1047 } 1071 }
1048 let parts = refspec.split(':').collect::<Vec<&str>>(); 1072 let parts = refspec.split(':').collect::<Vec<&str>>();
1049 Ok((parts.first().unwrap(), parts.get(1).unwrap())) 1073 Ok((
1074 if parts.first().unwrap().starts_with('+') {
1075 &parts.first().unwrap()[1..]
1076 } else {
1077 parts.first().unwrap()
1078 },
1079 parts.get(1).unwrap(),
1080 ))
1050} 1081}
1051 1082
1052fn refspec_remote_ref_name( 1083fn refspec_remote_ref_name(
@@ -1061,7 +1092,8 @@ fn refspec_remote_ref_name(
1061 Ok(format!( 1092 Ok(format!(
1062 "refs/remotes/{}/{}", 1093 "refs/remotes/{}/{}",
1063 nostr_remote.name().context("remote should have a name")?, 1094 nostr_remote.name().context("remote should have a name")?,
1064 to.replace("refs/heads/", ""), // TODO only replace if it begins with this 1095 to.replace("refs/heads/", ""), /* TODO only replace if it begins with this
1096 * TODO what about tags? */
1065 )) 1097 ))
1066} 1098}
1067 1099
@@ -1289,4 +1321,14 @@ mod tests {
1289 } 1321 }
1290 } 1322 }
1291 } 1323 }
1324
1325 mod refspec_to_from_to {
1326 use super::*;
1327
1328 #[test]
1329 fn trailing_plus_stripped() {
1330 let (from, _) = refspec_to_from_to("+testing:testingb").unwrap();
1331 assert_eq!(from, "testing");
1332 }
1333 }
1292} 1334}