diff options
| author | DanConwayDev <DanConwayDev@protonmail.com> | 2024-02-21 11:07:38 +0000 |
|---|---|---|
| committer | DanConwayDev <DanConwayDev@protonmail.com> | 2024-02-21 11:07:38 +0000 |
| commit | 125ead4bb64d9e4a76266aabe5e826fc23551edc (patch) | |
| tree | ad6807af12e11f9fba9d2e04e15e1c56bb5f64b3 /src/sub_commands/send.rs | |
| parent | 141ebf0cc0c6cfea640debc9b9073303509a8bc7 (diff) | |
feat(send): specify commits eg HEAD~2
specifiy commits or commit ranges in the
same way that `git format-patch` allows
Diffstat (limited to 'src/sub_commands/send.rs')
| -rw-r--r-- | src/sub_commands/send.rs | 65 |
1 files changed, 40 insertions, 25 deletions
diff --git a/src/sub_commands/send.rs b/src/sub_commands/send.rs index 004d263..105f87a 100644 --- a/src/sub_commands/send.rs +++ b/src/sub_commands/send.rs | |||
| @@ -21,8 +21,12 @@ use crate::{ | |||
| 21 | 21 | ||
| 22 | #[derive(Debug, clap::Args)] | 22 | #[derive(Debug, clap::Args)] |
| 23 | pub struct SubCommandArgs { | 23 | pub struct SubCommandArgs { |
| 24 | #[clap(short, long)] | 24 | #[arg(default_value = "")] |
| 25 | /// starting commit (commits since in current branch) or commit range, like | ||
| 26 | /// in `git format-patch` | ||
| 27 | starting_commit: String, | ||
| 25 | /// optional cover letter title | 28 | /// optional cover letter title |
| 29 | #[clap(short, long)] | ||
| 26 | title: Option<String>, | 30 | title: Option<String>, |
| 27 | #[clap(short, long)] | 31 | #[clap(short, long)] |
| 28 | /// optional cover letter description | 32 | /// optional cover letter description |
| @@ -42,22 +46,24 @@ pub struct SubCommandArgs { | |||
| 42 | pub async fn launch(cli_args: &Cli, args: &SubCommandArgs) -> Result<()> { | 46 | pub async fn launch(cli_args: &Cli, args: &SubCommandArgs) -> Result<()> { |
| 43 | let git_repo = Repo::discover().context("cannot find a git repository")?; | 47 | let git_repo = Repo::discover().context("cannot find a git repository")?; |
| 44 | 48 | ||
| 45 | let (from_branch, to_branch, mut ahead, behind) = | 49 | let mut commits: Vec<Sha1Hash> = { |
| 46 | identify_ahead_behind(&git_repo, &args.from_branch, &args.to_branch)?; | 50 | if args.starting_commit.is_empty() { |
| 51 | let (from_branch, to_branch, ahead, behind) = | ||
| 52 | identify_ahead_behind(&git_repo, &args.from_branch, &args.to_branch)?; | ||
| 47 | 53 | ||
| 48 | if ahead.is_empty() { | 54 | if ahead.is_empty() { |
| 49 | bail!(format!( | 55 | bail!(format!( |
| 50 | "'{from_branch}' is 0 commits ahead of '{to_branch}' so no patches were created" | 56 | "'{from_branch}' is 0 commits ahead of '{to_branch}' so no patches were created" |
| 51 | )); | 57 | )); |
| 52 | } | 58 | } |
| 53 | 59 | ||
| 54 | if behind.is_empty() { | 60 | if behind.is_empty() { |
| 55 | println!( | 61 | println!( |
| 56 | "creating patch for {} commits from '{from_branch}' that can be merged into '{to_branch}'", | 62 | "creating patch for {} commits from '{from_branch}' that can be merged into '{to_branch}'", |
| 57 | ahead.len(), | 63 | ahead.len(), |
| 58 | ); | 64 | ); |
| 59 | } else { | 65 | } else { |
| 60 | if !Interactor::default().confirm( | 66 | if !Interactor::default().confirm( |
| 61 | PromptConfirmParms::default() | 67 | PromptConfirmParms::default() |
| 62 | .with_prompt( | 68 | .with_prompt( |
| 63 | format!( | 69 | format!( |
| @@ -70,14 +76,23 @@ pub async fn launch(cli_args: &Cli, args: &SubCommandArgs) -> Result<()> { | |||
| 70 | ).context("failed to get confirmation response from interactor confirm")? { | 76 | ).context("failed to get confirmation response from interactor confirm")? { |
| 71 | bail!("aborting so branch can be rebased"); | 77 | bail!("aborting so branch can be rebased"); |
| 72 | } | 78 | } |
| 73 | println!( | 79 | println!( |
| 74 | "creating patch for {} commit{} from '{from_branch}' that {} {} behind '{to_branch}'", | 80 | "creating patch for {} commit{} from '{from_branch}' that {} {} behind '{to_branch}'", |
| 75 | ahead.len(), | 81 | ahead.len(), |
| 76 | if ahead.len() > 1 { "s" } else { "" }, | 82 | if ahead.len() > 1 { "s" } else { "" }, |
| 77 | if ahead.len() > 1 { "are" } else { "is" }, | 83 | if ahead.len() > 1 { "are" } else { "is" }, |
| 78 | behind.len(), | 84 | behind.len(), |
| 79 | ); | 85 | ); |
| 80 | } | 86 | } |
| 87 | ahead | ||
| 88 | } else { | ||
| 89 | let ahead = git_repo | ||
| 90 | .parse_starting_commits(&args.starting_commit) | ||
| 91 | .context("cannot parse specified starting commit or range")?; | ||
| 92 | println!("creating patch for {} commits", ahead.len(),); | ||
| 93 | ahead | ||
| 94 | } | ||
| 95 | }; | ||
| 81 | 96 | ||
| 82 | let title = if args.no_cover_letter { | 97 | let title = if args.no_cover_letter { |
| 83 | None | 98 | None |
| @@ -138,12 +153,12 @@ pub async fn launch(cli_args: &Cli, args: &SubCommandArgs) -> Result<()> { | |||
| 138 | .await?; | 153 | .await?; |
| 139 | 154 | ||
| 140 | // oldest first | 155 | // oldest first |
| 141 | ahead.reverse(); | 156 | commits.reverse(); |
| 142 | 157 | ||
| 143 | let events = generate_cover_letter_and_patch_events( | 158 | let events = generate_cover_letter_and_patch_events( |
| 144 | cover_letter_title_description.clone(), | 159 | cover_letter_title_description.clone(), |
| 145 | &git_repo, | 160 | &git_repo, |
| 146 | &ahead, | 161 | &commits, |
| 147 | &keys, | 162 | &keys, |
| 148 | &repo_ref, | 163 | &repo_ref, |
| 149 | )?; | 164 | )?; |