upleb.uk

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

summaryrefslogtreecommitdiff
path: root/src/bin/ngit/sub_commands/list.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/bin/ngit/sub_commands/list.rs')
-rw-r--r--src/bin/ngit/sub_commands/list.rs158
1 files changed, 44 insertions, 114 deletions
diff --git a/src/bin/ngit/sub_commands/list.rs b/src/bin/ngit/sub_commands/list.rs
index 133ac83..3d5e876 100644
--- a/src/bin/ngit/sub_commands/list.rs
+++ b/src/bin/ngit/sub_commands/list.rs
@@ -35,7 +35,7 @@ use crate::{
35 git::{Repo, RepoActions, str_to_sha1}, 35 git::{Repo, RepoActions, str_to_sha1},
36 git_events::{ 36 git_events::{
37 commit_msg_from_patch_oneliner, event_is_revision_root, event_to_cover_letter, 37 commit_msg_from_patch_oneliner, event_is_revision_root, event_to_cover_letter,
38 get_parent_commit_from_patch, patch_supports_commit_ids, 38 get_parent_commit_from_patch,
39 }, 39 },
40 repo_ref::get_repo_coordinates_when_remote_unknown, 40 repo_ref::get_repo_coordinates_when_remote_unknown,
41}; 41};
@@ -623,72 +623,6 @@ async fn launch_interactive() -> Result<()> {
623 } 623 }
624 } 624 }
625 625
626 let binding_patch_text_ref = format!(
627 "{} commits",
628 most_recent_proposal_patch_chain_or_pr_or_pr_update.len()
629 );
630 let patch_text_ref = if most_recent_proposal_patch_chain_or_pr_or_pr_update
631 .len()
632 .gt(&1)
633 {
634 binding_patch_text_ref.as_str()
635 } else {
636 "1 commit"
637 };
638
639 let no_support_for_patches_as_branch = most_recent_proposal_patch_chain_or_pr_or_pr_update
640 .iter()
641 .any(|event| !patch_supports_commit_ids(event));
642
643 if no_support_for_patches_as_branch {
644 println!("{patch_text_ref}");
645 return match Interactor::default().choice(
646 PromptChoiceParms::default()
647 .with_default(0)
648 .with_choices(vec![
649 "learn why this proposals can't be checked out".to_string(),
650 format!("apply to current branch with `git am`"),
651 format!("download to ./patches"),
652 "back".to_string(),
653 ]),
654 )? {
655 0 => {
656 println!(
657 "Some proposals are posted as patch without listing a parent commit\n"
658 );
659 println!(
660 "they are not anchored against a particular state of the code base like a standard patch or a pull request can be\n"
661 );
662 println!(
663 "they are designed to reviewed by studying the diff (in a tool like gitworkshop.dev) and if acceptable by a maintainer, applied to the latest version of master with any conflicts resolved as the do so\n"
664 );
665 println!(
666 "this has proven to be a smoother workflow for large scale projects with a high frequency of changes, even when patches are exchanged via email\n"
667 );
668 println!(
669 "by default ngit posts proposals with a parent commit so either workflow can be used"
670 );
671 Interactor::default().choice(
672 PromptChoiceParms::default()
673 .with_default(0)
674 .with_choices(vec!["back".to_string()]),
675 )?;
676 continue;
677 }
678 1 => {
679 launch_git_am_with_patches(most_recent_proposal_patch_chain_or_pr_or_pr_update)
680 }
681 2 => save_patches_to_dir(
682 most_recent_proposal_patch_chain_or_pr_or_pr_update,
683 &git_repo,
684 ),
685 3 => continue,
686 _ => {
687 bail!("unexpected choice")
688 }
689 };
690 }
691
692 let branch_exists = git_repo 626 let branch_exists = git_repo
693 .get_local_branch_names() 627 .get_local_branch_names()
694 .context("gitlib2 will not show a list of local branch names")? 628 .context("gitlib2 will not show a list of local branch names")?
@@ -705,35 +639,36 @@ async fn launch_interactive() -> Result<()> {
705 639
706 let last_patch = most_recent_proposal_patch_chain_or_pr_or_pr_update 640 let last_patch = most_recent_proposal_patch_chain_or_pr_or_pr_update
707 .last() 641 .last()
708 .context( 642 .context("there should be at least one patch as we have already checked for this")?;
709 "there should be at least one patch as we have already checked for this",
710 )?;
711 643
712 let proposal_base_commit = str_to_sha1(&get_parent_commit_from_patch(last_patch, Some(&git_repo))?) 644 let proposal_base_commit = get_parent_commit_from_patch(last_patch, Some(&git_repo))
713 .context("failed to get valid parent commit id from patch")?; 645 .ok()
646 .and_then(|s| str_to_sha1(&s).ok());
714 647
715 let (main_branch_name, master_tip) = git_repo.get_main_or_master_branch()?; 648 let (main_branch_name, master_tip) = git_repo.get_main_or_master_branch()?;
716 649
717 if !git_repo.does_commit_exist(&proposal_base_commit.to_string())? { 650 if let Some(ref base_commit) = proposal_base_commit {
718 println!("your '{main_branch_name}' branch may not be up-to-date."); 651 if !git_repo.does_commit_exist(&base_commit.to_string())? {
719 println!("the proposal parent commit doesnt exist in your local repository."); 652 println!("your '{main_branch_name}' branch may not be up-to-date.");
720 return match Interactor::default().choice(PromptChoiceParms::default().with_default(0).with_choices( 653 println!("the proposal parent commit doesnt exist in your local repository.");
721 vec![ 654 return match Interactor::default().choice(PromptChoiceParms::default().with_default(0).with_choices(
722 format!( 655 vec![
723 "manually run `git pull` on '{main_branch_name}' and select proposal again" 656 format!(
724 ), 657 "manually run `git pull` on '{main_branch_name}' and select proposal again"
725 format!("apply to current branch with `git am`"), 658 ),
726 format!("download to ./patches"), 659 format!("apply to current branch with `git am`"),
727 "back".to_string(), 660 format!("download to ./patches"),
728 ], 661 "back".to_string(),
729 ))? { 662 ],
730 0 | 3 => continue, 663 ))? {
731 1 => launch_git_am_with_patches(most_recent_proposal_patch_chain_or_pr_or_pr_update), 664 0 | 3 => continue,
732 2 => save_patches_to_dir(most_recent_proposal_patch_chain_or_pr_or_pr_update, &git_repo), 665 1 => launch_git_am_with_patches(most_recent_proposal_patch_chain_or_pr_or_pr_update),
733 _ => { 666 2 => save_patches_to_dir(most_recent_proposal_patch_chain_or_pr_or_pr_update, &git_repo),
734 bail!("unexpected choice") 667 _ => {
735 } 668 bail!("unexpected choice")
736 }; 669 }
670 };
671 }
737 } 672 }
738 673
739 let proposal_tip = str_to_sha1( 674 let proposal_tip = str_to_sha1(
@@ -748,8 +683,14 @@ async fn launch_interactive() -> Result<()> {
748 ) 683 )
749 .context("failed to get valid commit_id from patch")?; 684 .context("failed to get valid commit_id from patch")?;
750 685
751 let (_, proposal_behind_main) = 686 let proposal_behind_main_len = if let Some(ref base_commit) = proposal_base_commit {
752 git_repo.get_commits_ahead_behind(&master_tip, &proposal_base_commit)?; 687 git_repo
688 .get_commits_ahead_behind(&master_tip, base_commit)
689 .map(|(_, behind)| behind.len())
690 .unwrap_or(0)
691 } else {
692 0
693 };
753 694
754 // branch doesnt exist 695 // branch doesnt exist
755 if !branch_exists { 696 if !branch_exists {
@@ -758,7 +699,7 @@ async fn launch_interactive() -> Result<()> {
758 format!( 699 format!(
759 "create and checkout proposal branch ({} ahead {} behind '{main_branch_name}')", 700 "create and checkout proposal branch ({} ahead {} behind '{main_branch_name}')",
760 most_recent_proposal_patch_chain_or_pr_or_pr_update.len(), 701 most_recent_proposal_patch_chain_or_pr_or_pr_update.len(),
761 proposal_behind_main.len(), 702 proposal_behind_main_len,
762 ), 703 ),
763 format!("apply to current branch with `git am`"), 704 format!("apply to current branch with `git am`"),
764 format!("download to ./patches"), 705 format!("download to ./patches"),
@@ -815,7 +756,7 @@ async fn launch_interactive() -> Result<()> {
815 format!( 756 format!(
816 "checkout proposal branch ({} ahead {} behind '{main_branch_name}')", 757 "checkout proposal branch ({} ahead {} behind '{main_branch_name}')",
817 most_recent_proposal_patch_chain_or_pr_or_pr_update.len(), 758 most_recent_proposal_patch_chain_or_pr_or_pr_update.len(),
818 proposal_behind_main.len(), 759 proposal_behind_main_len,
819 ), 760 ),
820 format!("apply to current branch with `git am`"), 761 format!("apply to current branch with `git am`"),
821 format!("download to ./patches"), 762 format!("download to ./patches"),
@@ -913,7 +854,7 @@ async fn launch_interactive() -> Result<()> {
913 println!( 854 println!(
914 "updated proposal available ({} ahead {} behind '{main_branch_name}'). existing version is {} ahead {} behind '{main_branch_name}'", 855 "updated proposal available ({} ahead {} behind '{main_branch_name}'). existing version is {} ahead {} behind '{main_branch_name}'",
915 most_recent_proposal_patch_chain_or_pr_or_pr_update.len(), 856 most_recent_proposal_patch_chain_or_pr_or_pr_update.len(),
916 proposal_behind_main.len(), 857 proposal_behind_main_len,
917 local_ahead_of_main.len(), 858 local_ahead_of_main.len(),
918 local_beind_main.len(), 859 local_beind_main.len(),
919 ); 860 );
@@ -930,13 +871,6 @@ async fn launch_interactive() -> Result<()> {
930 )? { 871 )? {
931 0 => { 872 0 => {
932 check_clean(&git_repo)?; 873 check_clean(&git_repo)?;
933 git_repo.create_branch_at_commit(
934 &cover_letter.get_branch_name_with_pr_prefix_and_shorthand_id()?,
935 &proposal_base_commit.to_string(),
936 )?;
937 git_repo.checkout(
938 &cover_letter.get_branch_name_with_pr_prefix_and_shorthand_id()?,
939 )?;
940 let chain_length = most_recent_proposal_patch_chain_or_pr_or_pr_update.len(); 874 let chain_length = most_recent_proposal_patch_chain_or_pr_or_pr_update.len();
941 let _ = git_repo 875 let _ = git_repo
942 .apply_patch_chain( 876 .apply_patch_chain(
@@ -947,7 +881,7 @@ async fn launch_interactive() -> Result<()> {
947 println!( 881 println!(
948 "checked out new version of proposal ({} ahead {} behind '{main_branch_name}'), replacing old version ({} ahead {} behind '{main_branch_name}')", 882 "checked out new version of proposal ({} ahead {} behind '{main_branch_name}'), replacing old version ({} ahead {} behind '{main_branch_name}')",
949 chain_length, 883 chain_length,
950 proposal_behind_main.len(), 884 proposal_behind_main_len,
951 local_ahead_of_main.len(), 885 local_ahead_of_main.len(),
952 local_beind_main.len(), 886 local_beind_main.len(),
953 ); 887 );
@@ -991,7 +925,7 @@ async fn launch_interactive() -> Result<()> {
991 "local proposal branch exists with {} unpublished commits on top of the most up-to-date version of the proposal ({} ahead {} behind '{main_branch_name}')", 925 "local proposal branch exists with {} unpublished commits on top of the most up-to-date version of the proposal ({} ahead {} behind '{main_branch_name}')",
992 local_ahead_of_proposal.len(), 926 local_ahead_of_proposal.len(),
993 local_ahead_of_main.len(), 927 local_ahead_of_main.len(),
994 proposal_behind_main.len(), 928 proposal_behind_main_len,
995 ); 929 );
996 return match Interactor::default().choice( 930 return match Interactor::default().choice(
997 PromptChoiceParms::default() 931 PromptChoiceParms::default()
@@ -1012,7 +946,7 @@ async fn launch_interactive() -> Result<()> {
1012 "checked out proposal branch with {} unpublished commits ({} ahead {} behind '{main_branch_name}')", 946 "checked out proposal branch with {} unpublished commits ({} ahead {} behind '{main_branch_name}')",
1013 local_ahead_of_proposal.len(), 947 local_ahead_of_proposal.len(),
1014 local_ahead_of_main.len(), 948 local_ahead_of_main.len(),
1015 proposal_behind_main.len(), 949 proposal_behind_main_len,
1016 ); 950 );
1017 Ok(()) 951 Ok(())
1018 } 952 }
@@ -1032,7 +966,7 @@ async fn launch_interactive() -> Result<()> {
1032 println!( 966 println!(
1033 "you have previously applied the latest version of the proposal ({} ahead {} behind '{main_branch_name}') but your local proposal branch has amended or rebased it ({} ahead {} behind '{main_branch_name}')", 967 "you have previously applied the latest version of the proposal ({} ahead {} behind '{main_branch_name}') but your local proposal branch has amended or rebased it ({} ahead {} behind '{main_branch_name}')",
1034 most_recent_proposal_patch_chain_or_pr_or_pr_update.len(), 968 most_recent_proposal_patch_chain_or_pr_or_pr_update.len(),
1035 proposal_behind_main.len(), 969 proposal_behind_main_len,
1036 local_ahead_of_main.len(), 970 local_ahead_of_main.len(),
1037 local_beind_main.len(), 971 local_beind_main.len(),
1038 ); 972 );
@@ -1045,7 +979,7 @@ async fn launch_interactive() -> Result<()> {
1045 local_ahead_of_main.len(), 979 local_ahead_of_main.len(),
1046 local_beind_main.len(), 980 local_beind_main.len(),
1047 most_recent_proposal_patch_chain_or_pr_or_pr_update.len(), 981 most_recent_proposal_patch_chain_or_pr_or_pr_update.len(),
1048 proposal_behind_main.len(), 982 proposal_behind_main_len,
1049 ); 983 );
1050 984
1051 println!( 985 println!(
@@ -1085,10 +1019,6 @@ async fn launch_interactive() -> Result<()> {
1085 } 1019 }
1086 1 => { 1020 1 => {
1087 check_clean(&git_repo)?; 1021 check_clean(&git_repo)?;
1088 git_repo.create_branch_at_commit(
1089 &cover_letter.get_branch_name_with_pr_prefix_and_shorthand_id()?,
1090 &proposal_base_commit.to_string(),
1091 )?;
1092 let chain_length = most_recent_proposal_patch_chain_or_pr_or_pr_update.len(); 1022 let chain_length = most_recent_proposal_patch_chain_or_pr_or_pr_update.len();
1093 let _ = git_repo 1023 let _ = git_repo
1094 .apply_patch_chain( 1024 .apply_patch_chain(
@@ -1102,7 +1032,7 @@ async fn launch_interactive() -> Result<()> {
1102 println!( 1032 println!(
1103 "checked out latest version of proposal ({} ahead {} behind '{main_branch_name}'), replacing unpublished version ({} ahead {} behind '{main_branch_name}')", 1033 "checked out latest version of proposal ({} ahead {} behind '{main_branch_name}'), replacing unpublished version ({} ahead {} behind '{main_branch_name}')",
1104 chain_length, 1034 chain_length,
1105 proposal_behind_main.len(), 1035 proposal_behind_main_len,
1106 local_ahead_of_main.len(), 1036 local_ahead_of_main.len(),
1107 local_beind_main.len(), 1037 local_beind_main.len(),
1108 ); 1038 );